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