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