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 	mpt3sas_base_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 /**
954  * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
955  * @ioc: per adapter object
956  * @mpi_reply: reply mf payload returned from firmware
957  * @config_page: contents of the config page
958  * @form: GET_NEXT_HANDLE or HANDLE
959  * @handle: device handle
960  * Context: sleep.
961  *
962  * Return: 0 for success, non-zero for failure.
963  */
964 int
965 mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
966 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
967 	u32 form, u32 handle)
968 {
969 	Mpi2ConfigRequest_t mpi_request;
970 	int r;
971 
972 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
973 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
974 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
975 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
976 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
977 	mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
978 	mpi_request.Header.PageNumber = 0;
979 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
980 	r = _config_request(ioc, &mpi_request, mpi_reply,
981 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
982 	if (r)
983 		goto out;
984 
985 	mpi_request.PageAddress = cpu_to_le32(form | handle);
986 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
987 	r = _config_request(ioc, &mpi_request, mpi_reply,
988 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
989 	    sizeof(*config_page));
990  out:
991 	return r;
992 }
993 
994 /**
995  * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
996  * @ioc: per adapter object
997  * @mpi_reply: reply mf payload returned from firmware
998  * @config_page: contents of the config page
999  * @form: GET_NEXT_HANDLE or HANDLE
1000  * @handle: device handle
1001  * Context: sleep.
1002  *
1003  * Return: 0 for success, non-zero for failure.
1004  */
1005 int
1006 mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1007 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1008 	u32 form, u32 handle)
1009 {
1010 	Mpi2ConfigRequest_t mpi_request;
1011 	int r;
1012 
1013 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1014 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1015 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1016 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1017 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1018 	mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1019 	mpi_request.Header.PageNumber = 1;
1020 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1021 	r = _config_request(ioc, &mpi_request, mpi_reply,
1022 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1023 	if (r)
1024 		goto out;
1025 
1026 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1027 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1028 	r = _config_request(ioc, &mpi_request, mpi_reply,
1029 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1030 	    sizeof(*config_page));
1031  out:
1032 	return r;
1033 }
1034 
1035 /**
1036  * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
1037  * @ioc: per adapter object
1038  * @mpi_reply: reply mf payload returned from firmware
1039  * @config_page: contents of the config page
1040  * @form: GET_NEXT_HANDLE or HANDLE
1041  * @handle: device handle
1042  * Context: sleep.
1043  *
1044  * Return: 0 for success, non-zero for failure.
1045  */
1046 int
1047 mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1048 	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
1049 	u32 form, u32 handle)
1050 {
1051 	Mpi2ConfigRequest_t mpi_request;
1052 	int r;
1053 
1054 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1055 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1056 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1057 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1058 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1059 	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
1060 	mpi_request.Header.PageNumber = 0;
1061 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1062 	r = _config_request(ioc, &mpi_request, mpi_reply,
1063 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1064 	if (r)
1065 		goto out;
1066 
1067 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1068 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1069 	r = _config_request(ioc, &mpi_request, mpi_reply,
1070 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1071 			sizeof(*config_page));
1072 out:
1073 	return r;
1074 }
1075 
1076 /**
1077  * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
1078  * @ioc: per adapter object
1079  * @mpi_reply: reply mf payload returned from firmware
1080  * @config_page: contents of the config page
1081  * @form: GET_NEXT_HANDLE or HANDLE
1082  * @handle: device handle
1083  * Context: sleep.
1084  *
1085  * Return: 0 for success, non-zero for failure.
1086  */
1087 int
1088 mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
1089 	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
1090 	u32 form, u32 handle)
1091 {
1092 	Mpi2ConfigRequest_t mpi_request;
1093 	int r;
1094 
1095 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1096 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1097 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1098 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1099 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1100 	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
1101 	mpi_request.Header.PageNumber = 2;
1102 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1103 	r = _config_request(ioc, &mpi_request, mpi_reply,
1104 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1105 	if (r)
1106 		goto out;
1107 
1108 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1109 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1110 	r = _config_request(ioc, &mpi_request, mpi_reply,
1111 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1112 			sizeof(*config_page));
1113 out:
1114 	return r;
1115 }
1116 
1117 /**
1118  * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1119  * @ioc: per adapter object
1120  * @num_phys: pointer returned with the number of phys
1121  * Context: sleep.
1122  *
1123  * Return: 0 for success, non-zero for failure.
1124  */
1125 int
1126 mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1127 {
1128 	Mpi2ConfigRequest_t mpi_request;
1129 	int r;
1130 	u16 ioc_status;
1131 	Mpi2ConfigReply_t mpi_reply;
1132 	Mpi2SasIOUnitPage0_t config_page;
1133 
1134 	*num_phys = 0;
1135 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1136 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1137 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1138 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1139 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1140 	mpi_request.Header.PageNumber = 0;
1141 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1142 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1143 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1144 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1145 	if (r)
1146 		goto out;
1147 
1148 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1149 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1150 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1151 	    sizeof(Mpi2SasIOUnitPage0_t));
1152 	if (!r) {
1153 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1154 		    MPI2_IOCSTATUS_MASK;
1155 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1156 			*num_phys = config_page.NumPhys;
1157 	}
1158  out:
1159 	return r;
1160 }
1161 
1162 /**
1163  * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1164  * @ioc: per adapter object
1165  * @mpi_reply: reply mf payload returned from firmware
1166  * @config_page: contents of the config page
1167  * @sz: size of buffer passed in config_page
1168  * Context: sleep.
1169  *
1170  * Calling function should call config_get_number_hba_phys prior to
1171  * this function, so enough memory is allocated for config_page.
1172  *
1173  * Return: 0 for success, non-zero for failure.
1174  */
1175 int
1176 mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1177 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1178 	u16 sz)
1179 {
1180 	Mpi2ConfigRequest_t mpi_request;
1181 	int r;
1182 
1183 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1184 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1185 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1186 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1187 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1188 	mpi_request.Header.PageNumber = 0;
1189 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1190 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1191 	r = _config_request(ioc, &mpi_request, mpi_reply,
1192 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1193 	if (r)
1194 		goto out;
1195 
1196 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1197 	r = _config_request(ioc, &mpi_request, mpi_reply,
1198 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1199  out:
1200 	return r;
1201 }
1202 
1203 /**
1204  * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1205  * @ioc: per adapter object
1206  * @mpi_reply: reply mf payload returned from firmware
1207  * @config_page: contents of the config page
1208  * @sz: size of buffer passed in config_page
1209  * Context: sleep.
1210  *
1211  * Calling function should call config_get_number_hba_phys prior to
1212  * this function, so enough memory is allocated for config_page.
1213  *
1214  * Return: 0 for success, non-zero for failure.
1215  */
1216 int
1217 mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1218 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1219 	u16 sz)
1220 {
1221 	Mpi2ConfigRequest_t mpi_request;
1222 	int r;
1223 
1224 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1225 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1226 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1227 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1228 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1229 	mpi_request.Header.PageNumber = 1;
1230 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1231 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1232 	r = _config_request(ioc, &mpi_request, mpi_reply,
1233 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1234 	if (r)
1235 		goto out;
1236 
1237 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1238 	r = _config_request(ioc, &mpi_request, mpi_reply,
1239 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1240  out:
1241 	return r;
1242 }
1243 
1244 /**
1245  * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1246  * @ioc: per adapter object
1247  * @mpi_reply: reply mf payload returned from firmware
1248  * @config_page: contents of the config page
1249  * @sz: size of buffer passed in config_page
1250  * Context: sleep.
1251  *
1252  * Calling function should call config_get_number_hba_phys prior to
1253  * this function, so enough memory is allocated for config_page.
1254  *
1255  * Return: 0 for success, non-zero for failure.
1256  */
1257 int
1258 mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1259 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1260 	u16 sz)
1261 {
1262 	Mpi2ConfigRequest_t mpi_request;
1263 	int r;
1264 
1265 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1266 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1267 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1268 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1269 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1270 	mpi_request.Header.PageNumber = 1;
1271 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1272 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1273 	r = _config_request(ioc, &mpi_request, mpi_reply,
1274 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1275 	if (r)
1276 		goto out;
1277 
1278 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1279 	_config_request(ioc, &mpi_request, mpi_reply,
1280 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1281 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1282 	r = _config_request(ioc, &mpi_request, mpi_reply,
1283 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1284  out:
1285 	return r;
1286 }
1287 
1288 /**
1289  * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1290  * @ioc: per adapter object
1291  * @mpi_reply: reply mf payload returned from firmware
1292  * @config_page: contents of the config page
1293  * @form: GET_NEXT_HANDLE or HANDLE
1294  * @handle: expander handle
1295  * Context: sleep.
1296  *
1297  * Return: 0 for success, non-zero for failure.
1298  */
1299 int
1300 mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1301 	*mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1302 {
1303 	Mpi2ConfigRequest_t mpi_request;
1304 	int r;
1305 
1306 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1307 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1308 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1309 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1310 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1311 	mpi_request.Header.PageNumber = 0;
1312 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1313 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1314 	r = _config_request(ioc, &mpi_request, mpi_reply,
1315 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1316 	if (r)
1317 		goto out;
1318 
1319 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1320 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1321 	r = _config_request(ioc, &mpi_request, mpi_reply,
1322 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1323 	    sizeof(*config_page));
1324  out:
1325 	return r;
1326 }
1327 
1328 /**
1329  * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1330  * @ioc: per adapter object
1331  * @mpi_reply: reply mf payload returned from firmware
1332  * @config_page: contents of the config page
1333  * @phy_number: phy number
1334  * @handle: expander handle
1335  * Context: sleep.
1336  *
1337  * Return: 0 for success, non-zero for failure.
1338  */
1339 int
1340 mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1341 	*mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1342 	u16 handle)
1343 {
1344 	Mpi2ConfigRequest_t mpi_request;
1345 	int r;
1346 
1347 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1348 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1349 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1350 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1351 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1352 	mpi_request.Header.PageNumber = 1;
1353 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1354 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1355 	r = _config_request(ioc, &mpi_request, mpi_reply,
1356 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1357 	if (r)
1358 		goto out;
1359 
1360 	mpi_request.PageAddress =
1361 	    cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1362 	    (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1363 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1364 	r = _config_request(ioc, &mpi_request, mpi_reply,
1365 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1366 	    sizeof(*config_page));
1367  out:
1368 	return r;
1369 }
1370 
1371 /**
1372  * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1373  * @ioc: per adapter object
1374  * @mpi_reply: reply mf payload returned from firmware
1375  * @config_page: contents of the config page
1376  * @form: GET_NEXT_HANDLE or HANDLE
1377  * @handle: expander handle
1378  * Context: sleep.
1379  *
1380  * Return: 0 for success, non-zero for failure.
1381  */
1382 int
1383 mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1384 	*mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1385 {
1386 	Mpi2ConfigRequest_t mpi_request;
1387 	int r;
1388 
1389 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1390 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1391 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1392 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1393 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1394 	mpi_request.Header.PageNumber = 0;
1395 	mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1396 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1397 	r = _config_request(ioc, &mpi_request, mpi_reply,
1398 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1399 	if (r)
1400 		goto out;
1401 
1402 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1403 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1404 	r = _config_request(ioc, &mpi_request, mpi_reply,
1405 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1406 	    sizeof(*config_page));
1407  out:
1408 	return r;
1409 }
1410 
1411 /**
1412  * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1413  * @ioc: per adapter object
1414  * @mpi_reply: reply mf payload returned from firmware
1415  * @config_page: contents of the config page
1416  * @phy_number: phy number
1417  * Context: sleep.
1418  *
1419  * Return: 0 for success, non-zero for failure.
1420  */
1421 int
1422 mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1423 	*mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1424 {
1425 	Mpi2ConfigRequest_t mpi_request;
1426 	int r;
1427 
1428 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1429 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1430 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1431 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1432 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1433 	mpi_request.Header.PageNumber = 0;
1434 	mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1435 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1436 	r = _config_request(ioc, &mpi_request, mpi_reply,
1437 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1438 	if (r)
1439 		goto out;
1440 
1441 	mpi_request.PageAddress =
1442 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1443 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1444 	r = _config_request(ioc, &mpi_request, mpi_reply,
1445 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1446 	    sizeof(*config_page));
1447  out:
1448 	return r;
1449 }
1450 
1451 /**
1452  * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1453  * @ioc: per adapter object
1454  * @mpi_reply: reply mf payload returned from firmware
1455  * @config_page: contents of the config page
1456  * @phy_number: phy number
1457  * Context: sleep.
1458  *
1459  * Return: 0 for success, non-zero for failure.
1460  */
1461 int
1462 mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1463 	*mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1464 {
1465 	Mpi2ConfigRequest_t mpi_request;
1466 	int r;
1467 
1468 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1469 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1470 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1471 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1472 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1473 	mpi_request.Header.PageNumber = 1;
1474 	mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1475 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1476 	r = _config_request(ioc, &mpi_request, mpi_reply,
1477 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1478 	if (r)
1479 		goto out;
1480 
1481 	mpi_request.PageAddress =
1482 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1483 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1484 	r = _config_request(ioc, &mpi_request, mpi_reply,
1485 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1486 	    sizeof(*config_page));
1487  out:
1488 	return r;
1489 }
1490 
1491 /**
1492  * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1493  * @ioc: per adapter object
1494  * @mpi_reply: reply mf payload returned from firmware
1495  * @config_page: contents of the config page
1496  * @form: GET_NEXT_HANDLE or HANDLE
1497  * @handle: volume handle
1498  * Context: sleep.
1499  *
1500  * Return: 0 for success, non-zero for failure.
1501  */
1502 int
1503 mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1504 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1505 	u32 handle)
1506 {
1507 	Mpi2ConfigRequest_t mpi_request;
1508 	int r;
1509 
1510 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1511 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1512 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1513 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1514 	mpi_request.Header.PageNumber = 1;
1515 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1516 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1517 	r = _config_request(ioc, &mpi_request, mpi_reply,
1518 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1519 	if (r)
1520 		goto out;
1521 
1522 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1523 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1524 	r = _config_request(ioc, &mpi_request, mpi_reply,
1525 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1526 	    sizeof(*config_page));
1527  out:
1528 	return r;
1529 }
1530 
1531 /**
1532  * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1533  * @ioc: per adapter object
1534  * @handle: volume handle
1535  * @num_pds: returns pds count
1536  * Context: sleep.
1537  *
1538  * Return: 0 for success, non-zero for failure.
1539  */
1540 int
1541 mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1542 	u8 *num_pds)
1543 {
1544 	Mpi2ConfigRequest_t mpi_request;
1545 	Mpi2RaidVolPage0_t config_page;
1546 	Mpi2ConfigReply_t mpi_reply;
1547 	int r;
1548 	u16 ioc_status;
1549 
1550 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1551 	*num_pds = 0;
1552 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1553 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1554 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1555 	mpi_request.Header.PageNumber = 0;
1556 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1557 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1558 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1559 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1560 	if (r)
1561 		goto out;
1562 
1563 	mpi_request.PageAddress =
1564 	    cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1565 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1566 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1567 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1568 	    sizeof(Mpi2RaidVolPage0_t));
1569 	if (!r) {
1570 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1571 		    MPI2_IOCSTATUS_MASK;
1572 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1573 			*num_pds = config_page.NumPhysDisks;
1574 	}
1575 
1576  out:
1577 	return r;
1578 }
1579 
1580 /**
1581  * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1582  * @ioc: per adapter object
1583  * @mpi_reply: reply mf payload returned from firmware
1584  * @config_page: contents of the config page
1585  * @form: GET_NEXT_HANDLE or HANDLE
1586  * @handle: volume handle
1587  * @sz: size of buffer passed in config_page
1588  * Context: sleep.
1589  *
1590  * Return: 0 for success, non-zero for failure.
1591  */
1592 int
1593 mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1594 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1595 	u32 handle, u16 sz)
1596 {
1597 	Mpi2ConfigRequest_t mpi_request;
1598 	int r;
1599 
1600 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1601 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1602 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1603 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1604 	mpi_request.Header.PageNumber = 0;
1605 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1606 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1607 	r = _config_request(ioc, &mpi_request, mpi_reply,
1608 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1609 	if (r)
1610 		goto out;
1611 
1612 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1613 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1614 	r = _config_request(ioc, &mpi_request, mpi_reply,
1615 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1616  out:
1617 	return r;
1618 }
1619 
1620 /**
1621  * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1622  * @ioc: per adapter object
1623  * @mpi_reply: reply mf payload returned from firmware
1624  * @config_page: contents of the config page
1625  * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1626  * @form_specific: specific to the form
1627  * Context: sleep.
1628  *
1629  * Return: 0 for success, non-zero for failure.
1630  */
1631 int
1632 mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1633 	*mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1634 	u32 form_specific)
1635 {
1636 	Mpi2ConfigRequest_t mpi_request;
1637 	int r;
1638 
1639 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1640 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1641 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1642 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1643 	mpi_request.Header.PageNumber = 0;
1644 	mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1645 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1646 	r = _config_request(ioc, &mpi_request, mpi_reply,
1647 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1648 	if (r)
1649 		goto out;
1650 
1651 	mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1652 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1653 	r = _config_request(ioc, &mpi_request, mpi_reply,
1654 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1655 	    sizeof(*config_page));
1656  out:
1657 	return r;
1658 }
1659 
1660 /**
1661  * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
1662  * raid components
1663  * @ioc: per adapter object
1664  * @pd_handle: phys disk handle
1665  * @volume_handle: volume handle
1666  * Context: sleep.
1667  *
1668  * Return: 0 for success, non-zero for failure.
1669  */
1670 int
1671 mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
1672 	u16 *volume_handle)
1673 {
1674 	Mpi2RaidConfigurationPage0_t *config_page = NULL;
1675 	Mpi2ConfigRequest_t mpi_request;
1676 	Mpi2ConfigReply_t mpi_reply;
1677 	int r, i, config_page_sz;
1678 	u16 ioc_status;
1679 	int config_num;
1680 	u16 element_type;
1681 	u16 phys_disk_dev_handle;
1682 
1683 	*volume_handle = 0;
1684 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1685 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1686 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1687 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1688 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1689 	mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1690 	mpi_request.Header.PageNumber = 0;
1691 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1692 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1693 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1694 	if (r)
1695 		goto out;
1696 
1697 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1698 	config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1699 	config_page = kmalloc(config_page_sz, GFP_KERNEL);
1700 	if (!config_page) {
1701 		r = -1;
1702 		goto out;
1703 	}
1704 
1705 	config_num = 0xff;
1706 	while (1) {
1707 		mpi_request.PageAddress = cpu_to_le32(config_num +
1708 		    MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1709 		r = _config_request(ioc, &mpi_request, &mpi_reply,
1710 		    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1711 		    config_page_sz);
1712 		if (r)
1713 			goto out;
1714 		r = -1;
1715 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1716 		    MPI2_IOCSTATUS_MASK;
1717 		if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1718 			goto out;
1719 		for (i = 0; i < config_page->NumElements; i++) {
1720 			element_type = le16_to_cpu(config_page->
1721 			    ConfigElement[i].ElementFlags) &
1722 			    MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1723 			if (element_type ==
1724 			    MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1725 			    element_type ==
1726 			    MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1727 				phys_disk_dev_handle =
1728 				    le16_to_cpu(config_page->ConfigElement[i].
1729 				    PhysDiskDevHandle);
1730 				if (phys_disk_dev_handle == pd_handle) {
1731 					*volume_handle =
1732 					    le16_to_cpu(config_page->
1733 					    ConfigElement[i].VolDevHandle);
1734 					r = 0;
1735 					goto out;
1736 				}
1737 			} else if (element_type ==
1738 			    MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1739 				*volume_handle = 0;
1740 				r = 0;
1741 				goto out;
1742 			}
1743 		}
1744 		config_num = config_page->ConfigNum;
1745 	}
1746  out:
1747 	kfree(config_page);
1748 	return r;
1749 }
1750 
1751 /**
1752  * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
1753  * @ioc: per adapter object
1754  * @volume_handle: volume handle
1755  * @wwid: volume wwid
1756  * Context: sleep.
1757  *
1758  * Return: 0 for success, non-zero for failure.
1759  */
1760 int
1761 mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
1762 	u64 *wwid)
1763 {
1764 	Mpi2ConfigReply_t mpi_reply;
1765 	Mpi2RaidVolPage1_t raid_vol_pg1;
1766 
1767 	*wwid = 0;
1768 	if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1769 	    &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1770 	    volume_handle))) {
1771 		*wwid = le64_to_cpu(raid_vol_pg1.WWID);
1772 		return 0;
1773 	} else
1774 		return -1;
1775 }
1776