xref: /linux/drivers/scsi/mpt3sas/mpt3sas_config.c (revision c84b06a48c4d8ac8270624453132f3fa1a4a0f9d)
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 	if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
105 		return;
106 
107 	mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
108 	switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
109 	case MPI2_CONFIG_PAGETYPE_IO_UNIT:
110 		desc = "io_unit";
111 		break;
112 	case MPI2_CONFIG_PAGETYPE_IOC:
113 		desc = "ioc";
114 		break;
115 	case MPI2_CONFIG_PAGETYPE_BIOS:
116 		desc = "bios";
117 		break;
118 	case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
119 		desc = "raid_volume";
120 		break;
121 	case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
122 		desc = "manufaucturing";
123 		break;
124 	case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
125 		desc = "physdisk";
126 		break;
127 	case MPI2_CONFIG_PAGETYPE_EXTENDED:
128 		switch (mpi_request->ExtPageType) {
129 		case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
130 			desc = "sas_io_unit";
131 			break;
132 		case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
133 			desc = "sas_expander";
134 			break;
135 		case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
136 			desc = "sas_device";
137 			break;
138 		case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
139 			desc = "sas_phy";
140 			break;
141 		case MPI2_CONFIG_EXTPAGETYPE_LOG:
142 			desc = "log";
143 			break;
144 		case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
145 			desc = "enclosure";
146 			break;
147 		case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
148 			desc = "raid_config";
149 			break;
150 		case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
151 			desc = "driver_mapping";
152 			break;
153 		}
154 		break;
155 	}
156 
157 	if (!desc)
158 		return;
159 
160 	pr_info(MPT3SAS_FMT
161 		"%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n",
162 		ioc->name, calling_function_name, desc,
163 	    mpi_request->Header.PageNumber, mpi_request->Action,
164 	    le32_to_cpu(mpi_request->PageAddress), smid);
165 
166 	if (!mpi_reply)
167 		return;
168 
169 	if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
170 		pr_info(MPT3SAS_FMT
171 		    "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
172 		    ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
173 		    le32_to_cpu(mpi_reply->IOCLogInfo));
174 }
175 
176 /**
177  * _config_alloc_config_dma_memory - obtain physical memory
178  * @ioc: per adapter object
179  * @mem: struct config_request
180  *
181  * A wrapper for obtaining dma-able memory for config page request.
182  *
183  * Returns 0 for success, non-zero for failure.
184  */
185 static int
186 _config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
187 	struct config_request *mem)
188 {
189 	int r = 0;
190 
191 	if (mem->sz > ioc->config_page_sz) {
192 		mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
193 		    &mem->page_dma, GFP_KERNEL);
194 		if (!mem->page) {
195 			pr_err(MPT3SAS_FMT
196 				"%s: dma_alloc_coherent failed asking for (%d) bytes!!\n",
197 			    ioc->name, __func__, mem->sz);
198 			r = -ENOMEM;
199 		}
200 	} else { /* use tmp buffer if less than 512 bytes */
201 		mem->page = ioc->config_page;
202 		mem->page_dma = ioc->config_page_dma;
203 	}
204 	return r;
205 }
206 
207 /**
208  * _config_free_config_dma_memory - wrapper to free the memory
209  * @ioc: per adapter object
210  * @mem: struct config_request
211  *
212  * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
213  *
214  * Returns 0 for success, non-zero for failure.
215  */
216 static void
217 _config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
218 	struct config_request *mem)
219 {
220 	if (mem->sz > ioc->config_page_sz)
221 		dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
222 		    mem->page_dma);
223 }
224 
225 /**
226  * mpt3sas_config_done - config page completion routine
227  * @ioc: per adapter object
228  * @smid: system request message index
229  * @msix_index: MSIX table index supplied by the OS
230  * @reply: reply message frame(lower 32bit addr)
231  * Context: none.
232  *
233  * The callback handler when using _config_request.
234  *
235  * Return 1 meaning mf should be freed from _base_interrupt
236  *        0 means the mf is freed from this function.
237  */
238 u8
239 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
240 	u32 reply)
241 {
242 	MPI2DefaultReply_t *mpi_reply;
243 
244 	if (ioc->config_cmds.status == MPT3_CMD_NOT_USED)
245 		return 1;
246 	if (ioc->config_cmds.smid != smid)
247 		return 1;
248 	ioc->config_cmds.status |= MPT3_CMD_COMPLETE;
249 	mpi_reply =  mpt3sas_base_get_reply_virt_addr(ioc, reply);
250 	if (mpi_reply) {
251 		ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID;
252 		memcpy(ioc->config_cmds.reply, mpi_reply,
253 		    mpi_reply->MsgLength*4);
254 	}
255 	ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
256 	_config_display_some_debug(ioc, smid, "config_done", mpi_reply);
257 	ioc->config_cmds.smid = USHRT_MAX;
258 	complete(&ioc->config_cmds.done);
259 	return 1;
260 }
261 
262 /**
263  * _config_request - main routine for sending config page requests
264  * @ioc: per adapter object
265  * @mpi_request: request message frame
266  * @mpi_reply: reply mf payload returned from firmware
267  * @timeout: timeout in seconds
268  * @config_page: contents of the config page
269  * @config_page_sz: size of config page
270  * Context: sleep
271  *
272  * A generic API for config page requests to firmware.
273  *
274  * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling
275  * this API.
276  *
277  * The callback index is set inside `ioc->config_cb_idx.
278  *
279  * Returns 0 for success, non-zero for failure.
280  */
281 static int
282 _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
283 	*mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
284 	void *config_page, u16 config_page_sz)
285 {
286 	u16 smid;
287 	u32 ioc_state;
288 	unsigned long timeleft;
289 	Mpi2ConfigRequest_t *config_request;
290 	int r;
291 	u8 retry_count, issue_host_reset = 0;
292 	u16 wait_state_count;
293 	struct config_request mem;
294 	u32 ioc_status = UINT_MAX;
295 
296 	mutex_lock(&ioc->config_cmds.mutex);
297 	if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
298 		pr_err(MPT3SAS_FMT "%s: config_cmd in use\n",
299 		    ioc->name, __func__);
300 		mutex_unlock(&ioc->config_cmds.mutex);
301 		return -EAGAIN;
302 	}
303 
304 	retry_count = 0;
305 	memset(&mem, 0, sizeof(struct config_request));
306 
307 	mpi_request->VF_ID = 0; /* TODO */
308 	mpi_request->VP_ID = 0;
309 
310 	if (config_page) {
311 		mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
312 		mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
313 		mpi_request->Header.PageType = mpi_reply->Header.PageType;
314 		mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
315 		mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
316 		mpi_request->ExtPageType = mpi_reply->ExtPageType;
317 		if (mpi_request->Header.PageLength)
318 			mem.sz = mpi_request->Header.PageLength * 4;
319 		else
320 			mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
321 		r = _config_alloc_config_dma_memory(ioc, &mem);
322 		if (r != 0)
323 			goto out;
324 		if (mpi_request->Action ==
325 		    MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
326 		    mpi_request->Action ==
327 		    MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
328 			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
329 			    MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
330 			    mem.page_dma);
331 			memcpy(mem.page, config_page, min_t(u16, mem.sz,
332 			    config_page_sz));
333 		} else {
334 			memset(config_page, 0, config_page_sz);
335 			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
336 			    MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
337 			memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
338 		}
339 	}
340 
341  retry_config:
342 	if (retry_count) {
343 		if (retry_count > 2) { /* attempt only 2 retries */
344 			r = -EFAULT;
345 			goto free_mem;
346 		}
347 		pr_info(MPT3SAS_FMT "%s: attempting retry (%d)\n",
348 		    ioc->name, __func__, retry_count);
349 	}
350 	wait_state_count = 0;
351 	ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
352 	while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
353 		if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) {
354 			pr_err(MPT3SAS_FMT
355 			    "%s: failed due to ioc not operational\n",
356 			    ioc->name, __func__);
357 			ioc->config_cmds.status = MPT3_CMD_NOT_USED;
358 			r = -EFAULT;
359 			goto free_mem;
360 		}
361 		ssleep(1);
362 		ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
363 		pr_info(MPT3SAS_FMT
364 			"%s: waiting for operational state(count=%d)\n",
365 			ioc->name, __func__, wait_state_count);
366 	}
367 	if (wait_state_count)
368 		pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
369 		    ioc->name, __func__);
370 
371 	smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
372 	if (!smid) {
373 		pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
374 		    ioc->name, __func__);
375 		ioc->config_cmds.status = MPT3_CMD_NOT_USED;
376 		r = -EAGAIN;
377 		goto free_mem;
378 	}
379 
380 	r = 0;
381 	memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
382 	ioc->config_cmds.status = MPT3_CMD_PENDING;
383 	config_request = mpt3sas_base_get_msg_frame(ioc, smid);
384 	ioc->config_cmds.smid = smid;
385 	memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
386 	_config_display_some_debug(ioc, smid, "config_request", NULL);
387 	init_completion(&ioc->config_cmds.done);
388 	mpt3sas_base_put_smid_default(ioc, smid);
389 	timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
390 	    timeout*HZ);
391 	if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
392 		pr_err(MPT3SAS_FMT "%s: timeout\n",
393 		    ioc->name, __func__);
394 		_debug_dump_mf(mpi_request,
395 		    sizeof(Mpi2ConfigRequest_t)/4);
396 		retry_count++;
397 		if (ioc->config_cmds.smid == smid)
398 			mpt3sas_base_free_smid(ioc, smid);
399 		if ((ioc->shost_recovery) || (ioc->config_cmds.status &
400 		    MPT3_CMD_RESET) || ioc->pci_error_recovery)
401 			goto retry_config;
402 		issue_host_reset = 1;
403 		r = -EFAULT;
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 			_debug_dump_mf(mpi_request, ioc->request_sz/4);
415 			_debug_dump_reply(mpi_reply, ioc->request_sz/4);
416 			panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
417 			    " mpi_reply mismatch: Requested PageType(0x%02x)" \
418 			    " Reply PageType(0x%02x)\n", \
419 			    ioc->name, __func__,
420 			    (mpi_request->Header.PageType & 0xF),
421 			    (mpi_reply->Header.PageType & 0xF));
422 		}
423 
424 		if (((mpi_request->Header.PageType & 0xF) ==
425 		    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
426 		    mpi_request->ExtPageType != mpi_reply->ExtPageType) {
427 			_debug_dump_mf(mpi_request, ioc->request_sz/4);
428 			_debug_dump_reply(mpi_reply, ioc->request_sz/4);
429 			panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
430 			    " mpi_reply mismatch: Requested ExtPageType(0x%02x)"
431 			    " Reply ExtPageType(0x%02x)\n",
432 			    ioc->name, __func__, mpi_request->ExtPageType,
433 			    mpi_reply->ExtPageType);
434 		}
435 		ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
436 		    & MPI2_IOCSTATUS_MASK;
437 	}
438 
439 	if (retry_count)
440 		pr_info(MPT3SAS_FMT "%s: retry (%d) completed!!\n", \
441 		    ioc->name, __func__, retry_count);
442 
443 	if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
444 	    config_page && mpi_request->Action ==
445 	    MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
446 		u8 *p = (u8 *)mem.page;
447 
448 		/* Config Page Sanity Checks to workaround FW issues */
449 		if (p) {
450 			if ((mpi_request->Header.PageType & 0xF) !=
451 			    (p[3] & 0xF)) {
452 				_debug_dump_mf(mpi_request, ioc->request_sz/4);
453 				_debug_dump_reply(mpi_reply, ioc->request_sz/4);
454 				_debug_dump_config(p, min_t(u16, mem.sz,
455 				    config_page_sz)/4);
456 				panic(KERN_WARNING MPT3SAS_FMT
457 					"%s: Firmware BUG:" \
458 				    " config page mismatch:"
459 				    " Requested PageType(0x%02x)"
460 				    " Reply PageType(0x%02x)\n",
461 				    ioc->name, __func__,
462 				    (mpi_request->Header.PageType & 0xF),
463 				    (p[3] & 0xF));
464 			}
465 
466 			if (((mpi_request->Header.PageType & 0xF) ==
467 			    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
468 			    (mpi_request->ExtPageType != p[6])) {
469 				_debug_dump_mf(mpi_request, ioc->request_sz/4);
470 				_debug_dump_reply(mpi_reply, ioc->request_sz/4);
471 				_debug_dump_config(p, min_t(u16, mem.sz,
472 				    config_page_sz)/4);
473 				panic(KERN_WARNING MPT3SAS_FMT
474 					"%s: Firmware BUG:" \
475 				    " config page mismatch:"
476 				    " Requested ExtPageType(0x%02x)"
477 				    " Reply ExtPageType(0x%02x)\n",
478 				    ioc->name, __func__,
479 				    mpi_request->ExtPageType, p[6]);
480 			}
481 		}
482 		memcpy(config_page, mem.page, min_t(u16, mem.sz,
483 		    config_page_sz));
484 	}
485 
486  free_mem:
487 	if (config_page)
488 		_config_free_config_dma_memory(ioc, &mem);
489  out:
490 	ioc->config_cmds.status = MPT3_CMD_NOT_USED;
491 	mutex_unlock(&ioc->config_cmds.mutex);
492 
493 	if (issue_host_reset)
494 		mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
495 		    FORCE_BIG_HAMMER);
496 	return r;
497 }
498 
499 /**
500  * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
501  * @ioc: per adapter object
502  * @mpi_reply: reply mf payload returned from firmware
503  * @config_page: contents of the config page
504  * Context: sleep.
505  *
506  * Returns 0 for success, non-zero for failure.
507  */
508 int
509 mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
510 	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
511 {
512 	Mpi2ConfigRequest_t mpi_request;
513 	int r;
514 
515 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
516 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
517 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
518 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
519 	mpi_request.Header.PageNumber = 0;
520 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
521 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
522 	r = _config_request(ioc, &mpi_request, mpi_reply,
523 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
524 	if (r)
525 		goto out;
526 
527 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
528 	r = _config_request(ioc, &mpi_request, mpi_reply,
529 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
530 	    sizeof(*config_page));
531  out:
532 	return r;
533 }
534 
535 /**
536  * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
537  * @ioc: per adapter object
538  * @mpi_reply: reply mf payload returned from firmware
539  * @config_page: contents of the config page
540  * @sz: size of buffer passed in config_page
541  * Context: sleep.
542  *
543  * Returns 0 for success, non-zero for failure.
544  */
545 int
546 mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
547 	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
548 	u16 sz)
549 {
550 	Mpi2ConfigRequest_t mpi_request;
551 	int r;
552 
553 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
554 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
555 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
556 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
557 	mpi_request.Header.PageNumber = 7;
558 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
559 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
560 	r = _config_request(ioc, &mpi_request, mpi_reply,
561 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
562 	if (r)
563 		goto out;
564 
565 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
566 	r = _config_request(ioc, &mpi_request, mpi_reply,
567 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
568 	    sz);
569  out:
570 	return r;
571 }
572 
573 /**
574  * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
575  * @ioc: per adapter object
576  * @mpi_reply: reply mf payload returned from firmware
577  * @config_page: contents of the config page
578  * Context: sleep.
579  *
580  * Returns 0 for success, non-zero for failure.
581  */
582 int
583 mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
584 	Mpi2ConfigReply_t *mpi_reply,
585 	struct Mpi2ManufacturingPage10_t *config_page)
586 {
587 	Mpi2ConfigRequest_t mpi_request;
588 	int r;
589 
590 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
591 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
592 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
593 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
594 	mpi_request.Header.PageNumber = 10;
595 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
596 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
597 	r = _config_request(ioc, &mpi_request, mpi_reply,
598 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
599 	if (r)
600 		goto out;
601 
602 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
603 	r = _config_request(ioc, &mpi_request, mpi_reply,
604 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
605 	    sizeof(*config_page));
606  out:
607 	return r;
608 }
609 
610 /**
611  * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
612  * @ioc: per adapter object
613  * @mpi_reply: reply mf payload returned from firmware
614  * @config_page: contents of the config page
615  * Context: sleep.
616  *
617  * Returns 0 for success, non-zero for failure.
618  */
619 int
620 mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
621 	Mpi2ConfigReply_t *mpi_reply,
622 	struct Mpi2ManufacturingPage11_t *config_page)
623 {
624 	Mpi2ConfigRequest_t mpi_request;
625 	int r;
626 
627 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
628 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
629 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
630 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
631 	mpi_request.Header.PageNumber = 11;
632 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
633 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
634 	r = _config_request(ioc, &mpi_request, mpi_reply,
635 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
636 	if (r)
637 		goto out;
638 
639 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
640 	r = _config_request(ioc, &mpi_request, mpi_reply,
641 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
642 	    sizeof(*config_page));
643  out:
644 	return r;
645 }
646 
647 /**
648  * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
649  * @ioc: per adapter object
650  * @mpi_reply: reply mf payload returned from firmware
651  * @config_page: contents of the config page
652  * Context: sleep.
653  *
654  * Returns 0 for success, non-zero for failure.
655  */
656 int
657 mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
658 	Mpi2ConfigReply_t *mpi_reply,
659 	struct Mpi2ManufacturingPage11_t *config_page)
660 {
661 	Mpi2ConfigRequest_t mpi_request;
662 	int r;
663 
664 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
665 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
666 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
667 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
668 	mpi_request.Header.PageNumber = 11;
669 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
670 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
671 	r = _config_request(ioc, &mpi_request, mpi_reply,
672 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
673 	if (r)
674 		goto out;
675 
676 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
677 	r = _config_request(ioc, &mpi_request, mpi_reply,
678 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
679 	    sizeof(*config_page));
680 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
681 	r = _config_request(ioc, &mpi_request, mpi_reply,
682 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
683 	    sizeof(*config_page));
684  out:
685 	return r;
686 }
687 
688 /**
689  * mpt3sas_config_get_bios_pg2 - obtain bios page 2
690  * @ioc: per adapter object
691  * @mpi_reply: reply mf payload returned from firmware
692  * @config_page: contents of the config page
693  * Context: sleep.
694  *
695  * Returns 0 for success, non-zero for failure.
696  */
697 int
698 mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
699 	Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
700 {
701 	Mpi2ConfigRequest_t mpi_request;
702 	int r;
703 
704 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
705 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
706 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
707 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
708 	mpi_request.Header.PageNumber = 2;
709 	mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
710 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
711 	r = _config_request(ioc, &mpi_request, mpi_reply,
712 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
713 	if (r)
714 		goto out;
715 
716 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
717 	r = _config_request(ioc, &mpi_request, mpi_reply,
718 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
719 	    sizeof(*config_page));
720  out:
721 	return r;
722 }
723 
724 /**
725  * mpt3sas_config_get_bios_pg3 - obtain bios page 3
726  * @ioc: per adapter object
727  * @mpi_reply: reply mf payload returned from firmware
728  * @config_page: contents of the config page
729  * Context: sleep.
730  *
731  * Returns 0 for success, non-zero for failure.
732  */
733 int
734 mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
735 	*mpi_reply, Mpi2BiosPage3_t *config_page)
736 {
737 	Mpi2ConfigRequest_t mpi_request;
738 	int r;
739 
740 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
741 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
742 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
743 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
744 	mpi_request.Header.PageNumber = 3;
745 	mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
746 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
747 	r = _config_request(ioc, &mpi_request, mpi_reply,
748 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
749 	if (r)
750 		goto out;
751 
752 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
753 	r = _config_request(ioc, &mpi_request, mpi_reply,
754 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
755 	    sizeof(*config_page));
756  out:
757 	return r;
758 }
759 
760 /**
761  * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
762  * @ioc: per adapter object
763  * @mpi_reply: reply mf payload returned from firmware
764  * @config_page: contents of the config page
765  * Context: sleep.
766  *
767  * Returns 0 for success, non-zero for failure.
768  */
769 int
770 mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
771 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
772 {
773 	Mpi2ConfigRequest_t mpi_request;
774 	int r;
775 
776 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
777 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
778 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
779 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
780 	mpi_request.Header.PageNumber = 0;
781 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
782 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
783 	r = _config_request(ioc, &mpi_request, mpi_reply,
784 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
785 	if (r)
786 		goto out;
787 
788 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
789 	r = _config_request(ioc, &mpi_request, mpi_reply,
790 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
791 	    sizeof(*config_page));
792  out:
793 	return r;
794 }
795 
796 /**
797  * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
798  * @ioc: per adapter object
799  * @mpi_reply: reply mf payload returned from firmware
800  * @config_page: contents of the config page
801  * Context: sleep.
802  *
803  * Returns 0 for success, non-zero for failure.
804  */
805 int
806 mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
807 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
808 {
809 	Mpi2ConfigRequest_t mpi_request;
810 	int r;
811 
812 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
813 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
814 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
815 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
816 	mpi_request.Header.PageNumber = 1;
817 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
818 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
819 	r = _config_request(ioc, &mpi_request, mpi_reply,
820 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
821 	if (r)
822 		goto out;
823 
824 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
825 	r = _config_request(ioc, &mpi_request, mpi_reply,
826 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
827 	    sizeof(*config_page));
828  out:
829 	return r;
830 }
831 
832 /**
833  * mpt3sas_config_set_iounit_pg1 - set iounit page 1
834  * @ioc: per adapter object
835  * @mpi_reply: reply mf payload returned from firmware
836  * @config_page: contents of the config page
837  * Context: sleep.
838  *
839  * Returns 0 for success, non-zero for failure.
840  */
841 int
842 mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
843 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
844 {
845 	Mpi2ConfigRequest_t mpi_request;
846 	int r;
847 
848 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
849 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
850 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
851 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
852 	mpi_request.Header.PageNumber = 1;
853 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
854 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
855 	r = _config_request(ioc, &mpi_request, mpi_reply,
856 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
857 	if (r)
858 		goto out;
859 
860 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
861 	r = _config_request(ioc, &mpi_request, mpi_reply,
862 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
863 	    sizeof(*config_page));
864  out:
865 	return r;
866 }
867 
868 /**
869  * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
870  * @ioc: per adapter object
871  * @mpi_reply: reply mf payload returned from firmware
872  * @config_page: contents of the config page
873  * @sz: size of buffer passed in config_page
874  * Context: sleep.
875  *
876  * Returns 0 for success, non-zero for failure.
877  */
878 int
879 mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
880 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
881 {
882 	Mpi2ConfigRequest_t mpi_request;
883 	int r;
884 
885 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
886 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
887 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
888 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
889 	mpi_request.Header.PageNumber = 3;
890 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
891 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
892 	r = _config_request(ioc, &mpi_request, mpi_reply,
893 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
894 	if (r)
895 		goto out;
896 
897 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
898 	r = _config_request(ioc, &mpi_request, mpi_reply,
899 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
900  out:
901 	return r;
902 }
903 
904 /**
905  * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
906  * @ioc: per adapter object
907  * @mpi_reply: reply mf payload returned from firmware
908  * @config_page: contents of the config page
909  * Context: sleep.
910  *
911  * Returns 0 for success, non-zero for failure.
912  */
913 int
914 mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
915 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
916 {
917 	Mpi2ConfigRequest_t mpi_request;
918 	int r;
919 
920 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
921 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
922 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
923 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
924 	mpi_request.Header.PageNumber = 8;
925 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
926 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
927 	r = _config_request(ioc, &mpi_request, mpi_reply,
928 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
929 	if (r)
930 		goto out;
931 
932 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
933 	r = _config_request(ioc, &mpi_request, mpi_reply,
934 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
935 	    sizeof(*config_page));
936  out:
937 	return r;
938 }
939 
940 /**
941  * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
942  * @ioc: per adapter object
943  * @mpi_reply: reply mf payload returned from firmware
944  * @config_page: contents of the config page
945  * Context: sleep.
946  *
947  * Returns 0 for success, non-zero for failure.
948  */
949 int
950 mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
951 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
952 {
953 	Mpi2ConfigRequest_t mpi_request;
954 	int r;
955 
956 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
957 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
958 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
959 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
960 	mpi_request.Header.PageNumber = 8;
961 	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
962 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
963 	r = _config_request(ioc, &mpi_request, mpi_reply,
964 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
965 	if (r)
966 		goto out;
967 
968 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
969 	r = _config_request(ioc, &mpi_request, mpi_reply,
970 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
971 	    sizeof(*config_page));
972  out:
973 	return r;
974 }
975 
976 /**
977  * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
978  * @ioc: per adapter object
979  * @mpi_reply: reply mf payload returned from firmware
980  * @config_page: contents of the config page
981  * @form: GET_NEXT_HANDLE or HANDLE
982  * @handle: device handle
983  * Context: sleep.
984  *
985  * Returns 0 for success, non-zero for failure.
986  */
987 int
988 mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
989 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
990 	u32 form, u32 handle)
991 {
992 	Mpi2ConfigRequest_t mpi_request;
993 	int r;
994 
995 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
996 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
997 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
998 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
999 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1000 	mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
1001 	mpi_request.Header.PageNumber = 0;
1002 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1003 	r = _config_request(ioc, &mpi_request, mpi_reply,
1004 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1005 	if (r)
1006 		goto out;
1007 
1008 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1009 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1010 	r = _config_request(ioc, &mpi_request, mpi_reply,
1011 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1012 	    sizeof(*config_page));
1013  out:
1014 	return r;
1015 }
1016 
1017 /**
1018  * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
1019  * @ioc: per adapter object
1020  * @mpi_reply: reply mf payload returned from firmware
1021  * @config_page: contents of the config page
1022  * @form: GET_NEXT_HANDLE or HANDLE
1023  * @handle: device handle
1024  * Context: sleep.
1025  *
1026  * Returns 0 for success, non-zero for failure.
1027  */
1028 int
1029 mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1030 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1031 	u32 form, u32 handle)
1032 {
1033 	Mpi2ConfigRequest_t mpi_request;
1034 	int r;
1035 
1036 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1037 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1038 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1039 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1040 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1041 	mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1042 	mpi_request.Header.PageNumber = 1;
1043 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1044 	r = _config_request(ioc, &mpi_request, mpi_reply,
1045 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1046 	if (r)
1047 		goto out;
1048 
1049 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1050 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1051 	r = _config_request(ioc, &mpi_request, mpi_reply,
1052 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1053 	    sizeof(*config_page));
1054  out:
1055 	return r;
1056 }
1057 
1058 /**
1059  * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1060  * @ioc: per adapter object
1061  * @num_phys: pointer returned with the number of phys
1062  * Context: sleep.
1063  *
1064  * Returns 0 for success, non-zero for failure.
1065  */
1066 int
1067 mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1068 {
1069 	Mpi2ConfigRequest_t mpi_request;
1070 	int r;
1071 	u16 ioc_status;
1072 	Mpi2ConfigReply_t mpi_reply;
1073 	Mpi2SasIOUnitPage0_t config_page;
1074 
1075 	*num_phys = 0;
1076 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1077 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1078 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1079 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1080 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1081 	mpi_request.Header.PageNumber = 0;
1082 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1083 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1084 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1085 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1086 	if (r)
1087 		goto out;
1088 
1089 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1090 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1091 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1092 	    sizeof(Mpi2SasIOUnitPage0_t));
1093 	if (!r) {
1094 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1095 		    MPI2_IOCSTATUS_MASK;
1096 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1097 			*num_phys = config_page.NumPhys;
1098 	}
1099  out:
1100 	return r;
1101 }
1102 
1103 /**
1104  * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1105  * @ioc: per adapter object
1106  * @mpi_reply: reply mf payload returned from firmware
1107  * @config_page: contents of the config page
1108  * @sz: size of buffer passed in config_page
1109  * Context: sleep.
1110  *
1111  * Calling function should call config_get_number_hba_phys prior to
1112  * this function, so enough memory is allocated for config_page.
1113  *
1114  * Returns 0 for success, non-zero for failure.
1115  */
1116 int
1117 mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1118 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1119 	u16 sz)
1120 {
1121 	Mpi2ConfigRequest_t mpi_request;
1122 	int r;
1123 
1124 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1125 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1126 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1127 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1128 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1129 	mpi_request.Header.PageNumber = 0;
1130 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1131 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1132 	r = _config_request(ioc, &mpi_request, mpi_reply,
1133 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1134 	if (r)
1135 		goto out;
1136 
1137 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1138 	r = _config_request(ioc, &mpi_request, mpi_reply,
1139 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1140  out:
1141 	return r;
1142 }
1143 
1144 /**
1145  * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1146  * @ioc: per adapter object
1147  * @mpi_reply: reply mf payload returned from firmware
1148  * @config_page: contents of the config page
1149  * @sz: size of buffer passed in config_page
1150  * Context: sleep.
1151  *
1152  * Calling function should call config_get_number_hba_phys prior to
1153  * this function, so enough memory is allocated for config_page.
1154  *
1155  * Returns 0 for success, non-zero for failure.
1156  */
1157 int
1158 mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1159 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1160 	u16 sz)
1161 {
1162 	Mpi2ConfigRequest_t mpi_request;
1163 	int r;
1164 
1165 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1166 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1167 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1168 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1169 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1170 	mpi_request.Header.PageNumber = 1;
1171 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1172 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1173 	r = _config_request(ioc, &mpi_request, mpi_reply,
1174 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1175 	if (r)
1176 		goto out;
1177 
1178 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1179 	r = _config_request(ioc, &mpi_request, mpi_reply,
1180 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1181  out:
1182 	return r;
1183 }
1184 
1185 /**
1186  * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1187  * @ioc: per adapter object
1188  * @mpi_reply: reply mf payload returned from firmware
1189  * @config_page: contents of the config page
1190  * @sz: size of buffer passed in config_page
1191  * Context: sleep.
1192  *
1193  * Calling function should call config_get_number_hba_phys prior to
1194  * this function, so enough memory is allocated for config_page.
1195  *
1196  * Returns 0 for success, non-zero for failure.
1197  */
1198 int
1199 mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1200 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1201 	u16 sz)
1202 {
1203 	Mpi2ConfigRequest_t mpi_request;
1204 	int r;
1205 
1206 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1207 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1208 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1209 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1210 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1211 	mpi_request.Header.PageNumber = 1;
1212 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1213 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1214 	r = _config_request(ioc, &mpi_request, mpi_reply,
1215 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1216 	if (r)
1217 		goto out;
1218 
1219 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1220 	_config_request(ioc, &mpi_request, mpi_reply,
1221 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1222 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1223 	r = _config_request(ioc, &mpi_request, mpi_reply,
1224 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1225  out:
1226 	return r;
1227 }
1228 
1229 /**
1230  * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1231  * @ioc: per adapter object
1232  * @mpi_reply: reply mf payload returned from firmware
1233  * @config_page: contents of the config page
1234  * @form: GET_NEXT_HANDLE or HANDLE
1235  * @handle: expander handle
1236  * Context: sleep.
1237  *
1238  * Returns 0 for success, non-zero for failure.
1239  */
1240 int
1241 mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1242 	*mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1243 {
1244 	Mpi2ConfigRequest_t mpi_request;
1245 	int r;
1246 
1247 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1248 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1249 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1250 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1251 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1252 	mpi_request.Header.PageNumber = 0;
1253 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1254 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1255 	r = _config_request(ioc, &mpi_request, mpi_reply,
1256 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1257 	if (r)
1258 		goto out;
1259 
1260 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1261 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1262 	r = _config_request(ioc, &mpi_request, mpi_reply,
1263 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1264 	    sizeof(*config_page));
1265  out:
1266 	return r;
1267 }
1268 
1269 /**
1270  * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1271  * @ioc: per adapter object
1272  * @mpi_reply: reply mf payload returned from firmware
1273  * @config_page: contents of the config page
1274  * @phy_number: phy number
1275  * @handle: expander handle
1276  * Context: sleep.
1277  *
1278  * Returns 0 for success, non-zero for failure.
1279  */
1280 int
1281 mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1282 	*mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1283 	u16 handle)
1284 {
1285 	Mpi2ConfigRequest_t mpi_request;
1286 	int r;
1287 
1288 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1289 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1290 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1291 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1292 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1293 	mpi_request.Header.PageNumber = 1;
1294 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1295 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1296 	r = _config_request(ioc, &mpi_request, mpi_reply,
1297 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1298 	if (r)
1299 		goto out;
1300 
1301 	mpi_request.PageAddress =
1302 	    cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1303 	    (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1304 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1305 	r = _config_request(ioc, &mpi_request, mpi_reply,
1306 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1307 	    sizeof(*config_page));
1308  out:
1309 	return r;
1310 }
1311 
1312 /**
1313  * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1314  * @ioc: per adapter object
1315  * @mpi_reply: reply mf payload returned from firmware
1316  * @config_page: contents of the config page
1317  * @form: GET_NEXT_HANDLE or HANDLE
1318  * @handle: expander handle
1319  * Context: sleep.
1320  *
1321  * Returns 0 for success, non-zero for failure.
1322  */
1323 int
1324 mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1325 	*mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1326 {
1327 	Mpi2ConfigRequest_t mpi_request;
1328 	int r;
1329 
1330 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1331 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1332 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1333 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1334 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1335 	mpi_request.Header.PageNumber = 0;
1336 	mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1337 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1338 	r = _config_request(ioc, &mpi_request, mpi_reply,
1339 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1340 	if (r)
1341 		goto out;
1342 
1343 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1344 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1345 	r = _config_request(ioc, &mpi_request, mpi_reply,
1346 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1347 	    sizeof(*config_page));
1348  out:
1349 	return r;
1350 }
1351 
1352 /**
1353  * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1354  * @ioc: per adapter object
1355  * @mpi_reply: reply mf payload returned from firmware
1356  * @config_page: contents of the config page
1357  * @phy_number: phy number
1358  * Context: sleep.
1359  *
1360  * Returns 0 for success, non-zero for failure.
1361  */
1362 int
1363 mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1364 	*mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1365 {
1366 	Mpi2ConfigRequest_t mpi_request;
1367 	int r;
1368 
1369 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1370 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1371 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1372 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1373 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1374 	mpi_request.Header.PageNumber = 0;
1375 	mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1376 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1377 	r = _config_request(ioc, &mpi_request, mpi_reply,
1378 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1379 	if (r)
1380 		goto out;
1381 
1382 	mpi_request.PageAddress =
1383 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1384 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1385 	r = _config_request(ioc, &mpi_request, mpi_reply,
1386 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1387 	    sizeof(*config_page));
1388  out:
1389 	return r;
1390 }
1391 
1392 /**
1393  * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1394  * @ioc: per adapter object
1395  * @mpi_reply: reply mf payload returned from firmware
1396  * @config_page: contents of the config page
1397  * @phy_number: phy number
1398  * Context: sleep.
1399  *
1400  * Returns 0 for success, non-zero for failure.
1401  */
1402 int
1403 mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1404 	*mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1405 {
1406 	Mpi2ConfigRequest_t mpi_request;
1407 	int r;
1408 
1409 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1410 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1411 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1412 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1413 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1414 	mpi_request.Header.PageNumber = 1;
1415 	mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1416 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1417 	r = _config_request(ioc, &mpi_request, mpi_reply,
1418 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1419 	if (r)
1420 		goto out;
1421 
1422 	mpi_request.PageAddress =
1423 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1424 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1425 	r = _config_request(ioc, &mpi_request, mpi_reply,
1426 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1427 	    sizeof(*config_page));
1428  out:
1429 	return r;
1430 }
1431 
1432 /**
1433  * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1434  * @ioc: per adapter object
1435  * @mpi_reply: reply mf payload returned from firmware
1436  * @config_page: contents of the config page
1437  * @form: GET_NEXT_HANDLE or HANDLE
1438  * @handle: volume handle
1439  * Context: sleep.
1440  *
1441  * Returns 0 for success, non-zero for failure.
1442  */
1443 int
1444 mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1445 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1446 	u32 handle)
1447 {
1448 	Mpi2ConfigRequest_t mpi_request;
1449 	int r;
1450 
1451 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1452 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1453 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1454 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1455 	mpi_request.Header.PageNumber = 1;
1456 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1457 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1458 	r = _config_request(ioc, &mpi_request, mpi_reply,
1459 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1460 	if (r)
1461 		goto out;
1462 
1463 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1464 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1465 	r = _config_request(ioc, &mpi_request, mpi_reply,
1466 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1467 	    sizeof(*config_page));
1468  out:
1469 	return r;
1470 }
1471 
1472 /**
1473  * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1474  * @ioc: per adapter object
1475  * @handle: volume handle
1476  * @num_pds: returns pds count
1477  * Context: sleep.
1478  *
1479  * Returns 0 for success, non-zero for failure.
1480  */
1481 int
1482 mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1483 	u8 *num_pds)
1484 {
1485 	Mpi2ConfigRequest_t mpi_request;
1486 	Mpi2RaidVolPage0_t config_page;
1487 	Mpi2ConfigReply_t mpi_reply;
1488 	int r;
1489 	u16 ioc_status;
1490 
1491 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1492 	*num_pds = 0;
1493 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1494 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1495 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1496 	mpi_request.Header.PageNumber = 0;
1497 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1498 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1499 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1500 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1501 	if (r)
1502 		goto out;
1503 
1504 	mpi_request.PageAddress =
1505 	    cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1506 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1507 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1508 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1509 	    sizeof(Mpi2RaidVolPage0_t));
1510 	if (!r) {
1511 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1512 		    MPI2_IOCSTATUS_MASK;
1513 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1514 			*num_pds = config_page.NumPhysDisks;
1515 	}
1516 
1517  out:
1518 	return r;
1519 }
1520 
1521 /**
1522  * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1523  * @ioc: per adapter object
1524  * @mpi_reply: reply mf payload returned from firmware
1525  * @config_page: contents of the config page
1526  * @form: GET_NEXT_HANDLE or HANDLE
1527  * @handle: volume handle
1528  * @sz: size of buffer passed in config_page
1529  * Context: sleep.
1530  *
1531  * Returns 0 for success, non-zero for failure.
1532  */
1533 int
1534 mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1535 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1536 	u32 handle, u16 sz)
1537 {
1538 	Mpi2ConfigRequest_t mpi_request;
1539 	int r;
1540 
1541 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1542 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1543 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1544 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1545 	mpi_request.Header.PageNumber = 0;
1546 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1547 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1548 	r = _config_request(ioc, &mpi_request, mpi_reply,
1549 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1550 	if (r)
1551 		goto out;
1552 
1553 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1554 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1555 	r = _config_request(ioc, &mpi_request, mpi_reply,
1556 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1557  out:
1558 	return r;
1559 }
1560 
1561 /**
1562  * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1563  * @ioc: per adapter object
1564  * @mpi_reply: reply mf payload returned from firmware
1565  * @config_page: contents of the config page
1566  * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1567  * @form_specific: specific to the form
1568  * Context: sleep.
1569  *
1570  * Returns 0 for success, non-zero for failure.
1571  */
1572 int
1573 mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1574 	*mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1575 	u32 form_specific)
1576 {
1577 	Mpi2ConfigRequest_t mpi_request;
1578 	int r;
1579 
1580 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1581 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1582 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1583 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1584 	mpi_request.Header.PageNumber = 0;
1585 	mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1586 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1587 	r = _config_request(ioc, &mpi_request, mpi_reply,
1588 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1589 	if (r)
1590 		goto out;
1591 
1592 	mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1593 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1594 	r = _config_request(ioc, &mpi_request, mpi_reply,
1595 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1596 	    sizeof(*config_page));
1597  out:
1598 	return r;
1599 }
1600 
1601 /**
1602  * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
1603  * raid components
1604  * @ioc: per adapter object
1605  * @pd_handle: phys disk handle
1606  * @volume_handle: volume handle
1607  * Context: sleep.
1608  *
1609  * Returns 0 for success, non-zero for failure.
1610  */
1611 int
1612 mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
1613 	u16 *volume_handle)
1614 {
1615 	Mpi2RaidConfigurationPage0_t *config_page = NULL;
1616 	Mpi2ConfigRequest_t mpi_request;
1617 	Mpi2ConfigReply_t mpi_reply;
1618 	int r, i, config_page_sz;
1619 	u16 ioc_status;
1620 	int config_num;
1621 	u16 element_type;
1622 	u16 phys_disk_dev_handle;
1623 
1624 	*volume_handle = 0;
1625 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1626 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1627 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1628 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1629 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1630 	mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1631 	mpi_request.Header.PageNumber = 0;
1632 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1633 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1634 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1635 	if (r)
1636 		goto out;
1637 
1638 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1639 	config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1640 	config_page = kmalloc(config_page_sz, GFP_KERNEL);
1641 	if (!config_page) {
1642 		r = -1;
1643 		goto out;
1644 	}
1645 
1646 	config_num = 0xff;
1647 	while (1) {
1648 		mpi_request.PageAddress = cpu_to_le32(config_num +
1649 		    MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1650 		r = _config_request(ioc, &mpi_request, &mpi_reply,
1651 		    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1652 		    config_page_sz);
1653 		if (r)
1654 			goto out;
1655 		r = -1;
1656 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1657 		    MPI2_IOCSTATUS_MASK;
1658 		if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1659 			goto out;
1660 		for (i = 0; i < config_page->NumElements; i++) {
1661 			element_type = le16_to_cpu(config_page->
1662 			    ConfigElement[i].ElementFlags) &
1663 			    MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1664 			if (element_type ==
1665 			    MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1666 			    element_type ==
1667 			    MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1668 				phys_disk_dev_handle =
1669 				    le16_to_cpu(config_page->ConfigElement[i].
1670 				    PhysDiskDevHandle);
1671 				if (phys_disk_dev_handle == pd_handle) {
1672 					*volume_handle =
1673 					    le16_to_cpu(config_page->
1674 					    ConfigElement[i].VolDevHandle);
1675 					r = 0;
1676 					goto out;
1677 				}
1678 			} else if (element_type ==
1679 			    MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1680 				*volume_handle = 0;
1681 				r = 0;
1682 				goto out;
1683 			}
1684 		}
1685 		config_num = config_page->ConfigNum;
1686 	}
1687  out:
1688 	kfree(config_page);
1689 	return r;
1690 }
1691 
1692 /**
1693  * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
1694  * @ioc: per adapter object
1695  * @volume_handle: volume handle
1696  * @wwid: volume wwid
1697  * Context: sleep.
1698  *
1699  * Returns 0 for success, non-zero for failure.
1700  */
1701 int
1702 mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
1703 	u64 *wwid)
1704 {
1705 	Mpi2ConfigReply_t mpi_reply;
1706 	Mpi2RaidVolPage1_t raid_vol_pg1;
1707 
1708 	*wwid = 0;
1709 	if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1710 	    &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1711 	    volume_handle))) {
1712 		*wwid = le64_to_cpu(raid_vol_pg1.WWID);
1713 		return 0;
1714 	} else
1715 		return -1;
1716 }
1717