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