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