1/*
2 * This module provides common API for accessing firmware configuration pages
3 *
4 * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c
5 * Copyright (C) 2012-2014  LSI Corporation
6 * Copyright (C) 2013-2014 Avago Technologies
7 *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * NO WARRANTY
20 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
21 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
22 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
23 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
24 * solely responsible for determining the appropriateness of using and
25 * distributing the Program and assumes all risks associated with its
26 * exercise of rights under this Agreement, including but not limited to
27 * the risks and costs of program errors, damage to or loss of data,
28 * programs or equipment, and unavailability or interruption of operations.
29
30 * DISCLAIMER OF LIABILITY
31 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
37 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
38
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
42 * USA.
43 */
44
45#include <linux/module.h>
46#include <linux/kernel.h>
47#include <linux/init.h>
48#include <linux/errno.h>
49#include <linux/blkdev.h>
50#include <linux/sched.h>
51#include <linux/workqueue.h>
52#include <linux/delay.h>
53#include <linux/pci.h>
54
55#include "mpt3sas_base.h"
56
57/* local definitions */
58
59/* Timeout for config page request (in seconds) */
60#define MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT 15
61
62/* Common sgl flags for READING a config page. */
63#define MPT3_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
64	MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
65	| MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT)
66
67/* Common sgl flags for WRITING a config page. */
68#define MPT3_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
69	MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
70	| MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \
71	<< MPI2_SGE_FLAGS_SHIFT)
72
73/**
74 * struct config_request - obtain dma memory via routine
75 * @sz: size
76 * @page: virt pointer
77 * @page_dma: phys pointer
78 *
79 */
80struct config_request {
81	u16			sz;
82	void			*page;
83	dma_addr_t		page_dma;
84};
85
86/**
87 * _config_display_some_debug - debug routine
88 * @ioc: per adapter object
89 * @smid: system request message index
90 * @calling_function_name: string pass from calling function
91 * @mpi_reply: reply message frame
92 * Context: none.
93 *
94 * Function for displaying debug info helpful when debugging issues
95 * in this module.
96 */
97static void
98_config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
99	char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
100{
101	Mpi2ConfigRequest_t *mpi_request;
102	char *desc = NULL;
103
104	mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
105	switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
106	case MPI2_CONFIG_PAGETYPE_IO_UNIT:
107		desc = "io_unit";
108		break;
109	case MPI2_CONFIG_PAGETYPE_IOC:
110		desc = "ioc";
111		break;
112	case MPI2_CONFIG_PAGETYPE_BIOS:
113		desc = "bios";
114		break;
115	case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
116		desc = "raid_volume";
117		break;
118	case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
119		desc = "manufacturing";
120		break;
121	case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
122		desc = "physdisk";
123		break;
124	case MPI2_CONFIG_PAGETYPE_EXTENDED:
125		switch (mpi_request->ExtPageType) {
126		case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
127			desc = "sas_io_unit";
128			break;
129		case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
130			desc = "sas_expander";
131			break;
132		case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
133			desc = "sas_device";
134			break;
135		case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
136			desc = "sas_phy";
137			break;
138		case MPI2_CONFIG_EXTPAGETYPE_LOG:
139			desc = "log";
140			break;
141		case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
142			desc = "enclosure";
143			break;
144		case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
145			desc = "raid_config";
146			break;
147		case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
148			desc = "driver_mapping";
149			break;
150		case MPI2_CONFIG_EXTPAGETYPE_SAS_PORT:
151			desc = "sas_port";
152			break;
153		case MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING:
154			desc = "ext_manufacturing";
155			break;
156		case MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT:
157			desc = "pcie_io_unit";
158			break;
159		case MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH:
160			desc = "pcie_switch";
161			break;
162		case MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE:
163			desc = "pcie_device";
164			break;
165		case MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK:
166			desc = "pcie_link";
167			break;
168		}
169		break;
170	}
171
172	if (!desc)
173		return;
174
175	ioc_info(ioc, "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n",
176		 calling_function_name, desc,
177		 mpi_request->Header.PageNumber, mpi_request->Action,
178		 le32_to_cpu(mpi_request->PageAddress), smid);
179
180	if (!mpi_reply)
181		return;
182
183	if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
184		ioc_info(ioc, "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
185			 le16_to_cpu(mpi_reply->IOCStatus),
186			 le32_to_cpu(mpi_reply->IOCLogInfo));
187}
188
189/**
190 * _config_alloc_config_dma_memory - obtain physical memory
191 * @ioc: per adapter object
192 * @mem: struct config_request
193 *
194 * A wrapper for obtaining dma-able memory for config page request.
195 *
196 * Return: 0 for success, non-zero for failure.
197 */
198static int
199_config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
200	struct config_request *mem)
201{
202	int r = 0;
203
204	if (mem->sz > ioc->config_page_sz) {
205		mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
206		    &mem->page_dma, GFP_KERNEL);
207		if (!mem->page) {
208			ioc_err(ioc, "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n",
209				__func__, mem->sz);
210			r = -ENOMEM;
211		}
212	} else { /* use tmp buffer if less than 512 bytes */
213		mem->page = ioc->config_page;
214		mem->page_dma = ioc->config_page_dma;
215	}
216	ioc->config_vaddr = mem->page;
217	return r;
218}
219
220/**
221 * _config_free_config_dma_memory - wrapper to free the memory
222 * @ioc: per adapter object
223 * @mem: struct config_request
224 *
225 * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
226 *
227 * Return: 0 for success, non-zero for failure.
228 */
229static void
230_config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
231	struct config_request *mem)
232{
233	if (mem->sz > ioc->config_page_sz)
234		dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
235		    mem->page_dma);
236}
237
238/**
239 * mpt3sas_config_done - config page completion routine
240 * @ioc: per adapter object
241 * @smid: system request message index
242 * @msix_index: MSIX table index supplied by the OS
243 * @reply: reply message frame(lower 32bit addr)
244 * Context: none.
245 *
246 * The callback handler when using _config_request.
247 *
248 * Return: 1 meaning mf should be freed from _base_interrupt
249 *         0 means the mf is freed from this function.
250 */
251u8
252mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
253	u32 reply)
254{
255	MPI2DefaultReply_t *mpi_reply;
256
257	if (ioc->config_cmds.status == MPT3_CMD_NOT_USED)
258		return 1;
259	if (ioc->config_cmds.smid != smid)
260		return 1;
261	ioc->config_cmds.status |= MPT3_CMD_COMPLETE;
262	mpi_reply =  mpt3sas_base_get_reply_virt_addr(ioc, reply);
263	if (mpi_reply) {
264		ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID;
265		memcpy(ioc->config_cmds.reply, mpi_reply,
266		    mpi_reply->MsgLength*4);
267	}
268	ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
269	if (ioc->logging_level & MPT_DEBUG_CONFIG)
270		_config_display_some_debug(ioc, smid, "config_done", mpi_reply);
271	ioc->config_cmds.smid = USHRT_MAX;
272	complete(&ioc->config_cmds.done);
273	return 1;
274}
275
276/**
277 * _config_request - main routine for sending config page requests
278 * @ioc: per adapter object
279 * @mpi_request: request message frame
280 * @mpi_reply: reply mf payload returned from firmware
281 * @timeout: timeout in seconds
282 * @config_page: contents of the config page
283 * @config_page_sz: size of config page
284 * Context: sleep
285 *
286 * A generic API for config page requests to firmware.
287 *
288 * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling
289 * this API.
290 *
291 * The callback index is set inside `ioc->config_cb_idx.
292 *
293 * Return: 0 for success, non-zero for failure.
294 */
295static int
296_config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
297	*mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
298	void *config_page, u16 config_page_sz)
299{
300	u16 smid;
301	Mpi2ConfigRequest_t *config_request;
302	int r;
303	u8 retry_count, issue_host_reset = 0;
304	struct config_request mem;
305	u32 ioc_status = UINT_MAX;
306
307	mutex_lock(&ioc->config_cmds.mutex);
308	if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
309		ioc_err(ioc, "%s: config_cmd in use\n", __func__);
310		mutex_unlock(&ioc->config_cmds.mutex);
311		return -EAGAIN;
312	}
313
314	retry_count = 0;
315	memset(&mem, 0, sizeof(struct config_request));
316
317	mpi_request->VF_ID = 0; /* TODO */
318	mpi_request->VP_ID = 0;
319
320	if (config_page) {
321		mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
322		mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
323		mpi_request->Header.PageType = mpi_reply->Header.PageType;
324		mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
325		mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
326		mpi_request->ExtPageType = mpi_reply->ExtPageType;
327		if (mpi_request->Header.PageLength)
328			mem.sz = mpi_request->Header.PageLength * 4;
329		else
330			mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
331		r = _config_alloc_config_dma_memory(ioc, &mem);
332		if (r != 0)
333			goto out;
334		if (mpi_request->Action ==
335		    MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
336		    mpi_request->Action ==
337		    MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
338			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
339			    MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
340			    mem.page_dma);
341			memcpy(mem.page, config_page, min_t(u16, mem.sz,
342			    config_page_sz));
343		} else {
344			memset(config_page, 0, config_page_sz);
345			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
346			    MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
347			memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
348		}
349	}
350
351 retry_config:
352	if (retry_count) {
353		if (retry_count > 2) { /* attempt only 2 retries */
354			r = -EFAULT;
355			goto free_mem;
356		}
357		ioc_info(ioc, "%s: attempting retry (%d)\n",
358			 __func__, retry_count);
359	}
360
361	r = mpt3sas_wait_for_ioc(ioc, MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT);
362	if (r) {
363		if (r == -ETIME)
364			issue_host_reset = 1;
365		goto free_mem;
366	}
367
368	smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
369	if (!smid) {
370		ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
371		ioc->config_cmds.status = MPT3_CMD_NOT_USED;
372		r = -EAGAIN;
373		goto free_mem;
374	}
375
376	r = 0;
377	memset(ioc->config_cmds.reply, 0, sizeof(Mpi2ConfigReply_t));
378	ioc->config_cmds.status = MPT3_CMD_PENDING;
379	config_request = mpt3sas_base_get_msg_frame(ioc, smid);
380	ioc->config_cmds.smid = smid;
381	memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
382	if (ioc->logging_level & MPT_DEBUG_CONFIG)
383		_config_display_some_debug(ioc, smid, "config_request", NULL);
384	init_completion(&ioc->config_cmds.done);
385	ioc->put_smid_default(ioc, smid);
386	wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ);
387	if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
388		if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
389			_config_display_some_debug(ioc,
390			    smid, "config_request", NULL);
391		ioc_err(ioc, "%s: command timeout\n", __func__);
392		mpt3sas_base_check_cmd_timeout(ioc, ioc->config_cmds.status,
393				mpi_request, sizeof(Mpi2ConfigRequest_t) / 4);
394		retry_count++;
395		if (ioc->config_cmds.smid == smid)
396			mpt3sas_base_free_smid(ioc, smid);
397		if (ioc->config_cmds.status & MPT3_CMD_RESET)
398			goto retry_config;
399		if (ioc->shost_recovery || ioc->pci_error_recovery) {
400			issue_host_reset = 0;
401			r = -EFAULT;
402		} else
403			issue_host_reset = 1;
404		goto free_mem;
405	}
406
407	if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
408		memcpy(mpi_reply, ioc->config_cmds.reply,
409		    sizeof(Mpi2ConfigReply_t));
410
411		/* Reply Frame Sanity Checks to workaround FW issues */
412		if ((mpi_request->Header.PageType & 0xF) !=
413		    (mpi_reply->Header.PageType & 0xF)) {
414			if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
415				_config_display_some_debug(ioc,
416				    smid, "config_request", NULL);
417			_debug_dump_mf(mpi_request, ioc->request_sz/4);
418			_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
419			panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
420			      ioc->name, __func__,
421			      mpi_request->Header.PageType & 0xF,
422			      mpi_reply->Header.PageType & 0xF);
423		}
424
425		if (((mpi_request->Header.PageType & 0xF) ==
426		    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
427		    mpi_request->ExtPageType != mpi_reply->ExtPageType) {
428			if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
429				_config_display_some_debug(ioc,
430				    smid, "config_request", NULL);
431			_debug_dump_mf(mpi_request, ioc->request_sz/4);
432			_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
433			panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
434			      ioc->name, __func__,
435			      mpi_request->ExtPageType,
436			      mpi_reply->ExtPageType);
437		}
438		ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
439		    & MPI2_IOCSTATUS_MASK;
440	}
441
442	if (retry_count)
443		ioc_info(ioc, "%s: retry (%d) completed!!\n",
444			 __func__, retry_count);
445
446	if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
447	    config_page && mpi_request->Action ==
448	    MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
449		u8 *p = (u8 *)mem.page;
450
451		/* Config Page Sanity Checks to workaround FW issues */
452		if (p) {
453			if ((mpi_request->Header.PageType & 0xF) !=
454			    (p[3] & 0xF)) {
455				if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
456					_config_display_some_debug(ioc,
457					    smid, "config_request", NULL);
458				_debug_dump_mf(mpi_request, ioc->request_sz/4);
459				_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
460				_debug_dump_config(p, min_t(u16, mem.sz,
461				    config_page_sz)/4);
462				panic("%s: %s: Firmware BUG: config page mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
463				      ioc->name, __func__,
464				      mpi_request->Header.PageType & 0xF,
465				      p[3] & 0xF);
466			}
467
468			if (((mpi_request->Header.PageType & 0xF) ==
469			    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
470			    (mpi_request->ExtPageType != p[6])) {
471				if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
472					_config_display_some_debug(ioc,
473					    smid, "config_request", NULL);
474				_debug_dump_mf(mpi_request, ioc->request_sz/4);
475				_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
476				_debug_dump_config(p, min_t(u16, mem.sz,
477				    config_page_sz)/4);
478				panic("%s: %s: Firmware BUG: config page mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
479				      ioc->name, __func__,
480				      mpi_request->ExtPageType, p[6]);
481			}
482		}
483		memcpy(config_page, mem.page, min_t(u16, mem.sz,
484		    config_page_sz));
485	}
486
487 free_mem:
488	if (config_page)
489		_config_free_config_dma_memory(ioc, &mem);
490 out:
491	ioc->config_cmds.status = MPT3_CMD_NOT_USED;
492	mutex_unlock(&ioc->config_cmds.mutex);
493
494	if (issue_host_reset) {
495		if (ioc->drv_internal_flags & MPT_DRV_INTERNAL_FIRST_PE_ISSUED) {
496			mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
497			r = -EFAULT;
498		} else {
499			if (mpt3sas_base_check_for_fault_and_issue_reset(ioc))
500				return -EFAULT;
501			r = -EAGAIN;
502		}
503	}
504	return r;
505}
506
507/**
508 * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
509 * @ioc: per adapter object
510 * @mpi_reply: reply mf payload returned from firmware
511 * @config_page: contents of the config page
512 * Context: sleep.
513 *
514 * Return: 0 for success, non-zero for failure.
515 */
516int
517mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
518	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
519{
520	Mpi2ConfigRequest_t mpi_request;
521	int r;
522
523	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
524	mpi_request.Function = MPI2_FUNCTION_CONFIG;
525	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
526	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
527	mpi_request.Header.PageNumber = 0;
528	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
529	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
530	r = _config_request(ioc, &mpi_request, mpi_reply,
531	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
532	if (r)
533		goto out;
534
535	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
536	r = _config_request(ioc, &mpi_request, mpi_reply,
537	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
538	    sizeof(*config_page));
539 out:
540	return r;
541}
542
543/**
544 * mpt3sas_config_get_manufacturing_pg1 - obtain manufacturing page 1
545 * @ioc: per adapter object
546 * @mpi_reply: reply mf payload returned from firmware
547 * @config_page: contents of the config page
548 * Context: sleep.
549 *
550 * Return: 0 for success, non-zero for failure.
551 */
552int
553mpt3sas_config_get_manufacturing_pg1(struct MPT3SAS_ADAPTER *ioc,
554	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage1_t *config_page)
555{
556	Mpi2ConfigRequest_t mpi_request;
557	int r;
558
559	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
560	mpi_request.Function = MPI2_FUNCTION_CONFIG;
561	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
562	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
563	mpi_request.Header.PageNumber = 1;
564	mpi_request.Header.PageVersion = MPI2_MANUFACTURING1_PAGEVERSION;
565	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
566	r = _config_request(ioc, &mpi_request, mpi_reply,
567		MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
568	if (r)
569		goto out;
570
571	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
572	r = _config_request(ioc, &mpi_request, mpi_reply,
573		MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
574		sizeof(*config_page));
575 out:
576	return r;
577}
578
579/**
580 * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
581 * @ioc: per adapter object
582 * @mpi_reply: reply mf payload returned from firmware
583 * @config_page: contents of the config page
584 * @sz: size of buffer passed in config_page
585 * Context: sleep.
586 *
587 * Return: 0 for success, non-zero for failure.
588 */
589int
590mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
591	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
592	u16 sz)
593{
594	Mpi2ConfigRequest_t mpi_request;
595	int r;
596
597	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
598	mpi_request.Function = MPI2_FUNCTION_CONFIG;
599	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
600	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
601	mpi_request.Header.PageNumber = 7;
602	mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
603	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
604	r = _config_request(ioc, &mpi_request, mpi_reply,
605	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
606	if (r)
607		goto out;
608
609	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
610	r = _config_request(ioc, &mpi_request, mpi_reply,
611	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
612	    sz);
613 out:
614	return r;
615}
616
617/**
618 * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
619 * @ioc: per adapter object
620 * @mpi_reply: reply mf payload returned from firmware
621 * @config_page: contents of the config page
622 * Context: sleep.
623 *
624 * Return: 0 for success, non-zero for failure.
625 */
626int
627mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
628	Mpi2ConfigReply_t *mpi_reply,
629	struct Mpi2ManufacturingPage10_t *config_page)
630{
631	Mpi2ConfigRequest_t mpi_request;
632	int r;
633
634	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
635	mpi_request.Function = MPI2_FUNCTION_CONFIG;
636	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
637	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
638	mpi_request.Header.PageNumber = 10;
639	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
640	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
641	r = _config_request(ioc, &mpi_request, mpi_reply,
642	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
643	if (r)
644		goto out;
645
646	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
647	r = _config_request(ioc, &mpi_request, mpi_reply,
648	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
649	    sizeof(*config_page));
650 out:
651	return r;
652}
653
654/**
655 * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
656 * @ioc: per adapter object
657 * @mpi_reply: reply mf payload returned from firmware
658 * @config_page: contents of the config page
659 * Context: sleep.
660 *
661 * Return: 0 for success, non-zero for failure.
662 */
663int
664mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
665	Mpi2ConfigReply_t *mpi_reply,
666	struct Mpi2ManufacturingPage11_t *config_page)
667{
668	Mpi2ConfigRequest_t mpi_request;
669	int r;
670
671	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
672	mpi_request.Function = MPI2_FUNCTION_CONFIG;
673	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
674	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
675	mpi_request.Header.PageNumber = 11;
676	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
677	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
678	r = _config_request(ioc, &mpi_request, mpi_reply,
679	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
680	if (r)
681		goto out;
682
683	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
684	r = _config_request(ioc, &mpi_request, mpi_reply,
685	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
686	    sizeof(*config_page));
687 out:
688	return r;
689}
690
691/**
692 * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
693 * @ioc: per adapter object
694 * @mpi_reply: reply mf payload returned from firmware
695 * @config_page: contents of the config page
696 * Context: sleep.
697 *
698 * Return: 0 for success, non-zero for failure.
699 */
700int
701mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
702	Mpi2ConfigReply_t *mpi_reply,
703	struct Mpi2ManufacturingPage11_t *config_page)
704{
705	Mpi2ConfigRequest_t mpi_request;
706	int r;
707
708	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
709	mpi_request.Function = MPI2_FUNCTION_CONFIG;
710	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
711	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
712	mpi_request.Header.PageNumber = 11;
713	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
714	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
715	r = _config_request(ioc, &mpi_request, mpi_reply,
716	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
717	if (r)
718		goto out;
719
720	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
721	r = _config_request(ioc, &mpi_request, mpi_reply,
722	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
723	    sizeof(*config_page));
724 out:
725	return r;
726}
727
728/**
729 * mpt3sas_config_get_bios_pg2 - obtain bios page 2
730 * @ioc: per adapter object
731 * @mpi_reply: reply mf payload returned from firmware
732 * @config_page: contents of the config page
733 * Context: sleep.
734 *
735 * Return: 0 for success, non-zero for failure.
736 */
737int
738mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
739	Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
740{
741	Mpi2ConfigRequest_t mpi_request;
742	int r;
743
744	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
745	mpi_request.Function = MPI2_FUNCTION_CONFIG;
746	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
747	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
748	mpi_request.Header.PageNumber = 2;
749	mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
750	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
751	r = _config_request(ioc, &mpi_request, mpi_reply,
752	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
753	if (r)
754		goto out;
755
756	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
757	r = _config_request(ioc, &mpi_request, mpi_reply,
758	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
759	    sizeof(*config_page));
760 out:
761	return r;
762}
763
764/**
765 * mpt3sas_config_get_bios_pg3 - obtain bios page 3
766 * @ioc: per adapter object
767 * @mpi_reply: reply mf payload returned from firmware
768 * @config_page: contents of the config page
769 * Context: sleep.
770 *
771 * Return: 0 for success, non-zero for failure.
772 */
773int
774mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
775	*mpi_reply, Mpi2BiosPage3_t *config_page)
776{
777	Mpi2ConfigRequest_t mpi_request;
778	int r;
779
780	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
781	mpi_request.Function = MPI2_FUNCTION_CONFIG;
782	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
783	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
784	mpi_request.Header.PageNumber = 3;
785	mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
786	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
787	r = _config_request(ioc, &mpi_request, mpi_reply,
788	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
789	if (r)
790		goto out;
791
792	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
793	r = _config_request(ioc, &mpi_request, mpi_reply,
794	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
795	    sizeof(*config_page));
796
797 out:
798	return r;
799}
800
801/**
802 * mpt3sas_config_set_bios_pg4 - write out bios page 4
803 * @ioc: per adapter object
804 * @mpi_reply: reply mf payload returned from firmware
805 * @config_page: contents of the config page
806 * @sz_config_pg: sizeof the config page
807 * Context: sleep.
808 *
809 * Return: 0 for success, non-zero for failure.
810 */
811int
812mpt3sas_config_set_bios_pg4(struct MPT3SAS_ADAPTER *ioc,
813	Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage4_t *config_page,
814	int sz_config_pg)
815{
816	Mpi2ConfigRequest_t mpi_request;
817	int r;
818
819	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
820
821	mpi_request.Function = MPI2_FUNCTION_CONFIG;
822	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
823	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
824	mpi_request.Header.PageNumber = 4;
825	mpi_request.Header.PageVersion = MPI2_BIOSPAGE4_PAGEVERSION;
826
827	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
828
829	r = _config_request(ioc, &mpi_request, mpi_reply,
830		MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
831	if (r)
832		goto out;
833
834	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
835	r = _config_request(ioc, &mpi_request, mpi_reply,
836		MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
837		sz_config_pg);
838 out:
839	return r;
840}
841
842/**
843 * mpt3sas_config_get_bios_pg4 - read bios page 4
844 * @ioc: per adapter object
845 * @mpi_reply: reply mf payload returned from firmware
846 * @config_page: contents of the config page
847 * @sz_config_pg: sizeof the config page
848 * Context: sleep.
849 *
850 * Return: 0 for success, non-zero for failure.
851 */
852int
853mpt3sas_config_get_bios_pg4(struct MPT3SAS_ADAPTER *ioc,
854	Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage4_t *config_page,
855	int sz_config_pg)
856{
857	Mpi2ConfigRequest_t mpi_request;
858	int r;
859
860	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
861	mpi_request.Function = MPI2_FUNCTION_CONFIG;
862	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
863	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
864	mpi_request.Header.PageNumber = 4;
865	mpi_request.Header.PageVersion =  MPI2_BIOSPAGE4_PAGEVERSION;
866	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
867	r = _config_request(ioc, &mpi_request, mpi_reply,
868		MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
869	if (r)
870		goto out;
871
872	/*
873	 * The sizeof the page is variable. Allow for just the
874	 * size to be returned
875	 */
876	if (config_page && sz_config_pg) {
877		mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
878
879		r = _config_request(ioc, &mpi_request, mpi_reply,
880			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
881			sz_config_pg);
882	}
883
884out:
885	return r;
886}
887
888/**
889 * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
890 * @ioc: per adapter object
891 * @mpi_reply: reply mf payload returned from firmware
892 * @config_page: contents of the config page
893 * Context: sleep.
894 *
895 * Return: 0 for success, non-zero for failure.
896 */
897int
898mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
899	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
900{
901	Mpi2ConfigRequest_t mpi_request;
902	int r;
903
904	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
905	mpi_request.Function = MPI2_FUNCTION_CONFIG;
906	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
907	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
908	mpi_request.Header.PageNumber = 0;
909	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
910	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
911	r = _config_request(ioc, &mpi_request, mpi_reply,
912	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
913	if (r)
914		goto out;
915
916	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
917	r = _config_request(ioc, &mpi_request, mpi_reply,
918	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
919	    sizeof(*config_page));
920 out:
921	return r;
922}
923
924/**
925 * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
926 * @ioc: per adapter object
927 * @mpi_reply: reply mf payload returned from firmware
928 * @config_page: contents of the config page
929 * Context: sleep.
930 *
931 * Return: 0 for success, non-zero for failure.
932 */
933int
934mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
935	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
936{
937	Mpi2ConfigRequest_t mpi_request;
938	int r;
939
940	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
941	mpi_request.Function = MPI2_FUNCTION_CONFIG;
942	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
943	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
944	mpi_request.Header.PageNumber = 1;
945	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
946	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
947	r = _config_request(ioc, &mpi_request, mpi_reply,
948	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
949	if (r)
950		goto out;
951
952	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
953	r = _config_request(ioc, &mpi_request, mpi_reply,
954	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
955	    sizeof(*config_page));
956 out:
957	return r;
958}
959
960/**
961 * mpt3sas_config_set_iounit_pg1 - set iounit page 1
962 * @ioc: per adapter object
963 * @mpi_reply: reply mf payload returned from firmware
964 * @config_page: contents of the config page
965 * Context: sleep.
966 *
967 * Return: 0 for success, non-zero for failure.
968 */
969int
970mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
971	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
972{
973	Mpi2ConfigRequest_t mpi_request;
974	int r;
975
976	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
977	mpi_request.Function = MPI2_FUNCTION_CONFIG;
978	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
979	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
980	mpi_request.Header.PageNumber = 1;
981	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
982	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
983	r = _config_request(ioc, &mpi_request, mpi_reply,
984	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
985	if (r)
986		goto out;
987
988	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
989	r = _config_request(ioc, &mpi_request, mpi_reply,
990	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
991	    sizeof(*config_page));
992 out:
993	return r;
994}
995
996/**
997 * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
998 * @ioc: per adapter object
999 * @mpi_reply: reply mf payload returned from firmware
1000 * @config_page: contents of the config page
1001 * @sz: size of buffer passed in config_page
1002 * Context: sleep.
1003 *
1004 * Return: 0 for success, non-zero for failure.
1005 */
1006int
1007mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
1008	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
1009{
1010	Mpi2ConfigRequest_t mpi_request;
1011	int r;
1012
1013	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1014	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1015	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1016	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
1017	mpi_request.Header.PageNumber = 3;
1018	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
1019	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1020	r = _config_request(ioc, &mpi_request, mpi_reply,
1021	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1022	if (r)
1023		goto out;
1024
1025	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1026	r = _config_request(ioc, &mpi_request, mpi_reply,
1027	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1028 out:
1029	return r;
1030}
1031
1032/**
1033 * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
1034 * @ioc: per adapter object
1035 * @mpi_reply: reply mf payload returned from firmware
1036 * @config_page: contents of the config page
1037 * Context: sleep.
1038 *
1039 * Return: 0 for success, non-zero for failure.
1040 */
1041int
1042mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
1043	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
1044{
1045	Mpi2ConfigRequest_t mpi_request;
1046	int r;
1047
1048	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1049	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1050	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1051	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
1052	mpi_request.Header.PageNumber = 8;
1053	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
1054	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1055	r = _config_request(ioc, &mpi_request, mpi_reply,
1056	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1057	if (r)
1058		goto out;
1059
1060	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1061	r = _config_request(ioc, &mpi_request, mpi_reply,
1062	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1063	    sizeof(*config_page));
1064 out:
1065	return r;
1066}
1067
1068/**
1069 * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
1070 * @ioc: per adapter object
1071 * @mpi_reply: reply mf payload returned from firmware
1072 * @config_page: contents of the config page
1073 * Context: sleep.
1074 *
1075 * Return: 0 for success, non-zero for failure.
1076 */
1077int
1078mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
1079	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
1080{
1081	Mpi2ConfigRequest_t mpi_request;
1082	int r;
1083
1084	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1085	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1086	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1087	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
1088	mpi_request.Header.PageNumber = 8;
1089	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
1090	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1091	r = _config_request(ioc, &mpi_request, mpi_reply,
1092	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1093	if (r)
1094		goto out;
1095
1096	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1097	r = _config_request(ioc, &mpi_request, mpi_reply,
1098	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1099	    sizeof(*config_page));
1100 out:
1101	return r;
1102}
1103/**
1104 * mpt3sas_config_get_ioc_pg1 - obtain ioc page 1
1105 * @ioc: per adapter object
1106 * @mpi_reply: reply mf payload returned from firmware
1107 * @config_page: contents of the config page
1108 * Context: sleep.
1109 *
1110 * Return: 0 for success, non-zero for failure.
1111 */
1112int
1113mpt3sas_config_get_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
1114	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
1115{
1116	Mpi2ConfigRequest_t mpi_request;
1117	int r;
1118
1119	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1120	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1121	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1122	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
1123	mpi_request.Header.PageNumber = 1;
1124	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
1125	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1126	r = _config_request(ioc, &mpi_request, mpi_reply,
1127	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1128	if (r)
1129		goto out;
1130
1131	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1132	r = _config_request(ioc, &mpi_request, mpi_reply,
1133	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1134	    sizeof(*config_page));
1135 out:
1136	return r;
1137}
1138
1139/**
1140 * mpt3sas_config_set_ioc_pg1 - modify ioc page 1
1141 * @ioc: per adapter object
1142 * @mpi_reply: reply mf payload returned from firmware
1143 * @config_page: contents of the config page
1144 * Context: sleep.
1145 *
1146 * Return: 0 for success, non-zero for failure.
1147 */
1148int
1149mpt3sas_config_set_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
1150	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
1151{
1152	Mpi2ConfigRequest_t mpi_request;
1153	int r;
1154
1155	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1156	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1157	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1158	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
1159	mpi_request.Header.PageNumber = 1;
1160	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
1161	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1162	r = _config_request(ioc, &mpi_request, mpi_reply,
1163	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1164	if (r)
1165		goto out;
1166
1167	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1168	r = _config_request(ioc, &mpi_request, mpi_reply,
1169	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1170	    sizeof(*config_page));
1171 out:
1172	return r;
1173}
1174
1175/**
1176 * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
1177 * @ioc: per adapter object
1178 * @mpi_reply: reply mf payload returned from firmware
1179 * @config_page: contents of the config page
1180 * @form: GET_NEXT_HANDLE or HANDLE
1181 * @handle: device handle
1182 * Context: sleep.
1183 *
1184 * Return: 0 for success, non-zero for failure.
1185 */
1186int
1187mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1188	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
1189	u32 form, u32 handle)
1190{
1191	Mpi2ConfigRequest_t mpi_request;
1192	int r;
1193
1194	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1195	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1196	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1197	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1198	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1199	mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
1200	mpi_request.Header.PageNumber = 0;
1201	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1202	r = _config_request(ioc, &mpi_request, mpi_reply,
1203	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1204	if (r)
1205		goto out;
1206
1207	mpi_request.PageAddress = cpu_to_le32(form | handle);
1208	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1209	r = _config_request(ioc, &mpi_request, mpi_reply,
1210	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1211	    sizeof(*config_page));
1212 out:
1213	return r;
1214}
1215
1216/**
1217 * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
1218 * @ioc: per adapter object
1219 * @mpi_reply: reply mf payload returned from firmware
1220 * @config_page: contents of the config page
1221 * @form: GET_NEXT_HANDLE or HANDLE
1222 * @handle: device handle
1223 * Context: sleep.
1224 *
1225 * Return: 0 for success, non-zero for failure.
1226 */
1227int
1228mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1229	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1230	u32 form, u32 handle)
1231{
1232	Mpi2ConfigRequest_t mpi_request;
1233	int r;
1234
1235	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1236	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1237	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1238	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1239	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1240	mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1241	mpi_request.Header.PageNumber = 1;
1242	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1243	r = _config_request(ioc, &mpi_request, mpi_reply,
1244	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1245	if (r)
1246		goto out;
1247
1248	mpi_request.PageAddress = cpu_to_le32(form | handle);
1249	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1250	r = _config_request(ioc, &mpi_request, mpi_reply,
1251	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1252	    sizeof(*config_page));
1253 out:
1254	return r;
1255}
1256
1257/**
1258 * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
1259 * @ioc: per adapter object
1260 * @mpi_reply: reply mf payload returned from firmware
1261 * @config_page: contents of the config page
1262 * @form: GET_NEXT_HANDLE or HANDLE
1263 * @handle: device handle
1264 * Context: sleep.
1265 *
1266 * Return: 0 for success, non-zero for failure.
1267 */
1268int
1269mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1270	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
1271	u32 form, u32 handle)
1272{
1273	Mpi2ConfigRequest_t mpi_request;
1274	int r;
1275
1276	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1277	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1278	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1279	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1280	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1281	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
1282	mpi_request.Header.PageNumber = 0;
1283	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1284	r = _config_request(ioc, &mpi_request, mpi_reply,
1285			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1286	if (r)
1287		goto out;
1288
1289	mpi_request.PageAddress = cpu_to_le32(form | handle);
1290	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1291	r = _config_request(ioc, &mpi_request, mpi_reply,
1292			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1293			sizeof(*config_page));
1294out:
1295	return r;
1296}
1297
1298/**
1299 * mpt3sas_config_get_pcie_iounit_pg1 - obtain pcie iounit page 1
1300 * @ioc: per adapter object
1301 * @mpi_reply: reply mf payload returned from firmware
1302 * @config_page: contents of the config page
1303 * @sz: size of buffer passed in config_page
1304 * Context: sleep.
1305 *
1306 * Returns 0 for success, non-zero for failure.
1307 */
1308int
1309mpt3sas_config_get_pcie_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1310	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeIOUnitPage1_t *config_page,
1311	u16 sz)
1312{
1313	Mpi2ConfigRequest_t mpi_request;
1314	int r;
1315
1316	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1317	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1318	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1319	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1320	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT;
1321	mpi_request.Header.PageVersion = MPI26_PCIEIOUNITPAGE1_PAGEVERSION;
1322	mpi_request.Header.PageNumber = 1;
1323	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1324	r = _config_request(ioc, &mpi_request, mpi_reply,
1325	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1326	if (r)
1327		goto out;
1328	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1329	r = _config_request(ioc, &mpi_request, mpi_reply,
1330	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1331out:
1332	return r;
1333}
1334
1335/**
1336 * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
1337 * @ioc: per adapter object
1338 * @mpi_reply: reply mf payload returned from firmware
1339 * @config_page: contents of the config page
1340 * @form: GET_NEXT_HANDLE or HANDLE
1341 * @handle: device handle
1342 * Context: sleep.
1343 *
1344 * Return: 0 for success, non-zero for failure.
1345 */
1346int
1347mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
1348	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
1349	u32 form, u32 handle)
1350{
1351	Mpi2ConfigRequest_t mpi_request;
1352	int r;
1353
1354	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1355	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1356	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1357	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1358	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1359	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
1360	mpi_request.Header.PageNumber = 2;
1361	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1362	r = _config_request(ioc, &mpi_request, mpi_reply,
1363			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1364	if (r)
1365		goto out;
1366
1367	mpi_request.PageAddress = cpu_to_le32(form | handle);
1368	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1369	r = _config_request(ioc, &mpi_request, mpi_reply,
1370			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1371			sizeof(*config_page));
1372out:
1373	return r;
1374}
1375
1376/**
1377 * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1378 * @ioc: per adapter object
1379 * @num_phys: pointer returned with the number of phys
1380 * Context: sleep.
1381 *
1382 * Return: 0 for success, non-zero for failure.
1383 */
1384int
1385mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1386{
1387	Mpi2ConfigRequest_t mpi_request;
1388	int r;
1389	u16 ioc_status;
1390	Mpi2ConfigReply_t mpi_reply;
1391	Mpi2SasIOUnitPage0_t config_page;
1392
1393	*num_phys = 0;
1394	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1395	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1396	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1397	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1398	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1399	mpi_request.Header.PageNumber = 0;
1400	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1401	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1402	r = _config_request(ioc, &mpi_request, &mpi_reply,
1403	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1404	if (r)
1405		goto out;
1406
1407	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1408	r = _config_request(ioc, &mpi_request, &mpi_reply,
1409	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1410	    sizeof(Mpi2SasIOUnitPage0_t));
1411	if (!r) {
1412		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1413		    MPI2_IOCSTATUS_MASK;
1414		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1415			*num_phys = config_page.NumPhys;
1416	}
1417 out:
1418	return r;
1419}
1420
1421/**
1422 * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1423 * @ioc: per adapter object
1424 * @mpi_reply: reply mf payload returned from firmware
1425 * @config_page: contents of the config page
1426 * @sz: size of buffer passed in config_page
1427 * Context: sleep.
1428 *
1429 * Calling function should call config_get_number_hba_phys prior to
1430 * this function, so enough memory is allocated for config_page.
1431 *
1432 * Return: 0 for success, non-zero for failure.
1433 */
1434int
1435mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1436	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1437	u16 sz)
1438{
1439	Mpi2ConfigRequest_t mpi_request;
1440	int r;
1441
1442	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1443	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1444	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1445	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1446	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1447	mpi_request.Header.PageNumber = 0;
1448	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1449	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1450	r = _config_request(ioc, &mpi_request, mpi_reply,
1451	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1452	if (r)
1453		goto out;
1454
1455	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1456	r = _config_request(ioc, &mpi_request, mpi_reply,
1457	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1458 out:
1459	return r;
1460}
1461
1462/**
1463 * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1464 * @ioc: per adapter object
1465 * @mpi_reply: reply mf payload returned from firmware
1466 * @config_page: contents of the config page
1467 * @sz: size of buffer passed in config_page
1468 * Context: sleep.
1469 *
1470 * Calling function should call config_get_number_hba_phys prior to
1471 * this function, so enough memory is allocated for config_page.
1472 *
1473 * Return: 0 for success, non-zero for failure.
1474 */
1475int
1476mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1477	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1478	u16 sz)
1479{
1480	Mpi2ConfigRequest_t mpi_request;
1481	int r;
1482
1483	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1484	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1485	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1486	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1487	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1488	mpi_request.Header.PageNumber = 1;
1489	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1490	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1491	r = _config_request(ioc, &mpi_request, mpi_reply,
1492	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1493	if (r)
1494		goto out;
1495
1496	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1497	r = _config_request(ioc, &mpi_request, mpi_reply,
1498	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1499 out:
1500	return r;
1501}
1502
1503/**
1504 * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1505 * @ioc: per adapter object
1506 * @mpi_reply: reply mf payload returned from firmware
1507 * @config_page: contents of the config page
1508 * @sz: size of buffer passed in config_page
1509 * Context: sleep.
1510 *
1511 * Calling function should call config_get_number_hba_phys prior to
1512 * this function, so enough memory is allocated for config_page.
1513 *
1514 * Return: 0 for success, non-zero for failure.
1515 */
1516int
1517mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1518	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1519	u16 sz)
1520{
1521	Mpi2ConfigRequest_t mpi_request;
1522	int r;
1523
1524	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1525	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1526	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1527	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1528	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1529	mpi_request.Header.PageNumber = 1;
1530	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1531	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1532	r = _config_request(ioc, &mpi_request, mpi_reply,
1533	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1534	if (r)
1535		goto out;
1536
1537	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1538	_config_request(ioc, &mpi_request, mpi_reply,
1539	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1540	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1541	r = _config_request(ioc, &mpi_request, mpi_reply,
1542	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1543 out:
1544	return r;
1545}
1546
1547/**
1548 * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1549 * @ioc: per adapter object
1550 * @mpi_reply: reply mf payload returned from firmware
1551 * @config_page: contents of the config page
1552 * @form: GET_NEXT_HANDLE or HANDLE
1553 * @handle: expander handle
1554 * Context: sleep.
1555 *
1556 * Return: 0 for success, non-zero for failure.
1557 */
1558int
1559mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1560	*mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1561{
1562	Mpi2ConfigRequest_t mpi_request;
1563	int r;
1564
1565	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1566	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1567	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1568	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1569	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1570	mpi_request.Header.PageNumber = 0;
1571	mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1572	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1573	r = _config_request(ioc, &mpi_request, mpi_reply,
1574	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1575	if (r)
1576		goto out;
1577
1578	mpi_request.PageAddress = cpu_to_le32(form | handle);
1579	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1580	r = _config_request(ioc, &mpi_request, mpi_reply,
1581	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1582	    sizeof(*config_page));
1583 out:
1584	return r;
1585}
1586
1587/**
1588 * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1589 * @ioc: per adapter object
1590 * @mpi_reply: reply mf payload returned from firmware
1591 * @config_page: contents of the config page
1592 * @phy_number: phy number
1593 * @handle: expander handle
1594 * Context: sleep.
1595 *
1596 * Return: 0 for success, non-zero for failure.
1597 */
1598int
1599mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1600	*mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1601	u16 handle)
1602{
1603	Mpi2ConfigRequest_t mpi_request;
1604	int r;
1605
1606	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1607	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1608	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1609	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1610	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1611	mpi_request.Header.PageNumber = 1;
1612	mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1613	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1614	r = _config_request(ioc, &mpi_request, mpi_reply,
1615	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1616	if (r)
1617		goto out;
1618
1619	mpi_request.PageAddress =
1620	    cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1621	    (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1622	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1623	r = _config_request(ioc, &mpi_request, mpi_reply,
1624	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1625	    sizeof(*config_page));
1626 out:
1627	return r;
1628}
1629
1630/**
1631 * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1632 * @ioc: per adapter object
1633 * @mpi_reply: reply mf payload returned from firmware
1634 * @config_page: contents of the config page
1635 * @form: GET_NEXT_HANDLE or HANDLE
1636 * @handle: expander handle
1637 * Context: sleep.
1638 *
1639 * Return: 0 for success, non-zero for failure.
1640 */
1641int
1642mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1643	*mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1644{
1645	Mpi2ConfigRequest_t mpi_request;
1646	int r;
1647
1648	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1649	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1650	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1651	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1652	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1653	mpi_request.Header.PageNumber = 0;
1654	mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1655	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1656	r = _config_request(ioc, &mpi_request, mpi_reply,
1657	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1658	if (r)
1659		goto out;
1660
1661	mpi_request.PageAddress = cpu_to_le32(form | handle);
1662	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1663	r = _config_request(ioc, &mpi_request, mpi_reply,
1664	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1665	    sizeof(*config_page));
1666 out:
1667	return r;
1668}
1669
1670/**
1671 * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1672 * @ioc: per adapter object
1673 * @mpi_reply: reply mf payload returned from firmware
1674 * @config_page: contents of the config page
1675 * @phy_number: phy number
1676 * Context: sleep.
1677 *
1678 * Return: 0 for success, non-zero for failure.
1679 */
1680int
1681mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1682	*mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1683{
1684	Mpi2ConfigRequest_t mpi_request;
1685	int r;
1686
1687	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1688	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1689	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1690	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1691	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1692	mpi_request.Header.PageNumber = 0;
1693	mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1694	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1695	r = _config_request(ioc, &mpi_request, mpi_reply,
1696	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1697	if (r)
1698		goto out;
1699
1700	mpi_request.PageAddress =
1701	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1702	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1703	r = _config_request(ioc, &mpi_request, mpi_reply,
1704	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1705	    sizeof(*config_page));
1706 out:
1707	return r;
1708}
1709
1710/**
1711 * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1712 * @ioc: per adapter object
1713 * @mpi_reply: reply mf payload returned from firmware
1714 * @config_page: contents of the config page
1715 * @phy_number: phy number
1716 * Context: sleep.
1717 *
1718 * Return: 0 for success, non-zero for failure.
1719 */
1720int
1721mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1722	*mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1723{
1724	Mpi2ConfigRequest_t mpi_request;
1725	int r;
1726
1727	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1728	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1729	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1730	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1731	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1732	mpi_request.Header.PageNumber = 1;
1733	mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1734	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1735	r = _config_request(ioc, &mpi_request, mpi_reply,
1736	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1737	if (r)
1738		goto out;
1739
1740	mpi_request.PageAddress =
1741	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1742	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1743	r = _config_request(ioc, &mpi_request, mpi_reply,
1744	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1745	    sizeof(*config_page));
1746 out:
1747	return r;
1748}
1749
1750/**
1751 * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1752 * @ioc: per adapter object
1753 * @mpi_reply: reply mf payload returned from firmware
1754 * @config_page: contents of the config page
1755 * @form: GET_NEXT_HANDLE or HANDLE
1756 * @handle: volume handle
1757 * Context: sleep.
1758 *
1759 * Return: 0 for success, non-zero for failure.
1760 */
1761int
1762mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1763	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1764	u32 handle)
1765{
1766	Mpi2ConfigRequest_t mpi_request;
1767	int r;
1768
1769	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1770	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1771	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1772	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1773	mpi_request.Header.PageNumber = 1;
1774	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1775	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1776	r = _config_request(ioc, &mpi_request, mpi_reply,
1777	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1778	if (r)
1779		goto out;
1780
1781	mpi_request.PageAddress = cpu_to_le32(form | handle);
1782	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1783	r = _config_request(ioc, &mpi_request, mpi_reply,
1784	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1785	    sizeof(*config_page));
1786 out:
1787	return r;
1788}
1789
1790/**
1791 * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1792 * @ioc: per adapter object
1793 * @handle: volume handle
1794 * @num_pds: returns pds count
1795 * Context: sleep.
1796 *
1797 * Return: 0 for success, non-zero for failure.
1798 */
1799int
1800mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1801	u8 *num_pds)
1802{
1803	Mpi2ConfigRequest_t mpi_request;
1804	Mpi2RaidVolPage0_t config_page;
1805	Mpi2ConfigReply_t mpi_reply;
1806	int r;
1807	u16 ioc_status;
1808
1809	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1810	*num_pds = 0;
1811	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1812	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1813	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1814	mpi_request.Header.PageNumber = 0;
1815	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1816	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1817	r = _config_request(ioc, &mpi_request, &mpi_reply,
1818	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1819	if (r)
1820		goto out;
1821
1822	mpi_request.PageAddress =
1823	    cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1824	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1825	r = _config_request(ioc, &mpi_request, &mpi_reply,
1826	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1827	    sizeof(Mpi2RaidVolPage0_t));
1828	if (!r) {
1829		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1830		    MPI2_IOCSTATUS_MASK;
1831		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1832			*num_pds = config_page.NumPhysDisks;
1833	}
1834
1835 out:
1836	return r;
1837}
1838
1839/**
1840 * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1841 * @ioc: per adapter object
1842 * @mpi_reply: reply mf payload returned from firmware
1843 * @config_page: contents of the config page
1844 * @form: GET_NEXT_HANDLE or HANDLE
1845 * @handle: volume handle
1846 * @sz: size of buffer passed in config_page
1847 * Context: sleep.
1848 *
1849 * Return: 0 for success, non-zero for failure.
1850 */
1851int
1852mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1853	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1854	u32 handle, u16 sz)
1855{
1856	Mpi2ConfigRequest_t mpi_request;
1857	int r;
1858
1859	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1860	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1861	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1862	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1863	mpi_request.Header.PageNumber = 0;
1864	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1865	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1866	r = _config_request(ioc, &mpi_request, mpi_reply,
1867	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1868	if (r)
1869		goto out;
1870
1871	mpi_request.PageAddress = cpu_to_le32(form | handle);
1872	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1873	r = _config_request(ioc, &mpi_request, mpi_reply,
1874	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1875 out:
1876	return r;
1877}
1878
1879/**
1880 * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1881 * @ioc: per adapter object
1882 * @mpi_reply: reply mf payload returned from firmware
1883 * @config_page: contents of the config page
1884 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1885 * @form_specific: specific to the form
1886 * Context: sleep.
1887 *
1888 * Return: 0 for success, non-zero for failure.
1889 */
1890int
1891mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1892	*mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1893	u32 form_specific)
1894{
1895	Mpi2ConfigRequest_t mpi_request;
1896	int r;
1897
1898	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1899	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1900	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1901	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1902	mpi_request.Header.PageNumber = 0;
1903	mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1904	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1905	r = _config_request(ioc, &mpi_request, mpi_reply,
1906	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1907	if (r)
1908		goto out;
1909
1910	mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1911	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1912	r = _config_request(ioc, &mpi_request, mpi_reply,
1913	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1914	    sizeof(*config_page));
1915 out:
1916	return r;
1917}
1918
1919/**
1920 * mpt3sas_config_get_driver_trigger_pg0 - obtain driver trigger page 0
1921 * @ioc: per adapter object
1922 * @mpi_reply: reply mf payload returned from firmware
1923 * @config_page: contents of the config page
1924 * Context: sleep.
1925 *
1926 * Returns 0 for success, non-zero for failure.
1927 */
1928int
1929mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1930	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1931{
1932	Mpi2ConfigRequest_t mpi_request;
1933	int r;
1934
1935	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1936	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1937	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1938	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1939	mpi_request.ExtPageType =
1940	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1941	mpi_request.Header.PageNumber = 0;
1942	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1943	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1944	r = _config_request(ioc, &mpi_request, mpi_reply,
1945	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1946	if (r)
1947		goto out;
1948
1949	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1950	r = _config_request(ioc, &mpi_request, mpi_reply,
1951	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1952	    sizeof(*config_page));
1953 out:
1954	return r;
1955}
1956
1957/**
1958 * _config_set_driver_trigger_pg0 - write driver trigger page 0
1959 * @ioc: per adapter object
1960 * @mpi_reply: reply mf payload returned from firmware
1961 * @config_page: contents of the config page
1962 * Context: sleep.
1963 *
1964 * Returns 0 for success, non-zero for failure.
1965 */
1966static int
1967_config_set_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1968	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1969{
1970	Mpi2ConfigRequest_t mpi_request;
1971	int r;
1972
1973	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1974	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1975	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1976	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1977	mpi_request.ExtPageType =
1978	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1979	mpi_request.Header.PageNumber = 0;
1980	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1981	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1982	r = _config_request(ioc, &mpi_request, mpi_reply,
1983	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1984	if (r)
1985		goto out;
1986
1987	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1988	_config_request(ioc, &mpi_request, mpi_reply,
1989	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1990	    sizeof(*config_page));
1991	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1992	r = _config_request(ioc, &mpi_request, mpi_reply,
1993	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1994	    sizeof(*config_page));
1995 out:
1996	return r;
1997}
1998
1999/**
2000 * mpt3sas_config_update_driver_trigger_pg0 - update driver trigger page 0
2001 * @ioc: per adapter object
2002 * @trigger_flag: trigger type bit map
2003 * @set: set ot clear trigger values
2004 * Context: sleep.
2005 *
2006 * Returns 0 for success, non-zero for failure.
2007 */
2008static int
2009mpt3sas_config_update_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
2010	u16 trigger_flag, bool set)
2011{
2012	Mpi26DriverTriggerPage0_t tg_pg0;
2013	Mpi2ConfigReply_t mpi_reply;
2014	int rc;
2015	u16 flags, ioc_status;
2016
2017	rc = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
2018	if (rc)
2019		return rc;
2020	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2021	    MPI2_IOCSTATUS_MASK;
2022	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2023		dcprintk(ioc,
2024		    ioc_err(ioc,
2025		    "%s: Failed to get trigger pg0, ioc_status(0x%04x)\n",
2026		    __func__, ioc_status));
2027		return -EFAULT;
2028	}
2029
2030	if (set)
2031		flags = le16_to_cpu(tg_pg0.TriggerFlags) | trigger_flag;
2032	else
2033		flags = le16_to_cpu(tg_pg0.TriggerFlags) & ~trigger_flag;
2034
2035	tg_pg0.TriggerFlags = cpu_to_le16(flags);
2036
2037	rc = _config_set_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
2038	if (rc)
2039		return rc;
2040	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2041	    MPI2_IOCSTATUS_MASK;
2042	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2043		dcprintk(ioc,
2044		    ioc_err(ioc,
2045		    "%s: Failed to update trigger pg0, ioc_status(0x%04x)\n",
2046		    __func__, ioc_status));
2047		return -EFAULT;
2048	}
2049
2050	return 0;
2051}
2052
2053/**
2054 * mpt3sas_config_get_driver_trigger_pg1 - obtain driver trigger page 1
2055 * @ioc: per adapter object
2056 * @mpi_reply: reply mf payload returned from firmware
2057 * @config_page: contents of the config page
2058 * Context: sleep.
2059 *
2060 * Returns 0 for success, non-zero for failure.
2061 */
2062int
2063mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
2064	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
2065{
2066	Mpi2ConfigRequest_t mpi_request;
2067	int r;
2068
2069	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2070	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2071	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2072	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2073	mpi_request.ExtPageType =
2074	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2075	mpi_request.Header.PageNumber = 1;
2076	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
2077	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2078	r = _config_request(ioc, &mpi_request, mpi_reply,
2079	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2080	if (r)
2081		goto out;
2082
2083	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2084	r = _config_request(ioc, &mpi_request, mpi_reply,
2085	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2086	    sizeof(*config_page));
2087 out:
2088	return r;
2089}
2090
2091/**
2092 * _config_set_driver_trigger_pg1 - write driver trigger page 1
2093 * @ioc: per adapter object
2094 * @mpi_reply: reply mf payload returned from firmware
2095 * @config_page: contents of the config page
2096 * Context: sleep.
2097 *
2098 * Returns 0 for success, non-zero for failure.
2099 */
2100static int
2101_config_set_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
2102	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
2103{
2104	Mpi2ConfigRequest_t mpi_request;
2105	int r;
2106
2107	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2108	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2109	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2110	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2111	mpi_request.ExtPageType =
2112	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2113	mpi_request.Header.PageNumber = 1;
2114	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
2115	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2116	r = _config_request(ioc, &mpi_request, mpi_reply,
2117	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2118	if (r)
2119		goto out;
2120
2121	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2122	_config_request(ioc, &mpi_request, mpi_reply,
2123	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2124	    sizeof(*config_page));
2125	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2126	r = _config_request(ioc, &mpi_request, mpi_reply,
2127	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2128	    sizeof(*config_page));
2129 out:
2130	return r;
2131}
2132
2133/**
2134 * mpt3sas_config_update_driver_trigger_pg1 - update driver trigger page 1
2135 * @ioc: per adapter object
2136 * @master_tg: Master trigger bit map
2137 * @set: set ot clear trigger values
2138 * Context: sleep.
2139 *
2140 * Returns 0 for success, non-zero for failure.
2141 */
2142int
2143mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
2144	struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set)
2145{
2146	Mpi26DriverTriggerPage1_t tg_pg1;
2147	Mpi2ConfigReply_t mpi_reply;
2148	int rc;
2149	u16 ioc_status;
2150
2151	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2152	    MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, set);
2153	if (rc)
2154		return rc;
2155
2156	rc = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
2157	if (rc)
2158		goto out;
2159
2160	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2161	    MPI2_IOCSTATUS_MASK;
2162	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2163		dcprintk(ioc,
2164		    ioc_err(ioc,
2165		    "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
2166		    __func__, ioc_status));
2167		rc = -EFAULT;
2168		goto out;
2169	}
2170
2171	if (set) {
2172		tg_pg1.NumMasterTrigger = cpu_to_le16(1);
2173		tg_pg1.MasterTriggers[0].MasterTriggerFlags = cpu_to_le32(
2174		    master_tg->MasterData);
2175	} else {
2176		tg_pg1.NumMasterTrigger = 0;
2177		tg_pg1.MasterTriggers[0].MasterTriggerFlags = 0;
2178	}
2179
2180	rc = _config_set_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
2181	if (rc)
2182		goto out;
2183
2184	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2185	    MPI2_IOCSTATUS_MASK;
2186	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2187		dcprintk(ioc,
2188		    ioc_err(ioc,
2189		    "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
2190		    __func__, ioc_status));
2191		rc = -EFAULT;
2192		goto out;
2193	}
2194
2195	return 0;
2196
2197out:
2198	mpt3sas_config_update_driver_trigger_pg0(ioc,
2199	    MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, !set);
2200
2201	return rc;
2202}
2203
2204/**
2205 * mpt3sas_config_get_driver_trigger_pg2 - obtain driver trigger page 2
2206 * @ioc: per adapter object
2207 * @mpi_reply: reply mf payload returned from firmware
2208 * @config_page: contents of the config page
2209 * Context: sleep.
2210 *
2211 * Returns 0 for success, non-zero for failure.
2212 */
2213int
2214mpt3sas_config_get_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2215	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2216{
2217	Mpi2ConfigRequest_t mpi_request;
2218	int r;
2219
2220	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2221	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2222	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2223	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2224	mpi_request.ExtPageType =
2225	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2226	mpi_request.Header.PageNumber = 2;
2227	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2228	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2229	r = _config_request(ioc, &mpi_request, mpi_reply,
2230	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2231	if (r)
2232		goto out;
2233
2234	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2235	r = _config_request(ioc, &mpi_request, mpi_reply,
2236	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2237	    sizeof(*config_page));
2238 out:
2239	return r;
2240}
2241
2242/**
2243 * _config_set_driver_trigger_pg2 - write driver trigger page 2
2244 * @ioc: per adapter object
2245 * @mpi_reply: reply mf payload returned from firmware
2246 * @config_page: contents of the config page
2247 * Context: sleep.
2248 *
2249 * Returns 0 for success, non-zero for failure.
2250 */
2251static int
2252_config_set_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2253	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2254{
2255	Mpi2ConfigRequest_t mpi_request;
2256	int r;
2257
2258	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2259	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2260	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2261	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2262	mpi_request.ExtPageType =
2263	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2264	mpi_request.Header.PageNumber = 2;
2265	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2266	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2267	r = _config_request(ioc, &mpi_request, mpi_reply,
2268	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2269	if (r)
2270		goto out;
2271
2272	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2273	_config_request(ioc, &mpi_request, mpi_reply,
2274	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2275	    sizeof(*config_page));
2276	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2277	r = _config_request(ioc, &mpi_request, mpi_reply,
2278	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2279	    sizeof(*config_page));
2280 out:
2281	return r;
2282}
2283
2284/**
2285 * mpt3sas_config_update_driver_trigger_pg2 - update driver trigger page 2
2286 * @ioc: per adapter object
2287 * @event_tg: list of Event Triggers
2288 * @set: set ot clear trigger values
2289 * Context: sleep.
2290 *
2291 * Returns 0 for success, non-zero for failure.
2292 */
2293int
2294mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2295	struct SL_WH_EVENT_TRIGGERS_T *event_tg, bool set)
2296{
2297	Mpi26DriverTriggerPage2_t tg_pg2;
2298	Mpi2ConfigReply_t mpi_reply;
2299	int rc, i, count;
2300	u16 ioc_status;
2301
2302	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2303	    MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, set);
2304	if (rc)
2305		return rc;
2306
2307	rc = mpt3sas_config_get_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2308	if (rc)
2309		goto out;
2310
2311	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2312	    MPI2_IOCSTATUS_MASK;
2313	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2314		dcprintk(ioc,
2315		    ioc_err(ioc,
2316		    "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2317		    __func__, ioc_status));
2318		rc = -EFAULT;
2319		goto out;
2320	}
2321
2322	if (set) {
2323		count = event_tg->ValidEntries;
2324		tg_pg2.NumMPIEventTrigger = cpu_to_le16(count);
2325		for (i = 0; i < count; i++) {
2326			tg_pg2.MPIEventTriggers[i].MPIEventCode =
2327			    cpu_to_le16(
2328			    event_tg->EventTriggerEntry[i].EventValue);
2329			tg_pg2.MPIEventTriggers[i].MPIEventCodeSpecific =
2330			    cpu_to_le16(
2331			    event_tg->EventTriggerEntry[i].LogEntryQualifier);
2332		}
2333	} else {
2334		tg_pg2.NumMPIEventTrigger = 0;
2335		memset(&tg_pg2.MPIEventTriggers[0], 0,
2336		    NUM_VALID_ENTRIES * sizeof(
2337		    MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY));
2338	}
2339
2340	rc = _config_set_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2341	if (rc)
2342		goto out;
2343
2344	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2345	    MPI2_IOCSTATUS_MASK;
2346	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2347		dcprintk(ioc,
2348		    ioc_err(ioc,
2349		    "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2350		    __func__, ioc_status));
2351		rc = -EFAULT;
2352		goto out;
2353	}
2354
2355	return 0;
2356
2357out:
2358	mpt3sas_config_update_driver_trigger_pg0(ioc,
2359	    MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, !set);
2360
2361	return rc;
2362}
2363
2364/**
2365 * mpt3sas_config_get_driver_trigger_pg3 - obtain driver trigger page 3
2366 * @ioc: per adapter object
2367 * @mpi_reply: reply mf payload returned from firmware
2368 * @config_page: contents of the config page
2369 * Context: sleep.
2370 *
2371 * Returns 0 for success, non-zero for failure.
2372 */
2373int
2374mpt3sas_config_get_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2375	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2376{
2377	Mpi2ConfigRequest_t mpi_request;
2378	int r;
2379
2380	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2381	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2382	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2383	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2384	mpi_request.ExtPageType =
2385	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2386	mpi_request.Header.PageNumber = 3;
2387	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2388	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2389	r = _config_request(ioc, &mpi_request, mpi_reply,
2390	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2391	if (r)
2392		goto out;
2393
2394	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2395	r = _config_request(ioc, &mpi_request, mpi_reply,
2396	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2397	    sizeof(*config_page));
2398 out:
2399	return r;
2400}
2401
2402/**
2403 * _config_set_driver_trigger_pg3 - write driver trigger page 3
2404 * @ioc: per adapter object
2405 * @mpi_reply: reply mf payload returned from firmware
2406 * @config_page: contents of the config page
2407 * Context: sleep.
2408 *
2409 * Returns 0 for success, non-zero for failure.
2410 */
2411static int
2412_config_set_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2413	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2414{
2415	Mpi2ConfigRequest_t mpi_request;
2416	int r;
2417
2418	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2419	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2420	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2421	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2422	mpi_request.ExtPageType =
2423	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2424	mpi_request.Header.PageNumber = 3;
2425	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2426	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2427	r = _config_request(ioc, &mpi_request, mpi_reply,
2428	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2429	if (r)
2430		goto out;
2431
2432	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2433	_config_request(ioc, &mpi_request, mpi_reply,
2434	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2435	    sizeof(*config_page));
2436	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2437	r = _config_request(ioc, &mpi_request, mpi_reply,
2438	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2439	    sizeof(*config_page));
2440 out:
2441	return r;
2442}
2443
2444/**
2445 * mpt3sas_config_update_driver_trigger_pg3 - update driver trigger page 3
2446 * @ioc: per adapter object
2447 * @scsi_tg: scsi trigger list
2448 * @set: set ot clear trigger values
2449 * Context: sleep.
2450 *
2451 * Returns 0 for success, non-zero for failure.
2452 */
2453int
2454mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2455	struct SL_WH_SCSI_TRIGGERS_T *scsi_tg, bool set)
2456{
2457	Mpi26DriverTriggerPage3_t tg_pg3;
2458	Mpi2ConfigReply_t mpi_reply;
2459	int rc, i, count;
2460	u16 ioc_status;
2461
2462	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2463	    MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, set);
2464	if (rc)
2465		return rc;
2466
2467	rc = mpt3sas_config_get_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2468	if (rc)
2469		goto out;
2470
2471	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2472	    MPI2_IOCSTATUS_MASK;
2473	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2474		dcprintk(ioc,
2475		    ioc_err(ioc,
2476		    "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2477		    __func__, ioc_status));
2478		return -EFAULT;
2479	}
2480
2481	if (set) {
2482		count = scsi_tg->ValidEntries;
2483		tg_pg3.NumSCSISenseTrigger = cpu_to_le16(count);
2484		for (i = 0; i < count; i++) {
2485			tg_pg3.SCSISenseTriggers[i].ASCQ =
2486			    scsi_tg->SCSITriggerEntry[i].ASCQ;
2487			tg_pg3.SCSISenseTriggers[i].ASC =
2488			    scsi_tg->SCSITriggerEntry[i].ASC;
2489			tg_pg3.SCSISenseTriggers[i].SenseKey =
2490			    scsi_tg->SCSITriggerEntry[i].SenseKey;
2491		}
2492	} else {
2493		tg_pg3.NumSCSISenseTrigger = 0;
2494		memset(&tg_pg3.SCSISenseTriggers[0], 0,
2495		    NUM_VALID_ENTRIES * sizeof(
2496		    MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY));
2497	}
2498
2499	rc = _config_set_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2500	if (rc)
2501		goto out;
2502
2503	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2504	    MPI2_IOCSTATUS_MASK;
2505	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2506		dcprintk(ioc,
2507		    ioc_err(ioc,
2508		    "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2509		     __func__, ioc_status));
2510		return -EFAULT;
2511	}
2512
2513	return 0;
2514out:
2515	mpt3sas_config_update_driver_trigger_pg0(ioc,
2516	    MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, !set);
2517
2518	return rc;
2519}
2520
2521/**
2522 * mpt3sas_config_get_driver_trigger_pg4 - obtain driver trigger page 4
2523 * @ioc: per adapter object
2524 * @mpi_reply: reply mf payload returned from firmware
2525 * @config_page: contents of the config page
2526 * Context: sleep.
2527 *
2528 * Returns 0 for success, non-zero for failure.
2529 */
2530int
2531mpt3sas_config_get_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2532	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2533{
2534	Mpi2ConfigRequest_t mpi_request;
2535	int r;
2536
2537	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2538	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2539	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2540	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2541	mpi_request.ExtPageType =
2542	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2543	mpi_request.Header.PageNumber = 4;
2544	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2545	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2546	r = _config_request(ioc, &mpi_request, mpi_reply,
2547	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2548	if (r)
2549		goto out;
2550
2551	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2552	r = _config_request(ioc, &mpi_request, mpi_reply,
2553	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2554	    sizeof(*config_page));
2555 out:
2556	return r;
2557}
2558
2559/**
2560 * _config_set_driver_trigger_pg4 - write driver trigger page 4
2561 * @ioc: per adapter object
2562 * @mpi_reply: reply mf payload returned from firmware
2563 * @config_page: contents of the config page
2564 * Context: sleep.
2565 *
2566 * Returns 0 for success, non-zero for failure.
2567 */
2568static int
2569_config_set_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2570	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2571{
2572	Mpi2ConfigRequest_t mpi_request;
2573	int r;
2574
2575	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2576	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2577	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2578	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2579	mpi_request.ExtPageType =
2580	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2581	mpi_request.Header.PageNumber = 4;
2582	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2583	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2584	r = _config_request(ioc, &mpi_request, mpi_reply,
2585	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2586	if (r)
2587		goto out;
2588
2589	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2590	_config_request(ioc, &mpi_request, mpi_reply,
2591	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2592	    sizeof(*config_page));
2593	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2594	r = _config_request(ioc, &mpi_request, mpi_reply,
2595	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2596	    sizeof(*config_page));
2597 out:
2598	return r;
2599}
2600
2601/**
2602 * mpt3sas_config_update_driver_trigger_pg4 - update driver trigger page 4
2603 * @ioc: per adapter object
2604 * @mpi_tg: mpi trigger list
2605 * @set: set ot clear trigger values
2606 * Context: sleep.
2607 *
2608 * Returns 0 for success, non-zero for failure.
2609 */
2610int
2611mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2612	struct SL_WH_MPI_TRIGGERS_T *mpi_tg, bool set)
2613{
2614	Mpi26DriverTriggerPage4_t tg_pg4;
2615	Mpi2ConfigReply_t mpi_reply;
2616	int rc, i, count;
2617	u16 ioc_status;
2618
2619	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2620	    MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, set);
2621	if (rc)
2622		return rc;
2623
2624	rc = mpt3sas_config_get_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2625	if (rc)
2626		goto out;
2627
2628	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2629	    MPI2_IOCSTATUS_MASK;
2630	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2631		dcprintk(ioc,
2632		    ioc_err(ioc,
2633		    "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2634		    __func__, ioc_status));
2635		rc = -EFAULT;
2636		goto out;
2637	}
2638
2639	if (set) {
2640		count = mpi_tg->ValidEntries;
2641		tg_pg4.NumIOCStatusLogInfoTrigger = cpu_to_le16(count);
2642		for (i = 0; i < count; i++) {
2643			tg_pg4.IOCStatusLoginfoTriggers[i].IOCStatus =
2644			    cpu_to_le16(mpi_tg->MPITriggerEntry[i].IOCStatus);
2645			tg_pg4.IOCStatusLoginfoTriggers[i].LogInfo =
2646			    cpu_to_le32(mpi_tg->MPITriggerEntry[i].IocLogInfo);
2647		}
2648	} else {
2649		tg_pg4.NumIOCStatusLogInfoTrigger = 0;
2650		memset(&tg_pg4.IOCStatusLoginfoTriggers[0], 0,
2651		    NUM_VALID_ENTRIES * sizeof(
2652		    MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY));
2653	}
2654
2655	rc = _config_set_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2656	if (rc)
2657		goto out;
2658
2659	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2660	    MPI2_IOCSTATUS_MASK;
2661	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2662		dcprintk(ioc,
2663		    ioc_err(ioc,
2664		    "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2665		    __func__, ioc_status));
2666		rc = -EFAULT;
2667		goto out;
2668	}
2669
2670	return 0;
2671
2672out:
2673	mpt3sas_config_update_driver_trigger_pg0(ioc,
2674	    MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, !set);
2675
2676	return rc;
2677}
2678
2679/**
2680 * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
2681 * raid components
2682 * @ioc: per adapter object
2683 * @pd_handle: phys disk handle
2684 * @volume_handle: volume handle
2685 * Context: sleep.
2686 *
2687 * Return: 0 for success, non-zero for failure.
2688 */
2689int
2690mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
2691	u16 *volume_handle)
2692{
2693	Mpi2RaidConfigurationPage0_t *config_page = NULL;
2694	Mpi2ConfigRequest_t mpi_request;
2695	Mpi2ConfigReply_t mpi_reply;
2696	int r, i, config_page_sz;
2697	u16 ioc_status;
2698	int config_num;
2699	u16 element_type;
2700	u16 phys_disk_dev_handle;
2701
2702	*volume_handle = 0;
2703	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2704	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2705	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2706	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2707	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
2708	mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
2709	mpi_request.Header.PageNumber = 0;
2710	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2711	r = _config_request(ioc, &mpi_request, &mpi_reply,
2712	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2713	if (r)
2714		goto out;
2715
2716	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2717	config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
2718	config_page = kmalloc(config_page_sz, GFP_KERNEL);
2719	if (!config_page) {
2720		r = -1;
2721		goto out;
2722	}
2723
2724	config_num = 0xff;
2725	while (1) {
2726		mpi_request.PageAddress = cpu_to_le32(config_num +
2727		    MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
2728		r = _config_request(ioc, &mpi_request, &mpi_reply,
2729		    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2730		    config_page_sz);
2731		if (r)
2732			goto out;
2733		r = -1;
2734		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2735		    MPI2_IOCSTATUS_MASK;
2736		if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
2737			goto out;
2738		for (i = 0; i < config_page->NumElements; i++) {
2739			element_type = le16_to_cpu(config_page->
2740			    ConfigElement[i].ElementFlags) &
2741			    MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
2742			if (element_type ==
2743			    MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
2744			    element_type ==
2745			    MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
2746				phys_disk_dev_handle =
2747				    le16_to_cpu(config_page->ConfigElement[i].
2748				    PhysDiskDevHandle);
2749				if (phys_disk_dev_handle == pd_handle) {
2750					*volume_handle =
2751					    le16_to_cpu(config_page->
2752					    ConfigElement[i].VolDevHandle);
2753					r = 0;
2754					goto out;
2755				}
2756			} else if (element_type ==
2757			    MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
2758				*volume_handle = 0;
2759				r = 0;
2760				goto out;
2761			}
2762		}
2763		config_num = config_page->ConfigNum;
2764	}
2765 out:
2766	kfree(config_page);
2767	return r;
2768}
2769
2770/**
2771 * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
2772 * @ioc: per adapter object
2773 * @volume_handle: volume handle
2774 * @wwid: volume wwid
2775 * Context: sleep.
2776 *
2777 * Return: 0 for success, non-zero for failure.
2778 */
2779int
2780mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
2781	u64 *wwid)
2782{
2783	Mpi2ConfigReply_t mpi_reply;
2784	Mpi2RaidVolPage1_t raid_vol_pg1;
2785
2786	*wwid = 0;
2787	if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
2788	    &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
2789	    volume_handle))) {
2790		*wwid = le64_to_cpu(raid_vol_pg1.WWID);
2791		return 0;
2792	} else
2793		return -1;
2794}
2795