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 	mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
105 	switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
106 	case MPI2_CONFIG_PAGETYPE_IO_UNIT:
107 		desc = "io_unit";
108 		break;
109 	case MPI2_CONFIG_PAGETYPE_IOC:
110 		desc = "ioc";
111 		break;
112 	case MPI2_CONFIG_PAGETYPE_BIOS:
113 		desc = "bios";
114 		break;
115 	case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
116 		desc = "raid_volume";
117 		break;
118 	case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
119 		desc = "manufacturing";
120 		break;
121 	case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
122 		desc = "physdisk";
123 		break;
124 	case MPI2_CONFIG_PAGETYPE_EXTENDED:
125 		switch (mpi_request->ExtPageType) {
126 		case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
127 			desc = "sas_io_unit";
128 			break;
129 		case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
130 			desc = "sas_expander";
131 			break;
132 		case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
133 			desc = "sas_device";
134 			break;
135 		case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
136 			desc = "sas_phy";
137 			break;
138 		case MPI2_CONFIG_EXTPAGETYPE_LOG:
139 			desc = "log";
140 			break;
141 		case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
142 			desc = "enclosure";
143 			break;
144 		case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
145 			desc = "raid_config";
146 			break;
147 		case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
148 			desc = "driver_mapping";
149 			break;
150 		case MPI2_CONFIG_EXTPAGETYPE_SAS_PORT:
151 			desc = "sas_port";
152 			break;
153 		case MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING:
154 			desc = "ext_manufacturing";
155 			break;
156 		case MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT:
157 			desc = "pcie_io_unit";
158 			break;
159 		case MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH:
160 			desc = "pcie_switch";
161 			break;
162 		case MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE:
163 			desc = "pcie_device";
164 			break;
165 		case MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK:
166 			desc = "pcie_link";
167 			break;
168 		}
169 		break;
170 	}
171 
172 	if (!desc)
173 		return;
174 
175 	ioc_info(ioc, "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n",
176 		 calling_function_name, desc,
177 		 mpi_request->Header.PageNumber, mpi_request->Action,
178 		 le32_to_cpu(mpi_request->PageAddress), smid);
179 
180 	if (!mpi_reply)
181 		return;
182 
183 	if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
184 		ioc_info(ioc, "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
185 			 le16_to_cpu(mpi_reply->IOCStatus),
186 			 le32_to_cpu(mpi_reply->IOCLogInfo));
187 }
188 
189 /**
190  * _config_alloc_config_dma_memory - obtain physical memory
191  * @ioc: per adapter object
192  * @mem: struct config_request
193  *
194  * A wrapper for obtaining dma-able memory for config page request.
195  *
196  * Return: 0 for success, non-zero for failure.
197  */
198 static int
199 _config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
200 	struct config_request *mem)
201 {
202 	int r = 0;
203 
204 	if (mem->sz > ioc->config_page_sz) {
205 		mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
206 		    &mem->page_dma, GFP_KERNEL);
207 		if (!mem->page) {
208 			ioc_err(ioc, "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n",
209 				__func__, mem->sz);
210 			r = -ENOMEM;
211 		}
212 	} else { /* use tmp buffer if less than 512 bytes */
213 		mem->page = ioc->config_page;
214 		mem->page_dma = ioc->config_page_dma;
215 	}
216 	ioc->config_vaddr = mem->page;
217 	return r;
218 }
219 
220 /**
221  * _config_free_config_dma_memory - wrapper to free the memory
222  * @ioc: per adapter object
223  * @mem: struct config_request
224  *
225  * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
226  *
227  * Return: 0 for success, non-zero for failure.
228  */
229 static void
230 _config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
231 	struct config_request *mem)
232 {
233 	if (mem->sz > ioc->config_page_sz)
234 		dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
235 		    mem->page_dma);
236 }
237 
238 /**
239  * mpt3sas_config_done - config page completion routine
240  * @ioc: per adapter object
241  * @smid: system request message index
242  * @msix_index: MSIX table index supplied by the OS
243  * @reply: reply message frame(lower 32bit addr)
244  * Context: none.
245  *
246  * The callback handler when using _config_request.
247  *
248  * Return: 1 meaning mf should be freed from _base_interrupt
249  *         0 means the mf is freed from this function.
250  */
251 u8
252 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
253 	u32 reply)
254 {
255 	MPI2DefaultReply_t *mpi_reply;
256 
257 	if (ioc->config_cmds.status == MPT3_CMD_NOT_USED)
258 		return 1;
259 	if (ioc->config_cmds.smid != smid)
260 		return 1;
261 	ioc->config_cmds.status |= MPT3_CMD_COMPLETE;
262 	mpi_reply =  mpt3sas_base_get_reply_virt_addr(ioc, reply);
263 	if (mpi_reply) {
264 		ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID;
265 		memcpy(ioc->config_cmds.reply, mpi_reply,
266 		    mpi_reply->MsgLength*4);
267 	}
268 	ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
269 	if (ioc->logging_level & MPT_DEBUG_CONFIG)
270 		_config_display_some_debug(ioc, smid, "config_done", mpi_reply);
271 	ioc->config_cmds.smid = USHRT_MAX;
272 	complete(&ioc->config_cmds.done);
273 	return 1;
274 }
275 
276 /**
277  * _config_request - main routine for sending config page requests
278  * @ioc: per adapter object
279  * @mpi_request: request message frame
280  * @mpi_reply: reply mf payload returned from firmware
281  * @timeout: timeout in seconds
282  * @config_page: contents of the config page
283  * @config_page_sz: size of config page
284  * Context: sleep
285  *
286  * A generic API for config page requests to firmware.
287  *
288  * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling
289  * this API.
290  *
291  * The callback index is set inside `ioc->config_cb_idx.
292  *
293  * Return: 0 for success, non-zero for failure.
294  */
295 static int
296 _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
297 	*mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
298 	void *config_page, u16 config_page_sz)
299 {
300 	u16 smid;
301 	Mpi2ConfigRequest_t *config_request;
302 	int r;
303 	u8 retry_count, issue_host_reset = 0;
304 	struct config_request mem;
305 	u32 ioc_status = UINT_MAX;
306 
307 	mutex_lock(&ioc->config_cmds.mutex);
308 	if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
309 		ioc_err(ioc, "%s: config_cmd in use\n", __func__);
310 		mutex_unlock(&ioc->config_cmds.mutex);
311 		return -EAGAIN;
312 	}
313 
314 	retry_count = 0;
315 	memset(&mem, 0, sizeof(struct config_request));
316 
317 	mpi_request->VF_ID = 0; /* TODO */
318 	mpi_request->VP_ID = 0;
319 
320 	if (config_page) {
321 		mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
322 		mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
323 		mpi_request->Header.PageType = mpi_reply->Header.PageType;
324 		mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
325 		mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
326 		mpi_request->ExtPageType = mpi_reply->ExtPageType;
327 		if (mpi_request->Header.PageLength)
328 			mem.sz = mpi_request->Header.PageLength * 4;
329 		else
330 			mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
331 		r = _config_alloc_config_dma_memory(ioc, &mem);
332 		if (r != 0)
333 			goto out;
334 		if (mpi_request->Action ==
335 		    MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
336 		    mpi_request->Action ==
337 		    MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
338 			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
339 			    MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
340 			    mem.page_dma);
341 			memcpy(mem.page, config_page, min_t(u16, mem.sz,
342 			    config_page_sz));
343 		} else {
344 			memset(config_page, 0, config_page_sz);
345 			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
346 			    MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
347 			memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
348 		}
349 	}
350 
351  retry_config:
352 	if (retry_count) {
353 		if (retry_count > 2) { /* attempt only 2 retries */
354 			r = -EFAULT;
355 			goto free_mem;
356 		}
357 		ioc_info(ioc, "%s: attempting retry (%d)\n",
358 			 __func__, retry_count);
359 	}
360 
361 	r = mpt3sas_wait_for_ioc(ioc, MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT);
362 	if (r)
363 		goto free_mem;
364 
365 	smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
366 	if (!smid) {
367 		ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
368 		ioc->config_cmds.status = MPT3_CMD_NOT_USED;
369 		r = -EAGAIN;
370 		goto free_mem;
371 	}
372 
373 	r = 0;
374 	memset(ioc->config_cmds.reply, 0, sizeof(Mpi2ConfigReply_t));
375 	ioc->config_cmds.status = MPT3_CMD_PENDING;
376 	config_request = mpt3sas_base_get_msg_frame(ioc, smid);
377 	ioc->config_cmds.smid = smid;
378 	memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
379 	if (ioc->logging_level & MPT_DEBUG_CONFIG)
380 		_config_display_some_debug(ioc, smid, "config_request", NULL);
381 	init_completion(&ioc->config_cmds.done);
382 	ioc->put_smid_default(ioc, smid);
383 	wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ);
384 	if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
385 		if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
386 			_config_display_some_debug(ioc,
387 			    smid, "config_request", NULL);
388 		ioc_err(ioc, "%s: command timeout\n", __func__);
389 		mpt3sas_base_check_cmd_timeout(ioc, ioc->config_cmds.status,
390 				mpi_request, sizeof(Mpi2ConfigRequest_t) / 4);
391 		retry_count++;
392 		if (ioc->config_cmds.smid == smid)
393 			mpt3sas_base_free_smid(ioc, smid);
394 		if ((ioc->shost_recovery) || (ioc->config_cmds.status &
395 		    MPT3_CMD_RESET) || ioc->pci_error_recovery)
396 			goto retry_config;
397 		issue_host_reset = 1;
398 		r = -EFAULT;
399 		goto free_mem;
400 	}
401 
402 	if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
403 		memcpy(mpi_reply, ioc->config_cmds.reply,
404 		    sizeof(Mpi2ConfigReply_t));
405 
406 		/* Reply Frame Sanity Checks to workaround FW issues */
407 		if ((mpi_request->Header.PageType & 0xF) !=
408 		    (mpi_reply->Header.PageType & 0xF)) {
409 			if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
410 				_config_display_some_debug(ioc,
411 				    smid, "config_request", NULL);
412 			_debug_dump_mf(mpi_request, ioc->request_sz/4);
413 			_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
414 			panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
415 			      ioc->name, __func__,
416 			      mpi_request->Header.PageType & 0xF,
417 			      mpi_reply->Header.PageType & 0xF);
418 		}
419 
420 		if (((mpi_request->Header.PageType & 0xF) ==
421 		    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
422 		    mpi_request->ExtPageType != mpi_reply->ExtPageType) {
423 			if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
424 				_config_display_some_debug(ioc,
425 				    smid, "config_request", NULL);
426 			_debug_dump_mf(mpi_request, ioc->request_sz/4);
427 			_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
428 			panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
429 			      ioc->name, __func__,
430 			      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 		ioc_info(ioc, "%s: retry (%d) completed!!\n",
439 			 __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 				if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
451 					_config_display_some_debug(ioc,
452 					    smid, "config_request", NULL);
453 				_debug_dump_mf(mpi_request, ioc->request_sz/4);
454 				_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
455 				_debug_dump_config(p, min_t(u16, mem.sz,
456 				    config_page_sz)/4);
457 				panic("%s: %s: Firmware BUG: config page mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
458 				      ioc->name, __func__,
459 				      mpi_request->Header.PageType & 0xF,
460 				      p[3] & 0xF);
461 			}
462 
463 			if (((mpi_request->Header.PageType & 0xF) ==
464 			    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
465 			    (mpi_request->ExtPageType != p[6])) {
466 				if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
467 					_config_display_some_debug(ioc,
468 					    smid, "config_request", NULL);
469 				_debug_dump_mf(mpi_request, ioc->request_sz/4);
470 				_debug_dump_reply(mpi_reply, ioc->reply_sz/4);
471 				_debug_dump_config(p, min_t(u16, mem.sz,
472 				    config_page_sz)/4);
473 				panic("%s: %s: Firmware BUG: config page mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
474 				      ioc->name, __func__,
475 				      mpi_request->ExtPageType, p[6]);
476 			}
477 		}
478 		memcpy(config_page, mem.page, min_t(u16, mem.sz,
479 		    config_page_sz));
480 	}
481 
482  free_mem:
483 	if (config_page)
484 		_config_free_config_dma_memory(ioc, &mem);
485  out:
486 	ioc->config_cmds.status = MPT3_CMD_NOT_USED;
487 	mutex_unlock(&ioc->config_cmds.mutex);
488 
489 	if (issue_host_reset)
490 		mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
491 	return r;
492 }
493 
494 /**
495  * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
496  * @ioc: per adapter object
497  * @mpi_reply: reply mf payload returned from firmware
498  * @config_page: contents of the config page
499  * Context: sleep.
500  *
501  * Return: 0 for success, non-zero for failure.
502  */
503 int
504 mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
505 	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
506 {
507 	Mpi2ConfigRequest_t mpi_request;
508 	int r;
509 
510 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
511 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
512 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
513 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
514 	mpi_request.Header.PageNumber = 0;
515 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
516 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
517 	r = _config_request(ioc, &mpi_request, mpi_reply,
518 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
519 	if (r)
520 		goto out;
521 
522 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
523 	r = _config_request(ioc, &mpi_request, mpi_reply,
524 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
525 	    sizeof(*config_page));
526  out:
527 	return r;
528 }
529 
530 /**
531  * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
532  * @ioc: per adapter object
533  * @mpi_reply: reply mf payload returned from firmware
534  * @config_page: contents of the config page
535  * @sz: size of buffer passed in config_page
536  * Context: sleep.
537  *
538  * Return: 0 for success, non-zero for failure.
539  */
540 int
541 mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
542 	Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
543 	u16 sz)
544 {
545 	Mpi2ConfigRequest_t mpi_request;
546 	int r;
547 
548 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
549 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
550 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
551 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
552 	mpi_request.Header.PageNumber = 7;
553 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
554 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
555 	r = _config_request(ioc, &mpi_request, mpi_reply,
556 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
557 	if (r)
558 		goto out;
559 
560 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
561 	r = _config_request(ioc, &mpi_request, mpi_reply,
562 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
563 	    sz);
564  out:
565 	return r;
566 }
567 
568 /**
569  * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
570  * @ioc: per adapter object
571  * @mpi_reply: reply mf payload returned from firmware
572  * @config_page: contents of the config page
573  * Context: sleep.
574  *
575  * Return: 0 for success, non-zero for failure.
576  */
577 int
578 mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
579 	Mpi2ConfigReply_t *mpi_reply,
580 	struct Mpi2ManufacturingPage10_t *config_page)
581 {
582 	Mpi2ConfigRequest_t mpi_request;
583 	int r;
584 
585 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
586 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
587 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
588 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
589 	mpi_request.Header.PageNumber = 10;
590 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
591 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
592 	r = _config_request(ioc, &mpi_request, mpi_reply,
593 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
594 	if (r)
595 		goto out;
596 
597 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
598 	r = _config_request(ioc, &mpi_request, mpi_reply,
599 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
600 	    sizeof(*config_page));
601  out:
602 	return r;
603 }
604 
605 /**
606  * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
607  * @ioc: per adapter object
608  * @mpi_reply: reply mf payload returned from firmware
609  * @config_page: contents of the config page
610  * Context: sleep.
611  *
612  * Return: 0 for success, non-zero for failure.
613  */
614 int
615 mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
616 	Mpi2ConfigReply_t *mpi_reply,
617 	struct Mpi2ManufacturingPage11_t *config_page)
618 {
619 	Mpi2ConfigRequest_t mpi_request;
620 	int r;
621 
622 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
623 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
624 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
625 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
626 	mpi_request.Header.PageNumber = 11;
627 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
628 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
629 	r = _config_request(ioc, &mpi_request, mpi_reply,
630 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
631 	if (r)
632 		goto out;
633 
634 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
635 	r = _config_request(ioc, &mpi_request, mpi_reply,
636 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
637 	    sizeof(*config_page));
638  out:
639 	return r;
640 }
641 
642 /**
643  * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
644  * @ioc: per adapter object
645  * @mpi_reply: reply mf payload returned from firmware
646  * @config_page: contents of the config page
647  * Context: sleep.
648  *
649  * Return: 0 for success, non-zero for failure.
650  */
651 int
652 mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
653 	Mpi2ConfigReply_t *mpi_reply,
654 	struct Mpi2ManufacturingPage11_t *config_page)
655 {
656 	Mpi2ConfigRequest_t mpi_request;
657 	int r;
658 
659 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
660 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
661 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
662 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
663 	mpi_request.Header.PageNumber = 11;
664 	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
665 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
666 	r = _config_request(ioc, &mpi_request, mpi_reply,
667 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
668 	if (r)
669 		goto out;
670 
671 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
672 	r = _config_request(ioc, &mpi_request, mpi_reply,
673 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
674 	    sizeof(*config_page));
675  out:
676 	return r;
677 }
678 
679 /**
680  * mpt3sas_config_get_bios_pg2 - obtain bios page 2
681  * @ioc: per adapter object
682  * @mpi_reply: reply mf payload returned from firmware
683  * @config_page: contents of the config page
684  * Context: sleep.
685  *
686  * Return: 0 for success, non-zero for failure.
687  */
688 int
689 mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
690 	Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
691 {
692 	Mpi2ConfigRequest_t mpi_request;
693 	int r;
694 
695 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
696 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
697 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
698 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
699 	mpi_request.Header.PageNumber = 2;
700 	mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
701 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
702 	r = _config_request(ioc, &mpi_request, mpi_reply,
703 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
704 	if (r)
705 		goto out;
706 
707 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
708 	r = _config_request(ioc, &mpi_request, mpi_reply,
709 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
710 	    sizeof(*config_page));
711  out:
712 	return r;
713 }
714 
715 /**
716  * mpt3sas_config_get_bios_pg3 - obtain bios page 3
717  * @ioc: per adapter object
718  * @mpi_reply: reply mf payload returned from firmware
719  * @config_page: contents of the config page
720  * Context: sleep.
721  *
722  * Return: 0 for success, non-zero for failure.
723  */
724 int
725 mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
726 	*mpi_reply, Mpi2BiosPage3_t *config_page)
727 {
728 	Mpi2ConfigRequest_t mpi_request;
729 	int r;
730 
731 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
732 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
733 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
734 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
735 	mpi_request.Header.PageNumber = 3;
736 	mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
737 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
738 	r = _config_request(ioc, &mpi_request, mpi_reply,
739 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
740 	if (r)
741 		goto out;
742 
743 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
744 	r = _config_request(ioc, &mpi_request, mpi_reply,
745 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
746 	    sizeof(*config_page));
747  out:
748 	return r;
749 }
750 
751 /**
752  * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
753  * @ioc: per adapter object
754  * @mpi_reply: reply mf payload returned from firmware
755  * @config_page: contents of the config page
756  * Context: sleep.
757  *
758  * Return: 0 for success, non-zero for failure.
759  */
760 int
761 mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
762 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
763 {
764 	Mpi2ConfigRequest_t mpi_request;
765 	int r;
766 
767 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
768 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
769 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
770 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
771 	mpi_request.Header.PageNumber = 0;
772 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
773 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
774 	r = _config_request(ioc, &mpi_request, mpi_reply,
775 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
776 	if (r)
777 		goto out;
778 
779 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
780 	r = _config_request(ioc, &mpi_request, mpi_reply,
781 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
782 	    sizeof(*config_page));
783  out:
784 	return r;
785 }
786 
787 /**
788  * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
789  * @ioc: per adapter object
790  * @mpi_reply: reply mf payload returned from firmware
791  * @config_page: contents of the config page
792  * Context: sleep.
793  *
794  * Return: 0 for success, non-zero for failure.
795  */
796 int
797 mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
798 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
799 {
800 	Mpi2ConfigRequest_t mpi_request;
801 	int r;
802 
803 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
804 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
805 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
806 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
807 	mpi_request.Header.PageNumber = 1;
808 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
809 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
810 	r = _config_request(ioc, &mpi_request, mpi_reply,
811 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
812 	if (r)
813 		goto out;
814 
815 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
816 	r = _config_request(ioc, &mpi_request, mpi_reply,
817 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
818 	    sizeof(*config_page));
819  out:
820 	return r;
821 }
822 
823 /**
824  * mpt3sas_config_set_iounit_pg1 - set iounit page 1
825  * @ioc: per adapter object
826  * @mpi_reply: reply mf payload returned from firmware
827  * @config_page: contents of the config page
828  * Context: sleep.
829  *
830  * Return: 0 for success, non-zero for failure.
831  */
832 int
833 mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
834 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
835 {
836 	Mpi2ConfigRequest_t mpi_request;
837 	int r;
838 
839 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
840 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
841 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
842 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
843 	mpi_request.Header.PageNumber = 1;
844 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
845 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
846 	r = _config_request(ioc, &mpi_request, mpi_reply,
847 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
848 	if (r)
849 		goto out;
850 
851 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
852 	r = _config_request(ioc, &mpi_request, mpi_reply,
853 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
854 	    sizeof(*config_page));
855  out:
856 	return r;
857 }
858 
859 /**
860  * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
861  * @ioc: per adapter object
862  * @mpi_reply: reply mf payload returned from firmware
863  * @config_page: contents of the config page
864  * @sz: size of buffer passed in config_page
865  * Context: sleep.
866  *
867  * Return: 0 for success, non-zero for failure.
868  */
869 int
870 mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
871 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
872 {
873 	Mpi2ConfigRequest_t mpi_request;
874 	int r;
875 
876 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
877 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
878 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
879 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
880 	mpi_request.Header.PageNumber = 3;
881 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
882 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
883 	r = _config_request(ioc, &mpi_request, mpi_reply,
884 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
885 	if (r)
886 		goto out;
887 
888 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
889 	r = _config_request(ioc, &mpi_request, mpi_reply,
890 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
891  out:
892 	return r;
893 }
894 
895 /**
896  * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
897  * @ioc: per adapter object
898  * @mpi_reply: reply mf payload returned from firmware
899  * @config_page: contents of the config page
900  * Context: sleep.
901  *
902  * Return: 0 for success, non-zero for failure.
903  */
904 int
905 mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
906 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
907 {
908 	Mpi2ConfigRequest_t mpi_request;
909 	int r;
910 
911 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
912 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
913 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
914 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
915 	mpi_request.Header.PageNumber = 8;
916 	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
917 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
918 	r = _config_request(ioc, &mpi_request, mpi_reply,
919 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
920 	if (r)
921 		goto out;
922 
923 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
924 	r = _config_request(ioc, &mpi_request, mpi_reply,
925 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
926 	    sizeof(*config_page));
927  out:
928 	return r;
929 }
930 
931 /**
932  * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
933  * @ioc: per adapter object
934  * @mpi_reply: reply mf payload returned from firmware
935  * @config_page: contents of the config page
936  * Context: sleep.
937  *
938  * Return: 0 for success, non-zero for failure.
939  */
940 int
941 mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
942 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
943 {
944 	Mpi2ConfigRequest_t mpi_request;
945 	int r;
946 
947 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
948 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
949 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
950 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
951 	mpi_request.Header.PageNumber = 8;
952 	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
953 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
954 	r = _config_request(ioc, &mpi_request, mpi_reply,
955 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
956 	if (r)
957 		goto out;
958 
959 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
960 	r = _config_request(ioc, &mpi_request, mpi_reply,
961 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
962 	    sizeof(*config_page));
963  out:
964 	return r;
965 }
966 /**
967  * mpt3sas_config_get_ioc_pg1 - obtain ioc page 1
968  * @ioc: per adapter object
969  * @mpi_reply: reply mf payload returned from firmware
970  * @config_page: contents of the config page
971  * Context: sleep.
972  *
973  * Return: 0 for success, non-zero for failure.
974  */
975 int
976 mpt3sas_config_get_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
977 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
978 {
979 	Mpi2ConfigRequest_t mpi_request;
980 	int r;
981 
982 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
983 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
984 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
985 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
986 	mpi_request.Header.PageNumber = 1;
987 	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
988 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
989 	r = _config_request(ioc, &mpi_request, mpi_reply,
990 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
991 	if (r)
992 		goto out;
993 
994 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
995 	r = _config_request(ioc, &mpi_request, mpi_reply,
996 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
997 	    sizeof(*config_page));
998  out:
999 	return r;
1000 }
1001 
1002 /**
1003  * mpt3sas_config_set_ioc_pg1 - modify ioc page 1
1004  * @ioc: per adapter object
1005  * @mpi_reply: reply mf payload returned from firmware
1006  * @config_page: contents of the config page
1007  * Context: sleep.
1008  *
1009  * Return: 0 for success, non-zero for failure.
1010  */
1011 int
1012 mpt3sas_config_set_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
1013 	Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
1014 {
1015 	Mpi2ConfigRequest_t mpi_request;
1016 	int r;
1017 
1018 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1019 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1020 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1021 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
1022 	mpi_request.Header.PageNumber = 1;
1023 	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
1024 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1025 	r = _config_request(ioc, &mpi_request, mpi_reply,
1026 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1027 	if (r)
1028 		goto out;
1029 
1030 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1031 	r = _config_request(ioc, &mpi_request, mpi_reply,
1032 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1033 	    sizeof(*config_page));
1034  out:
1035 	return r;
1036 }
1037 
1038 /**
1039  * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
1040  * @ioc: per adapter object
1041  * @mpi_reply: reply mf payload returned from firmware
1042  * @config_page: contents of the config page
1043  * @form: GET_NEXT_HANDLE or HANDLE
1044  * @handle: device handle
1045  * Context: sleep.
1046  *
1047  * Return: 0 for success, non-zero for failure.
1048  */
1049 int
1050 mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1051 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
1052 	u32 form, u32 handle)
1053 {
1054 	Mpi2ConfigRequest_t mpi_request;
1055 	int r;
1056 
1057 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1058 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1059 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1060 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1061 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1062 	mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
1063 	mpi_request.Header.PageNumber = 0;
1064 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1065 	r = _config_request(ioc, &mpi_request, mpi_reply,
1066 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1067 	if (r)
1068 		goto out;
1069 
1070 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1071 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1072 	r = _config_request(ioc, &mpi_request, mpi_reply,
1073 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1074 	    sizeof(*config_page));
1075  out:
1076 	return r;
1077 }
1078 
1079 /**
1080  * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
1081  * @ioc: per adapter object
1082  * @mpi_reply: reply mf payload returned from firmware
1083  * @config_page: contents of the config page
1084  * @form: GET_NEXT_HANDLE or HANDLE
1085  * @handle: device handle
1086  * Context: sleep.
1087  *
1088  * Return: 0 for success, non-zero for failure.
1089  */
1090 int
1091 mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1092 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1093 	u32 form, u32 handle)
1094 {
1095 	Mpi2ConfigRequest_t mpi_request;
1096 	int r;
1097 
1098 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1099 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1100 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1101 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1102 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1103 	mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1104 	mpi_request.Header.PageNumber = 1;
1105 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1106 	r = _config_request(ioc, &mpi_request, mpi_reply,
1107 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1108 	if (r)
1109 		goto out;
1110 
1111 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1112 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1113 	r = _config_request(ioc, &mpi_request, mpi_reply,
1114 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1115 	    sizeof(*config_page));
1116  out:
1117 	return r;
1118 }
1119 
1120 /**
1121  * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
1122  * @ioc: per adapter object
1123  * @mpi_reply: reply mf payload returned from firmware
1124  * @config_page: contents of the config page
1125  * @form: GET_NEXT_HANDLE or HANDLE
1126  * @handle: device handle
1127  * Context: sleep.
1128  *
1129  * Return: 0 for success, non-zero for failure.
1130  */
1131 int
1132 mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1133 	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
1134 	u32 form, u32 handle)
1135 {
1136 	Mpi2ConfigRequest_t mpi_request;
1137 	int r;
1138 
1139 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1140 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1141 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1142 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1143 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1144 	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
1145 	mpi_request.Header.PageNumber = 0;
1146 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1147 	r = _config_request(ioc, &mpi_request, mpi_reply,
1148 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1149 	if (r)
1150 		goto out;
1151 
1152 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1153 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1154 	r = _config_request(ioc, &mpi_request, mpi_reply,
1155 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1156 			sizeof(*config_page));
1157 out:
1158 	return r;
1159 }
1160 
1161 /**
1162  * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
1163  * @ioc: per adapter object
1164  * @mpi_reply: reply mf payload returned from firmware
1165  * @config_page: contents of the config page
1166  * @form: GET_NEXT_HANDLE or HANDLE
1167  * @handle: device handle
1168  * Context: sleep.
1169  *
1170  * Return: 0 for success, non-zero for failure.
1171  */
1172 int
1173 mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
1174 	Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
1175 	u32 form, u32 handle)
1176 {
1177 	Mpi2ConfigRequest_t mpi_request;
1178 	int r;
1179 
1180 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1181 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1182 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1183 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1184 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1185 	mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
1186 	mpi_request.Header.PageNumber = 2;
1187 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1188 	r = _config_request(ioc, &mpi_request, mpi_reply,
1189 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1190 	if (r)
1191 		goto out;
1192 
1193 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1194 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1195 	r = _config_request(ioc, &mpi_request, mpi_reply,
1196 			MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1197 			sizeof(*config_page));
1198 out:
1199 	return r;
1200 }
1201 
1202 /**
1203  * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1204  * @ioc: per adapter object
1205  * @num_phys: pointer returned with the number of phys
1206  * Context: sleep.
1207  *
1208  * Return: 0 for success, non-zero for failure.
1209  */
1210 int
1211 mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1212 {
1213 	Mpi2ConfigRequest_t mpi_request;
1214 	int r;
1215 	u16 ioc_status;
1216 	Mpi2ConfigReply_t mpi_reply;
1217 	Mpi2SasIOUnitPage0_t config_page;
1218 
1219 	*num_phys = 0;
1220 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1221 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1222 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1223 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1224 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1225 	mpi_request.Header.PageNumber = 0;
1226 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1227 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1228 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1229 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1230 	if (r)
1231 		goto out;
1232 
1233 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1234 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1235 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1236 	    sizeof(Mpi2SasIOUnitPage0_t));
1237 	if (!r) {
1238 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1239 		    MPI2_IOCSTATUS_MASK;
1240 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1241 			*num_phys = config_page.NumPhys;
1242 	}
1243  out:
1244 	return r;
1245 }
1246 
1247 /**
1248  * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1249  * @ioc: per adapter object
1250  * @mpi_reply: reply mf payload returned from firmware
1251  * @config_page: contents of the config page
1252  * @sz: size of buffer passed in config_page
1253  * Context: sleep.
1254  *
1255  * Calling function should call config_get_number_hba_phys prior to
1256  * this function, so enough memory is allocated for config_page.
1257  *
1258  * Return: 0 for success, non-zero for failure.
1259  */
1260 int
1261 mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1262 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1263 	u16 sz)
1264 {
1265 	Mpi2ConfigRequest_t mpi_request;
1266 	int r;
1267 
1268 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1269 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1270 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1271 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1272 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1273 	mpi_request.Header.PageNumber = 0;
1274 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1275 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1276 	r = _config_request(ioc, &mpi_request, mpi_reply,
1277 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1278 	if (r)
1279 		goto out;
1280 
1281 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1282 	r = _config_request(ioc, &mpi_request, mpi_reply,
1283 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1284  out:
1285 	return r;
1286 }
1287 
1288 /**
1289  * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1290  * @ioc: per adapter object
1291  * @mpi_reply: reply mf payload returned from firmware
1292  * @config_page: contents of the config page
1293  * @sz: size of buffer passed in config_page
1294  * Context: sleep.
1295  *
1296  * Calling function should call config_get_number_hba_phys prior to
1297  * this function, so enough memory is allocated for config_page.
1298  *
1299  * Return: 0 for success, non-zero for failure.
1300  */
1301 int
1302 mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1303 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1304 	u16 sz)
1305 {
1306 	Mpi2ConfigRequest_t mpi_request;
1307 	int r;
1308 
1309 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1310 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1311 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1312 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1313 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1314 	mpi_request.Header.PageNumber = 1;
1315 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1316 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1317 	r = _config_request(ioc, &mpi_request, mpi_reply,
1318 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1319 	if (r)
1320 		goto out;
1321 
1322 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1323 	r = _config_request(ioc, &mpi_request, mpi_reply,
1324 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1325  out:
1326 	return r;
1327 }
1328 
1329 /**
1330  * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1331  * @ioc: per adapter object
1332  * @mpi_reply: reply mf payload returned from firmware
1333  * @config_page: contents of the config page
1334  * @sz: size of buffer passed in config_page
1335  * Context: sleep.
1336  *
1337  * Calling function should call config_get_number_hba_phys prior to
1338  * this function, so enough memory is allocated for config_page.
1339  *
1340  * Return: 0 for success, non-zero for failure.
1341  */
1342 int
1343 mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1344 	Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1345 	u16 sz)
1346 {
1347 	Mpi2ConfigRequest_t mpi_request;
1348 	int r;
1349 
1350 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1351 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1352 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1353 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1354 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1355 	mpi_request.Header.PageNumber = 1;
1356 	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1357 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1358 	r = _config_request(ioc, &mpi_request, mpi_reply,
1359 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1360 	if (r)
1361 		goto out;
1362 
1363 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1364 	_config_request(ioc, &mpi_request, mpi_reply,
1365 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1366 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1367 	r = _config_request(ioc, &mpi_request, mpi_reply,
1368 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1369  out:
1370 	return r;
1371 }
1372 
1373 /**
1374  * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1375  * @ioc: per adapter object
1376  * @mpi_reply: reply mf payload returned from firmware
1377  * @config_page: contents of the config page
1378  * @form: GET_NEXT_HANDLE or HANDLE
1379  * @handle: expander handle
1380  * Context: sleep.
1381  *
1382  * Return: 0 for success, non-zero for failure.
1383  */
1384 int
1385 mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1386 	*mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1387 {
1388 	Mpi2ConfigRequest_t mpi_request;
1389 	int r;
1390 
1391 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1392 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1393 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1394 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1395 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1396 	mpi_request.Header.PageNumber = 0;
1397 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1398 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1399 	r = _config_request(ioc, &mpi_request, mpi_reply,
1400 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1401 	if (r)
1402 		goto out;
1403 
1404 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1405 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1406 	r = _config_request(ioc, &mpi_request, mpi_reply,
1407 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1408 	    sizeof(*config_page));
1409  out:
1410 	return r;
1411 }
1412 
1413 /**
1414  * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1415  * @ioc: per adapter object
1416  * @mpi_reply: reply mf payload returned from firmware
1417  * @config_page: contents of the config page
1418  * @phy_number: phy number
1419  * @handle: expander handle
1420  * Context: sleep.
1421  *
1422  * Return: 0 for success, non-zero for failure.
1423  */
1424 int
1425 mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1426 	*mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1427 	u16 handle)
1428 {
1429 	Mpi2ConfigRequest_t mpi_request;
1430 	int r;
1431 
1432 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1433 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1434 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1435 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1436 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1437 	mpi_request.Header.PageNumber = 1;
1438 	mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1439 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1440 	r = _config_request(ioc, &mpi_request, mpi_reply,
1441 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1442 	if (r)
1443 		goto out;
1444 
1445 	mpi_request.PageAddress =
1446 	    cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1447 	    (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1448 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1449 	r = _config_request(ioc, &mpi_request, mpi_reply,
1450 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1451 	    sizeof(*config_page));
1452  out:
1453 	return r;
1454 }
1455 
1456 /**
1457  * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1458  * @ioc: per adapter object
1459  * @mpi_reply: reply mf payload returned from firmware
1460  * @config_page: contents of the config page
1461  * @form: GET_NEXT_HANDLE or HANDLE
1462  * @handle: expander handle
1463  * Context: sleep.
1464  *
1465  * Return: 0 for success, non-zero for failure.
1466  */
1467 int
1468 mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1469 	*mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1470 {
1471 	Mpi2ConfigRequest_t mpi_request;
1472 	int r;
1473 
1474 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1475 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1476 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1477 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1478 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1479 	mpi_request.Header.PageNumber = 0;
1480 	mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1481 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1482 	r = _config_request(ioc, &mpi_request, mpi_reply,
1483 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1484 	if (r)
1485 		goto out;
1486 
1487 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1488 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1489 	r = _config_request(ioc, &mpi_request, mpi_reply,
1490 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1491 	    sizeof(*config_page));
1492  out:
1493 	return r;
1494 }
1495 
1496 /**
1497  * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1498  * @ioc: per adapter object
1499  * @mpi_reply: reply mf payload returned from firmware
1500  * @config_page: contents of the config page
1501  * @phy_number: phy number
1502  * Context: sleep.
1503  *
1504  * Return: 0 for success, non-zero for failure.
1505  */
1506 int
1507 mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1508 	*mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1509 {
1510 	Mpi2ConfigRequest_t mpi_request;
1511 	int r;
1512 
1513 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1514 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1515 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1516 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1517 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1518 	mpi_request.Header.PageNumber = 0;
1519 	mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1520 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1521 	r = _config_request(ioc, &mpi_request, mpi_reply,
1522 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1523 	if (r)
1524 		goto out;
1525 
1526 	mpi_request.PageAddress =
1527 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1528 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1529 	r = _config_request(ioc, &mpi_request, mpi_reply,
1530 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1531 	    sizeof(*config_page));
1532  out:
1533 	return r;
1534 }
1535 
1536 /**
1537  * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1538  * @ioc: per adapter object
1539  * @mpi_reply: reply mf payload returned from firmware
1540  * @config_page: contents of the config page
1541  * @phy_number: phy number
1542  * Context: sleep.
1543  *
1544  * Return: 0 for success, non-zero for failure.
1545  */
1546 int
1547 mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1548 	*mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1549 {
1550 	Mpi2ConfigRequest_t mpi_request;
1551 	int r;
1552 
1553 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1554 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1555 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1556 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1557 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1558 	mpi_request.Header.PageNumber = 1;
1559 	mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1560 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1561 	r = _config_request(ioc, &mpi_request, mpi_reply,
1562 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1563 	if (r)
1564 		goto out;
1565 
1566 	mpi_request.PageAddress =
1567 	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1568 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1569 	r = _config_request(ioc, &mpi_request, mpi_reply,
1570 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1571 	    sizeof(*config_page));
1572  out:
1573 	return r;
1574 }
1575 
1576 /**
1577  * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1578  * @ioc: per adapter object
1579  * @mpi_reply: reply mf payload returned from firmware
1580  * @config_page: contents of the config page
1581  * @form: GET_NEXT_HANDLE or HANDLE
1582  * @handle: volume handle
1583  * Context: sleep.
1584  *
1585  * Return: 0 for success, non-zero for failure.
1586  */
1587 int
1588 mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1589 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1590 	u32 handle)
1591 {
1592 	Mpi2ConfigRequest_t mpi_request;
1593 	int r;
1594 
1595 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1596 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1597 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1598 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1599 	mpi_request.Header.PageNumber = 1;
1600 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1601 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1602 	r = _config_request(ioc, &mpi_request, mpi_reply,
1603 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1604 	if (r)
1605 		goto out;
1606 
1607 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1608 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1609 	r = _config_request(ioc, &mpi_request, mpi_reply,
1610 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1611 	    sizeof(*config_page));
1612  out:
1613 	return r;
1614 }
1615 
1616 /**
1617  * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1618  * @ioc: per adapter object
1619  * @handle: volume handle
1620  * @num_pds: returns pds count
1621  * Context: sleep.
1622  *
1623  * Return: 0 for success, non-zero for failure.
1624  */
1625 int
1626 mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1627 	u8 *num_pds)
1628 {
1629 	Mpi2ConfigRequest_t mpi_request;
1630 	Mpi2RaidVolPage0_t config_page;
1631 	Mpi2ConfigReply_t mpi_reply;
1632 	int r;
1633 	u16 ioc_status;
1634 
1635 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1636 	*num_pds = 0;
1637 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1638 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1639 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1640 	mpi_request.Header.PageNumber = 0;
1641 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1642 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1643 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1644 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1645 	if (r)
1646 		goto out;
1647 
1648 	mpi_request.PageAddress =
1649 	    cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1650 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1651 	r = _config_request(ioc, &mpi_request, &mpi_reply,
1652 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1653 	    sizeof(Mpi2RaidVolPage0_t));
1654 	if (!r) {
1655 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1656 		    MPI2_IOCSTATUS_MASK;
1657 		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1658 			*num_pds = config_page.NumPhysDisks;
1659 	}
1660 
1661  out:
1662 	return r;
1663 }
1664 
1665 /**
1666  * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1667  * @ioc: per adapter object
1668  * @mpi_reply: reply mf payload returned from firmware
1669  * @config_page: contents of the config page
1670  * @form: GET_NEXT_HANDLE or HANDLE
1671  * @handle: volume handle
1672  * @sz: size of buffer passed in config_page
1673  * Context: sleep.
1674  *
1675  * Return: 0 for success, non-zero for failure.
1676  */
1677 int
1678 mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1679 	Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1680 	u32 handle, u16 sz)
1681 {
1682 	Mpi2ConfigRequest_t mpi_request;
1683 	int r;
1684 
1685 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1686 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1687 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1688 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1689 	mpi_request.Header.PageNumber = 0;
1690 	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1691 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1692 	r = _config_request(ioc, &mpi_request, mpi_reply,
1693 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1694 	if (r)
1695 		goto out;
1696 
1697 	mpi_request.PageAddress = cpu_to_le32(form | handle);
1698 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1699 	r = _config_request(ioc, &mpi_request, mpi_reply,
1700 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1701  out:
1702 	return r;
1703 }
1704 
1705 /**
1706  * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1707  * @ioc: per adapter object
1708  * @mpi_reply: reply mf payload returned from firmware
1709  * @config_page: contents of the config page
1710  * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1711  * @form_specific: specific to the form
1712  * Context: sleep.
1713  *
1714  * Return: 0 for success, non-zero for failure.
1715  */
1716 int
1717 mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1718 	*mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1719 	u32 form_specific)
1720 {
1721 	Mpi2ConfigRequest_t mpi_request;
1722 	int r;
1723 
1724 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1725 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1726 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1727 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1728 	mpi_request.Header.PageNumber = 0;
1729 	mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1730 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1731 	r = _config_request(ioc, &mpi_request, mpi_reply,
1732 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1733 	if (r)
1734 		goto out;
1735 
1736 	mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1737 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1738 	r = _config_request(ioc, &mpi_request, mpi_reply,
1739 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1740 	    sizeof(*config_page));
1741  out:
1742 	return r;
1743 }
1744 
1745 /**
1746  * mpt3sas_config_get_driver_trigger_pg0 - obtain driver trigger page 0
1747  * @ioc: per adapter object
1748  * @mpi_reply: reply mf payload returned from firmware
1749  * @config_page: contents of the config page
1750  * Context: sleep.
1751  *
1752  * Returns 0 for success, non-zero for failure.
1753  */
1754 int
1755 mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1756 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1757 {
1758 	Mpi2ConfigRequest_t mpi_request;
1759 	int r;
1760 
1761 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1762 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1763 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1764 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1765 	mpi_request.ExtPageType =
1766 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1767 	mpi_request.Header.PageNumber = 0;
1768 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1769 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1770 	r = _config_request(ioc, &mpi_request, mpi_reply,
1771 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1772 	if (r)
1773 		goto out;
1774 
1775 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1776 	r = _config_request(ioc, &mpi_request, mpi_reply,
1777 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1778 	    sizeof(*config_page));
1779  out:
1780 	return r;
1781 }
1782 
1783 /**
1784  * mpt3sas_config_set_driver_trigger_pg0 - write driver trigger page 0
1785  * @ioc: per adapter object
1786  * @mpi_reply: reply mf payload returned from firmware
1787  * @config_page: contents of the config page
1788  * Context: sleep.
1789  *
1790  * Returns 0 for success, non-zero for failure.
1791  */
1792 static int
1793 _config_set_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1794 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1795 {
1796 	Mpi2ConfigRequest_t mpi_request;
1797 	int r;
1798 
1799 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1800 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1801 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1802 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1803 	mpi_request.ExtPageType =
1804 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1805 	mpi_request.Header.PageNumber = 0;
1806 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1807 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1808 	r = _config_request(ioc, &mpi_request, mpi_reply,
1809 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1810 	if (r)
1811 		goto out;
1812 
1813 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1814 	_config_request(ioc, &mpi_request, mpi_reply,
1815 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1816 	    sizeof(*config_page));
1817 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1818 	r = _config_request(ioc, &mpi_request, mpi_reply,
1819 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1820 	    sizeof(*config_page));
1821  out:
1822 	return r;
1823 }
1824 
1825 /**
1826  * mpt3sas_config_update_driver_trigger_pg0 - update driver trigger page 0
1827  * @ioc: per adapter object
1828  * @trigger_flag: trigger type bit map
1829  * @set: set ot clear trigger values
1830  * Context: sleep.
1831  *
1832  * Returns 0 for success, non-zero for failure.
1833  */
1834 static int
1835 mpt3sas_config_update_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1836 	u16 trigger_flag, bool set)
1837 {
1838 	Mpi26DriverTriggerPage0_t tg_pg0;
1839 	Mpi2ConfigReply_t mpi_reply;
1840 	int rc;
1841 	u16 flags, ioc_status;
1842 
1843 	rc = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
1844 	if (rc)
1845 		return rc;
1846 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1847 	    MPI2_IOCSTATUS_MASK;
1848 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1849 		dcprintk(ioc,
1850 		    ioc_err(ioc,
1851 		    "%s: Failed to get trigger pg0, ioc_status(0x%04x)\n",
1852 		    __func__, ioc_status));
1853 		return -EFAULT;
1854 	}
1855 
1856 	if (set)
1857 		flags = le16_to_cpu(tg_pg0.TriggerFlags) | trigger_flag;
1858 	else
1859 		flags = le16_to_cpu(tg_pg0.TriggerFlags) & ~trigger_flag;
1860 
1861 	tg_pg0.TriggerFlags = cpu_to_le16(flags);
1862 
1863 	rc = _config_set_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
1864 	if (rc)
1865 		return rc;
1866 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1867 	    MPI2_IOCSTATUS_MASK;
1868 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1869 		dcprintk(ioc,
1870 		    ioc_err(ioc,
1871 		    "%s: Failed to update trigger pg0, ioc_status(0x%04x)\n",
1872 		    __func__, ioc_status));
1873 		return -EFAULT;
1874 	}
1875 
1876 	return 0;
1877 }
1878 
1879 /**
1880  * mpt3sas_config_get_driver_trigger_pg1 - obtain driver trigger page 1
1881  * @ioc: per adapter object
1882  * @mpi_reply: reply mf payload returned from firmware
1883  * @config_page: contents of the config page
1884  * Context: sleep.
1885  *
1886  * Returns 0 for success, non-zero for failure.
1887  */
1888 int
1889 mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
1890 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
1891 {
1892 	Mpi2ConfigRequest_t mpi_request;
1893 	int r;
1894 
1895 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1896 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1897 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1898 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1899 	mpi_request.ExtPageType =
1900 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1901 	mpi_request.Header.PageNumber = 1;
1902 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
1903 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1904 	r = _config_request(ioc, &mpi_request, mpi_reply,
1905 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1906 	if (r)
1907 		goto out;
1908 
1909 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1910 	r = _config_request(ioc, &mpi_request, mpi_reply,
1911 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1912 	    sizeof(*config_page));
1913  out:
1914 	return r;
1915 }
1916 
1917 /**
1918  * mpt3sas_config_set_driver_trigger_pg1 - write driver trigger page 1
1919  * @ioc: per adapter object
1920  * @mpi_reply: reply mf payload returned from firmware
1921  * @config_page: contents of the config page
1922  * Context: sleep.
1923  *
1924  * Returns 0 for success, non-zero for failure.
1925  */
1926 static int
1927 _config_set_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
1928 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
1929 {
1930 	Mpi2ConfigRequest_t mpi_request;
1931 	int r;
1932 
1933 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1934 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1935 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1936 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1937 	mpi_request.ExtPageType =
1938 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1939 	mpi_request.Header.PageNumber = 1;
1940 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
1941 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1942 	r = _config_request(ioc, &mpi_request, mpi_reply,
1943 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1944 	if (r)
1945 		goto out;
1946 
1947 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1948 	_config_request(ioc, &mpi_request, mpi_reply,
1949 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1950 	    sizeof(*config_page));
1951 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1952 	r = _config_request(ioc, &mpi_request, mpi_reply,
1953 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1954 	    sizeof(*config_page));
1955  out:
1956 	return r;
1957 }
1958 
1959 /**
1960  * mpt3sas_config_update_driver_trigger_pg1 - update driver trigger page 1
1961  * @ioc: per adapter object
1962  * @master_tg: Master trigger bit map
1963  * @set: set ot clear trigger values
1964  * Context: sleep.
1965  *
1966  * Returns 0 for success, non-zero for failure.
1967  */
1968 int
1969 mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
1970 	struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set)
1971 {
1972 	Mpi26DriverTriggerPage1_t tg_pg1;
1973 	Mpi2ConfigReply_t mpi_reply;
1974 	int rc;
1975 	u16 ioc_status;
1976 
1977 	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
1978 	    MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, set);
1979 	if (rc)
1980 		return rc;
1981 
1982 	rc = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
1983 	if (rc)
1984 		goto out;
1985 
1986 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1987 	    MPI2_IOCSTATUS_MASK;
1988 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1989 		dcprintk(ioc,
1990 		    ioc_err(ioc,
1991 		    "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
1992 		    __func__, ioc_status));
1993 		rc = -EFAULT;
1994 		goto out;
1995 	}
1996 
1997 	if (set) {
1998 		tg_pg1.NumMasterTrigger = cpu_to_le16(1);
1999 		tg_pg1.MasterTriggers[0].MasterTriggerFlags = cpu_to_le32(
2000 		    master_tg->MasterData);
2001 	} else {
2002 		tg_pg1.NumMasterTrigger = 0;
2003 		tg_pg1.MasterTriggers[0].MasterTriggerFlags = 0;
2004 	}
2005 
2006 	rc = _config_set_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
2007 	if (rc)
2008 		goto out;
2009 
2010 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2011 	    MPI2_IOCSTATUS_MASK;
2012 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2013 		dcprintk(ioc,
2014 		    ioc_err(ioc,
2015 		    "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
2016 		    __func__, ioc_status));
2017 		rc = -EFAULT;
2018 		goto out;
2019 	}
2020 
2021 	return 0;
2022 
2023 out:
2024 	mpt3sas_config_update_driver_trigger_pg0(ioc,
2025 	    MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, !set);
2026 
2027 	return rc;
2028 }
2029 
2030 /**
2031  * mpt3sas_config_get_driver_trigger_pg2 - obtain driver trigger page 2
2032  * @ioc: per adapter object
2033  * @mpi_reply: reply mf payload returned from firmware
2034  * @config_page: contents of the config page
2035  * Context: sleep.
2036  *
2037  * Returns 0 for success, non-zero for failure.
2038  */
2039 int
2040 mpt3sas_config_get_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2041 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2042 {
2043 	Mpi2ConfigRequest_t mpi_request;
2044 	int r;
2045 
2046 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2047 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2048 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2049 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2050 	mpi_request.ExtPageType =
2051 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2052 	mpi_request.Header.PageNumber = 2;
2053 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2054 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2055 	r = _config_request(ioc, &mpi_request, mpi_reply,
2056 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2057 	if (r)
2058 		goto out;
2059 
2060 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2061 	r = _config_request(ioc, &mpi_request, mpi_reply,
2062 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2063 	    sizeof(*config_page));
2064  out:
2065 	return r;
2066 }
2067 
2068 /**
2069  * mpt3sas_config_set_driver_trigger_pg2 - write driver trigger page 2
2070  * @ioc: per adapter object
2071  * @mpi_reply: reply mf payload returned from firmware
2072  * @config_page: contents of the config page
2073  * Context: sleep.
2074  *
2075  * Returns 0 for success, non-zero for failure.
2076  */
2077 static int
2078 _config_set_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2079 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2080 {
2081 	Mpi2ConfigRequest_t mpi_request;
2082 	int r;
2083 
2084 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2085 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2086 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2087 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2088 	mpi_request.ExtPageType =
2089 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2090 	mpi_request.Header.PageNumber = 2;
2091 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2092 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2093 	r = _config_request(ioc, &mpi_request, mpi_reply,
2094 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2095 	if (r)
2096 		goto out;
2097 
2098 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2099 	_config_request(ioc, &mpi_request, mpi_reply,
2100 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2101 	    sizeof(*config_page));
2102 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2103 	r = _config_request(ioc, &mpi_request, mpi_reply,
2104 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2105 	    sizeof(*config_page));
2106  out:
2107 	return r;
2108 }
2109 
2110 /**
2111  * mpt3sas_config_update_driver_trigger_pg2 - update driver trigger page 2
2112  * @ioc: per adapter object
2113  * @event_tg: list of Event Triggers
2114  * @set: set ot clear trigger values
2115  * Context: sleep.
2116  *
2117  * Returns 0 for success, non-zero for failure.
2118  */
2119 int
2120 mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2121 	struct SL_WH_EVENT_TRIGGERS_T *event_tg, bool set)
2122 {
2123 	Mpi26DriverTriggerPage2_t tg_pg2;
2124 	Mpi2ConfigReply_t mpi_reply;
2125 	int rc, i, count;
2126 	u16 ioc_status;
2127 
2128 	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2129 	    MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, set);
2130 	if (rc)
2131 		return rc;
2132 
2133 	rc = mpt3sas_config_get_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2134 	if (rc)
2135 		goto out;
2136 
2137 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2138 	    MPI2_IOCSTATUS_MASK;
2139 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2140 		dcprintk(ioc,
2141 		    ioc_err(ioc,
2142 		    "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2143 		    __func__, ioc_status));
2144 		rc = -EFAULT;
2145 		goto out;
2146 	}
2147 
2148 	if (set) {
2149 		count = event_tg->ValidEntries;
2150 		tg_pg2.NumMPIEventTrigger = cpu_to_le16(count);
2151 		for (i = 0; i < count; i++) {
2152 			tg_pg2.MPIEventTriggers[i].MPIEventCode =
2153 			    cpu_to_le16(
2154 			    event_tg->EventTriggerEntry[i].EventValue);
2155 			tg_pg2.MPIEventTriggers[i].MPIEventCodeSpecific =
2156 			    cpu_to_le16(
2157 			    event_tg->EventTriggerEntry[i].LogEntryQualifier);
2158 		}
2159 	} else {
2160 		tg_pg2.NumMPIEventTrigger = 0;
2161 		memset(&tg_pg2.MPIEventTriggers[0], 0,
2162 		    NUM_VALID_ENTRIES * sizeof(
2163 		    MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY));
2164 	}
2165 
2166 	rc = _config_set_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2167 	if (rc)
2168 		goto out;
2169 
2170 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2171 	    MPI2_IOCSTATUS_MASK;
2172 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2173 		dcprintk(ioc,
2174 		    ioc_err(ioc,
2175 		    "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2176 		    __func__, ioc_status));
2177 		rc = -EFAULT;
2178 		goto out;
2179 	}
2180 
2181 	return 0;
2182 
2183 out:
2184 	mpt3sas_config_update_driver_trigger_pg0(ioc,
2185 	    MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, !set);
2186 
2187 	return rc;
2188 }
2189 
2190 /**
2191  * mpt3sas_config_get_driver_trigger_pg3 - obtain driver trigger page 3
2192  * @ioc: per adapter object
2193  * @mpi_reply: reply mf payload returned from firmware
2194  * @config_page: contents of the config page
2195  * Context: sleep.
2196  *
2197  * Returns 0 for success, non-zero for failure.
2198  */
2199 int
2200 mpt3sas_config_get_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2201 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2202 {
2203 	Mpi2ConfigRequest_t mpi_request;
2204 	int r;
2205 
2206 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2207 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2208 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2209 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2210 	mpi_request.ExtPageType =
2211 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2212 	mpi_request.Header.PageNumber = 3;
2213 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2214 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2215 	r = _config_request(ioc, &mpi_request, mpi_reply,
2216 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2217 	if (r)
2218 		goto out;
2219 
2220 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2221 	r = _config_request(ioc, &mpi_request, mpi_reply,
2222 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2223 	    sizeof(*config_page));
2224  out:
2225 	return r;
2226 }
2227 
2228 /**
2229  * mpt3sas_config_set_driver_trigger_pg3 - write driver trigger page 3
2230  * @ioc: per adapter object
2231  * @mpi_reply: reply mf payload returned from firmware
2232  * @config_page: contents of the config page
2233  * Context: sleep.
2234  *
2235  * Returns 0 for success, non-zero for failure.
2236  */
2237 static int
2238 _config_set_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2239 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2240 {
2241 	Mpi2ConfigRequest_t mpi_request;
2242 	int r;
2243 
2244 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2245 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2246 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2247 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2248 	mpi_request.ExtPageType =
2249 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2250 	mpi_request.Header.PageNumber = 3;
2251 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2252 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2253 	r = _config_request(ioc, &mpi_request, mpi_reply,
2254 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2255 	if (r)
2256 		goto out;
2257 
2258 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2259 	_config_request(ioc, &mpi_request, mpi_reply,
2260 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2261 	    sizeof(*config_page));
2262 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2263 	r = _config_request(ioc, &mpi_request, mpi_reply,
2264 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2265 	    sizeof(*config_page));
2266  out:
2267 	return r;
2268 }
2269 
2270 /**
2271  * mpt3sas_config_update_driver_trigger_pg3 - update driver trigger page 3
2272  * @ioc: per adapter object
2273  * @scsi_tg: scsi trigger list
2274  * @set: set ot clear trigger values
2275  * Context: sleep.
2276  *
2277  * Returns 0 for success, non-zero for failure.
2278  */
2279 int
2280 mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2281 	struct SL_WH_SCSI_TRIGGERS_T *scsi_tg, bool set)
2282 {
2283 	Mpi26DriverTriggerPage3_t tg_pg3;
2284 	Mpi2ConfigReply_t mpi_reply;
2285 	int rc, i, count;
2286 	u16 ioc_status;
2287 
2288 	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2289 	    MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, set);
2290 	if (rc)
2291 		return rc;
2292 
2293 	rc = mpt3sas_config_get_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2294 	if (rc)
2295 		goto out;
2296 
2297 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2298 	    MPI2_IOCSTATUS_MASK;
2299 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2300 		dcprintk(ioc,
2301 		    ioc_err(ioc,
2302 		    "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2303 		    __func__, ioc_status));
2304 		return -EFAULT;
2305 	}
2306 
2307 	if (set) {
2308 		count = scsi_tg->ValidEntries;
2309 		tg_pg3.NumSCSISenseTrigger = cpu_to_le16(count);
2310 		for (i = 0; i < count; i++) {
2311 			tg_pg3.SCSISenseTriggers[i].ASCQ =
2312 			    scsi_tg->SCSITriggerEntry[i].ASCQ;
2313 			tg_pg3.SCSISenseTriggers[i].ASC =
2314 			    scsi_tg->SCSITriggerEntry[i].ASC;
2315 			tg_pg3.SCSISenseTriggers[i].SenseKey =
2316 			    scsi_tg->SCSITriggerEntry[i].SenseKey;
2317 		}
2318 	} else {
2319 		tg_pg3.NumSCSISenseTrigger = 0;
2320 		memset(&tg_pg3.SCSISenseTriggers[0], 0,
2321 		    NUM_VALID_ENTRIES * sizeof(
2322 		    MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY));
2323 	}
2324 
2325 	rc = _config_set_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2326 	if (rc)
2327 		goto out;
2328 
2329 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2330 	    MPI2_IOCSTATUS_MASK;
2331 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2332 		dcprintk(ioc,
2333 		    ioc_err(ioc,
2334 		    "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2335 		     __func__, ioc_status));
2336 		return -EFAULT;
2337 	}
2338 
2339 	return 0;
2340 out:
2341 	mpt3sas_config_update_driver_trigger_pg0(ioc,
2342 	    MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, !set);
2343 
2344 	return rc;
2345 }
2346 
2347 /**
2348  * mpt3sas_config_get_driver_trigger_pg4 - obtain driver trigger page 4
2349  * @ioc: per adapter object
2350  * @mpi_reply: reply mf payload returned from firmware
2351  * @config_page: contents of the config page
2352  * Context: sleep.
2353  *
2354  * Returns 0 for success, non-zero for failure.
2355  */
2356 int
2357 mpt3sas_config_get_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2358 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2359 {
2360 	Mpi2ConfigRequest_t mpi_request;
2361 	int r;
2362 
2363 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2364 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2365 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2366 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2367 	mpi_request.ExtPageType =
2368 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2369 	mpi_request.Header.PageNumber = 4;
2370 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2371 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2372 	r = _config_request(ioc, &mpi_request, mpi_reply,
2373 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2374 	if (r)
2375 		goto out;
2376 
2377 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2378 	r = _config_request(ioc, &mpi_request, mpi_reply,
2379 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2380 	    sizeof(*config_page));
2381  out:
2382 	return r;
2383 }
2384 
2385 /**
2386  * mpt3sas_config_set_driver_trigger_pg4 - write driver trigger page 4
2387  * @ioc: per adapter object
2388  * @mpi_reply: reply mf payload returned from firmware
2389  * @config_page: contents of the config page
2390  * Context: sleep.
2391  *
2392  * Returns 0 for success, non-zero for failure.
2393  */
2394 static int
2395 _config_set_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2396 	Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2397 {
2398 	Mpi2ConfigRequest_t mpi_request;
2399 	int r;
2400 
2401 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2402 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2403 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2404 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2405 	mpi_request.ExtPageType =
2406 	    MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2407 	mpi_request.Header.PageNumber = 4;
2408 	mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2409 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2410 	r = _config_request(ioc, &mpi_request, mpi_reply,
2411 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2412 	if (r)
2413 		goto out;
2414 
2415 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2416 	_config_request(ioc, &mpi_request, mpi_reply,
2417 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2418 	    sizeof(*config_page));
2419 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2420 	r = _config_request(ioc, &mpi_request, mpi_reply,
2421 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2422 	    sizeof(*config_page));
2423  out:
2424 	return r;
2425 }
2426 
2427 /**
2428  * mpt3sas_config_update_driver_trigger_pg4 - update driver trigger page 4
2429  * @ioc: per adapter object
2430  * @mpi_tg: mpi trigger list
2431  * @set: set ot clear trigger values
2432  * Context: sleep.
2433  *
2434  * Returns 0 for success, non-zero for failure.
2435  */
2436 int
2437 mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2438 	struct SL_WH_MPI_TRIGGERS_T *mpi_tg, bool set)
2439 {
2440 	Mpi26DriverTriggerPage4_t tg_pg4;
2441 	Mpi2ConfigReply_t mpi_reply;
2442 	int rc, i, count;
2443 	u16 ioc_status;
2444 
2445 	rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2446 	    MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, set);
2447 	if (rc)
2448 		return rc;
2449 
2450 	rc = mpt3sas_config_get_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2451 	if (rc)
2452 		goto out;
2453 
2454 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2455 	    MPI2_IOCSTATUS_MASK;
2456 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2457 		dcprintk(ioc,
2458 		    ioc_err(ioc,
2459 		    "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2460 		    __func__, ioc_status));
2461 		rc = -EFAULT;
2462 		goto out;
2463 	}
2464 
2465 	if (set) {
2466 		count = mpi_tg->ValidEntries;
2467 		tg_pg4.NumIOCStatusLogInfoTrigger = cpu_to_le16(count);
2468 		for (i = 0; i < count; i++) {
2469 			tg_pg4.IOCStatusLoginfoTriggers[i].IOCStatus =
2470 			    cpu_to_le16(mpi_tg->MPITriggerEntry[i].IOCStatus);
2471 			tg_pg4.IOCStatusLoginfoTriggers[i].LogInfo =
2472 			    cpu_to_le32(mpi_tg->MPITriggerEntry[i].IocLogInfo);
2473 		}
2474 	} else {
2475 		tg_pg4.NumIOCStatusLogInfoTrigger = 0;
2476 		memset(&tg_pg4.IOCStatusLoginfoTriggers[0], 0,
2477 		    NUM_VALID_ENTRIES * sizeof(
2478 		    MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY));
2479 	}
2480 
2481 	rc = _config_set_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2482 	if (rc)
2483 		goto out;
2484 
2485 	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2486 	    MPI2_IOCSTATUS_MASK;
2487 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2488 		dcprintk(ioc,
2489 		    ioc_err(ioc,
2490 		    "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2491 		    __func__, ioc_status));
2492 		rc = -EFAULT;
2493 		goto out;
2494 	}
2495 
2496 	return 0;
2497 
2498 out:
2499 	mpt3sas_config_update_driver_trigger_pg0(ioc,
2500 	    MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, !set);
2501 
2502 	return rc;
2503 }
2504 
2505 /**
2506  * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
2507  * raid components
2508  * @ioc: per adapter object
2509  * @pd_handle: phys disk handle
2510  * @volume_handle: volume handle
2511  * Context: sleep.
2512  *
2513  * Return: 0 for success, non-zero for failure.
2514  */
2515 int
2516 mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
2517 	u16 *volume_handle)
2518 {
2519 	Mpi2RaidConfigurationPage0_t *config_page = NULL;
2520 	Mpi2ConfigRequest_t mpi_request;
2521 	Mpi2ConfigReply_t mpi_reply;
2522 	int r, i, config_page_sz;
2523 	u16 ioc_status;
2524 	int config_num;
2525 	u16 element_type;
2526 	u16 phys_disk_dev_handle;
2527 
2528 	*volume_handle = 0;
2529 	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2530 	mpi_request.Function = MPI2_FUNCTION_CONFIG;
2531 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2532 	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2533 	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
2534 	mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
2535 	mpi_request.Header.PageNumber = 0;
2536 	ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2537 	r = _config_request(ioc, &mpi_request, &mpi_reply,
2538 	    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2539 	if (r)
2540 		goto out;
2541 
2542 	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2543 	config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
2544 	config_page = kmalloc(config_page_sz, GFP_KERNEL);
2545 	if (!config_page) {
2546 		r = -1;
2547 		goto out;
2548 	}
2549 
2550 	config_num = 0xff;
2551 	while (1) {
2552 		mpi_request.PageAddress = cpu_to_le32(config_num +
2553 		    MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
2554 		r = _config_request(ioc, &mpi_request, &mpi_reply,
2555 		    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2556 		    config_page_sz);
2557 		if (r)
2558 			goto out;
2559 		r = -1;
2560 		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2561 		    MPI2_IOCSTATUS_MASK;
2562 		if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
2563 			goto out;
2564 		for (i = 0; i < config_page->NumElements; i++) {
2565 			element_type = le16_to_cpu(config_page->
2566 			    ConfigElement[i].ElementFlags) &
2567 			    MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
2568 			if (element_type ==
2569 			    MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
2570 			    element_type ==
2571 			    MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
2572 				phys_disk_dev_handle =
2573 				    le16_to_cpu(config_page->ConfigElement[i].
2574 				    PhysDiskDevHandle);
2575 				if (phys_disk_dev_handle == pd_handle) {
2576 					*volume_handle =
2577 					    le16_to_cpu(config_page->
2578 					    ConfigElement[i].VolDevHandle);
2579 					r = 0;
2580 					goto out;
2581 				}
2582 			} else if (element_type ==
2583 			    MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
2584 				*volume_handle = 0;
2585 				r = 0;
2586 				goto out;
2587 			}
2588 		}
2589 		config_num = config_page->ConfigNum;
2590 	}
2591  out:
2592 	kfree(config_page);
2593 	return r;
2594 }
2595 
2596 /**
2597  * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
2598  * @ioc: per adapter object
2599  * @volume_handle: volume handle
2600  * @wwid: volume wwid
2601  * Context: sleep.
2602  *
2603  * Return: 0 for success, non-zero for failure.
2604  */
2605 int
2606 mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
2607 	u64 *wwid)
2608 {
2609 	Mpi2ConfigReply_t mpi_reply;
2610 	Mpi2RaidVolPage1_t raid_vol_pg1;
2611 
2612 	*wwid = 0;
2613 	if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
2614 	    &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
2615 	    volume_handle))) {
2616 		*wwid = le64_to_cpu(raid_vol_pg1.WWID);
2617 		return 0;
2618 	} else
2619 		return -1;
2620 }
2621