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