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  */
80 struct 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  */
97 static 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  */
198 static 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  */
229 static 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  */
251 u8
252 mpt3sas_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  */
295 static 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->shost_recovery) || (ioc->config_cmds.status &
398 		    MPT3_CMD_RESET) || ioc->pci_error_recovery)
399 			goto retry_config;
400 		issue_host_reset = 1;
401 		goto free_mem;
402 	}
403 
404 	if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
405 		memcpy(mpi_reply, ioc->config_cmds.reply,
406 		    sizeof(Mpi2ConfigReply_t));
407 
408 		/* Reply Frame Sanity Checks to workaround FW issues */
409 		if ((mpi_request->Header.PageType & 0xF) !=
410 		    (mpi_reply->Header.PageType & 0xF)) {
411 			if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
412 				_config_display_some_debug(ioc,
413 				    smid, "config_request", NULL);
414 			_debug_dump_mf(mpi_request, ioc->request_sz/4);
415 			_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
416 			panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
417 			      ioc->name, __func__,
418 			      mpi_request->Header.PageType & 0xF,
419 			      mpi_reply->Header.PageType & 0xF);
420 		}
421 
422 		if (((mpi_request->Header.PageType & 0xF) ==
423 		    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
424 		    mpi_request->ExtPageType != mpi_reply->ExtPageType) {
425 			if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
426 				_config_display_some_debug(ioc,
427 				    smid, "config_request", NULL);
428 			_debug_dump_mf(mpi_request, ioc->request_sz/4);
429 			_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
430 			panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
431 			      ioc->name, __func__,
432 			      mpi_request->ExtPageType,
433 			      mpi_reply->ExtPageType);
434 		}
435 		ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
436 		    & MPI2_IOCSTATUS_MASK;
437 	}
438 
439 	if (retry_count)
440 		ioc_info(ioc, "%s: retry (%d) completed!!\n",
441 			 __func__, retry_count);
442 
443 	if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
444 	    config_page && mpi_request->Action ==
445 	    MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
446 		u8 *p = (u8 *)mem.page;
447 
448 		/* Config Page Sanity Checks to workaround FW issues */
449 		if (p) {
450 			if ((mpi_request->Header.PageType & 0xF) !=
451 			    (p[3] & 0xF)) {
452 				if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
453 					_config_display_some_debug(ioc,
454 					    smid, "config_request", NULL);
455 				_debug_dump_mf(mpi_request, ioc->request_sz/4);
456 				_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
457 				_debug_dump_config(p, min_t(u16, mem.sz,
458 				    config_page_sz)/4);
459 				panic("%s: %s: Firmware BUG: config page mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
460 				      ioc->name, __func__,
461 				      mpi_request->Header.PageType & 0xF,
462 				      p[3] & 0xF);
463 			}
464 
465 			if (((mpi_request->Header.PageType & 0xF) ==
466 			    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
467 			    (mpi_request->ExtPageType != p[6])) {
468 				if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
469 					_config_display_some_debug(ioc,
470 					    smid, "config_request", NULL);
471 				_debug_dump_mf(mpi_request, ioc->request_sz/4);
472 				_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
473 				_debug_dump_config(p, min_t(u16, mem.sz,
474 				    config_page_sz)/4);
475 				panic("%s: %s: Firmware BUG: config page mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
476 				      ioc->name, __func__,
477 				      mpi_request->ExtPageType, p[6]);
478 			}
479 		}
480 		memcpy(config_page, mem.page, min_t(u16, mem.sz,
481 		    config_page_sz));
482 	}
483 
484  free_mem:
485 	if (config_page)
486 		_config_free_config_dma_memory(ioc, &mem);
487  out:
488 	ioc->config_cmds.status = MPT3_CMD_NOT_USED;
489 	mutex_unlock(&ioc->config_cmds.mutex);
490 
491 	if (issue_host_reset) {
492 		if (ioc->drv_internal_flags & MPT_DRV_INTERNAL_FIRST_PE_ISSUED) {
493 			mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
494 			r = -EFAULT;
495 		} else {
496 			if (mpt3sas_base_check_for_fault_and_issue_reset(ioc))
497 				return -EFAULT;
498 			r = -EAGAIN;
499 		}
500 	}
501 	return r;
502 }
503 
504 /**
505  * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
506  * @ioc: per adapter object
507  * @mpi_reply: reply mf payload returned from firmware
508  * @config_page: contents of the config page
509  * Context: sleep.
510  *
511  * Return: 0 for success, non-zero for failure.
512  */
513 int
514 mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
515 	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
516 {
517 	Mpi2ConfigRequest_t mpi_request;
518 	int r;
519 
520 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
521 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
522 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
523 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
524 	mpi_request.Header.PageNumber = 0;
525 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
526 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
527 	r = _config_request(ioc, &mpi_request, mpi_reply,
528 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
529 	if (r)
530 		goto out;
531 
532 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
533 	r = _config_request(ioc, &mpi_request, mpi_reply,
534 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
535 	    sizeof(*config_page));
536  out:
537 	return r;
538 }
539 
540 /**
541  * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
542  * @ioc: per adapter object
543  * @mpi_reply: reply mf payload returned from firmware
544  * @config_page: contents of the config page
545  * @sz: size of buffer passed in config_page
546  * Context: sleep.
547  *
548  * Return: 0 for success, non-zero for failure.
549  */
550 int
551 mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
552 	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
553 	u16 sz)
554 {
555 	Mpi2ConfigRequest_t mpi_request;
556 	int r;
557 
558 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
559 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
560 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
561 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
562 	mpi_request.Header.PageNumber = 7;
563 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
564 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
565 	r = _config_request(ioc, &mpi_request, mpi_reply,
566 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
567 	if (r)
568 		goto out;
569 
570 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
571 	r = _config_request(ioc, &mpi_request, mpi_reply,
572 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
573 	    sz);
574  out:
575 	return r;
576 }
577 
578 /**
579  * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
580  * @ioc: per adapter object
581  * @mpi_reply: reply mf payload returned from firmware
582  * @config_page: contents of the config page
583  * Context: sleep.
584  *
585  * Return: 0 for success, non-zero for failure.
586  */
587 int
588 mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
589 	Mpi2ConfigReply_t *mpi_reply,
590 	struct Mpi2ManufacturingPage10_t *config_page)
591 {
592 	Mpi2ConfigRequest_t mpi_request;
593 	int r;
594 
595 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
596 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
597 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
598 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
599 	mpi_request.Header.PageNumber = 10;
600 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
601 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
602 	r = _config_request(ioc, &mpi_request, mpi_reply,
603 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
604 	if (r)
605 		goto out;
606 
607 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
608 	r = _config_request(ioc, &mpi_request, mpi_reply,
609 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
610 	    sizeof(*config_page));
611  out:
612 	return r;
613 }
614 
615 /**
616  * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
617  * @ioc: per adapter object
618  * @mpi_reply: reply mf payload returned from firmware
619  * @config_page: contents of the config page
620  * Context: sleep.
621  *
622  * Return: 0 for success, non-zero for failure.
623  */
624 int
625 mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
626 	Mpi2ConfigReply_t *mpi_reply,
627 	struct Mpi2ManufacturingPage11_t *config_page)
628 {
629 	Mpi2ConfigRequest_t mpi_request;
630 	int r;
631 
632 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
633 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
634 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
635 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
636 	mpi_request.Header.PageNumber = 11;
637 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
638 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
639 	r = _config_request(ioc, &mpi_request, mpi_reply,
640 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
641 	if (r)
642 		goto out;
643 
644 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
645 	r = _config_request(ioc, &mpi_request, mpi_reply,
646 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
647 	    sizeof(*config_page));
648  out:
649 	return r;
650 }
651 
652 /**
653  * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
654  * @ioc: per adapter object
655  * @mpi_reply: reply mf payload returned from firmware
656  * @config_page: contents of the config page
657  * Context: sleep.
658  *
659  * Return: 0 for success, non-zero for failure.
660  */
661 int
662 mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
663 	Mpi2ConfigReply_t *mpi_reply,
664 	struct Mpi2ManufacturingPage11_t *config_page)
665 {
666 	Mpi2ConfigRequest_t mpi_request;
667 	int r;
668 
669 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
670 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
671 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
672 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
673 	mpi_request.Header.PageNumber = 11;
674 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
675 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
676 	r = _config_request(ioc, &mpi_request, mpi_reply,
677 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
678 	if (r)
679 		goto out;
680 
681 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
682 	r = _config_request(ioc, &mpi_request, mpi_reply,
683 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
684 	    sizeof(*config_page));
685  out:
686 	return r;
687 }
688 
689 /**
690  * mpt3sas_config_get_bios_pg2 - obtain bios page 2
691  * @ioc: per adapter object
692  * @mpi_reply: reply mf payload returned from firmware
693  * @config_page: contents of the config page
694  * Context: sleep.
695  *
696  * Return: 0 for success, non-zero for failure.
697  */
698 int
699 mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
700 	Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
701 {
702 	Mpi2ConfigRequest_t mpi_request;
703 	int r;
704 
705 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
706 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
707 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
708 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
709 	mpi_request.Header.PageNumber = 2;
710 	mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
711 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
712 	r = _config_request(ioc, &mpi_request, mpi_reply,
713 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
714 	if (r)
715 		goto out;
716 
717 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
718 	r = _config_request(ioc, &mpi_request, mpi_reply,
719 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
720 	    sizeof(*config_page));
721  out:
722 	return r;
723 }
724 
725 /**
726  * mpt3sas_config_get_bios_pg3 - obtain bios page 3
727  * @ioc: per adapter object
728  * @mpi_reply: reply mf payload returned from firmware
729  * @config_page: contents of the config page
730  * Context: sleep.
731  *
732  * Return: 0 for success, non-zero for failure.
733  */
734 int
735 mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
736 	*mpi_reply, Mpi2BiosPage3_t *config_page)
737 {
738 	Mpi2ConfigRequest_t mpi_request;
739 	int r;
740 
741 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
742 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
743 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
744 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
745 	mpi_request.Header.PageNumber = 3;
746 	mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
747 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
748 	r = _config_request(ioc, &mpi_request, mpi_reply,
749 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
750 	if (r)
751 		goto out;
752 
753 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
754 	r = _config_request(ioc, &mpi_request, mpi_reply,
755 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
756 	    sizeof(*config_page));
757  out:
758 	return r;
759 }
760 
761 /**
762  * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
763  * @ioc: per adapter object
764  * @mpi_reply: reply mf payload returned from firmware
765  * @config_page: contents of the config page
766  * Context: sleep.
767  *
768  * Return: 0 for success, non-zero for failure.
769  */
770 int
771 mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
772 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
773 {
774 	Mpi2ConfigRequest_t mpi_request;
775 	int r;
776 
777 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
778 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
779 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
780 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
781 	mpi_request.Header.PageNumber = 0;
782 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
783 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
784 	r = _config_request(ioc, &mpi_request, mpi_reply,
785 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
786 	if (r)
787 		goto out;
788 
789 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
790 	r = _config_request(ioc, &mpi_request, mpi_reply,
791 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
792 	    sizeof(*config_page));
793  out:
794 	return r;
795 }
796 
797 /**
798  * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
799  * @ioc: per adapter object
800  * @mpi_reply: reply mf payload returned from firmware
801  * @config_page: contents of the config page
802  * Context: sleep.
803  *
804  * Return: 0 for success, non-zero for failure.
805  */
806 int
807 mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
808 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
809 {
810 	Mpi2ConfigRequest_t mpi_request;
811 	int r;
812 
813 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
814 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
815 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
816 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
817 	mpi_request.Header.PageNumber = 1;
818 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
819 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
820 	r = _config_request(ioc, &mpi_request, mpi_reply,
821 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
822 	if (r)
823 		goto out;
824 
825 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
826 	r = _config_request(ioc, &mpi_request, mpi_reply,
827 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
828 	    sizeof(*config_page));
829  out:
830 	return r;
831 }
832 
833 /**
834  * mpt3sas_config_set_iounit_pg1 - set iounit page 1
835  * @ioc: per adapter object
836  * @mpi_reply: reply mf payload returned from firmware
837  * @config_page: contents of the config page
838  * Context: sleep.
839  *
840  * Return: 0 for success, non-zero for failure.
841  */
842 int
843 mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
844 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
845 {
846 	Mpi2ConfigRequest_t mpi_request;
847 	int r;
848 
849 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
850 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
851 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
852 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
853 	mpi_request.Header.PageNumber = 1;
854 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
855 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
856 	r = _config_request(ioc, &mpi_request, mpi_reply,
857 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
858 	if (r)
859 		goto out;
860 
861 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
862 	r = _config_request(ioc, &mpi_request, mpi_reply,
863 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
864 	    sizeof(*config_page));
865  out:
866 	return r;
867 }
868 
869 /**
870  * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
871  * @ioc: per adapter object
872  * @mpi_reply: reply mf payload returned from firmware
873  * @config_page: contents of the config page
874  * @sz: size of buffer passed in config_page
875  * Context: sleep.
876  *
877  * Return: 0 for success, non-zero for failure.
878  */
879 int
880 mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
881 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
882 {
883 	Mpi2ConfigRequest_t mpi_request;
884 	int r;
885 
886 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
887 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
888 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
889 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
890 	mpi_request.Header.PageNumber = 3;
891 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
892 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
893 	r = _config_request(ioc, &mpi_request, mpi_reply,
894 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
895 	if (r)
896 		goto out;
897 
898 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
899 	r = _config_request(ioc, &mpi_request, mpi_reply,
900 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
901  out:
902 	return r;
903 }
904 
905 /**
906  * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
907  * @ioc: per adapter object
908  * @mpi_reply: reply mf payload returned from firmware
909  * @config_page: contents of the config page
910  * Context: sleep.
911  *
912  * Return: 0 for success, non-zero for failure.
913  */
914 int
915 mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
916 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
917 {
918 	Mpi2ConfigRequest_t mpi_request;
919 	int r;
920 
921 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
922 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
923 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
924 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
925 	mpi_request.Header.PageNumber = 8;
926 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
927 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
928 	r = _config_request(ioc, &mpi_request, mpi_reply,
929 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
930 	if (r)
931 		goto out;
932 
933 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
934 	r = _config_request(ioc, &mpi_request, mpi_reply,
935 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
936 	    sizeof(*config_page));
937  out:
938 	return r;
939 }
940 
941 /**
942  * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
943  * @ioc: per adapter object
944  * @mpi_reply: reply mf payload returned from firmware
945  * @config_page: contents of the config page
946  * Context: sleep.
947  *
948  * Return: 0 for success, non-zero for failure.
949  */
950 int
951 mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
952 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
953 {
954 	Mpi2ConfigRequest_t mpi_request;
955 	int r;
956 
957 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
958 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
959 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
960 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
961 	mpi_request.Header.PageNumber = 8;
962 	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
963 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
964 	r = _config_request(ioc, &mpi_request, mpi_reply,
965 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
966 	if (r)
967 		goto out;
968 
969 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
970 	r = _config_request(ioc, &mpi_request, mpi_reply,
971 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
972 	    sizeof(*config_page));
973  out:
974 	return r;
975 }
976 /**
977  * mpt3sas_config_get_ioc_pg1 - obtain ioc page 1
978  * @ioc: per adapter object
979  * @mpi_reply: reply mf payload returned from firmware
980  * @config_page: contents of the config page
981  * Context: sleep.
982  *
983  * Return: 0 for success, non-zero for failure.
984  */
985 int
986 mpt3sas_config_get_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
987 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
988 {
989 	Mpi2ConfigRequest_t mpi_request;
990 	int r;
991 
992 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
993 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
994 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
995 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
996 	mpi_request.Header.PageNumber = 1;
997 	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
998 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
999 	r = _config_request(ioc, &mpi_request, mpi_reply,
1000 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1001 	if (r)
1002 		goto out;
1003 
1004 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1005 	r = _config_request(ioc, &mpi_request, mpi_reply,
1006 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1007 	    sizeof(*config_page));
1008  out:
1009 	return r;
1010 }
1011 
1012 /**
1013  * mpt3sas_config_set_ioc_pg1 - modify ioc page 1
1014  * @ioc: per adapter object
1015  * @mpi_reply: reply mf payload returned from firmware
1016  * @config_page: contents of the config page
1017  * Context: sleep.
1018  *
1019  * Return: 0 for success, non-zero for failure.
1020  */
1021 int
1022 mpt3sas_config_set_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
1023 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
1024 {
1025 	Mpi2ConfigRequest_t mpi_request;
1026 	int r;
1027 
1028 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1029 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1030 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1031 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
1032 	mpi_request.Header.PageNumber = 1;
1033 	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
1034 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1035 	r = _config_request(ioc, &mpi_request, mpi_reply,
1036 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1037 	if (r)
1038 		goto out;
1039 
1040 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1041 	r = _config_request(ioc, &mpi_request, mpi_reply,
1042 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1043 	    sizeof(*config_page));
1044  out:
1045 	return r;
1046 }
1047 
1048 /**
1049  * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
1050  * @ioc: per adapter object
1051  * @mpi_reply: reply mf payload returned from firmware
1052  * @config_page: contents of the config page
1053  * @form: GET_NEXT_HANDLE or HANDLE
1054  * @handle: device handle
1055  * Context: sleep.
1056  *
1057  * Return: 0 for success, non-zero for failure.
1058  */
1059 int
1060 mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1061 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
1062 	u32 form, u32 handle)
1063 {
1064 	Mpi2ConfigRequest_t mpi_request;
1065 	int r;
1066 
1067 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1068 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1069 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1070 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1071 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1072 	mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
1073 	mpi_request.Header.PageNumber = 0;
1074 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1075 	r = _config_request(ioc, &mpi_request, mpi_reply,
1076 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1077 	if (r)
1078 		goto out;
1079 
1080 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1081 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1082 	r = _config_request(ioc, &mpi_request, mpi_reply,
1083 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1084 	    sizeof(*config_page));
1085  out:
1086 	return r;
1087 }
1088 
1089 /**
1090  * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
1091  * @ioc: per adapter object
1092  * @mpi_reply: reply mf payload returned from firmware
1093  * @config_page: contents of the config page
1094  * @form: GET_NEXT_HANDLE or HANDLE
1095  * @handle: device handle
1096  * Context: sleep.
1097  *
1098  * Return: 0 for success, non-zero for failure.
1099  */
1100 int
1101 mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1102 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1103 	u32 form, u32 handle)
1104 {
1105 	Mpi2ConfigRequest_t mpi_request;
1106 	int r;
1107 
1108 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1109 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1110 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1111 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1112 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1113 	mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1114 	mpi_request.Header.PageNumber = 1;
1115 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1116 	r = _config_request(ioc, &mpi_request, mpi_reply,
1117 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1118 	if (r)
1119 		goto out;
1120 
1121 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1122 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1123 	r = _config_request(ioc, &mpi_request, mpi_reply,
1124 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1125 	    sizeof(*config_page));
1126  out:
1127 	return r;
1128 }
1129 
1130 /**
1131  * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
1132  * @ioc: per adapter object
1133  * @mpi_reply: reply mf payload returned from firmware
1134  * @config_page: contents of the config page
1135  * @form: GET_NEXT_HANDLE or HANDLE
1136  * @handle: device handle
1137  * Context: sleep.
1138  *
1139  * Return: 0 for success, non-zero for failure.
1140  */
1141 int
1142 mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1143 	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
1144 	u32 form, u32 handle)
1145 {
1146 	Mpi2ConfigRequest_t mpi_request;
1147 	int r;
1148 
1149 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1150 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1151 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1152 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1153 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1154 	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
1155 	mpi_request.Header.PageNumber = 0;
1156 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1157 	r = _config_request(ioc, &mpi_request, mpi_reply,
1158 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1159 	if (r)
1160 		goto out;
1161 
1162 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1163 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1164 	r = _config_request(ioc, &mpi_request, mpi_reply,
1165 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1166 			sizeof(*config_page));
1167 out:
1168 	return r;
1169 }
1170 
1171 /**
1172  * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
1173  * @ioc: per adapter object
1174  * @mpi_reply: reply mf payload returned from firmware
1175  * @config_page: contents of the config page
1176  * @form: GET_NEXT_HANDLE or HANDLE
1177  * @handle: device handle
1178  * Context: sleep.
1179  *
1180  * Return: 0 for success, non-zero for failure.
1181  */
1182 int
1183 mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
1184 	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
1185 	u32 form, u32 handle)
1186 {
1187 	Mpi2ConfigRequest_t mpi_request;
1188 	int r;
1189 
1190 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1191 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1192 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1193 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1194 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1195 	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
1196 	mpi_request.Header.PageNumber = 2;
1197 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1198 	r = _config_request(ioc, &mpi_request, mpi_reply,
1199 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1200 	if (r)
1201 		goto out;
1202 
1203 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1204 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1205 	r = _config_request(ioc, &mpi_request, mpi_reply,
1206 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1207 			sizeof(*config_page));
1208 out:
1209 	return r;
1210 }
1211 
1212 /**
1213  * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1214  * @ioc: per adapter object
1215  * @num_phys: pointer returned with the number of phys
1216  * Context: sleep.
1217  *
1218  * Return: 0 for success, non-zero for failure.
1219  */
1220 int
1221 mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1222 {
1223 	Mpi2ConfigRequest_t mpi_request;
1224 	int r;
1225 	u16 ioc_status;
1226 	Mpi2ConfigReply_t mpi_reply;
1227 	Mpi2SasIOUnitPage0_t config_page;
1228 
1229 	*num_phys = 0;
1230 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1231 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1232 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1233 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1234 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1235 	mpi_request.Header.PageNumber = 0;
1236 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1237 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1238 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1239 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1240 	if (r)
1241 		goto out;
1242 
1243 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1244 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1245 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1246 	    sizeof(Mpi2SasIOUnitPage0_t));
1247 	if (!r) {
1248 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1249 		    MPI2_IOCSTATUS_MASK;
1250 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1251 			*num_phys = config_page.NumPhys;
1252 	}
1253  out:
1254 	return r;
1255 }
1256 
1257 /**
1258  * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit 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  * @sz: size of buffer passed in config_page
1263  * Context: sleep.
1264  *
1265  * Calling function should call config_get_number_hba_phys prior to
1266  * this function, so enough memory is allocated for config_page.
1267  *
1268  * Return: 0 for success, non-zero for failure.
1269  */
1270 int
1271 mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1272 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1273 	u16 sz)
1274 {
1275 	Mpi2ConfigRequest_t mpi_request;
1276 	int r;
1277 
1278 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1279 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1280 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1281 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1282 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1283 	mpi_request.Header.PageNumber = 0;
1284 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1285 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1286 	r = _config_request(ioc, &mpi_request, mpi_reply,
1287 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1288 	if (r)
1289 		goto out;
1290 
1291 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1292 	r = _config_request(ioc, &mpi_request, mpi_reply,
1293 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1294  out:
1295 	return r;
1296 }
1297 
1298 /**
1299  * mpt3sas_config_get_sas_iounit_pg1 - obtain sas 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  * Calling function should call config_get_number_hba_phys prior to
1307  * this function, so enough memory is allocated for config_page.
1308  *
1309  * Return: 0 for success, non-zero for failure.
1310  */
1311 int
1312 mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1313 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1314 	u16 sz)
1315 {
1316 	Mpi2ConfigRequest_t mpi_request;
1317 	int r;
1318 
1319 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1320 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1321 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1322 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1323 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1324 	mpi_request.Header.PageNumber = 1;
1325 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1326 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1327 	r = _config_request(ioc, &mpi_request, mpi_reply,
1328 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1329 	if (r)
1330 		goto out;
1331 
1332 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1333 	r = _config_request(ioc, &mpi_request, mpi_reply,
1334 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1335  out:
1336 	return r;
1337 }
1338 
1339 /**
1340  * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1341  * @ioc: per adapter object
1342  * @mpi_reply: reply mf payload returned from firmware
1343  * @config_page: contents of the config page
1344  * @sz: size of buffer passed in config_page
1345  * Context: sleep.
1346  *
1347  * Calling function should call config_get_number_hba_phys prior to
1348  * this function, so enough memory is allocated for config_page.
1349  *
1350  * Return: 0 for success, non-zero for failure.
1351  */
1352 int
1353 mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1354 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1355 	u16 sz)
1356 {
1357 	Mpi2ConfigRequest_t mpi_request;
1358 	int r;
1359 
1360 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1361 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1362 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1363 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1364 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1365 	mpi_request.Header.PageNumber = 1;
1366 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1367 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1368 	r = _config_request(ioc, &mpi_request, mpi_reply,
1369 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1370 	if (r)
1371 		goto out;
1372 
1373 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1374 	_config_request(ioc, &mpi_request, mpi_reply,
1375 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1376 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1377 	r = _config_request(ioc, &mpi_request, mpi_reply,
1378 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1379  out:
1380 	return r;
1381 }
1382 
1383 /**
1384  * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1385  * @ioc: per adapter object
1386  * @mpi_reply: reply mf payload returned from firmware
1387  * @config_page: contents of the config page
1388  * @form: GET_NEXT_HANDLE or HANDLE
1389  * @handle: expander handle
1390  * Context: sleep.
1391  *
1392  * Return: 0 for success, non-zero for failure.
1393  */
1394 int
1395 mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1396 	*mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1397 {
1398 	Mpi2ConfigRequest_t mpi_request;
1399 	int r;
1400 
1401 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1402 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1403 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1404 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1405 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1406 	mpi_request.Header.PageNumber = 0;
1407 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1408 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1409 	r = _config_request(ioc, &mpi_request, mpi_reply,
1410 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1411 	if (r)
1412 		goto out;
1413 
1414 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1415 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1416 	r = _config_request(ioc, &mpi_request, mpi_reply,
1417 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1418 	    sizeof(*config_page));
1419  out:
1420 	return r;
1421 }
1422 
1423 /**
1424  * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1425  * @ioc: per adapter object
1426  * @mpi_reply: reply mf payload returned from firmware
1427  * @config_page: contents of the config page
1428  * @phy_number: phy number
1429  * @handle: expander handle
1430  * Context: sleep.
1431  *
1432  * Return: 0 for success, non-zero for failure.
1433  */
1434 int
1435 mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1436 	*mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1437 	u16 handle)
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_EXPANDER;
1447 	mpi_request.Header.PageNumber = 1;
1448 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_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.PageAddress =
1456 	    cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1457 	    (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1458 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1459 	r = _config_request(ioc, &mpi_request, mpi_reply,
1460 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1461 	    sizeof(*config_page));
1462  out:
1463 	return r;
1464 }
1465 
1466 /**
1467  * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1468  * @ioc: per adapter object
1469  * @mpi_reply: reply mf payload returned from firmware
1470  * @config_page: contents of the config page
1471  * @form: GET_NEXT_HANDLE or HANDLE
1472  * @handle: expander handle
1473  * Context: sleep.
1474  *
1475  * Return: 0 for success, non-zero for failure.
1476  */
1477 int
1478 mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1479 	*mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1480 {
1481 	Mpi2ConfigRequest_t mpi_request;
1482 	int r;
1483 
1484 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1485 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1486 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1487 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1488 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1489 	mpi_request.Header.PageNumber = 0;
1490 	mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1491 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1492 	r = _config_request(ioc, &mpi_request, mpi_reply,
1493 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1494 	if (r)
1495 		goto out;
1496 
1497 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1498 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1499 	r = _config_request(ioc, &mpi_request, mpi_reply,
1500 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1501 	    sizeof(*config_page));
1502  out:
1503 	return r;
1504 }
1505 
1506 /**
1507  * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1508  * @ioc: per adapter object
1509  * @mpi_reply: reply mf payload returned from firmware
1510  * @config_page: contents of the config page
1511  * @phy_number: phy number
1512  * Context: sleep.
1513  *
1514  * Return: 0 for success, non-zero for failure.
1515  */
1516 int
1517 mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1518 	*mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1519 {
1520 	Mpi2ConfigRequest_t mpi_request;
1521 	int r;
1522 
1523 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1524 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1525 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1526 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1527 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1528 	mpi_request.Header.PageNumber = 0;
1529 	mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1530 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1531 	r = _config_request(ioc, &mpi_request, mpi_reply,
1532 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1533 	if (r)
1534 		goto out;
1535 
1536 	mpi_request.PageAddress =
1537 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1538 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1539 	r = _config_request(ioc, &mpi_request, mpi_reply,
1540 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1541 	    sizeof(*config_page));
1542  out:
1543 	return r;
1544 }
1545 
1546 /**
1547  * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1548  * @ioc: per adapter object
1549  * @mpi_reply: reply mf payload returned from firmware
1550  * @config_page: contents of the config page
1551  * @phy_number: phy number
1552  * Context: sleep.
1553  *
1554  * Return: 0 for success, non-zero for failure.
1555  */
1556 int
1557 mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1558 	*mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1559 {
1560 	Mpi2ConfigRequest_t mpi_request;
1561 	int r;
1562 
1563 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1564 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1565 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1566 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1567 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1568 	mpi_request.Header.PageNumber = 1;
1569 	mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1570 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1571 	r = _config_request(ioc, &mpi_request, mpi_reply,
1572 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1573 	if (r)
1574 		goto out;
1575 
1576 	mpi_request.PageAddress =
1577 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1578 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1579 	r = _config_request(ioc, &mpi_request, mpi_reply,
1580 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1581 	    sizeof(*config_page));
1582  out:
1583 	return r;
1584 }
1585 
1586 /**
1587  * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1588  * @ioc: per adapter object
1589  * @mpi_reply: reply mf payload returned from firmware
1590  * @config_page: contents of the config page
1591  * @form: GET_NEXT_HANDLE or HANDLE
1592  * @handle: volume handle
1593  * Context: sleep.
1594  *
1595  * Return: 0 for success, non-zero for failure.
1596  */
1597 int
1598 mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1599 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1600 	u32 handle)
1601 {
1602 	Mpi2ConfigRequest_t mpi_request;
1603 	int r;
1604 
1605 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1606 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1607 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1608 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1609 	mpi_request.Header.PageNumber = 1;
1610 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1611 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1612 	r = _config_request(ioc, &mpi_request, mpi_reply,
1613 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1614 	if (r)
1615 		goto out;
1616 
1617 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1618 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1619 	r = _config_request(ioc, &mpi_request, mpi_reply,
1620 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1621 	    sizeof(*config_page));
1622  out:
1623 	return r;
1624 }
1625 
1626 /**
1627  * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1628  * @ioc: per adapter object
1629  * @handle: volume handle
1630  * @num_pds: returns pds count
1631  * Context: sleep.
1632  *
1633  * Return: 0 for success, non-zero for failure.
1634  */
1635 int
1636 mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1637 	u8 *num_pds)
1638 {
1639 	Mpi2ConfigRequest_t mpi_request;
1640 	Mpi2RaidVolPage0_t config_page;
1641 	Mpi2ConfigReply_t mpi_reply;
1642 	int r;
1643 	u16 ioc_status;
1644 
1645 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1646 	*num_pds = 0;
1647 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1648 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1649 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1650 	mpi_request.Header.PageNumber = 0;
1651 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1652 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1653 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1654 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1655 	if (r)
1656 		goto out;
1657 
1658 	mpi_request.PageAddress =
1659 	    cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1660 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1661 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1662 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1663 	    sizeof(Mpi2RaidVolPage0_t));
1664 	if (!r) {
1665 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1666 		    MPI2_IOCSTATUS_MASK;
1667 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1668 			*num_pds = config_page.NumPhysDisks;
1669 	}
1670 
1671  out:
1672 	return r;
1673 }
1674 
1675 /**
1676  * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1677  * @ioc: per adapter object
1678  * @mpi_reply: reply mf payload returned from firmware
1679  * @config_page: contents of the config page
1680  * @form: GET_NEXT_HANDLE or HANDLE
1681  * @handle: volume handle
1682  * @sz: size of buffer passed in config_page
1683  * Context: sleep.
1684  *
1685  * Return: 0 for success, non-zero for failure.
1686  */
1687 int
1688 mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1689 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1690 	u32 handle, u16 sz)
1691 {
1692 	Mpi2ConfigRequest_t mpi_request;
1693 	int r;
1694 
1695 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1696 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1697 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1698 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1699 	mpi_request.Header.PageNumber = 0;
1700 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1701 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1702 	r = _config_request(ioc, &mpi_request, mpi_reply,
1703 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1704 	if (r)
1705 		goto out;
1706 
1707 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1708 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1709 	r = _config_request(ioc, &mpi_request, mpi_reply,
1710 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1711  out:
1712 	return r;
1713 }
1714 
1715 /**
1716  * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1717  * @ioc: per adapter object
1718  * @mpi_reply: reply mf payload returned from firmware
1719  * @config_page: contents of the config page
1720  * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1721  * @form_specific: specific to the form
1722  * Context: sleep.
1723  *
1724  * Return: 0 for success, non-zero for failure.
1725  */
1726 int
1727 mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1728 	*mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1729 	u32 form_specific)
1730 {
1731 	Mpi2ConfigRequest_t mpi_request;
1732 	int r;
1733 
1734 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1735 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1736 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1737 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1738 	mpi_request.Header.PageNumber = 0;
1739 	mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1740 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1741 	r = _config_request(ioc, &mpi_request, mpi_reply,
1742 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1743 	if (r)
1744 		goto out;
1745 
1746 	mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1747 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1748 	r = _config_request(ioc, &mpi_request, mpi_reply,
1749 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1750 	    sizeof(*config_page));
1751  out:
1752 	return r;
1753 }
1754 
1755 /**
1756  * mpt3sas_config_get_driver_trigger_pg0 - obtain driver trigger page 0
1757  * @ioc: per adapter object
1758  * @mpi_reply: reply mf payload returned from firmware
1759  * @config_page: contents of the config page
1760  * Context: sleep.
1761  *
1762  * Returns 0 for success, non-zero for failure.
1763  */
1764 int
1765 mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1766 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1767 {
1768 	Mpi2ConfigRequest_t mpi_request;
1769 	int r;
1770 
1771 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1772 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1773 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1774 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1775 	mpi_request.ExtPageType =
1776 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1777 	mpi_request.Header.PageNumber = 0;
1778 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1779 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1780 	r = _config_request(ioc, &mpi_request, mpi_reply,
1781 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1782 	if (r)
1783 		goto out;
1784 
1785 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1786 	r = _config_request(ioc, &mpi_request, mpi_reply,
1787 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1788 	    sizeof(*config_page));
1789  out:
1790 	return r;
1791 }
1792 
1793 /**
1794  * _config_set_driver_trigger_pg0 - write driver trigger page 0
1795  * @ioc: per adapter object
1796  * @mpi_reply: reply mf payload returned from firmware
1797  * @config_page: contents of the config page
1798  * Context: sleep.
1799  *
1800  * Returns 0 for success, non-zero for failure.
1801  */
1802 static int
1803 _config_set_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1804 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1805 {
1806 	Mpi2ConfigRequest_t mpi_request;
1807 	int r;
1808 
1809 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1810 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1811 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1812 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1813 	mpi_request.ExtPageType =
1814 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1815 	mpi_request.Header.PageNumber = 0;
1816 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1817 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1818 	r = _config_request(ioc, &mpi_request, mpi_reply,
1819 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1820 	if (r)
1821 		goto out;
1822 
1823 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1824 	_config_request(ioc, &mpi_request, mpi_reply,
1825 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1826 	    sizeof(*config_page));
1827 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1828 	r = _config_request(ioc, &mpi_request, mpi_reply,
1829 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1830 	    sizeof(*config_page));
1831  out:
1832 	return r;
1833 }
1834 
1835 /**
1836  * mpt3sas_config_update_driver_trigger_pg0 - update driver trigger page 0
1837  * @ioc: per adapter object
1838  * @trigger_flag: trigger type bit map
1839  * @set: set ot clear trigger values
1840  * Context: sleep.
1841  *
1842  * Returns 0 for success, non-zero for failure.
1843  */
1844 static int
1845 mpt3sas_config_update_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1846 	u16 trigger_flag, bool set)
1847 {
1848 	Mpi26DriverTriggerPage0_t tg_pg0;
1849 	Mpi2ConfigReply_t mpi_reply;
1850 	int rc;
1851 	u16 flags, ioc_status;
1852 
1853 	rc = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
1854 	if (rc)
1855 		return rc;
1856 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1857 	    MPI2_IOCSTATUS_MASK;
1858 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1859 		dcprintk(ioc,
1860 		    ioc_err(ioc,
1861 		    "%s: Failed to get trigger pg0, ioc_status(0x%04x)\n",
1862 		    __func__, ioc_status));
1863 		return -EFAULT;
1864 	}
1865 
1866 	if (set)
1867 		flags = le16_to_cpu(tg_pg0.TriggerFlags) | trigger_flag;
1868 	else
1869 		flags = le16_to_cpu(tg_pg0.TriggerFlags) & ~trigger_flag;
1870 
1871 	tg_pg0.TriggerFlags = cpu_to_le16(flags);
1872 
1873 	rc = _config_set_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
1874 	if (rc)
1875 		return rc;
1876 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1877 	    MPI2_IOCSTATUS_MASK;
1878 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1879 		dcprintk(ioc,
1880 		    ioc_err(ioc,
1881 		    "%s: Failed to update trigger pg0, ioc_status(0x%04x)\n",
1882 		    __func__, ioc_status));
1883 		return -EFAULT;
1884 	}
1885 
1886 	return 0;
1887 }
1888 
1889 /**
1890  * mpt3sas_config_get_driver_trigger_pg1 - obtain driver trigger page 1
1891  * @ioc: per adapter object
1892  * @mpi_reply: reply mf payload returned from firmware
1893  * @config_page: contents of the config page
1894  * Context: sleep.
1895  *
1896  * Returns 0 for success, non-zero for failure.
1897  */
1898 int
1899 mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
1900 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
1901 {
1902 	Mpi2ConfigRequest_t mpi_request;
1903 	int r;
1904 
1905 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1906 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1907 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1908 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1909 	mpi_request.ExtPageType =
1910 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1911 	mpi_request.Header.PageNumber = 1;
1912 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
1913 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1914 	r = _config_request(ioc, &mpi_request, mpi_reply,
1915 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1916 	if (r)
1917 		goto out;
1918 
1919 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1920 	r = _config_request(ioc, &mpi_request, mpi_reply,
1921 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1922 	    sizeof(*config_page));
1923  out:
1924 	return r;
1925 }
1926 
1927 /**
1928  * _config_set_driver_trigger_pg1 - write driver trigger page 1
1929  * @ioc: per adapter object
1930  * @mpi_reply: reply mf payload returned from firmware
1931  * @config_page: contents of the config page
1932  * Context: sleep.
1933  *
1934  * Returns 0 for success, non-zero for failure.
1935  */
1936 static int
1937 _config_set_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
1938 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
1939 {
1940 	Mpi2ConfigRequest_t mpi_request;
1941 	int r;
1942 
1943 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1944 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1945 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1946 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1947 	mpi_request.ExtPageType =
1948 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1949 	mpi_request.Header.PageNumber = 1;
1950 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
1951 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1952 	r = _config_request(ioc, &mpi_request, mpi_reply,
1953 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1954 	if (r)
1955 		goto out;
1956 
1957 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1958 	_config_request(ioc, &mpi_request, mpi_reply,
1959 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1960 	    sizeof(*config_page));
1961 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1962 	r = _config_request(ioc, &mpi_request, mpi_reply,
1963 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1964 	    sizeof(*config_page));
1965  out:
1966 	return r;
1967 }
1968 
1969 /**
1970  * mpt3sas_config_update_driver_trigger_pg1 - update driver trigger page 1
1971  * @ioc: per adapter object
1972  * @master_tg: Master trigger bit map
1973  * @set: set ot clear trigger values
1974  * Context: sleep.
1975  *
1976  * Returns 0 for success, non-zero for failure.
1977  */
1978 int
1979 mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
1980 	struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set)
1981 {
1982 	Mpi26DriverTriggerPage1_t tg_pg1;
1983 	Mpi2ConfigReply_t mpi_reply;
1984 	int rc;
1985 	u16 ioc_status;
1986 
1987 	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
1988 	    MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, set);
1989 	if (rc)
1990 		return rc;
1991 
1992 	rc = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
1993 	if (rc)
1994 		goto out;
1995 
1996 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1997 	    MPI2_IOCSTATUS_MASK;
1998 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1999 		dcprintk(ioc,
2000 		    ioc_err(ioc,
2001 		    "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
2002 		    __func__, ioc_status));
2003 		rc = -EFAULT;
2004 		goto out;
2005 	}
2006 
2007 	if (set) {
2008 		tg_pg1.NumMasterTrigger = cpu_to_le16(1);
2009 		tg_pg1.MasterTriggers[0].MasterTriggerFlags = cpu_to_le32(
2010 		    master_tg->MasterData);
2011 	} else {
2012 		tg_pg1.NumMasterTrigger = 0;
2013 		tg_pg1.MasterTriggers[0].MasterTriggerFlags = 0;
2014 	}
2015 
2016 	rc = _config_set_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
2017 	if (rc)
2018 		goto out;
2019 
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 pg1, ioc_status(0x%04x)\n",
2026 		    __func__, ioc_status));
2027 		rc = -EFAULT;
2028 		goto out;
2029 	}
2030 
2031 	return 0;
2032 
2033 out:
2034 	mpt3sas_config_update_driver_trigger_pg0(ioc,
2035 	    MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, !set);
2036 
2037 	return rc;
2038 }
2039 
2040 /**
2041  * mpt3sas_config_get_driver_trigger_pg2 - obtain driver trigger page 2
2042  * @ioc: per adapter object
2043  * @mpi_reply: reply mf payload returned from firmware
2044  * @config_page: contents of the config page
2045  * Context: sleep.
2046  *
2047  * Returns 0 for success, non-zero for failure.
2048  */
2049 int
2050 mpt3sas_config_get_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2051 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2052 {
2053 	Mpi2ConfigRequest_t mpi_request;
2054 	int r;
2055 
2056 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2057 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2058 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2059 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2060 	mpi_request.ExtPageType =
2061 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2062 	mpi_request.Header.PageNumber = 2;
2063 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2064 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2065 	r = _config_request(ioc, &mpi_request, mpi_reply,
2066 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2067 	if (r)
2068 		goto out;
2069 
2070 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2071 	r = _config_request(ioc, &mpi_request, mpi_reply,
2072 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2073 	    sizeof(*config_page));
2074  out:
2075 	return r;
2076 }
2077 
2078 /**
2079  * _config_set_driver_trigger_pg2 - write driver trigger page 2
2080  * @ioc: per adapter object
2081  * @mpi_reply: reply mf payload returned from firmware
2082  * @config_page: contents of the config page
2083  * Context: sleep.
2084  *
2085  * Returns 0 for success, non-zero for failure.
2086  */
2087 static int
2088 _config_set_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2089 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2090 {
2091 	Mpi2ConfigRequest_t mpi_request;
2092 	int r;
2093 
2094 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2095 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2096 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2097 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2098 	mpi_request.ExtPageType =
2099 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2100 	mpi_request.Header.PageNumber = 2;
2101 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2102 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2103 	r = _config_request(ioc, &mpi_request, mpi_reply,
2104 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2105 	if (r)
2106 		goto out;
2107 
2108 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2109 	_config_request(ioc, &mpi_request, mpi_reply,
2110 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2111 	    sizeof(*config_page));
2112 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2113 	r = _config_request(ioc, &mpi_request, mpi_reply,
2114 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2115 	    sizeof(*config_page));
2116  out:
2117 	return r;
2118 }
2119 
2120 /**
2121  * mpt3sas_config_update_driver_trigger_pg2 - update driver trigger page 2
2122  * @ioc: per adapter object
2123  * @event_tg: list of Event Triggers
2124  * @set: set ot clear trigger values
2125  * Context: sleep.
2126  *
2127  * Returns 0 for success, non-zero for failure.
2128  */
2129 int
2130 mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2131 	struct SL_WH_EVENT_TRIGGERS_T *event_tg, bool set)
2132 {
2133 	Mpi26DriverTriggerPage2_t tg_pg2;
2134 	Mpi2ConfigReply_t mpi_reply;
2135 	int rc, i, count;
2136 	u16 ioc_status;
2137 
2138 	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2139 	    MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, set);
2140 	if (rc)
2141 		return rc;
2142 
2143 	rc = mpt3sas_config_get_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2144 	if (rc)
2145 		goto out;
2146 
2147 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2148 	    MPI2_IOCSTATUS_MASK;
2149 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2150 		dcprintk(ioc,
2151 		    ioc_err(ioc,
2152 		    "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2153 		    __func__, ioc_status));
2154 		rc = -EFAULT;
2155 		goto out;
2156 	}
2157 
2158 	if (set) {
2159 		count = event_tg->ValidEntries;
2160 		tg_pg2.NumMPIEventTrigger = cpu_to_le16(count);
2161 		for (i = 0; i < count; i++) {
2162 			tg_pg2.MPIEventTriggers[i].MPIEventCode =
2163 			    cpu_to_le16(
2164 			    event_tg->EventTriggerEntry[i].EventValue);
2165 			tg_pg2.MPIEventTriggers[i].MPIEventCodeSpecific =
2166 			    cpu_to_le16(
2167 			    event_tg->EventTriggerEntry[i].LogEntryQualifier);
2168 		}
2169 	} else {
2170 		tg_pg2.NumMPIEventTrigger = 0;
2171 		memset(&tg_pg2.MPIEventTriggers[0], 0,
2172 		    NUM_VALID_ENTRIES * sizeof(
2173 		    MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY));
2174 	}
2175 
2176 	rc = _config_set_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2177 	if (rc)
2178 		goto out;
2179 
2180 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2181 	    MPI2_IOCSTATUS_MASK;
2182 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2183 		dcprintk(ioc,
2184 		    ioc_err(ioc,
2185 		    "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2186 		    __func__, ioc_status));
2187 		rc = -EFAULT;
2188 		goto out;
2189 	}
2190 
2191 	return 0;
2192 
2193 out:
2194 	mpt3sas_config_update_driver_trigger_pg0(ioc,
2195 	    MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, !set);
2196 
2197 	return rc;
2198 }
2199 
2200 /**
2201  * mpt3sas_config_get_driver_trigger_pg3 - obtain driver trigger page 3
2202  * @ioc: per adapter object
2203  * @mpi_reply: reply mf payload returned from firmware
2204  * @config_page: contents of the config page
2205  * Context: sleep.
2206  *
2207  * Returns 0 for success, non-zero for failure.
2208  */
2209 int
2210 mpt3sas_config_get_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2211 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2212 {
2213 	Mpi2ConfigRequest_t mpi_request;
2214 	int r;
2215 
2216 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2217 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2218 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2219 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2220 	mpi_request.ExtPageType =
2221 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2222 	mpi_request.Header.PageNumber = 3;
2223 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2224 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2225 	r = _config_request(ioc, &mpi_request, mpi_reply,
2226 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2227 	if (r)
2228 		goto out;
2229 
2230 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2231 	r = _config_request(ioc, &mpi_request, mpi_reply,
2232 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2233 	    sizeof(*config_page));
2234  out:
2235 	return r;
2236 }
2237 
2238 /**
2239  * _config_set_driver_trigger_pg3 - write driver trigger page 3
2240  * @ioc: per adapter object
2241  * @mpi_reply: reply mf payload returned from firmware
2242  * @config_page: contents of the config page
2243  * Context: sleep.
2244  *
2245  * Returns 0 for success, non-zero for failure.
2246  */
2247 static int
2248 _config_set_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2249 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2250 {
2251 	Mpi2ConfigRequest_t mpi_request;
2252 	int r;
2253 
2254 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2255 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2256 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2257 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2258 	mpi_request.ExtPageType =
2259 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2260 	mpi_request.Header.PageNumber = 3;
2261 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2262 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2263 	r = _config_request(ioc, &mpi_request, mpi_reply,
2264 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2265 	if (r)
2266 		goto out;
2267 
2268 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2269 	_config_request(ioc, &mpi_request, mpi_reply,
2270 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2271 	    sizeof(*config_page));
2272 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2273 	r = _config_request(ioc, &mpi_request, mpi_reply,
2274 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2275 	    sizeof(*config_page));
2276  out:
2277 	return r;
2278 }
2279 
2280 /**
2281  * mpt3sas_config_update_driver_trigger_pg3 - update driver trigger page 3
2282  * @ioc: per adapter object
2283  * @scsi_tg: scsi trigger list
2284  * @set: set ot clear trigger values
2285  * Context: sleep.
2286  *
2287  * Returns 0 for success, non-zero for failure.
2288  */
2289 int
2290 mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2291 	struct SL_WH_SCSI_TRIGGERS_T *scsi_tg, bool set)
2292 {
2293 	Mpi26DriverTriggerPage3_t tg_pg3;
2294 	Mpi2ConfigReply_t mpi_reply;
2295 	int rc, i, count;
2296 	u16 ioc_status;
2297 
2298 	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2299 	    MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, set);
2300 	if (rc)
2301 		return rc;
2302 
2303 	rc = mpt3sas_config_get_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2304 	if (rc)
2305 		goto out;
2306 
2307 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2308 	    MPI2_IOCSTATUS_MASK;
2309 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2310 		dcprintk(ioc,
2311 		    ioc_err(ioc,
2312 		    "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2313 		    __func__, ioc_status));
2314 		return -EFAULT;
2315 	}
2316 
2317 	if (set) {
2318 		count = scsi_tg->ValidEntries;
2319 		tg_pg3.NumSCSISenseTrigger = cpu_to_le16(count);
2320 		for (i = 0; i < count; i++) {
2321 			tg_pg3.SCSISenseTriggers[i].ASCQ =
2322 			    scsi_tg->SCSITriggerEntry[i].ASCQ;
2323 			tg_pg3.SCSISenseTriggers[i].ASC =
2324 			    scsi_tg->SCSITriggerEntry[i].ASC;
2325 			tg_pg3.SCSISenseTriggers[i].SenseKey =
2326 			    scsi_tg->SCSITriggerEntry[i].SenseKey;
2327 		}
2328 	} else {
2329 		tg_pg3.NumSCSISenseTrigger = 0;
2330 		memset(&tg_pg3.SCSISenseTriggers[0], 0,
2331 		    NUM_VALID_ENTRIES * sizeof(
2332 		    MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY));
2333 	}
2334 
2335 	rc = _config_set_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2336 	if (rc)
2337 		goto out;
2338 
2339 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2340 	    MPI2_IOCSTATUS_MASK;
2341 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2342 		dcprintk(ioc,
2343 		    ioc_err(ioc,
2344 		    "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2345 		     __func__, ioc_status));
2346 		return -EFAULT;
2347 	}
2348 
2349 	return 0;
2350 out:
2351 	mpt3sas_config_update_driver_trigger_pg0(ioc,
2352 	    MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, !set);
2353 
2354 	return rc;
2355 }
2356 
2357 /**
2358  * mpt3sas_config_get_driver_trigger_pg4 - obtain driver trigger page 4
2359  * @ioc: per adapter object
2360  * @mpi_reply: reply mf payload returned from firmware
2361  * @config_page: contents of the config page
2362  * Context: sleep.
2363  *
2364  * Returns 0 for success, non-zero for failure.
2365  */
2366 int
2367 mpt3sas_config_get_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2368 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2369 {
2370 	Mpi2ConfigRequest_t mpi_request;
2371 	int r;
2372 
2373 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2374 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2375 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2376 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2377 	mpi_request.ExtPageType =
2378 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2379 	mpi_request.Header.PageNumber = 4;
2380 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2381 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2382 	r = _config_request(ioc, &mpi_request, mpi_reply,
2383 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2384 	if (r)
2385 		goto out;
2386 
2387 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2388 	r = _config_request(ioc, &mpi_request, mpi_reply,
2389 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2390 	    sizeof(*config_page));
2391  out:
2392 	return r;
2393 }
2394 
2395 /**
2396  * _config_set_driver_trigger_pg4 - write driver trigger page 4
2397  * @ioc: per adapter object
2398  * @mpi_reply: reply mf payload returned from firmware
2399  * @config_page: contents of the config page
2400  * Context: sleep.
2401  *
2402  * Returns 0 for success, non-zero for failure.
2403  */
2404 static int
2405 _config_set_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2406 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2407 {
2408 	Mpi2ConfigRequest_t mpi_request;
2409 	int r;
2410 
2411 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2412 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2413 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2414 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2415 	mpi_request.ExtPageType =
2416 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2417 	mpi_request.Header.PageNumber = 4;
2418 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2419 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2420 	r = _config_request(ioc, &mpi_request, mpi_reply,
2421 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2422 	if (r)
2423 		goto out;
2424 
2425 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2426 	_config_request(ioc, &mpi_request, mpi_reply,
2427 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2428 	    sizeof(*config_page));
2429 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2430 	r = _config_request(ioc, &mpi_request, mpi_reply,
2431 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2432 	    sizeof(*config_page));
2433  out:
2434 	return r;
2435 }
2436 
2437 /**
2438  * mpt3sas_config_update_driver_trigger_pg4 - update driver trigger page 4
2439  * @ioc: per adapter object
2440  * @mpi_tg: mpi trigger list
2441  * @set: set ot clear trigger values
2442  * Context: sleep.
2443  *
2444  * Returns 0 for success, non-zero for failure.
2445  */
2446 int
2447 mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2448 	struct SL_WH_MPI_TRIGGERS_T *mpi_tg, bool set)
2449 {
2450 	Mpi26DriverTriggerPage4_t tg_pg4;
2451 	Mpi2ConfigReply_t mpi_reply;
2452 	int rc, i, count;
2453 	u16 ioc_status;
2454 
2455 	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2456 	    MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, set);
2457 	if (rc)
2458 		return rc;
2459 
2460 	rc = mpt3sas_config_get_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2461 	if (rc)
2462 		goto out;
2463 
2464 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2465 	    MPI2_IOCSTATUS_MASK;
2466 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2467 		dcprintk(ioc,
2468 		    ioc_err(ioc,
2469 		    "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2470 		    __func__, ioc_status));
2471 		rc = -EFAULT;
2472 		goto out;
2473 	}
2474 
2475 	if (set) {
2476 		count = mpi_tg->ValidEntries;
2477 		tg_pg4.NumIOCStatusLogInfoTrigger = cpu_to_le16(count);
2478 		for (i = 0; i < count; i++) {
2479 			tg_pg4.IOCStatusLoginfoTriggers[i].IOCStatus =
2480 			    cpu_to_le16(mpi_tg->MPITriggerEntry[i].IOCStatus);
2481 			tg_pg4.IOCStatusLoginfoTriggers[i].LogInfo =
2482 			    cpu_to_le32(mpi_tg->MPITriggerEntry[i].IocLogInfo);
2483 		}
2484 	} else {
2485 		tg_pg4.NumIOCStatusLogInfoTrigger = 0;
2486 		memset(&tg_pg4.IOCStatusLoginfoTriggers[0], 0,
2487 		    NUM_VALID_ENTRIES * sizeof(
2488 		    MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY));
2489 	}
2490 
2491 	rc = _config_set_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2492 	if (rc)
2493 		goto out;
2494 
2495 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2496 	    MPI2_IOCSTATUS_MASK;
2497 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2498 		dcprintk(ioc,
2499 		    ioc_err(ioc,
2500 		    "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2501 		    __func__, ioc_status));
2502 		rc = -EFAULT;
2503 		goto out;
2504 	}
2505 
2506 	return 0;
2507 
2508 out:
2509 	mpt3sas_config_update_driver_trigger_pg0(ioc,
2510 	    MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, !set);
2511 
2512 	return rc;
2513 }
2514 
2515 /**
2516  * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
2517  * raid components
2518  * @ioc: per adapter object
2519  * @pd_handle: phys disk handle
2520  * @volume_handle: volume handle
2521  * Context: sleep.
2522  *
2523  * Return: 0 for success, non-zero for failure.
2524  */
2525 int
2526 mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
2527 	u16 *volume_handle)
2528 {
2529 	Mpi2RaidConfigurationPage0_t *config_page = NULL;
2530 	Mpi2ConfigRequest_t mpi_request;
2531 	Mpi2ConfigReply_t mpi_reply;
2532 	int r, i, config_page_sz;
2533 	u16 ioc_status;
2534 	int config_num;
2535 	u16 element_type;
2536 	u16 phys_disk_dev_handle;
2537 
2538 	*volume_handle = 0;
2539 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2540 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2541 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2542 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2543 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
2544 	mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
2545 	mpi_request.Header.PageNumber = 0;
2546 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2547 	r = _config_request(ioc, &mpi_request, &mpi_reply,
2548 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2549 	if (r)
2550 		goto out;
2551 
2552 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2553 	config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
2554 	config_page = kmalloc(config_page_sz, GFP_KERNEL);
2555 	if (!config_page) {
2556 		r = -1;
2557 		goto out;
2558 	}
2559 
2560 	config_num = 0xff;
2561 	while (1) {
2562 		mpi_request.PageAddress = cpu_to_le32(config_num +
2563 		    MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
2564 		r = _config_request(ioc, &mpi_request, &mpi_reply,
2565 		    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2566 		    config_page_sz);
2567 		if (r)
2568 			goto out;
2569 		r = -1;
2570 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2571 		    MPI2_IOCSTATUS_MASK;
2572 		if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
2573 			goto out;
2574 		for (i = 0; i < config_page->NumElements; i++) {
2575 			element_type = le16_to_cpu(config_page->
2576 			    ConfigElement[i].ElementFlags) &
2577 			    MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
2578 			if (element_type ==
2579 			    MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
2580 			    element_type ==
2581 			    MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
2582 				phys_disk_dev_handle =
2583 				    le16_to_cpu(config_page->ConfigElement[i].
2584 				    PhysDiskDevHandle);
2585 				if (phys_disk_dev_handle == pd_handle) {
2586 					*volume_handle =
2587 					    le16_to_cpu(config_page->
2588 					    ConfigElement[i].VolDevHandle);
2589 					r = 0;
2590 					goto out;
2591 				}
2592 			} else if (element_type ==
2593 			    MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
2594 				*volume_handle = 0;
2595 				r = 0;
2596 				goto out;
2597 			}
2598 		}
2599 		config_num = config_page->ConfigNum;
2600 	}
2601  out:
2602 	kfree(config_page);
2603 	return r;
2604 }
2605 
2606 /**
2607  * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
2608  * @ioc: per adapter object
2609  * @volume_handle: volume handle
2610  * @wwid: volume wwid
2611  * Context: sleep.
2612  *
2613  * Return: 0 for success, non-zero for failure.
2614  */
2615 int
2616 mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
2617 	u64 *wwid)
2618 {
2619 	Mpi2ConfigReply_t mpi_reply;
2620 	Mpi2RaidVolPage1_t raid_vol_pg1;
2621 
2622 	*wwid = 0;
2623 	if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
2624 	    &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
2625 	    volume_handle))) {
2626 		*wwid = le64_to_cpu(raid_vol_pg1.WWID);
2627 		return 0;
2628 	} else
2629 		return -1;
2630 }
2631