xref: /linux/drivers/scsi/mpt3sas/mpt3sas_config.c (revision c5d3cdad688ed75fb311a3a671eb30ba7106d7d3)
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 	u8 issue_reset = 0;
307 
308 	mutex_lock(&ioc->config_cmds.mutex);
309 	if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
310 		ioc_err(ioc, "%s: config_cmd in use\n", __func__);
311 		mutex_unlock(&ioc->config_cmds.mutex);
312 		return -EAGAIN;
313 	}
314 
315 	retry_count = 0;
316 	memset(&mem, 0, sizeof(struct config_request));
317 
318 	mpi_request->VF_ID = 0; /* TODO */
319 	mpi_request->VP_ID = 0;
320 
321 	if (config_page) {
322 		mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
323 		mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
324 		mpi_request->Header.PageType = mpi_reply->Header.PageType;
325 		mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
326 		mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
327 		mpi_request->ExtPageType = mpi_reply->ExtPageType;
328 		if (mpi_request->Header.PageLength)
329 			mem.sz = mpi_request->Header.PageLength * 4;
330 		else
331 			mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
332 		r = _config_alloc_config_dma_memory(ioc, &mem);
333 		if (r != 0)
334 			goto out;
335 		if (mpi_request->Action ==
336 		    MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
337 		    mpi_request->Action ==
338 		    MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
339 			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
340 			    MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
341 			    mem.page_dma);
342 			memcpy(mem.page, config_page, min_t(u16, mem.sz,
343 			    config_page_sz));
344 		} else {
345 			memset(config_page, 0, config_page_sz);
346 			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
347 			    MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
348 			memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
349 		}
350 	}
351 
352  retry_config:
353 	if (retry_count) {
354 		if (retry_count > 2) { /* attempt only 2 retries */
355 			r = -EFAULT;
356 			goto free_mem;
357 		}
358 		ioc_info(ioc, "%s: attempting retry (%d)\n",
359 			 __func__, retry_count);
360 	}
361 
362 	r = mpt3sas_wait_for_ioc(ioc, MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT);
363 	if (r)
364 		goto free_mem;
365 
366 	smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
367 	if (!smid) {
368 		ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
369 		ioc->config_cmds.status = MPT3_CMD_NOT_USED;
370 		r = -EAGAIN;
371 		goto free_mem;
372 	}
373 
374 	r = 0;
375 	memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
376 	ioc->config_cmds.status = MPT3_CMD_PENDING;
377 	config_request = mpt3sas_base_get_msg_frame(ioc, smid);
378 	ioc->config_cmds.smid = smid;
379 	memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
380 	if (ioc->logging_level & MPT_DEBUG_CONFIG)
381 		_config_display_some_debug(ioc, smid, "config_request", NULL);
382 	init_completion(&ioc->config_cmds.done);
383 	ioc->put_smid_default(ioc, smid);
384 	wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ);
385 	if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
386 		if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
387 			_config_display_some_debug(ioc,
388 			    smid, "config_request", NULL);
389 		mpt3sas_check_cmd_timeout(ioc,
390 		    ioc->config_cmds.status, mpi_request,
391 		    sizeof(Mpi2ConfigRequest_t)/4, issue_reset);
392 		retry_count++;
393 		if (ioc->config_cmds.smid == smid)
394 			mpt3sas_base_free_smid(ioc, smid);
395 		if ((ioc->shost_recovery) || (ioc->config_cmds.status &
396 		    MPT3_CMD_RESET) || ioc->pci_error_recovery)
397 			goto retry_config;
398 		issue_host_reset = 1;
399 		r = -EFAULT;
400 		goto free_mem;
401 	}
402 
403 	if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
404 		memcpy(mpi_reply, ioc->config_cmds.reply,
405 		    sizeof(Mpi2ConfigReply_t));
406 
407 		/* Reply Frame Sanity Checks to workaround FW issues */
408 		if ((mpi_request->Header.PageType & 0xF) !=
409 		    (mpi_reply->Header.PageType & 0xF)) {
410 			if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
411 				_config_display_some_debug(ioc,
412 				    smid, "config_request", NULL);
413 			_debug_dump_mf(mpi_request, ioc->request_sz/4);
414 			_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
415 			panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
416 			      ioc->name, __func__,
417 			      mpi_request->Header.PageType & 0xF,
418 			      mpi_reply->Header.PageType & 0xF);
419 		}
420 
421 		if (((mpi_request->Header.PageType & 0xF) ==
422 		    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
423 		    mpi_request->ExtPageType != mpi_reply->ExtPageType) {
424 			if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
425 				_config_display_some_debug(ioc,
426 				    smid, "config_request", NULL);
427 			_debug_dump_mf(mpi_request, ioc->request_sz/4);
428 			_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
429 			panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
430 			      ioc->name, __func__,
431 			      mpi_request->ExtPageType,
432 			      mpi_reply->ExtPageType);
433 		}
434 		ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
435 		    & MPI2_IOCSTATUS_MASK;
436 	}
437 
438 	if (retry_count)
439 		ioc_info(ioc, "%s: retry (%d) completed!!\n",
440 			 __func__, retry_count);
441 
442 	if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
443 	    config_page && mpi_request->Action ==
444 	    MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
445 		u8 *p = (u8 *)mem.page;
446 
447 		/* Config Page Sanity Checks to workaround FW issues */
448 		if (p) {
449 			if ((mpi_request->Header.PageType & 0xF) !=
450 			    (p[3] & 0xF)) {
451 				if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
452 					_config_display_some_debug(ioc,
453 					    smid, "config_request", NULL);
454 				_debug_dump_mf(mpi_request, ioc->request_sz/4);
455 				_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
456 				_debug_dump_config(p, min_t(u16, mem.sz,
457 				    config_page_sz)/4);
458 				panic("%s: %s: Firmware BUG: config page mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
459 				      ioc->name, __func__,
460 				      mpi_request->Header.PageType & 0xF,
461 				      p[3] & 0xF);
462 			}
463 
464 			if (((mpi_request->Header.PageType & 0xF) ==
465 			    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
466 			    (mpi_request->ExtPageType != p[6])) {
467 				if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
468 					_config_display_some_debug(ioc,
469 					    smid, "config_request", NULL);
470 				_debug_dump_mf(mpi_request, ioc->request_sz/4);
471 				_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
472 				_debug_dump_config(p, min_t(u16, mem.sz,
473 				    config_page_sz)/4);
474 				panic("%s: %s: Firmware BUG: config page mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
475 				      ioc->name, __func__,
476 				      mpi_request->ExtPageType, p[6]);
477 			}
478 		}
479 		memcpy(config_page, mem.page, min_t(u16, mem.sz,
480 		    config_page_sz));
481 	}
482 
483  free_mem:
484 	if (config_page)
485 		_config_free_config_dma_memory(ioc, &mem);
486  out:
487 	ioc->config_cmds.status = MPT3_CMD_NOT_USED;
488 	mutex_unlock(&ioc->config_cmds.mutex);
489 
490 	if (issue_host_reset)
491 		mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
492 	return r;
493 }
494 
495 /**
496  * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
497  * @ioc: per adapter object
498  * @mpi_reply: reply mf payload returned from firmware
499  * @config_page: contents of the config page
500  * Context: sleep.
501  *
502  * Return: 0 for success, non-zero for failure.
503  */
504 int
505 mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
506 	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
507 {
508 	Mpi2ConfigRequest_t mpi_request;
509 	int r;
510 
511 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
512 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
513 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
514 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
515 	mpi_request.Header.PageNumber = 0;
516 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
517 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
518 	r = _config_request(ioc, &mpi_request, mpi_reply,
519 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
520 	if (r)
521 		goto out;
522 
523 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
524 	r = _config_request(ioc, &mpi_request, mpi_reply,
525 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
526 	    sizeof(*config_page));
527  out:
528 	return r;
529 }
530 
531 /**
532  * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
533  * @ioc: per adapter object
534  * @mpi_reply: reply mf payload returned from firmware
535  * @config_page: contents of the config page
536  * @sz: size of buffer passed in config_page
537  * Context: sleep.
538  *
539  * Return: 0 for success, non-zero for failure.
540  */
541 int
542 mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
543 	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
544 	u16 sz)
545 {
546 	Mpi2ConfigRequest_t mpi_request;
547 	int r;
548 
549 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
550 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
551 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
552 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
553 	mpi_request.Header.PageNumber = 7;
554 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
555 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
556 	r = _config_request(ioc, &mpi_request, mpi_reply,
557 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
558 	if (r)
559 		goto out;
560 
561 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
562 	r = _config_request(ioc, &mpi_request, mpi_reply,
563 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
564 	    sz);
565  out:
566 	return r;
567 }
568 
569 /**
570  * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
571  * @ioc: per adapter object
572  * @mpi_reply: reply mf payload returned from firmware
573  * @config_page: contents of the config page
574  * Context: sleep.
575  *
576  * Return: 0 for success, non-zero for failure.
577  */
578 int
579 mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
580 	Mpi2ConfigReply_t *mpi_reply,
581 	struct Mpi2ManufacturingPage10_t *config_page)
582 {
583 	Mpi2ConfigRequest_t mpi_request;
584 	int r;
585 
586 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
587 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
588 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
589 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
590 	mpi_request.Header.PageNumber = 10;
591 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
592 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
593 	r = _config_request(ioc, &mpi_request, mpi_reply,
594 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
595 	if (r)
596 		goto out;
597 
598 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
599 	r = _config_request(ioc, &mpi_request, mpi_reply,
600 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
601 	    sizeof(*config_page));
602  out:
603 	return r;
604 }
605 
606 /**
607  * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
608  * @ioc: per adapter object
609  * @mpi_reply: reply mf payload returned from firmware
610  * @config_page: contents of the config page
611  * Context: sleep.
612  *
613  * Return: 0 for success, non-zero for failure.
614  */
615 int
616 mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
617 	Mpi2ConfigReply_t *mpi_reply,
618 	struct Mpi2ManufacturingPage11_t *config_page)
619 {
620 	Mpi2ConfigRequest_t mpi_request;
621 	int r;
622 
623 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
624 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
625 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
626 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
627 	mpi_request.Header.PageNumber = 11;
628 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
629 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
630 	r = _config_request(ioc, &mpi_request, mpi_reply,
631 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
632 	if (r)
633 		goto out;
634 
635 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
636 	r = _config_request(ioc, &mpi_request, mpi_reply,
637 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
638 	    sizeof(*config_page));
639  out:
640 	return r;
641 }
642 
643 /**
644  * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
645  * @ioc: per adapter object
646  * @mpi_reply: reply mf payload returned from firmware
647  * @config_page: contents of the config page
648  * Context: sleep.
649  *
650  * Return: 0 for success, non-zero for failure.
651  */
652 int
653 mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
654 	Mpi2ConfigReply_t *mpi_reply,
655 	struct Mpi2ManufacturingPage11_t *config_page)
656 {
657 	Mpi2ConfigRequest_t mpi_request;
658 	int r;
659 
660 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
661 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
662 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
663 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
664 	mpi_request.Header.PageNumber = 11;
665 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
666 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
667 	r = _config_request(ioc, &mpi_request, mpi_reply,
668 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
669 	if (r)
670 		goto out;
671 
672 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
673 	r = _config_request(ioc, &mpi_request, mpi_reply,
674 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
675 	    sizeof(*config_page));
676  out:
677 	return r;
678 }
679 
680 /**
681  * mpt3sas_config_get_bios_pg2 - obtain bios page 2
682  * @ioc: per adapter object
683  * @mpi_reply: reply mf payload returned from firmware
684  * @config_page: contents of the config page
685  * Context: sleep.
686  *
687  * Return: 0 for success, non-zero for failure.
688  */
689 int
690 mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
691 	Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
692 {
693 	Mpi2ConfigRequest_t mpi_request;
694 	int r;
695 
696 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
697 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
698 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
699 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
700 	mpi_request.Header.PageNumber = 2;
701 	mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
702 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
703 	r = _config_request(ioc, &mpi_request, mpi_reply,
704 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
705 	if (r)
706 		goto out;
707 
708 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
709 	r = _config_request(ioc, &mpi_request, mpi_reply,
710 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
711 	    sizeof(*config_page));
712  out:
713 	return r;
714 }
715 
716 /**
717  * mpt3sas_config_get_bios_pg3 - obtain bios page 3
718  * @ioc: per adapter object
719  * @mpi_reply: reply mf payload returned from firmware
720  * @config_page: contents of the config page
721  * Context: sleep.
722  *
723  * Return: 0 for success, non-zero for failure.
724  */
725 int
726 mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
727 	*mpi_reply, Mpi2BiosPage3_t *config_page)
728 {
729 	Mpi2ConfigRequest_t mpi_request;
730 	int r;
731 
732 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
733 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
734 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
735 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
736 	mpi_request.Header.PageNumber = 3;
737 	mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
738 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
739 	r = _config_request(ioc, &mpi_request, mpi_reply,
740 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
741 	if (r)
742 		goto out;
743 
744 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
745 	r = _config_request(ioc, &mpi_request, mpi_reply,
746 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
747 	    sizeof(*config_page));
748  out:
749 	return r;
750 }
751 
752 /**
753  * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
754  * @ioc: per adapter object
755  * @mpi_reply: reply mf payload returned from firmware
756  * @config_page: contents of the config page
757  * Context: sleep.
758  *
759  * Return: 0 for success, non-zero for failure.
760  */
761 int
762 mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
763 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
764 {
765 	Mpi2ConfigRequest_t mpi_request;
766 	int r;
767 
768 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
769 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
770 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
771 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
772 	mpi_request.Header.PageNumber = 0;
773 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
774 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
775 	r = _config_request(ioc, &mpi_request, mpi_reply,
776 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
777 	if (r)
778 		goto out;
779 
780 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
781 	r = _config_request(ioc, &mpi_request, mpi_reply,
782 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
783 	    sizeof(*config_page));
784  out:
785 	return r;
786 }
787 
788 /**
789  * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
790  * @ioc: per adapter object
791  * @mpi_reply: reply mf payload returned from firmware
792  * @config_page: contents of the config page
793  * Context: sleep.
794  *
795  * Return: 0 for success, non-zero for failure.
796  */
797 int
798 mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
799 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
800 {
801 	Mpi2ConfigRequest_t mpi_request;
802 	int r;
803 
804 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
805 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
806 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
807 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
808 	mpi_request.Header.PageNumber = 1;
809 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
810 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
811 	r = _config_request(ioc, &mpi_request, mpi_reply,
812 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
813 	if (r)
814 		goto out;
815 
816 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
817 	r = _config_request(ioc, &mpi_request, mpi_reply,
818 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
819 	    sizeof(*config_page));
820  out:
821 	return r;
822 }
823 
824 /**
825  * mpt3sas_config_set_iounit_pg1 - set iounit page 1
826  * @ioc: per adapter object
827  * @mpi_reply: reply mf payload returned from firmware
828  * @config_page: contents of the config page
829  * Context: sleep.
830  *
831  * Return: 0 for success, non-zero for failure.
832  */
833 int
834 mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
835 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
836 {
837 	Mpi2ConfigRequest_t mpi_request;
838 	int r;
839 
840 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
841 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
842 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
843 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
844 	mpi_request.Header.PageNumber = 1;
845 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
846 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
847 	r = _config_request(ioc, &mpi_request, mpi_reply,
848 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
849 	if (r)
850 		goto out;
851 
852 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
853 	r = _config_request(ioc, &mpi_request, mpi_reply,
854 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
855 	    sizeof(*config_page));
856  out:
857 	return r;
858 }
859 
860 /**
861  * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
862  * @ioc: per adapter object
863  * @mpi_reply: reply mf payload returned from firmware
864  * @config_page: contents of the config page
865  * @sz: size of buffer passed in config_page
866  * Context: sleep.
867  *
868  * Return: 0 for success, non-zero for failure.
869  */
870 int
871 mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
872 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
873 {
874 	Mpi2ConfigRequest_t mpi_request;
875 	int r;
876 
877 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
878 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
879 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
880 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
881 	mpi_request.Header.PageNumber = 3;
882 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
883 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
884 	r = _config_request(ioc, &mpi_request, mpi_reply,
885 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
886 	if (r)
887 		goto out;
888 
889 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
890 	r = _config_request(ioc, &mpi_request, mpi_reply,
891 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
892  out:
893 	return r;
894 }
895 
896 /**
897  * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
898  * @ioc: per adapter object
899  * @mpi_reply: reply mf payload returned from firmware
900  * @config_page: contents of the config page
901  * Context: sleep.
902  *
903  * Return: 0 for success, non-zero for failure.
904  */
905 int
906 mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
907 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
908 {
909 	Mpi2ConfigRequest_t mpi_request;
910 	int r;
911 
912 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
913 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
914 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
915 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
916 	mpi_request.Header.PageNumber = 8;
917 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
918 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
919 	r = _config_request(ioc, &mpi_request, mpi_reply,
920 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
921 	if (r)
922 		goto out;
923 
924 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
925 	r = _config_request(ioc, &mpi_request, mpi_reply,
926 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
927 	    sizeof(*config_page));
928  out:
929 	return r;
930 }
931 
932 /**
933  * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
934  * @ioc: per adapter object
935  * @mpi_reply: reply mf payload returned from firmware
936  * @config_page: contents of the config page
937  * Context: sleep.
938  *
939  * Return: 0 for success, non-zero for failure.
940  */
941 int
942 mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
943 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
944 {
945 	Mpi2ConfigRequest_t mpi_request;
946 	int r;
947 
948 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
949 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
950 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
951 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
952 	mpi_request.Header.PageNumber = 8;
953 	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
954 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
955 	r = _config_request(ioc, &mpi_request, mpi_reply,
956 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
957 	if (r)
958 		goto out;
959 
960 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
961 	r = _config_request(ioc, &mpi_request, mpi_reply,
962 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
963 	    sizeof(*config_page));
964  out:
965 	return r;
966 }
967 /**
968  * mpt3sas_config_get_ioc_pg1 - obtain ioc page 1
969  * @ioc: per adapter object
970  * @mpi_reply: reply mf payload returned from firmware
971  * @config_page: contents of the config page
972  * Context: sleep.
973  *
974  * Return: 0 for success, non-zero for failure.
975  */
976 int
977 mpt3sas_config_get_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
978 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
979 {
980 	Mpi2ConfigRequest_t mpi_request;
981 	int r;
982 
983 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
984 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
985 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
986 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
987 	mpi_request.Header.PageNumber = 1;
988 	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
989 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
990 	r = _config_request(ioc, &mpi_request, mpi_reply,
991 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
992 	if (r)
993 		goto out;
994 
995 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
996 	r = _config_request(ioc, &mpi_request, mpi_reply,
997 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
998 	    sizeof(*config_page));
999  out:
1000 	return r;
1001 }
1002 
1003 /**
1004  * mpt3sas_config_set_ioc_pg1 - modify ioc page 1
1005  * @ioc: per adapter object
1006  * @mpi_reply: reply mf payload returned from firmware
1007  * @config_page: contents of the config page
1008  * Context: sleep.
1009  *
1010  * Return: 0 for success, non-zero for failure.
1011  */
1012 int
1013 mpt3sas_config_set_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
1014 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
1015 {
1016 	Mpi2ConfigRequest_t mpi_request;
1017 	int r;
1018 
1019 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1020 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1021 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1022 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
1023 	mpi_request.Header.PageNumber = 1;
1024 	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
1025 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1026 	r = _config_request(ioc, &mpi_request, mpi_reply,
1027 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1028 	if (r)
1029 		goto out;
1030 
1031 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1032 	r = _config_request(ioc, &mpi_request, mpi_reply,
1033 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1034 	    sizeof(*config_page));
1035  out:
1036 	return r;
1037 }
1038 
1039 /**
1040  * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
1041  * @ioc: per adapter object
1042  * @mpi_reply: reply mf payload returned from firmware
1043  * @config_page: contents of the config page
1044  * @form: GET_NEXT_HANDLE or HANDLE
1045  * @handle: device handle
1046  * Context: sleep.
1047  *
1048  * Return: 0 for success, non-zero for failure.
1049  */
1050 int
1051 mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1052 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
1053 	u32 form, u32 handle)
1054 {
1055 	Mpi2ConfigRequest_t mpi_request;
1056 	int r;
1057 
1058 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1059 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1060 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1061 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1062 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1063 	mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
1064 	mpi_request.Header.PageNumber = 0;
1065 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1066 	r = _config_request(ioc, &mpi_request, mpi_reply,
1067 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1068 	if (r)
1069 		goto out;
1070 
1071 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1072 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1073 	r = _config_request(ioc, &mpi_request, mpi_reply,
1074 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1075 	    sizeof(*config_page));
1076  out:
1077 	return r;
1078 }
1079 
1080 /**
1081  * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
1082  * @ioc: per adapter object
1083  * @mpi_reply: reply mf payload returned from firmware
1084  * @config_page: contents of the config page
1085  * @form: GET_NEXT_HANDLE or HANDLE
1086  * @handle: device handle
1087  * Context: sleep.
1088  *
1089  * Return: 0 for success, non-zero for failure.
1090  */
1091 int
1092 mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1093 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1094 	u32 form, u32 handle)
1095 {
1096 	Mpi2ConfigRequest_t mpi_request;
1097 	int r;
1098 
1099 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1100 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1101 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1102 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1103 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1104 	mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1105 	mpi_request.Header.PageNumber = 1;
1106 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1107 	r = _config_request(ioc, &mpi_request, mpi_reply,
1108 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1109 	if (r)
1110 		goto out;
1111 
1112 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1113 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1114 	r = _config_request(ioc, &mpi_request, mpi_reply,
1115 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1116 	    sizeof(*config_page));
1117  out:
1118 	return r;
1119 }
1120 
1121 /**
1122  * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
1123  * @ioc: per adapter object
1124  * @mpi_reply: reply mf payload returned from firmware
1125  * @config_page: contents of the config page
1126  * @form: GET_NEXT_HANDLE or HANDLE
1127  * @handle: device handle
1128  * Context: sleep.
1129  *
1130  * Return: 0 for success, non-zero for failure.
1131  */
1132 int
1133 mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1134 	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
1135 	u32 form, u32 handle)
1136 {
1137 	Mpi2ConfigRequest_t mpi_request;
1138 	int r;
1139 
1140 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1141 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1142 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1143 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1144 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1145 	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
1146 	mpi_request.Header.PageNumber = 0;
1147 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1148 	r = _config_request(ioc, &mpi_request, mpi_reply,
1149 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1150 	if (r)
1151 		goto out;
1152 
1153 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1154 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1155 	r = _config_request(ioc, &mpi_request, mpi_reply,
1156 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1157 			sizeof(*config_page));
1158 out:
1159 	return r;
1160 }
1161 
1162 /**
1163  * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
1164  * @ioc: per adapter object
1165  * @mpi_reply: reply mf payload returned from firmware
1166  * @config_page: contents of the config page
1167  * @form: GET_NEXT_HANDLE or HANDLE
1168  * @handle: device handle
1169  * Context: sleep.
1170  *
1171  * Return: 0 for success, non-zero for failure.
1172  */
1173 int
1174 mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
1175 	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
1176 	u32 form, u32 handle)
1177 {
1178 	Mpi2ConfigRequest_t mpi_request;
1179 	int r;
1180 
1181 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1182 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1183 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1184 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1185 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1186 	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
1187 	mpi_request.Header.PageNumber = 2;
1188 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1189 	r = _config_request(ioc, &mpi_request, mpi_reply,
1190 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1191 	if (r)
1192 		goto out;
1193 
1194 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1195 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1196 	r = _config_request(ioc, &mpi_request, mpi_reply,
1197 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1198 			sizeof(*config_page));
1199 out:
1200 	return r;
1201 }
1202 
1203 /**
1204  * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1205  * @ioc: per adapter object
1206  * @num_phys: pointer returned with the number of phys
1207  * Context: sleep.
1208  *
1209  * Return: 0 for success, non-zero for failure.
1210  */
1211 int
1212 mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1213 {
1214 	Mpi2ConfigRequest_t mpi_request;
1215 	int r;
1216 	u16 ioc_status;
1217 	Mpi2ConfigReply_t mpi_reply;
1218 	Mpi2SasIOUnitPage0_t config_page;
1219 
1220 	*num_phys = 0;
1221 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1222 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1223 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1224 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1225 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1226 	mpi_request.Header.PageNumber = 0;
1227 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1228 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1229 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1230 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1231 	if (r)
1232 		goto out;
1233 
1234 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1235 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1236 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1237 	    sizeof(Mpi2SasIOUnitPage0_t));
1238 	if (!r) {
1239 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1240 		    MPI2_IOCSTATUS_MASK;
1241 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1242 			*num_phys = config_page.NumPhys;
1243 	}
1244  out:
1245 	return r;
1246 }
1247 
1248 /**
1249  * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1250  * @ioc: per adapter object
1251  * @mpi_reply: reply mf payload returned from firmware
1252  * @config_page: contents of the config page
1253  * @sz: size of buffer passed in config_page
1254  * Context: sleep.
1255  *
1256  * Calling function should call config_get_number_hba_phys prior to
1257  * this function, so enough memory is allocated for config_page.
1258  *
1259  * Return: 0 for success, non-zero for failure.
1260  */
1261 int
1262 mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1263 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1264 	u16 sz)
1265 {
1266 	Mpi2ConfigRequest_t mpi_request;
1267 	int r;
1268 
1269 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1270 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1271 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1272 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1273 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1274 	mpi_request.Header.PageNumber = 0;
1275 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1276 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1277 	r = _config_request(ioc, &mpi_request, mpi_reply,
1278 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1279 	if (r)
1280 		goto out;
1281 
1282 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1283 	r = _config_request(ioc, &mpi_request, mpi_reply,
1284 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1285  out:
1286 	return r;
1287 }
1288 
1289 /**
1290  * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1291  * @ioc: per adapter object
1292  * @mpi_reply: reply mf payload returned from firmware
1293  * @config_page: contents of the config page
1294  * @sz: size of buffer passed in config_page
1295  * Context: sleep.
1296  *
1297  * Calling function should call config_get_number_hba_phys prior to
1298  * this function, so enough memory is allocated for config_page.
1299  *
1300  * Return: 0 for success, non-zero for failure.
1301  */
1302 int
1303 mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1304 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1305 	u16 sz)
1306 {
1307 	Mpi2ConfigRequest_t mpi_request;
1308 	int r;
1309 
1310 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1311 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1312 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1313 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1314 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1315 	mpi_request.Header.PageNumber = 1;
1316 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1317 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1318 	r = _config_request(ioc, &mpi_request, mpi_reply,
1319 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1320 	if (r)
1321 		goto out;
1322 
1323 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1324 	r = _config_request(ioc, &mpi_request, mpi_reply,
1325 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1326  out:
1327 	return r;
1328 }
1329 
1330 /**
1331  * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1332  * @ioc: per adapter object
1333  * @mpi_reply: reply mf payload returned from firmware
1334  * @config_page: contents of the config page
1335  * @sz: size of buffer passed in config_page
1336  * Context: sleep.
1337  *
1338  * Calling function should call config_get_number_hba_phys prior to
1339  * this function, so enough memory is allocated for config_page.
1340  *
1341  * Return: 0 for success, non-zero for failure.
1342  */
1343 int
1344 mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1345 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1346 	u16 sz)
1347 {
1348 	Mpi2ConfigRequest_t mpi_request;
1349 	int r;
1350 
1351 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1352 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1353 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1354 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1355 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1356 	mpi_request.Header.PageNumber = 1;
1357 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1358 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1359 	r = _config_request(ioc, &mpi_request, mpi_reply,
1360 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1361 	if (r)
1362 		goto out;
1363 
1364 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1365 	_config_request(ioc, &mpi_request, mpi_reply,
1366 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1367 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1368 	r = _config_request(ioc, &mpi_request, mpi_reply,
1369 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1370  out:
1371 	return r;
1372 }
1373 
1374 /**
1375  * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1376  * @ioc: per adapter object
1377  * @mpi_reply: reply mf payload returned from firmware
1378  * @config_page: contents of the config page
1379  * @form: GET_NEXT_HANDLE or HANDLE
1380  * @handle: expander handle
1381  * Context: sleep.
1382  *
1383  * Return: 0 for success, non-zero for failure.
1384  */
1385 int
1386 mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1387 	*mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1388 {
1389 	Mpi2ConfigRequest_t mpi_request;
1390 	int r;
1391 
1392 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1393 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1394 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1395 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1396 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1397 	mpi_request.Header.PageNumber = 0;
1398 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1399 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1400 	r = _config_request(ioc, &mpi_request, mpi_reply,
1401 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1402 	if (r)
1403 		goto out;
1404 
1405 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1406 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1407 	r = _config_request(ioc, &mpi_request, mpi_reply,
1408 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1409 	    sizeof(*config_page));
1410  out:
1411 	return r;
1412 }
1413 
1414 /**
1415  * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1416  * @ioc: per adapter object
1417  * @mpi_reply: reply mf payload returned from firmware
1418  * @config_page: contents of the config page
1419  * @phy_number: phy number
1420  * @handle: expander handle
1421  * Context: sleep.
1422  *
1423  * Return: 0 for success, non-zero for failure.
1424  */
1425 int
1426 mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1427 	*mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1428 	u16 handle)
1429 {
1430 	Mpi2ConfigRequest_t mpi_request;
1431 	int r;
1432 
1433 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1434 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1435 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1436 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1437 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1438 	mpi_request.Header.PageNumber = 1;
1439 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1440 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1441 	r = _config_request(ioc, &mpi_request, mpi_reply,
1442 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1443 	if (r)
1444 		goto out;
1445 
1446 	mpi_request.PageAddress =
1447 	    cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1448 	    (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1449 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1450 	r = _config_request(ioc, &mpi_request, mpi_reply,
1451 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1452 	    sizeof(*config_page));
1453  out:
1454 	return r;
1455 }
1456 
1457 /**
1458  * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1459  * @ioc: per adapter object
1460  * @mpi_reply: reply mf payload returned from firmware
1461  * @config_page: contents of the config page
1462  * @form: GET_NEXT_HANDLE or HANDLE
1463  * @handle: expander handle
1464  * Context: sleep.
1465  *
1466  * Return: 0 for success, non-zero for failure.
1467  */
1468 int
1469 mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1470 	*mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1471 {
1472 	Mpi2ConfigRequest_t mpi_request;
1473 	int r;
1474 
1475 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1476 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1477 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1478 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1479 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1480 	mpi_request.Header.PageNumber = 0;
1481 	mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1482 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1483 	r = _config_request(ioc, &mpi_request, mpi_reply,
1484 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1485 	if (r)
1486 		goto out;
1487 
1488 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1489 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1490 	r = _config_request(ioc, &mpi_request, mpi_reply,
1491 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1492 	    sizeof(*config_page));
1493  out:
1494 	return r;
1495 }
1496 
1497 /**
1498  * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1499  * @ioc: per adapter object
1500  * @mpi_reply: reply mf payload returned from firmware
1501  * @config_page: contents of the config page
1502  * @phy_number: phy number
1503  * Context: sleep.
1504  *
1505  * Return: 0 for success, non-zero for failure.
1506  */
1507 int
1508 mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1509 	*mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1510 {
1511 	Mpi2ConfigRequest_t mpi_request;
1512 	int r;
1513 
1514 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1515 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1516 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1517 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1518 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1519 	mpi_request.Header.PageNumber = 0;
1520 	mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1521 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1522 	r = _config_request(ioc, &mpi_request, mpi_reply,
1523 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1524 	if (r)
1525 		goto out;
1526 
1527 	mpi_request.PageAddress =
1528 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1529 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1530 	r = _config_request(ioc, &mpi_request, mpi_reply,
1531 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1532 	    sizeof(*config_page));
1533  out:
1534 	return r;
1535 }
1536 
1537 /**
1538  * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1539  * @ioc: per adapter object
1540  * @mpi_reply: reply mf payload returned from firmware
1541  * @config_page: contents of the config page
1542  * @phy_number: phy number
1543  * Context: sleep.
1544  *
1545  * Return: 0 for success, non-zero for failure.
1546  */
1547 int
1548 mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1549 	*mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1550 {
1551 	Mpi2ConfigRequest_t mpi_request;
1552 	int r;
1553 
1554 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1555 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1556 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1557 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1558 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1559 	mpi_request.Header.PageNumber = 1;
1560 	mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1561 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1562 	r = _config_request(ioc, &mpi_request, mpi_reply,
1563 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1564 	if (r)
1565 		goto out;
1566 
1567 	mpi_request.PageAddress =
1568 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1569 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1570 	r = _config_request(ioc, &mpi_request, mpi_reply,
1571 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1572 	    sizeof(*config_page));
1573  out:
1574 	return r;
1575 }
1576 
1577 /**
1578  * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1579  * @ioc: per adapter object
1580  * @mpi_reply: reply mf payload returned from firmware
1581  * @config_page: contents of the config page
1582  * @form: GET_NEXT_HANDLE or HANDLE
1583  * @handle: volume handle
1584  * Context: sleep.
1585  *
1586  * Return: 0 for success, non-zero for failure.
1587  */
1588 int
1589 mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1590 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1591 	u32 handle)
1592 {
1593 	Mpi2ConfigRequest_t mpi_request;
1594 	int r;
1595 
1596 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1597 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1598 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1599 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1600 	mpi_request.Header.PageNumber = 1;
1601 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1602 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1603 	r = _config_request(ioc, &mpi_request, mpi_reply,
1604 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1605 	if (r)
1606 		goto out;
1607 
1608 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1609 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1610 	r = _config_request(ioc, &mpi_request, mpi_reply,
1611 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1612 	    sizeof(*config_page));
1613  out:
1614 	return r;
1615 }
1616 
1617 /**
1618  * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1619  * @ioc: per adapter object
1620  * @handle: volume handle
1621  * @num_pds: returns pds count
1622  * Context: sleep.
1623  *
1624  * Return: 0 for success, non-zero for failure.
1625  */
1626 int
1627 mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1628 	u8 *num_pds)
1629 {
1630 	Mpi2ConfigRequest_t mpi_request;
1631 	Mpi2RaidVolPage0_t config_page;
1632 	Mpi2ConfigReply_t mpi_reply;
1633 	int r;
1634 	u16 ioc_status;
1635 
1636 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1637 	*num_pds = 0;
1638 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1639 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1640 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1641 	mpi_request.Header.PageNumber = 0;
1642 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1643 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1644 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1645 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1646 	if (r)
1647 		goto out;
1648 
1649 	mpi_request.PageAddress =
1650 	    cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1651 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1652 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1653 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1654 	    sizeof(Mpi2RaidVolPage0_t));
1655 	if (!r) {
1656 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1657 		    MPI2_IOCSTATUS_MASK;
1658 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1659 			*num_pds = config_page.NumPhysDisks;
1660 	}
1661 
1662  out:
1663 	return r;
1664 }
1665 
1666 /**
1667  * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1668  * @ioc: per adapter object
1669  * @mpi_reply: reply mf payload returned from firmware
1670  * @config_page: contents of the config page
1671  * @form: GET_NEXT_HANDLE or HANDLE
1672  * @handle: volume handle
1673  * @sz: size of buffer passed in config_page
1674  * Context: sleep.
1675  *
1676  * Return: 0 for success, non-zero for failure.
1677  */
1678 int
1679 mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1680 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1681 	u32 handle, u16 sz)
1682 {
1683 	Mpi2ConfigRequest_t mpi_request;
1684 	int r;
1685 
1686 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1687 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1688 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1689 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1690 	mpi_request.Header.PageNumber = 0;
1691 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1692 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1693 	r = _config_request(ioc, &mpi_request, mpi_reply,
1694 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1695 	if (r)
1696 		goto out;
1697 
1698 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1699 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1700 	r = _config_request(ioc, &mpi_request, mpi_reply,
1701 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1702  out:
1703 	return r;
1704 }
1705 
1706 /**
1707  * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1708  * @ioc: per adapter object
1709  * @mpi_reply: reply mf payload returned from firmware
1710  * @config_page: contents of the config page
1711  * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1712  * @form_specific: specific to the form
1713  * Context: sleep.
1714  *
1715  * Return: 0 for success, non-zero for failure.
1716  */
1717 int
1718 mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1719 	*mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1720 	u32 form_specific)
1721 {
1722 	Mpi2ConfigRequest_t mpi_request;
1723 	int r;
1724 
1725 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1726 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1727 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1728 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1729 	mpi_request.Header.PageNumber = 0;
1730 	mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1731 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1732 	r = _config_request(ioc, &mpi_request, mpi_reply,
1733 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1734 	if (r)
1735 		goto out;
1736 
1737 	mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1738 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1739 	r = _config_request(ioc, &mpi_request, mpi_reply,
1740 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1741 	    sizeof(*config_page));
1742  out:
1743 	return r;
1744 }
1745 
1746 /**
1747  * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
1748  * raid components
1749  * @ioc: per adapter object
1750  * @pd_handle: phys disk handle
1751  * @volume_handle: volume handle
1752  * Context: sleep.
1753  *
1754  * Return: 0 for success, non-zero for failure.
1755  */
1756 int
1757 mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
1758 	u16 *volume_handle)
1759 {
1760 	Mpi2RaidConfigurationPage0_t *config_page = NULL;
1761 	Mpi2ConfigRequest_t mpi_request;
1762 	Mpi2ConfigReply_t mpi_reply;
1763 	int r, i, config_page_sz;
1764 	u16 ioc_status;
1765 	int config_num;
1766 	u16 element_type;
1767 	u16 phys_disk_dev_handle;
1768 
1769 	*volume_handle = 0;
1770 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1771 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1772 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1773 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1774 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1775 	mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1776 	mpi_request.Header.PageNumber = 0;
1777 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1778 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1779 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1780 	if (r)
1781 		goto out;
1782 
1783 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1784 	config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1785 	config_page = kmalloc(config_page_sz, GFP_KERNEL);
1786 	if (!config_page) {
1787 		r = -1;
1788 		goto out;
1789 	}
1790 
1791 	config_num = 0xff;
1792 	while (1) {
1793 		mpi_request.PageAddress = cpu_to_le32(config_num +
1794 		    MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1795 		r = _config_request(ioc, &mpi_request, &mpi_reply,
1796 		    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1797 		    config_page_sz);
1798 		if (r)
1799 			goto out;
1800 		r = -1;
1801 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1802 		    MPI2_IOCSTATUS_MASK;
1803 		if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1804 			goto out;
1805 		for (i = 0; i < config_page->NumElements; i++) {
1806 			element_type = le16_to_cpu(config_page->
1807 			    ConfigElement[i].ElementFlags) &
1808 			    MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1809 			if (element_type ==
1810 			    MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1811 			    element_type ==
1812 			    MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1813 				phys_disk_dev_handle =
1814 				    le16_to_cpu(config_page->ConfigElement[i].
1815 				    PhysDiskDevHandle);
1816 				if (phys_disk_dev_handle == pd_handle) {
1817 					*volume_handle =
1818 					    le16_to_cpu(config_page->
1819 					    ConfigElement[i].VolDevHandle);
1820 					r = 0;
1821 					goto out;
1822 				}
1823 			} else if (element_type ==
1824 			    MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1825 				*volume_handle = 0;
1826 				r = 0;
1827 				goto out;
1828 			}
1829 		}
1830 		config_num = config_page->ConfigNum;
1831 	}
1832  out:
1833 	kfree(config_page);
1834 	return r;
1835 }
1836 
1837 /**
1838  * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
1839  * @ioc: per adapter object
1840  * @volume_handle: volume handle
1841  * @wwid: volume wwid
1842  * Context: sleep.
1843  *
1844  * Return: 0 for success, non-zero for failure.
1845  */
1846 int
1847 mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
1848 	u64 *wwid)
1849 {
1850 	Mpi2ConfigReply_t mpi_reply;
1851 	Mpi2RaidVolPage1_t raid_vol_pg1;
1852 
1853 	*wwid = 0;
1854 	if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1855 	    &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1856 	    volume_handle))) {
1857 		*wwid = le64_to_cpu(raid_vol_pg1.WWID);
1858 		return 0;
1859 	} else
1860 		return -1;
1861 }
1862