1 /*
2  * This module provides common API for accessing firmware configuration pages
3  *
4  * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c
5  * Copyright (C) 2012-2014  LSI Corporation
6  * Copyright (C) 2013-2014 Avago Technologies
7  *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * NO WARRANTY
20  * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
21  * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
22  * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
23  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
24  * solely responsible for determining the appropriateness of using and
25  * distributing the Program and assumes all risks associated with its
26  * exercise of rights under this Agreement, including but not limited to
27  * the risks and costs of program errors, damage to or loss of data,
28  * programs or equipment, and unavailability or interruption of operations.
29 
30  * DISCLAIMER OF LIABILITY
31  * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
32  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
34  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36  * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
37  * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
38 
39  * You should have received a copy of the GNU General Public License
40  * along with this program; if not, write to the Free Software
41  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
42  * USA.
43  */
44 
45 #include <linux/module.h>
46 #include <linux/kernel.h>
47 #include <linux/init.h>
48 #include <linux/errno.h>
49 #include <linux/blkdev.h>
50 #include <linux/sched.h>
51 #include <linux/workqueue.h>
52 #include <linux/delay.h>
53 #include <linux/pci.h>
54 
55 #include "mpt3sas_base.h"
56 
57 /* local definitions */
58 
59 /* Timeout for config page request (in seconds) */
60 #define MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT 15
61 
62 /* Common sgl flags for READING a config page. */
63 #define MPT3_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
64 	MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
65 	| MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT)
66 
67 /* Common sgl flags for WRITING a config page. */
68 #define MPT3_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
69 	MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
70 	| MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \
71 	<< MPI2_SGE_FLAGS_SHIFT)
72 
73 /**
74  * struct config_request - obtain dma memory via routine
75  * @sz: size
76  * @page: virt pointer
77  * @page_dma: phys pointer
78  *
79  */
80 struct config_request {
81 	u16			sz;
82 	void			*page;
83 	dma_addr_t		page_dma;
84 };
85 
86 /**
87  * _config_display_some_debug - debug routine
88  * @ioc: per adapter object
89  * @smid: system request message index
90  * @calling_function_name: string pass from calling function
91  * @mpi_reply: reply message frame
92  * Context: none.
93  *
94  * Function for displaying debug info helpful when debugging issues
95  * in this module.
96  */
97 static void
98 _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
99 	char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
100 {
101 	Mpi2ConfigRequest_t *mpi_request;
102 	char *desc = NULL;
103 
104 	if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
105 		return;
106 
107 	mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
108 	switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
109 	case MPI2_CONFIG_PAGETYPE_IO_UNIT:
110 		desc = "io_unit";
111 		break;
112 	case MPI2_CONFIG_PAGETYPE_IOC:
113 		desc = "ioc";
114 		break;
115 	case MPI2_CONFIG_PAGETYPE_BIOS:
116 		desc = "bios";
117 		break;
118 	case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
119 		desc = "raid_volume";
120 		break;
121 	case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
122 		desc = "manufaucturing";
123 		break;
124 	case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
125 		desc = "physdisk";
126 		break;
127 	case MPI2_CONFIG_PAGETYPE_EXTENDED:
128 		switch (mpi_request->ExtPageType) {
129 		case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
130 			desc = "sas_io_unit";
131 			break;
132 		case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
133 			desc = "sas_expander";
134 			break;
135 		case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
136 			desc = "sas_device";
137 			break;
138 		case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
139 			desc = "sas_phy";
140 			break;
141 		case MPI2_CONFIG_EXTPAGETYPE_LOG:
142 			desc = "log";
143 			break;
144 		case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
145 			desc = "enclosure";
146 			break;
147 		case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
148 			desc = "raid_config";
149 			break;
150 		case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
151 			desc = "driver_mapping";
152 			break;
153 		case MPI2_CONFIG_EXTPAGETYPE_SAS_PORT:
154 			desc = "sas_port";
155 			break;
156 		case MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING:
157 			desc = "ext_manufacturing";
158 			break;
159 		case MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT:
160 			desc = "pcie_io_unit";
161 			break;
162 		case MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH:
163 			desc = "pcie_switch";
164 			break;
165 		case MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE:
166 			desc = "pcie_device";
167 			break;
168 		case MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK:
169 			desc = "pcie_link";
170 			break;
171 		}
172 		break;
173 	}
174 
175 	if (!desc)
176 		return;
177 
178 	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 	u32 ioc_state;
304 	Mpi2ConfigRequest_t *config_request;
305 	int r;
306 	u8 retry_count, issue_host_reset = 0;
307 	u16 wait_state_count;
308 	struct config_request mem;
309 	u32 ioc_status = UINT_MAX;
310 
311 	mutex_lock(&ioc->config_cmds.mutex);
312 	if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
313 		ioc_err(ioc, "%s: config_cmd in use\n", __func__);
314 		mutex_unlock(&ioc->config_cmds.mutex);
315 		return -EAGAIN;
316 	}
317 
318 	retry_count = 0;
319 	memset(&mem, 0, sizeof(struct config_request));
320 
321 	mpi_request->VF_ID = 0; /* TODO */
322 	mpi_request->VP_ID = 0;
323 
324 	if (config_page) {
325 		mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
326 		mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
327 		mpi_request->Header.PageType = mpi_reply->Header.PageType;
328 		mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
329 		mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
330 		mpi_request->ExtPageType = mpi_reply->ExtPageType;
331 		if (mpi_request->Header.PageLength)
332 			mem.sz = mpi_request->Header.PageLength * 4;
333 		else
334 			mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
335 		r = _config_alloc_config_dma_memory(ioc, &mem);
336 		if (r != 0)
337 			goto out;
338 		if (mpi_request->Action ==
339 		    MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
340 		    mpi_request->Action ==
341 		    MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
342 			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
343 			    MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
344 			    mem.page_dma);
345 			memcpy(mem.page, config_page, min_t(u16, mem.sz,
346 			    config_page_sz));
347 		} else {
348 			memset(config_page, 0, config_page_sz);
349 			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
350 			    MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
351 			memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
352 		}
353 	}
354 
355  retry_config:
356 	if (retry_count) {
357 		if (retry_count > 2) { /* attempt only 2 retries */
358 			r = -EFAULT;
359 			goto free_mem;
360 		}
361 		ioc_info(ioc, "%s: attempting retry (%d)\n",
362 			 __func__, retry_count);
363 	}
364 	wait_state_count = 0;
365 	ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
366 	while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
367 		if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) {
368 			ioc_err(ioc, "%s: failed due to ioc not operational\n",
369 				__func__);
370 			ioc->config_cmds.status = MPT3_CMD_NOT_USED;
371 			r = -EFAULT;
372 			goto free_mem;
373 		}
374 		ssleep(1);
375 		ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
376 		ioc_info(ioc, "%s: waiting for operational state(count=%d)\n",
377 			 __func__, wait_state_count);
378 	}
379 	if (wait_state_count)
380 		ioc_info(ioc, "%s: ioc is operational\n", __func__);
381 
382 	smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
383 	if (!smid) {
384 		ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
385 		ioc->config_cmds.status = MPT3_CMD_NOT_USED;
386 		r = -EAGAIN;
387 		goto free_mem;
388 	}
389 
390 	r = 0;
391 	memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
392 	ioc->config_cmds.status = MPT3_CMD_PENDING;
393 	config_request = mpt3sas_base_get_msg_frame(ioc, smid);
394 	ioc->config_cmds.smid = smid;
395 	memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
396 	_config_display_some_debug(ioc, smid, "config_request", NULL);
397 	init_completion(&ioc->config_cmds.done);
398 	mpt3sas_base_put_smid_default(ioc, smid);
399 	wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ);
400 	if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
401 		mpt3sas_base_check_cmd_timeout(ioc,
402 			ioc->config_cmds.status, mpi_request,
403 			sizeof(Mpi2ConfigRequest_t)/4);
404 		retry_count++;
405 		if (ioc->config_cmds.smid == smid)
406 			mpt3sas_base_free_smid(ioc, smid);
407 		if ((ioc->shost_recovery) || (ioc->config_cmds.status &
408 		    MPT3_CMD_RESET) || ioc->pci_error_recovery)
409 			goto retry_config;
410 		issue_host_reset = 1;
411 		r = -EFAULT;
412 		goto free_mem;
413 	}
414 
415 	if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
416 		memcpy(mpi_reply, ioc->config_cmds.reply,
417 		    sizeof(Mpi2ConfigReply_t));
418 
419 		/* Reply Frame Sanity Checks to workaround FW issues */
420 		if ((mpi_request->Header.PageType & 0xF) !=
421 		    (mpi_reply->Header.PageType & 0xF)) {
422 			_debug_dump_mf(mpi_request, ioc->request_sz/4);
423 			_debug_dump_reply(mpi_reply, ioc->request_sz/4);
424 			panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
425 			      ioc->name, __func__,
426 			      mpi_request->Header.PageType & 0xF,
427 			      mpi_reply->Header.PageType & 0xF);
428 		}
429 
430 		if (((mpi_request->Header.PageType & 0xF) ==
431 		    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
432 		    mpi_request->ExtPageType != mpi_reply->ExtPageType) {
433 			_debug_dump_mf(mpi_request, ioc->request_sz/4);
434 			_debug_dump_reply(mpi_reply, ioc->request_sz/4);
435 			panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
436 			      ioc->name, __func__,
437 			      mpi_request->ExtPageType,
438 			      mpi_reply->ExtPageType);
439 		}
440 		ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
441 		    & MPI2_IOCSTATUS_MASK;
442 	}
443 
444 	if (retry_count)
445 		ioc_info(ioc, "%s: retry (%d) completed!!\n",
446 			 __func__, retry_count);
447 
448 	if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
449 	    config_page && mpi_request->Action ==
450 	    MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
451 		u8 *p = (u8 *)mem.page;
452 
453 		/* Config Page Sanity Checks to workaround FW issues */
454 		if (p) {
455 			if ((mpi_request->Header.PageType & 0xF) !=
456 			    (p[3] & 0xF)) {
457 				_debug_dump_mf(mpi_request, ioc->request_sz/4);
458 				_debug_dump_reply(mpi_reply, ioc->request_sz/4);
459 				_debug_dump_config(p, min_t(u16, mem.sz,
460 				    config_page_sz)/4);
461 				panic("%s: %s: Firmware BUG: config page mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
462 				      ioc->name, __func__,
463 				      mpi_request->Header.PageType & 0xF,
464 				      p[3] & 0xF);
465 			}
466 
467 			if (((mpi_request->Header.PageType & 0xF) ==
468 			    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
469 			    (mpi_request->ExtPageType != p[6])) {
470 				_debug_dump_mf(mpi_request, ioc->request_sz/4);
471 				_debug_dump_reply(mpi_reply, ioc->request_sz/4);
472 				_debug_dump_config(p, min_t(u16, mem.sz,
473 				    config_page_sz)/4);
474 				panic("%s: %s: Firmware BUG: config page mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
475 				      ioc->name, __func__,
476 				      mpi_request->ExtPageType, p[6]);
477 			}
478 		}
479 		memcpy(config_page, mem.page, min_t(u16, mem.sz,
480 		    config_page_sz));
481 	}
482 
483  free_mem:
484 	if (config_page)
485 		_config_free_config_dma_memory(ioc, &mem);
486  out:
487 	ioc->config_cmds.status = MPT3_CMD_NOT_USED;
488 	mutex_unlock(&ioc->config_cmds.mutex);
489 
490 	if (issue_host_reset)
491 		mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
492 	return r;
493 }
494 
495 /**
496  * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
497  * @ioc: per adapter object
498  * @mpi_reply: reply mf payload returned from firmware
499  * @config_page: contents of the config page
500  * Context: sleep.
501  *
502  * Return: 0 for success, non-zero for failure.
503  */
504 int
505 mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
506 	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
507 {
508 	Mpi2ConfigRequest_t mpi_request;
509 	int r;
510 
511 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
512 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
513 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
514 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
515 	mpi_request.Header.PageNumber = 0;
516 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
517 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
518 	r = _config_request(ioc, &mpi_request, mpi_reply,
519 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
520 	if (r)
521 		goto out;
522 
523 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
524 	r = _config_request(ioc, &mpi_request, mpi_reply,
525 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
526 	    sizeof(*config_page));
527  out:
528 	return r;
529 }
530 
531 /**
532  * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
533  * @ioc: per adapter object
534  * @mpi_reply: reply mf payload returned from firmware
535  * @config_page: contents of the config page
536  * @sz: size of buffer passed in config_page
537  * Context: sleep.
538  *
539  * Return: 0 for success, non-zero for failure.
540  */
541 int
542 mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
543 	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
544 	u16 sz)
545 {
546 	Mpi2ConfigRequest_t mpi_request;
547 	int r;
548 
549 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
550 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
551 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
552 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
553 	mpi_request.Header.PageNumber = 7;
554 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
555 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
556 	r = _config_request(ioc, &mpi_request, mpi_reply,
557 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
558 	if (r)
559 		goto out;
560 
561 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
562 	r = _config_request(ioc, &mpi_request, mpi_reply,
563 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
564 	    sz);
565  out:
566 	return r;
567 }
568 
569 /**
570  * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
571  * @ioc: per adapter object
572  * @mpi_reply: reply mf payload returned from firmware
573  * @config_page: contents of the config page
574  * Context: sleep.
575  *
576  * Return: 0 for success, non-zero for failure.
577  */
578 int
579 mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
580 	Mpi2ConfigReply_t *mpi_reply,
581 	struct Mpi2ManufacturingPage10_t *config_page)
582 {
583 	Mpi2ConfigRequest_t mpi_request;
584 	int r;
585 
586 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
587 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
588 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
589 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
590 	mpi_request.Header.PageNumber = 10;
591 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
592 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
593 	r = _config_request(ioc, &mpi_request, mpi_reply,
594 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
595 	if (r)
596 		goto out;
597 
598 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
599 	r = _config_request(ioc, &mpi_request, mpi_reply,
600 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
601 	    sizeof(*config_page));
602  out:
603 	return r;
604 }
605 
606 /**
607  * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
608  * @ioc: per adapter object
609  * @mpi_reply: reply mf payload returned from firmware
610  * @config_page: contents of the config page
611  * Context: sleep.
612  *
613  * Return: 0 for success, non-zero for failure.
614  */
615 int
616 mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
617 	Mpi2ConfigReply_t *mpi_reply,
618 	struct Mpi2ManufacturingPage11_t *config_page)
619 {
620 	Mpi2ConfigRequest_t mpi_request;
621 	int r;
622 
623 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
624 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
625 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
626 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
627 	mpi_request.Header.PageNumber = 11;
628 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
629 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
630 	r = _config_request(ioc, &mpi_request, mpi_reply,
631 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
632 	if (r)
633 		goto out;
634 
635 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
636 	r = _config_request(ioc, &mpi_request, mpi_reply,
637 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
638 	    sizeof(*config_page));
639  out:
640 	return r;
641 }
642 
643 /**
644  * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
645  * @ioc: per adapter object
646  * @mpi_reply: reply mf payload returned from firmware
647  * @config_page: contents of the config page
648  * Context: sleep.
649  *
650  * Return: 0 for success, non-zero for failure.
651  */
652 int
653 mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
654 	Mpi2ConfigReply_t *mpi_reply,
655 	struct Mpi2ManufacturingPage11_t *config_page)
656 {
657 	Mpi2ConfigRequest_t mpi_request;
658 	int r;
659 
660 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
661 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
662 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
663 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
664 	mpi_request.Header.PageNumber = 11;
665 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
666 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
667 	r = _config_request(ioc, &mpi_request, mpi_reply,
668 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
669 	if (r)
670 		goto out;
671 
672 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
673 	r = _config_request(ioc, &mpi_request, mpi_reply,
674 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
675 	    sizeof(*config_page));
676 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
677 	r = _config_request(ioc, &mpi_request, mpi_reply,
678 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
679 	    sizeof(*config_page));
680  out:
681 	return r;
682 }
683 
684 /**
685  * mpt3sas_config_get_bios_pg2 - obtain bios page 2
686  * @ioc: per adapter object
687  * @mpi_reply: reply mf payload returned from firmware
688  * @config_page: contents of the config page
689  * Context: sleep.
690  *
691  * Return: 0 for success, non-zero for failure.
692  */
693 int
694 mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
695 	Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
696 {
697 	Mpi2ConfigRequest_t mpi_request;
698 	int r;
699 
700 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
701 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
702 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
703 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
704 	mpi_request.Header.PageNumber = 2;
705 	mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
706 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
707 	r = _config_request(ioc, &mpi_request, mpi_reply,
708 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
709 	if (r)
710 		goto out;
711 
712 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
713 	r = _config_request(ioc, &mpi_request, mpi_reply,
714 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
715 	    sizeof(*config_page));
716  out:
717 	return r;
718 }
719 
720 /**
721  * mpt3sas_config_get_bios_pg3 - obtain bios page 3
722  * @ioc: per adapter object
723  * @mpi_reply: reply mf payload returned from firmware
724  * @config_page: contents of the config page
725  * Context: sleep.
726  *
727  * Return: 0 for success, non-zero for failure.
728  */
729 int
730 mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
731 	*mpi_reply, Mpi2BiosPage3_t *config_page)
732 {
733 	Mpi2ConfigRequest_t mpi_request;
734 	int r;
735 
736 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
737 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
738 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
739 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
740 	mpi_request.Header.PageNumber = 3;
741 	mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
742 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
743 	r = _config_request(ioc, &mpi_request, mpi_reply,
744 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
745 	if (r)
746 		goto out;
747 
748 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
749 	r = _config_request(ioc, &mpi_request, mpi_reply,
750 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
751 	    sizeof(*config_page));
752  out:
753 	return r;
754 }
755 
756 /**
757  * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
758  * @ioc: per adapter object
759  * @mpi_reply: reply mf payload returned from firmware
760  * @config_page: contents of the config page
761  * Context: sleep.
762  *
763  * Return: 0 for success, non-zero for failure.
764  */
765 int
766 mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
767 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
768 {
769 	Mpi2ConfigRequest_t mpi_request;
770 	int r;
771 
772 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
773 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
774 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
775 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
776 	mpi_request.Header.PageNumber = 0;
777 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
778 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
779 	r = _config_request(ioc, &mpi_request, mpi_reply,
780 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
781 	if (r)
782 		goto out;
783 
784 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
785 	r = _config_request(ioc, &mpi_request, mpi_reply,
786 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
787 	    sizeof(*config_page));
788  out:
789 	return r;
790 }
791 
792 /**
793  * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
794  * @ioc: per adapter object
795  * @mpi_reply: reply mf payload returned from firmware
796  * @config_page: contents of the config page
797  * Context: sleep.
798  *
799  * Return: 0 for success, non-zero for failure.
800  */
801 int
802 mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
803 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
804 {
805 	Mpi2ConfigRequest_t mpi_request;
806 	int r;
807 
808 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
809 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
810 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
811 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
812 	mpi_request.Header.PageNumber = 1;
813 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
814 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
815 	r = _config_request(ioc, &mpi_request, mpi_reply,
816 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
817 	if (r)
818 		goto out;
819 
820 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
821 	r = _config_request(ioc, &mpi_request, mpi_reply,
822 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
823 	    sizeof(*config_page));
824  out:
825 	return r;
826 }
827 
828 /**
829  * mpt3sas_config_set_iounit_pg1 - set iounit page 1
830  * @ioc: per adapter object
831  * @mpi_reply: reply mf payload returned from firmware
832  * @config_page: contents of the config page
833  * Context: sleep.
834  *
835  * Return: 0 for success, non-zero for failure.
836  */
837 int
838 mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
839 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
840 {
841 	Mpi2ConfigRequest_t mpi_request;
842 	int r;
843 
844 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
845 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
846 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
847 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
848 	mpi_request.Header.PageNumber = 1;
849 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
850 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
851 	r = _config_request(ioc, &mpi_request, mpi_reply,
852 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
853 	if (r)
854 		goto out;
855 
856 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
857 	r = _config_request(ioc, &mpi_request, mpi_reply,
858 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
859 	    sizeof(*config_page));
860  out:
861 	return r;
862 }
863 
864 /**
865  * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
866  * @ioc: per adapter object
867  * @mpi_reply: reply mf payload returned from firmware
868  * @config_page: contents of the config page
869  * @sz: size of buffer passed in config_page
870  * Context: sleep.
871  *
872  * Return: 0 for success, non-zero for failure.
873  */
874 int
875 mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
876 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
877 {
878 	Mpi2ConfigRequest_t mpi_request;
879 	int r;
880 
881 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
882 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
883 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
884 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
885 	mpi_request.Header.PageNumber = 3;
886 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
887 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
888 	r = _config_request(ioc, &mpi_request, mpi_reply,
889 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
890 	if (r)
891 		goto out;
892 
893 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
894 	r = _config_request(ioc, &mpi_request, mpi_reply,
895 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
896  out:
897 	return r;
898 }
899 
900 /**
901  * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
902  * @ioc: per adapter object
903  * @mpi_reply: reply mf payload returned from firmware
904  * @config_page: contents of the config page
905  * Context: sleep.
906  *
907  * Return: 0 for success, non-zero for failure.
908  */
909 int
910 mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
911 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
912 {
913 	Mpi2ConfigRequest_t mpi_request;
914 	int r;
915 
916 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
917 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
918 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
919 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
920 	mpi_request.Header.PageNumber = 8;
921 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
922 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
923 	r = _config_request(ioc, &mpi_request, mpi_reply,
924 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
925 	if (r)
926 		goto out;
927 
928 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
929 	r = _config_request(ioc, &mpi_request, mpi_reply,
930 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
931 	    sizeof(*config_page));
932  out:
933 	return r;
934 }
935 
936 /**
937  * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
938  * @ioc: per adapter object
939  * @mpi_reply: reply mf payload returned from firmware
940  * @config_page: contents of the config page
941  * Context: sleep.
942  *
943  * Return: 0 for success, non-zero for failure.
944  */
945 int
946 mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
947 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
948 {
949 	Mpi2ConfigRequest_t mpi_request;
950 	int r;
951 
952 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
953 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
954 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
955 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
956 	mpi_request.Header.PageNumber = 8;
957 	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
958 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
959 	r = _config_request(ioc, &mpi_request, mpi_reply,
960 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
961 	if (r)
962 		goto out;
963 
964 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
965 	r = _config_request(ioc, &mpi_request, mpi_reply,
966 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
967 	    sizeof(*config_page));
968  out:
969 	return r;
970 }
971 
972 /**
973  * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
974  * @ioc: per adapter object
975  * @mpi_reply: reply mf payload returned from firmware
976  * @config_page: contents of the config page
977  * @form: GET_NEXT_HANDLE or HANDLE
978  * @handle: device handle
979  * Context: sleep.
980  *
981  * Return: 0 for success, non-zero for failure.
982  */
983 int
984 mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
985 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
986 	u32 form, u32 handle)
987 {
988 	Mpi2ConfigRequest_t mpi_request;
989 	int r;
990 
991 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
992 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
993 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
994 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
995 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
996 	mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
997 	mpi_request.Header.PageNumber = 0;
998 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
999 	r = _config_request(ioc, &mpi_request, mpi_reply,
1000 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1001 	if (r)
1002 		goto out;
1003 
1004 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1005 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1006 	r = _config_request(ioc, &mpi_request, mpi_reply,
1007 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1008 	    sizeof(*config_page));
1009  out:
1010 	return r;
1011 }
1012 
1013 /**
1014  * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
1015  * @ioc: per adapter object
1016  * @mpi_reply: reply mf payload returned from firmware
1017  * @config_page: contents of the config page
1018  * @form: GET_NEXT_HANDLE or HANDLE
1019  * @handle: device handle
1020  * Context: sleep.
1021  *
1022  * Return: 0 for success, non-zero for failure.
1023  */
1024 int
1025 mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1026 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1027 	u32 form, u32 handle)
1028 {
1029 	Mpi2ConfigRequest_t mpi_request;
1030 	int r;
1031 
1032 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1033 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1034 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1035 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1036 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1037 	mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1038 	mpi_request.Header.PageNumber = 1;
1039 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1040 	r = _config_request(ioc, &mpi_request, mpi_reply,
1041 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1042 	if (r)
1043 		goto out;
1044 
1045 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1046 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1047 	r = _config_request(ioc, &mpi_request, mpi_reply,
1048 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1049 	    sizeof(*config_page));
1050  out:
1051 	return r;
1052 }
1053 
1054 /**
1055  * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
1056  * @ioc: per adapter object
1057  * @mpi_reply: reply mf payload returned from firmware
1058  * @config_page: contents of the config page
1059  * @form: GET_NEXT_HANDLE or HANDLE
1060  * @handle: device handle
1061  * Context: sleep.
1062  *
1063  * Return: 0 for success, non-zero for failure.
1064  */
1065 int
1066 mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1067 	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
1068 	u32 form, u32 handle)
1069 {
1070 	Mpi2ConfigRequest_t mpi_request;
1071 	int r;
1072 
1073 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1074 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1075 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1076 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1077 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1078 	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
1079 	mpi_request.Header.PageNumber = 0;
1080 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1081 	r = _config_request(ioc, &mpi_request, mpi_reply,
1082 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1083 	if (r)
1084 		goto out;
1085 
1086 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1087 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1088 	r = _config_request(ioc, &mpi_request, mpi_reply,
1089 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1090 			sizeof(*config_page));
1091 out:
1092 	return r;
1093 }
1094 
1095 /**
1096  * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
1097  * @ioc: per adapter object
1098  * @mpi_reply: reply mf payload returned from firmware
1099  * @config_page: contents of the config page
1100  * @form: GET_NEXT_HANDLE or HANDLE
1101  * @handle: device handle
1102  * Context: sleep.
1103  *
1104  * Return: 0 for success, non-zero for failure.
1105  */
1106 int
1107 mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
1108 	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
1109 	u32 form, u32 handle)
1110 {
1111 	Mpi2ConfigRequest_t mpi_request;
1112 	int r;
1113 
1114 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1115 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1116 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1117 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1118 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1119 	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
1120 	mpi_request.Header.PageNumber = 2;
1121 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1122 	r = _config_request(ioc, &mpi_request, mpi_reply,
1123 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1124 	if (r)
1125 		goto out;
1126 
1127 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1128 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1129 	r = _config_request(ioc, &mpi_request, mpi_reply,
1130 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1131 			sizeof(*config_page));
1132 out:
1133 	return r;
1134 }
1135 
1136 /**
1137  * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1138  * @ioc: per adapter object
1139  * @num_phys: pointer returned with the number of phys
1140  * Context: sleep.
1141  *
1142  * Return: 0 for success, non-zero for failure.
1143  */
1144 int
1145 mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1146 {
1147 	Mpi2ConfigRequest_t mpi_request;
1148 	int r;
1149 	u16 ioc_status;
1150 	Mpi2ConfigReply_t mpi_reply;
1151 	Mpi2SasIOUnitPage0_t config_page;
1152 
1153 	*num_phys = 0;
1154 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1155 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1156 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1157 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1158 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1159 	mpi_request.Header.PageNumber = 0;
1160 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1161 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1162 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1163 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1164 	if (r)
1165 		goto out;
1166 
1167 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1168 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1169 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1170 	    sizeof(Mpi2SasIOUnitPage0_t));
1171 	if (!r) {
1172 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1173 		    MPI2_IOCSTATUS_MASK;
1174 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1175 			*num_phys = config_page.NumPhys;
1176 	}
1177  out:
1178 	return r;
1179 }
1180 
1181 /**
1182  * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1183  * @ioc: per adapter object
1184  * @mpi_reply: reply mf payload returned from firmware
1185  * @config_page: contents of the config page
1186  * @sz: size of buffer passed in config_page
1187  * Context: sleep.
1188  *
1189  * Calling function should call config_get_number_hba_phys prior to
1190  * this function, so enough memory is allocated for config_page.
1191  *
1192  * Return: 0 for success, non-zero for failure.
1193  */
1194 int
1195 mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1196 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1197 	u16 sz)
1198 {
1199 	Mpi2ConfigRequest_t mpi_request;
1200 	int r;
1201 
1202 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1203 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1204 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1205 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1206 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1207 	mpi_request.Header.PageNumber = 0;
1208 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1209 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1210 	r = _config_request(ioc, &mpi_request, mpi_reply,
1211 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1212 	if (r)
1213 		goto out;
1214 
1215 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1216 	r = _config_request(ioc, &mpi_request, mpi_reply,
1217 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1218  out:
1219 	return r;
1220 }
1221 
1222 /**
1223  * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1224  * @ioc: per adapter object
1225  * @mpi_reply: reply mf payload returned from firmware
1226  * @config_page: contents of the config page
1227  * @sz: size of buffer passed in config_page
1228  * Context: sleep.
1229  *
1230  * Calling function should call config_get_number_hba_phys prior to
1231  * this function, so enough memory is allocated for config_page.
1232  *
1233  * Return: 0 for success, non-zero for failure.
1234  */
1235 int
1236 mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1237 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1238 	u16 sz)
1239 {
1240 	Mpi2ConfigRequest_t mpi_request;
1241 	int r;
1242 
1243 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1244 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1245 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1246 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1247 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1248 	mpi_request.Header.PageNumber = 1;
1249 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1250 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1251 	r = _config_request(ioc, &mpi_request, mpi_reply,
1252 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1253 	if (r)
1254 		goto out;
1255 
1256 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1257 	r = _config_request(ioc, &mpi_request, mpi_reply,
1258 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1259  out:
1260 	return r;
1261 }
1262 
1263 /**
1264  * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1265  * @ioc: per adapter object
1266  * @mpi_reply: reply mf payload returned from firmware
1267  * @config_page: contents of the config page
1268  * @sz: size of buffer passed in config_page
1269  * Context: sleep.
1270  *
1271  * Calling function should call config_get_number_hba_phys prior to
1272  * this function, so enough memory is allocated for config_page.
1273  *
1274  * Return: 0 for success, non-zero for failure.
1275  */
1276 int
1277 mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1278 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1279 	u16 sz)
1280 {
1281 	Mpi2ConfigRequest_t mpi_request;
1282 	int r;
1283 
1284 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1285 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1286 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1287 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1288 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1289 	mpi_request.Header.PageNumber = 1;
1290 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1291 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1292 	r = _config_request(ioc, &mpi_request, mpi_reply,
1293 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1294 	if (r)
1295 		goto out;
1296 
1297 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1298 	_config_request(ioc, &mpi_request, mpi_reply,
1299 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1300 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1301 	r = _config_request(ioc, &mpi_request, mpi_reply,
1302 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1303  out:
1304 	return r;
1305 }
1306 
1307 /**
1308  * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1309  * @ioc: per adapter object
1310  * @mpi_reply: reply mf payload returned from firmware
1311  * @config_page: contents of the config page
1312  * @form: GET_NEXT_HANDLE or HANDLE
1313  * @handle: expander handle
1314  * Context: sleep.
1315  *
1316  * Return: 0 for success, non-zero for failure.
1317  */
1318 int
1319 mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1320 	*mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1321 {
1322 	Mpi2ConfigRequest_t mpi_request;
1323 	int r;
1324 
1325 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1326 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1327 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1328 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1329 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1330 	mpi_request.Header.PageNumber = 0;
1331 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1332 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1333 	r = _config_request(ioc, &mpi_request, mpi_reply,
1334 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1335 	if (r)
1336 		goto out;
1337 
1338 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1339 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1340 	r = _config_request(ioc, &mpi_request, mpi_reply,
1341 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1342 	    sizeof(*config_page));
1343  out:
1344 	return r;
1345 }
1346 
1347 /**
1348  * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1349  * @ioc: per adapter object
1350  * @mpi_reply: reply mf payload returned from firmware
1351  * @config_page: contents of the config page
1352  * @phy_number: phy number
1353  * @handle: expander handle
1354  * Context: sleep.
1355  *
1356  * Return: 0 for success, non-zero for failure.
1357  */
1358 int
1359 mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1360 	*mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1361 	u16 handle)
1362 {
1363 	Mpi2ConfigRequest_t mpi_request;
1364 	int r;
1365 
1366 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1367 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1368 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1369 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1370 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1371 	mpi_request.Header.PageNumber = 1;
1372 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1373 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1374 	r = _config_request(ioc, &mpi_request, mpi_reply,
1375 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1376 	if (r)
1377 		goto out;
1378 
1379 	mpi_request.PageAddress =
1380 	    cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1381 	    (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1382 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1383 	r = _config_request(ioc, &mpi_request, mpi_reply,
1384 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1385 	    sizeof(*config_page));
1386  out:
1387 	return r;
1388 }
1389 
1390 /**
1391  * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1392  * @ioc: per adapter object
1393  * @mpi_reply: reply mf payload returned from firmware
1394  * @config_page: contents of the config page
1395  * @form: GET_NEXT_HANDLE or HANDLE
1396  * @handle: expander handle
1397  * Context: sleep.
1398  *
1399  * Return: 0 for success, non-zero for failure.
1400  */
1401 int
1402 mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1403 	*mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1404 {
1405 	Mpi2ConfigRequest_t mpi_request;
1406 	int r;
1407 
1408 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1409 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1410 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1411 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1412 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1413 	mpi_request.Header.PageNumber = 0;
1414 	mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1415 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1416 	r = _config_request(ioc, &mpi_request, mpi_reply,
1417 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1418 	if (r)
1419 		goto out;
1420 
1421 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1422 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1423 	r = _config_request(ioc, &mpi_request, mpi_reply,
1424 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1425 	    sizeof(*config_page));
1426  out:
1427 	return r;
1428 }
1429 
1430 /**
1431  * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1432  * @ioc: per adapter object
1433  * @mpi_reply: reply mf payload returned from firmware
1434  * @config_page: contents of the config page
1435  * @phy_number: phy number
1436  * Context: sleep.
1437  *
1438  * Return: 0 for success, non-zero for failure.
1439  */
1440 int
1441 mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1442 	*mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1443 {
1444 	Mpi2ConfigRequest_t mpi_request;
1445 	int r;
1446 
1447 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1448 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1449 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1450 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1451 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1452 	mpi_request.Header.PageNumber = 0;
1453 	mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1454 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1455 	r = _config_request(ioc, &mpi_request, mpi_reply,
1456 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1457 	if (r)
1458 		goto out;
1459 
1460 	mpi_request.PageAddress =
1461 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1462 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1463 	r = _config_request(ioc, &mpi_request, mpi_reply,
1464 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1465 	    sizeof(*config_page));
1466  out:
1467 	return r;
1468 }
1469 
1470 /**
1471  * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1472  * @ioc: per adapter object
1473  * @mpi_reply: reply mf payload returned from firmware
1474  * @config_page: contents of the config page
1475  * @phy_number: phy number
1476  * Context: sleep.
1477  *
1478  * Return: 0 for success, non-zero for failure.
1479  */
1480 int
1481 mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1482 	*mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1483 {
1484 	Mpi2ConfigRequest_t mpi_request;
1485 	int r;
1486 
1487 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1488 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1489 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1490 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1491 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1492 	mpi_request.Header.PageNumber = 1;
1493 	mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1494 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1495 	r = _config_request(ioc, &mpi_request, mpi_reply,
1496 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1497 	if (r)
1498 		goto out;
1499 
1500 	mpi_request.PageAddress =
1501 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1502 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1503 	r = _config_request(ioc, &mpi_request, mpi_reply,
1504 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1505 	    sizeof(*config_page));
1506  out:
1507 	return r;
1508 }
1509 
1510 /**
1511  * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1512  * @ioc: per adapter object
1513  * @mpi_reply: reply mf payload returned from firmware
1514  * @config_page: contents of the config page
1515  * @form: GET_NEXT_HANDLE or HANDLE
1516  * @handle: volume handle
1517  * Context: sleep.
1518  *
1519  * Return: 0 for success, non-zero for failure.
1520  */
1521 int
1522 mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1523 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1524 	u32 handle)
1525 {
1526 	Mpi2ConfigRequest_t mpi_request;
1527 	int r;
1528 
1529 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1530 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1531 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1532 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1533 	mpi_request.Header.PageNumber = 1;
1534 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1535 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1536 	r = _config_request(ioc, &mpi_request, mpi_reply,
1537 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1538 	if (r)
1539 		goto out;
1540 
1541 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1542 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1543 	r = _config_request(ioc, &mpi_request, mpi_reply,
1544 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1545 	    sizeof(*config_page));
1546  out:
1547 	return r;
1548 }
1549 
1550 /**
1551  * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1552  * @ioc: per adapter object
1553  * @handle: volume handle
1554  * @num_pds: returns pds count
1555  * Context: sleep.
1556  *
1557  * Return: 0 for success, non-zero for failure.
1558  */
1559 int
1560 mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1561 	u8 *num_pds)
1562 {
1563 	Mpi2ConfigRequest_t mpi_request;
1564 	Mpi2RaidVolPage0_t config_page;
1565 	Mpi2ConfigReply_t mpi_reply;
1566 	int r;
1567 	u16 ioc_status;
1568 
1569 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1570 	*num_pds = 0;
1571 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1572 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1573 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1574 	mpi_request.Header.PageNumber = 0;
1575 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1576 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1577 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1578 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1579 	if (r)
1580 		goto out;
1581 
1582 	mpi_request.PageAddress =
1583 	    cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1584 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1585 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1586 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1587 	    sizeof(Mpi2RaidVolPage0_t));
1588 	if (!r) {
1589 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1590 		    MPI2_IOCSTATUS_MASK;
1591 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1592 			*num_pds = config_page.NumPhysDisks;
1593 	}
1594 
1595  out:
1596 	return r;
1597 }
1598 
1599 /**
1600  * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1601  * @ioc: per adapter object
1602  * @mpi_reply: reply mf payload returned from firmware
1603  * @config_page: contents of the config page
1604  * @form: GET_NEXT_HANDLE or HANDLE
1605  * @handle: volume handle
1606  * @sz: size of buffer passed in config_page
1607  * Context: sleep.
1608  *
1609  * Return: 0 for success, non-zero for failure.
1610  */
1611 int
1612 mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1613 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1614 	u32 handle, u16 sz)
1615 {
1616 	Mpi2ConfigRequest_t mpi_request;
1617 	int r;
1618 
1619 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1620 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1621 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1622 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1623 	mpi_request.Header.PageNumber = 0;
1624 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1625 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1626 	r = _config_request(ioc, &mpi_request, mpi_reply,
1627 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1628 	if (r)
1629 		goto out;
1630 
1631 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1632 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1633 	r = _config_request(ioc, &mpi_request, mpi_reply,
1634 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1635  out:
1636 	return r;
1637 }
1638 
1639 /**
1640  * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1641  * @ioc: per adapter object
1642  * @mpi_reply: reply mf payload returned from firmware
1643  * @config_page: contents of the config page
1644  * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1645  * @form_specific: specific to the form
1646  * Context: sleep.
1647  *
1648  * Return: 0 for success, non-zero for failure.
1649  */
1650 int
1651 mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1652 	*mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1653 	u32 form_specific)
1654 {
1655 	Mpi2ConfigRequest_t mpi_request;
1656 	int r;
1657 
1658 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1659 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1660 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1661 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1662 	mpi_request.Header.PageNumber = 0;
1663 	mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1664 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1665 	r = _config_request(ioc, &mpi_request, mpi_reply,
1666 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1667 	if (r)
1668 		goto out;
1669 
1670 	mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1671 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1672 	r = _config_request(ioc, &mpi_request, mpi_reply,
1673 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1674 	    sizeof(*config_page));
1675  out:
1676 	return r;
1677 }
1678 
1679 /**
1680  * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
1681  * raid components
1682  * @ioc: per adapter object
1683  * @pd_handle: phys disk handle
1684  * @volume_handle: volume handle
1685  * Context: sleep.
1686  *
1687  * Return: 0 for success, non-zero for failure.
1688  */
1689 int
1690 mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
1691 	u16 *volume_handle)
1692 {
1693 	Mpi2RaidConfigurationPage0_t *config_page = NULL;
1694 	Mpi2ConfigRequest_t mpi_request;
1695 	Mpi2ConfigReply_t mpi_reply;
1696 	int r, i, config_page_sz;
1697 	u16 ioc_status;
1698 	int config_num;
1699 	u16 element_type;
1700 	u16 phys_disk_dev_handle;
1701 
1702 	*volume_handle = 0;
1703 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1704 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1705 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1706 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1707 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1708 	mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1709 	mpi_request.Header.PageNumber = 0;
1710 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1711 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1712 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1713 	if (r)
1714 		goto out;
1715 
1716 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1717 	config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1718 	config_page = kmalloc(config_page_sz, GFP_KERNEL);
1719 	if (!config_page) {
1720 		r = -1;
1721 		goto out;
1722 	}
1723 
1724 	config_num = 0xff;
1725 	while (1) {
1726 		mpi_request.PageAddress = cpu_to_le32(config_num +
1727 		    MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1728 		r = _config_request(ioc, &mpi_request, &mpi_reply,
1729 		    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1730 		    config_page_sz);
1731 		if (r)
1732 			goto out;
1733 		r = -1;
1734 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1735 		    MPI2_IOCSTATUS_MASK;
1736 		if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1737 			goto out;
1738 		for (i = 0; i < config_page->NumElements; i++) {
1739 			element_type = le16_to_cpu(config_page->
1740 			    ConfigElement[i].ElementFlags) &
1741 			    MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1742 			if (element_type ==
1743 			    MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1744 			    element_type ==
1745 			    MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1746 				phys_disk_dev_handle =
1747 				    le16_to_cpu(config_page->ConfigElement[i].
1748 				    PhysDiskDevHandle);
1749 				if (phys_disk_dev_handle == pd_handle) {
1750 					*volume_handle =
1751 					    le16_to_cpu(config_page->
1752 					    ConfigElement[i].VolDevHandle);
1753 					r = 0;
1754 					goto out;
1755 				}
1756 			} else if (element_type ==
1757 			    MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1758 				*volume_handle = 0;
1759 				r = 0;
1760 				goto out;
1761 			}
1762 		}
1763 		config_num = config_page->ConfigNum;
1764 	}
1765  out:
1766 	kfree(config_page);
1767 	return r;
1768 }
1769 
1770 /**
1771  * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
1772  * @ioc: per adapter object
1773  * @volume_handle: volume handle
1774  * @wwid: volume wwid
1775  * Context: sleep.
1776  *
1777  * Return: 0 for success, non-zero for failure.
1778  */
1779 int
1780 mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
1781 	u64 *wwid)
1782 {
1783 	Mpi2ConfigReply_t mpi_reply;
1784 	Mpi2RaidVolPage1_t raid_vol_pg1;
1785 
1786 	*wwid = 0;
1787 	if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1788 	    &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1789 	    volume_handle))) {
1790 		*wwid = le64_to_cpu(raid_vol_pg1.WWID);
1791 		return 0;
1792 	} else
1793 		return -1;
1794 }
1795