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

source code of linux/drivers/scsi/mpt3sas/mpt3sas_config.c