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