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