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