aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt3sas/mpt3sas_config.c
diff options
context:
space:
mode:
authorSreekanth Reddy <Sreekanth.Reddy@lsi.com>2012-11-29 21:14:21 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-12-01 05:09:17 -0500
commitf92363d12359498f9a9960511de1a550f0ec41c2 (patch)
treec7f34e33b085b5da0b36e8d830cd98fc74d5ab58 /drivers/scsi/mpt3sas/mpt3sas_config.c
parentd84fd392bd61524c4d81367969424e6c17086c8c (diff)
[SCSI] mpt3sas: add new driver supporting 12GB SAS
These driver files are initially, substantially similar to mpt2sas but, because mpt2sas is going into maintenance mode and mp3sas will become heavily developed, we elected to keep the code bases separate. Signed-off-by: Sreekanth Reddy <Sreekanth.Reddy@lsi.com> Reviewed-by: Nagalakshmi Nandigama <Nagalakshmi.Nandigama@lsi.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/mpt3sas/mpt3sas_config.c')
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_config.c1650
1 files changed, 1650 insertions, 0 deletions
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c
new file mode 100644
index 000000000000..ce7e59b2fc08
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -0,0 +1,1650 @@
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 LSI Corporation
6 * (mailto:DL-MPTFusionLinux@lsi.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * NO WARRANTY
19 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
20 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
23 * solely responsible for determining the appropriateness of using and
24 * distributing the Program and assumes all risks associated with its
25 * exercise of rights under this Agreement, including but not limited to
26 * the risks and costs of program errors, damage to or loss of data,
27 * programs or equipment, and unavailability or interruption of operations.
28
29 * DISCLAIMER OF LIABILITY
30 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
36 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
37
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
41 * USA.
42 */
43
44#include <linux/version.h>
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#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
87/**
88 * _config_display_some_debug - debug routine
89 * @ioc: per adapter object
90 * @smid: system request message index
91 * @calling_function_name: string pass from calling function
92 * @mpi_reply: reply message frame
93 * Context: none.
94 *
95 * Function for displaying debug info helpful when debugging issues
96 * in this module.
97 */
98static void
99_config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
100 char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
101{
102 Mpi2ConfigRequest_t *mpi_request;
103 char *desc = NULL;
104
105 if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
106 return;
107
108 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
109 switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
110 case MPI2_CONFIG_PAGETYPE_IO_UNIT:
111 desc = "io_unit";
112 break;
113 case MPI2_CONFIG_PAGETYPE_IOC:
114 desc = "ioc";
115 break;
116 case MPI2_CONFIG_PAGETYPE_BIOS:
117 desc = "bios";
118 break;
119 case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
120 desc = "raid_volume";
121 break;
122 case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
123 desc = "manufaucturing";
124 break;
125 case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
126 desc = "physdisk";
127 break;
128 case MPI2_CONFIG_PAGETYPE_EXTENDED:
129 switch (mpi_request->ExtPageType) {
130 case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
131 desc = "sas_io_unit";
132 break;
133 case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
134 desc = "sas_expander";
135 break;
136 case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
137 desc = "sas_device";
138 break;
139 case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
140 desc = "sas_phy";
141 break;
142 case MPI2_CONFIG_EXTPAGETYPE_LOG:
143 desc = "log";
144 break;
145 case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
146 desc = "enclosure";
147 break;
148 case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
149 desc = "raid_config";
150 break;
151 case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
152 desc = "driver_mappping";
153 break;
154 }
155 break;
156 }
157
158 if (!desc)
159 return;
160
161 pr_info(MPT3SAS_FMT
162 "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n",
163 ioc->name, calling_function_name, desc,
164 mpi_request->Header.PageNumber, mpi_request->Action,
165 le32_to_cpu(mpi_request->PageAddress), smid);
166
167 if (!mpi_reply)
168 return;
169
170 if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
171 pr_info(MPT3SAS_FMT
172 "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
173 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
174 le32_to_cpu(mpi_reply->IOCLogInfo));
175}
176#endif
177
178/**
179 * _config_alloc_config_dma_memory - obtain physical memory
180 * @ioc: per adapter object
181 * @mem: struct config_request
182 *
183 * A wrapper for obtaining dma-able memory for config page request.
184 *
185 * Returns 0 for success, non-zero for failure.
186 */
187static int
188_config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
189 struct config_request *mem)
190{
191 int r = 0;
192
193 if (mem->sz > ioc->config_page_sz) {
194 mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
195 &mem->page_dma, GFP_KERNEL);
196 if (!mem->page) {
197 pr_err(MPT3SAS_FMT
198 "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n",
199 ioc->name, __func__, mem->sz);
200 r = -ENOMEM;
201 }
202 } else { /* use tmp buffer if less than 512 bytes */
203 mem->page = ioc->config_page;
204 mem->page_dma = ioc->config_page_dma;
205 }
206 return r;
207}
208
209/**
210 * _config_free_config_dma_memory - wrapper to free the memory
211 * @ioc: per adapter object
212 * @mem: struct config_request
213 *
214 * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
215 *
216 * Returns 0 for success, non-zero for failure.
217 */
218static void
219_config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
220 struct config_request *mem)
221{
222 if (mem->sz > ioc->config_page_sz)
223 dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
224 mem->page_dma);
225}
226
227/**
228 * mpt3sas_config_done - config page completion routine
229 * @ioc: per adapter object
230 * @smid: system request message index
231 * @msix_index: MSIX table index supplied by the OS
232 * @reply: reply message frame(lower 32bit addr)
233 * Context: none.
234 *
235 * The callback handler when using _config_request.
236 *
237 * Return 1 meaning mf should be freed from _base_interrupt
238 * 0 means the mf is freed from this function.
239 */
240u8
241mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
242 u32 reply)
243{
244 MPI2DefaultReply_t *mpi_reply;
245
246 if (ioc->config_cmds.status == MPT3_CMD_NOT_USED)
247 return 1;
248 if (ioc->config_cmds.smid != smid)
249 return 1;
250 ioc->config_cmds.status |= MPT3_CMD_COMPLETE;
251 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
252 if (mpi_reply) {
253 ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID;
254 memcpy(ioc->config_cmds.reply, mpi_reply,
255 mpi_reply->MsgLength*4);
256 }
257 ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
258#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
259 _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
260#endif
261 ioc->config_cmds.smid = USHRT_MAX;
262 complete(&ioc->config_cmds.done);
263 return 1;
264}
265
266/**
267 * _config_request - main routine for sending config page requests
268 * @ioc: per adapter object
269 * @mpi_request: request message frame
270 * @mpi_reply: reply mf payload returned from firmware
271 * @timeout: timeout in seconds
272 * @config_page: contents of the config page
273 * @config_page_sz: size of config page
274 * Context: sleep
275 *
276 * A generic API for config page requests to firmware.
277 *
278 * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling
279 * this API.
280 *
281 * The callback index is set inside `ioc->config_cb_idx.
282 *
283 * Returns 0 for success, non-zero for failure.
284 */
285static int
286_config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
287 *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
288 void *config_page, u16 config_page_sz)
289{
290 u16 smid;
291 u32 ioc_state;
292 unsigned long timeleft;
293 Mpi2ConfigRequest_t *config_request;
294 int r;
295 u8 retry_count, issue_host_reset = 0;
296 u16 wait_state_count;
297 struct config_request mem;
298 u32 ioc_status = UINT_MAX;
299
300 mutex_lock(&ioc->config_cmds.mutex);
301 if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
302 pr_err(MPT3SAS_FMT "%s: config_cmd in use\n",
303 ioc->name, __func__);
304 mutex_unlock(&ioc->config_cmds.mutex);
305 return -EAGAIN;
306 }
307
308 retry_count = 0;
309 memset(&mem, 0, sizeof(struct config_request));
310
311 mpi_request->VF_ID = 0; /* TODO */
312 mpi_request->VP_ID = 0;
313
314 if (config_page) {
315 mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
316 mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
317 mpi_request->Header.PageType = mpi_reply->Header.PageType;
318 mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
319 mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
320 mpi_request->ExtPageType = mpi_reply->ExtPageType;
321 if (mpi_request->Header.PageLength)
322 mem.sz = mpi_request->Header.PageLength * 4;
323 else
324 mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
325 r = _config_alloc_config_dma_memory(ioc, &mem);
326 if (r != 0)
327 goto out;
328 if (mpi_request->Action ==
329 MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
330 mpi_request->Action ==
331 MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
332 ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
333 MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
334 mem.page_dma);
335 memcpy(mem.page, config_page, min_t(u16, mem.sz,
336 config_page_sz));
337 } else {
338 memset(config_page, 0, config_page_sz);
339 ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
340 MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
341 memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
342 }
343 }
344
345 retry_config:
346 if (retry_count) {
347 if (retry_count > 2) { /* attempt only 2 retries */
348 r = -EFAULT;
349 goto free_mem;
350 }
351 pr_info(MPT3SAS_FMT "%s: attempting retry (%d)\n",
352 ioc->name, __func__, retry_count);
353 }
354 wait_state_count = 0;
355 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
356 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
357 if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) {
358 pr_err(MPT3SAS_FMT
359 "%s: failed due to ioc not operational\n",
360 ioc->name, __func__);
361 ioc->config_cmds.status = MPT3_CMD_NOT_USED;
362 r = -EFAULT;
363 goto free_mem;
364 }
365 ssleep(1);
366 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
367 pr_info(MPT3SAS_FMT
368 "%s: waiting for operational state(count=%d)\n",
369 ioc->name, __func__, wait_state_count);
370 }
371 if (wait_state_count)
372 pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
373 ioc->name, __func__);
374
375 smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
376 if (!smid) {
377 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
378 ioc->name, __func__);
379 ioc->config_cmds.status = MPT3_CMD_NOT_USED;
380 r = -EAGAIN;
381 goto free_mem;
382 }
383
384 r = 0;
385 memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
386 ioc->config_cmds.status = MPT3_CMD_PENDING;
387 config_request = mpt3sas_base_get_msg_frame(ioc, smid);
388 ioc->config_cmds.smid = smid;
389 memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
390#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
391 _config_display_some_debug(ioc, smid, "config_request", NULL);
392#endif
393 init_completion(&ioc->config_cmds.done);
394 mpt3sas_base_put_smid_default(ioc, smid);
395 timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
396 timeout*HZ);
397 if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
398 pr_err(MPT3SAS_FMT "%s: timeout\n",
399 ioc->name, __func__);
400 _debug_dump_mf(mpi_request,
401 sizeof(Mpi2ConfigRequest_t)/4);
402 retry_count++;
403 if (ioc->config_cmds.smid == smid)
404 mpt3sas_base_free_smid(ioc, smid);
405 if ((ioc->shost_recovery) || (ioc->config_cmds.status &
406 MPT3_CMD_RESET) || ioc->pci_error_recovery)
407 goto retry_config;
408 issue_host_reset = 1;
409 r = -EFAULT;
410 goto free_mem;
411 }
412
413 if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
414 memcpy(mpi_reply, ioc->config_cmds.reply,
415 sizeof(Mpi2ConfigReply_t));
416
417 /* Reply Frame Sanity Checks to workaround FW issues */
418 if ((mpi_request->Header.PageType & 0xF) !=
419 (mpi_reply->Header.PageType & 0xF)) {
420 _debug_dump_mf(mpi_request, ioc->request_sz/4);
421 _debug_dump_reply(mpi_reply, ioc->request_sz/4);
422 panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
423 " mpi_reply mismatch: Requested PageType(0x%02x)" \
424 " Reply PageType(0x%02x)\n", \
425 ioc->name, __func__,
426 (mpi_request->Header.PageType & 0xF),
427 (mpi_reply->Header.PageType & 0xF));
428 }
429
430 if (((mpi_request->Header.PageType & 0xF) ==
431 MPI2_CONFIG_PAGETYPE_EXTENDED) &&
432 mpi_request->ExtPageType != mpi_reply->ExtPageType) {
433 _debug_dump_mf(mpi_request, ioc->request_sz/4);
434 _debug_dump_reply(mpi_reply, ioc->request_sz/4);
435 panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
436 " mpi_reply mismatch: Requested ExtPageType(0x%02x)"
437 " Reply ExtPageType(0x%02x)\n",
438 ioc->name, __func__, mpi_request->ExtPageType,
439 mpi_reply->ExtPageType);
440 }
441 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
442 & MPI2_IOCSTATUS_MASK;
443 }
444
445 if (retry_count)
446 pr_info(MPT3SAS_FMT "%s: retry (%d) completed!!\n", \
447 ioc->name, __func__, retry_count);
448
449 if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
450 config_page && mpi_request->Action ==
451 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
452 u8 *p = (u8 *)mem.page;
453
454 /* Config Page Sanity Checks to workaround FW issues */
455 if (p) {
456 if ((mpi_request->Header.PageType & 0xF) !=
457 (p[3] & 0xF)) {
458 _debug_dump_mf(mpi_request, ioc->request_sz/4);
459 _debug_dump_reply(mpi_reply, ioc->request_sz/4);
460 _debug_dump_config(p, min_t(u16, mem.sz,
461 config_page_sz)/4);
462 panic(KERN_WARNING MPT3SAS_FMT
463 "%s: Firmware BUG:" \
464 " config page mismatch:"
465 " Requested PageType(0x%02x)"
466 " Reply PageType(0x%02x)\n",
467 ioc->name, __func__,
468 (mpi_request->Header.PageType & 0xF),
469 (p[3] & 0xF));
470 }
471
472 if (((mpi_request->Header.PageType & 0xF) ==
473 MPI2_CONFIG_PAGETYPE_EXTENDED) &&
474 (mpi_request->ExtPageType != p[6])) {
475 _debug_dump_mf(mpi_request, ioc->request_sz/4);
476 _debug_dump_reply(mpi_reply, ioc->request_sz/4);
477 _debug_dump_config(p, min_t(u16, mem.sz,
478 config_page_sz)/4);
479 panic(KERN_WARNING MPT3SAS_FMT
480 "%s: Firmware BUG:" \
481 " config page mismatch:"
482 " Requested ExtPageType(0x%02x)"
483 " Reply ExtPageType(0x%02x)\n",
484 ioc->name, __func__,
485 mpi_request->ExtPageType, p[6]);
486 }
487 }
488 memcpy(config_page, mem.page, min_t(u16, mem.sz,
489 config_page_sz));
490 }
491
492 free_mem:
493 if (config_page)
494 _config_free_config_dma_memory(ioc, &mem);
495 out:
496 ioc->config_cmds.status = MPT3_CMD_NOT_USED;
497 mutex_unlock(&ioc->config_cmds.mutex);
498
499 if (issue_host_reset)
500 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
501 FORCE_BIG_HAMMER);
502 return r;
503}
504
505/**
506 * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
507 * @ioc: per adapter object
508 * @mpi_reply: reply mf payload returned from firmware
509 * @config_page: contents of the config page
510 * Context: sleep.
511 *
512 * Returns 0 for success, non-zero for failure.
513 */
514int
515mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
516 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
517{
518 Mpi2ConfigRequest_t mpi_request;
519 int r;
520
521 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
522 mpi_request.Function = MPI2_FUNCTION_CONFIG;
523 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
524 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
525 mpi_request.Header.PageNumber = 0;
526 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
527 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
528 r = _config_request(ioc, &mpi_request, mpi_reply,
529 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
530 if (r)
531 goto out;
532
533 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
534 r = _config_request(ioc, &mpi_request, mpi_reply,
535 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
536 sizeof(*config_page));
537 out:
538 return r;
539}
540
541/**
542 * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
543 * @ioc: per adapter object
544 * @mpi_reply: reply mf payload returned from firmware
545 * @config_page: contents of the config page
546 * @sz: size of buffer passed in config_page
547 * Context: sleep.
548 *
549 * Returns 0 for success, non-zero for failure.
550 */
551int
552mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
553 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
554 u16 sz)
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 = 7;
564 mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
565 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
566 r = _config_request(ioc, &mpi_request, mpi_reply,
567 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
568 if (r)
569 goto out;
570
571 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
572 r = _config_request(ioc, &mpi_request, mpi_reply,
573 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
574 sz);
575 out:
576 return r;
577}
578
579/**
580 * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
581 * @ioc: per adapter object
582 * @mpi_reply: reply mf payload returned from firmware
583 * @config_page: contents of the config page
584 * Context: sleep.
585 *
586 * Returns 0 for success, non-zero for failure.
587 */
588int
589mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
590 Mpi2ConfigReply_t *mpi_reply,
591 struct Mpi2ManufacturingPage10_t *config_page)
592{
593 Mpi2ConfigRequest_t mpi_request;
594 int r;
595
596 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
597 mpi_request.Function = MPI2_FUNCTION_CONFIG;
598 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
599 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
600 mpi_request.Header.PageNumber = 10;
601 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
602 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
603 r = _config_request(ioc, &mpi_request, mpi_reply,
604 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
605 if (r)
606 goto out;
607
608 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
609 r = _config_request(ioc, &mpi_request, mpi_reply,
610 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
611 sizeof(*config_page));
612 out:
613 return r;
614}
615
616/**
617 * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
618 * @ioc: per adapter object
619 * @mpi_reply: reply mf payload returned from firmware
620 * @config_page: contents of the config page
621 * Context: sleep.
622 *
623 * Returns 0 for success, non-zero for failure.
624 */
625int
626mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
627 Mpi2ConfigReply_t *mpi_reply,
628 struct Mpi2ManufacturingPage11_t *config_page)
629{
630 Mpi2ConfigRequest_t mpi_request;
631 int r;
632
633 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
634 mpi_request.Function = MPI2_FUNCTION_CONFIG;
635 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
636 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
637 mpi_request.Header.PageNumber = 11;
638 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
639 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
640 r = _config_request(ioc, &mpi_request, mpi_reply,
641 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
642 if (r)
643 goto out;
644
645 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
646 r = _config_request(ioc, &mpi_request, mpi_reply,
647 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
648 sizeof(*config_page));
649 out:
650 return r;
651}
652
653/**
654 * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
655 * @ioc: per adapter object
656 * @mpi_reply: reply mf payload returned from firmware
657 * @config_page: contents of the config page
658 * Context: sleep.
659 *
660 * Returns 0 for success, non-zero for failure.
661 */
662int
663mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
664 Mpi2ConfigReply_t *mpi_reply,
665 struct Mpi2ManufacturingPage11_t *config_page)
666{
667 Mpi2ConfigRequest_t mpi_request;
668 int r;
669
670 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
671 mpi_request.Function = MPI2_FUNCTION_CONFIG;
672 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
673 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
674 mpi_request.Header.PageNumber = 11;
675 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
676 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
677 r = _config_request(ioc, &mpi_request, mpi_reply,
678 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
679 if (r)
680 goto out;
681
682 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
683 r = _config_request(ioc, &mpi_request, mpi_reply,
684 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
685 sizeof(*config_page));
686 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
687 r = _config_request(ioc, &mpi_request, mpi_reply,
688 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
689 sizeof(*config_page));
690 out:
691 return r;
692}
693
694/**
695 * mpt3sas_config_get_bios_pg2 - obtain bios page 2
696 * @ioc: per adapter object
697 * @mpi_reply: reply mf payload returned from firmware
698 * @config_page: contents of the config page
699 * Context: sleep.
700 *
701 * Returns 0 for success, non-zero for failure.
702 */
703int
704mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
705 Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
706{
707 Mpi2ConfigRequest_t mpi_request;
708 int r;
709
710 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
711 mpi_request.Function = MPI2_FUNCTION_CONFIG;
712 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
713 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
714 mpi_request.Header.PageNumber = 2;
715 mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
716 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
717 r = _config_request(ioc, &mpi_request, mpi_reply,
718 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
719 if (r)
720 goto out;
721
722 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
723 r = _config_request(ioc, &mpi_request, mpi_reply,
724 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
725 sizeof(*config_page));
726 out:
727 return r;
728}
729
730/**
731 * mpt3sas_config_get_bios_pg3 - obtain bios page 3
732 * @ioc: per adapter object
733 * @mpi_reply: reply mf payload returned from firmware
734 * @config_page: contents of the config page
735 * Context: sleep.
736 *
737 * Returns 0 for success, non-zero for failure.
738 */
739int
740mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
741 *mpi_reply, Mpi2BiosPage3_t *config_page)
742{
743 Mpi2ConfigRequest_t mpi_request;
744 int r;
745
746 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
747 mpi_request.Function = MPI2_FUNCTION_CONFIG;
748 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
749 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
750 mpi_request.Header.PageNumber = 3;
751 mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
752 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
753 r = _config_request(ioc, &mpi_request, mpi_reply,
754 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
755 if (r)
756 goto out;
757
758 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
759 r = _config_request(ioc, &mpi_request, mpi_reply,
760 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
761 sizeof(*config_page));
762 out:
763 return r;
764}
765
766/**
767 * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
768 * @ioc: per adapter object
769 * @mpi_reply: reply mf payload returned from firmware
770 * @config_page: contents of the config page
771 * Context: sleep.
772 *
773 * Returns 0 for success, non-zero for failure.
774 */
775int
776mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
777 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
778{
779 Mpi2ConfigRequest_t mpi_request;
780 int r;
781
782 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
783 mpi_request.Function = MPI2_FUNCTION_CONFIG;
784 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
785 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
786 mpi_request.Header.PageNumber = 0;
787 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
788 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
789 r = _config_request(ioc, &mpi_request, mpi_reply,
790 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
791 if (r)
792 goto out;
793
794 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
795 r = _config_request(ioc, &mpi_request, mpi_reply,
796 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
797 sizeof(*config_page));
798 out:
799 return r;
800}
801
802/**
803 * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
804 * @ioc: per adapter object
805 * @mpi_reply: reply mf payload returned from firmware
806 * @config_page: contents of the config page
807 * Context: sleep.
808 *
809 * Returns 0 for success, non-zero for failure.
810 */
811int
812mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
813 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
814{
815 Mpi2ConfigRequest_t mpi_request;
816 int r;
817
818 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
819 mpi_request.Function = MPI2_FUNCTION_CONFIG;
820 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
821 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
822 mpi_request.Header.PageNumber = 1;
823 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
824 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
825 r = _config_request(ioc, &mpi_request, mpi_reply,
826 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
827 if (r)
828 goto out;
829
830 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
831 r = _config_request(ioc, &mpi_request, mpi_reply,
832 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
833 sizeof(*config_page));
834 out:
835 return r;
836}
837
838/**
839 * mpt3sas_config_set_iounit_pg1 - set iounit page 1
840 * @ioc: per adapter object
841 * @mpi_reply: reply mf payload returned from firmware
842 * @config_page: contents of the config page
843 * Context: sleep.
844 *
845 * Returns 0 for success, non-zero for failure.
846 */
847int
848mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
849 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
850{
851 Mpi2ConfigRequest_t mpi_request;
852 int r;
853
854 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
855 mpi_request.Function = MPI2_FUNCTION_CONFIG;
856 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
857 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
858 mpi_request.Header.PageNumber = 1;
859 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
860 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
861 r = _config_request(ioc, &mpi_request, mpi_reply,
862 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
863 if (r)
864 goto out;
865
866 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
867 r = _config_request(ioc, &mpi_request, mpi_reply,
868 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
869 sizeof(*config_page));
870 out:
871 return r;
872}
873
874/**
875 * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
876 * @ioc: per adapter object
877 * @mpi_reply: reply mf payload returned from firmware
878 * @config_page: contents of the config page
879 * Context: sleep.
880 *
881 * Returns 0 for success, non-zero for failure.
882 */
883int
884mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
885 Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
886{
887 Mpi2ConfigRequest_t mpi_request;
888 int r;
889
890 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
891 mpi_request.Function = MPI2_FUNCTION_CONFIG;
892 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
893 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
894 mpi_request.Header.PageNumber = 8;
895 mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
896 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
897 r = _config_request(ioc, &mpi_request, mpi_reply,
898 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
899 if (r)
900 goto out;
901
902 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
903 r = _config_request(ioc, &mpi_request, mpi_reply,
904 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
905 sizeof(*config_page));
906 out:
907 return r;
908}
909
910/**
911 * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
912 * @ioc: per adapter object
913 * @mpi_reply: reply mf payload returned from firmware
914 * @config_page: contents of the config page
915 * @form: GET_NEXT_HANDLE or HANDLE
916 * @handle: device handle
917 * Context: sleep.
918 *
919 * Returns 0 for success, non-zero for failure.
920 */
921int
922mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
923 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
924 u32 form, u32 handle)
925{
926 Mpi2ConfigRequest_t mpi_request;
927 int r;
928
929 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
930 mpi_request.Function = MPI2_FUNCTION_CONFIG;
931 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
932 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
933 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
934 mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
935 mpi_request.Header.PageNumber = 0;
936 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
937 r = _config_request(ioc, &mpi_request, mpi_reply,
938 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
939 if (r)
940 goto out;
941
942 mpi_request.PageAddress = cpu_to_le32(form | handle);
943 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
944 r = _config_request(ioc, &mpi_request, mpi_reply,
945 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
946 sizeof(*config_page));
947 out:
948 return r;
949}
950
951/**
952 * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
953 * @ioc: per adapter object
954 * @mpi_reply: reply mf payload returned from firmware
955 * @config_page: contents of the config page
956 * @form: GET_NEXT_HANDLE or HANDLE
957 * @handle: device handle
958 * Context: sleep.
959 *
960 * Returns 0 for success, non-zero for failure.
961 */
962int
963mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
964 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
965 u32 form, u32 handle)
966{
967 Mpi2ConfigRequest_t mpi_request;
968 int r;
969
970 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
971 mpi_request.Function = MPI2_FUNCTION_CONFIG;
972 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
973 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
974 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
975 mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
976 mpi_request.Header.PageNumber = 1;
977 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
978 r = _config_request(ioc, &mpi_request, mpi_reply,
979 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
980 if (r)
981 goto out;
982
983 mpi_request.PageAddress = cpu_to_le32(form | handle);
984 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
985 r = _config_request(ioc, &mpi_request, mpi_reply,
986 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
987 sizeof(*config_page));
988 out:
989 return r;
990}
991
992/**
993 * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
994 * @ioc: per adapter object
995 * @num_phys: pointer returned with the number of phys
996 * Context: sleep.
997 *
998 * Returns 0 for success, non-zero for failure.
999 */
1000int
1001mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1002{
1003 Mpi2ConfigRequest_t mpi_request;
1004 int r;
1005 u16 ioc_status;
1006 Mpi2ConfigReply_t mpi_reply;
1007 Mpi2SasIOUnitPage0_t config_page;
1008
1009 *num_phys = 0;
1010 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1011 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1012 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1013 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1014 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1015 mpi_request.Header.PageNumber = 0;
1016 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1017 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1018 r = _config_request(ioc, &mpi_request, &mpi_reply,
1019 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1020 if (r)
1021 goto out;
1022
1023 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1024 r = _config_request(ioc, &mpi_request, &mpi_reply,
1025 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1026 sizeof(Mpi2SasIOUnitPage0_t));
1027 if (!r) {
1028 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1029 MPI2_IOCSTATUS_MASK;
1030 if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1031 *num_phys = config_page.NumPhys;
1032 }
1033 out:
1034 return r;
1035}
1036
1037/**
1038 * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1039 * @ioc: per adapter object
1040 * @mpi_reply: reply mf payload returned from firmware
1041 * @config_page: contents of the config page
1042 * @sz: size of buffer passed in config_page
1043 * Context: sleep.
1044 *
1045 * Calling function should call config_get_number_hba_phys prior to
1046 * this function, so enough memory is allocated for config_page.
1047 *
1048 * Returns 0 for success, non-zero for failure.
1049 */
1050int
1051mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1052 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1053 u16 sz)
1054{
1055 Mpi2ConfigRequest_t mpi_request;
1056 int r;
1057
1058 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1059 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1060 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1061 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1062 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1063 mpi_request.Header.PageNumber = 0;
1064 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1065 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1066 r = _config_request(ioc, &mpi_request, mpi_reply,
1067 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1068 if (r)
1069 goto out;
1070
1071 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1072 r = _config_request(ioc, &mpi_request, mpi_reply,
1073 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1074 out:
1075 return r;
1076}
1077
1078/**
1079 * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1080 * @ioc: per adapter object
1081 * @mpi_reply: reply mf payload returned from firmware
1082 * @config_page: contents of the config page
1083 * @sz: size of buffer passed in config_page
1084 * Context: sleep.
1085 *
1086 * Calling function should call config_get_number_hba_phys prior to
1087 * this function, so enough memory is allocated for config_page.
1088 *
1089 * Returns 0 for success, non-zero for failure.
1090 */
1091int
1092mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1093 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1094 u16 sz)
1095{
1096 Mpi2ConfigRequest_t mpi_request;
1097 int r;
1098
1099 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1100 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1101 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1102 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1103 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1104 mpi_request.Header.PageNumber = 1;
1105 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1106 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1107 r = _config_request(ioc, &mpi_request, mpi_reply,
1108 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1109 if (r)
1110 goto out;
1111
1112 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1113 r = _config_request(ioc, &mpi_request, mpi_reply,
1114 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1115 out:
1116 return r;
1117}
1118
1119/**
1120 * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1121 * @ioc: per adapter object
1122 * @mpi_reply: reply mf payload returned from firmware
1123 * @config_page: contents of the config page
1124 * @sz: size of buffer passed in config_page
1125 * Context: sleep.
1126 *
1127 * Calling function should call config_get_number_hba_phys prior to
1128 * this function, so enough memory is allocated for config_page.
1129 *
1130 * Returns 0 for success, non-zero for failure.
1131 */
1132int
1133mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1134 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1135 u16 sz)
1136{
1137 Mpi2ConfigRequest_t mpi_request;
1138 int r;
1139
1140 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1141 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1142 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1143 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1144 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1145 mpi_request.Header.PageNumber = 1;
1146 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1147 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1148 r = _config_request(ioc, &mpi_request, mpi_reply,
1149 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1150 if (r)
1151 goto out;
1152
1153 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1154 _config_request(ioc, &mpi_request, mpi_reply,
1155 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1156 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1157 r = _config_request(ioc, &mpi_request, mpi_reply,
1158 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1159 out:
1160 return r;
1161}
1162
1163/**
1164 * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1165 * @ioc: per adapter object
1166 * @mpi_reply: reply mf payload returned from firmware
1167 * @config_page: contents of the config page
1168 * @form: GET_NEXT_HANDLE or HANDLE
1169 * @handle: expander handle
1170 * Context: sleep.
1171 *
1172 * Returns 0 for success, non-zero for failure.
1173 */
1174int
1175mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1176 *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1177{
1178 Mpi2ConfigRequest_t mpi_request;
1179 int r;
1180
1181 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1182 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1183 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1184 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1185 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1186 mpi_request.Header.PageNumber = 0;
1187 mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1188 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1189 r = _config_request(ioc, &mpi_request, mpi_reply,
1190 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1191 if (r)
1192 goto out;
1193
1194 mpi_request.PageAddress = cpu_to_le32(form | handle);
1195 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1196 r = _config_request(ioc, &mpi_request, mpi_reply,
1197 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1198 sizeof(*config_page));
1199 out:
1200 return r;
1201}
1202
1203/**
1204 * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1205 * @ioc: per adapter object
1206 * @mpi_reply: reply mf payload returned from firmware
1207 * @config_page: contents of the config page
1208 * @phy_number: phy number
1209 * @handle: expander handle
1210 * Context: sleep.
1211 *
1212 * Returns 0 for success, non-zero for failure.
1213 */
1214int
1215mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1216 *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1217 u16 handle)
1218{
1219 Mpi2ConfigRequest_t mpi_request;
1220 int r;
1221
1222 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1223 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1224 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1225 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1226 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1227 mpi_request.Header.PageNumber = 1;
1228 mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1229 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1230 r = _config_request(ioc, &mpi_request, mpi_reply,
1231 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1232 if (r)
1233 goto out;
1234
1235 mpi_request.PageAddress =
1236 cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1237 (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1238 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1239 r = _config_request(ioc, &mpi_request, mpi_reply,
1240 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1241 sizeof(*config_page));
1242 out:
1243 return r;
1244}
1245
1246/**
1247 * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1248 * @ioc: per adapter object
1249 * @mpi_reply: reply mf payload returned from firmware
1250 * @config_page: contents of the config page
1251 * @form: GET_NEXT_HANDLE or HANDLE
1252 * @handle: expander handle
1253 * Context: sleep.
1254 *
1255 * Returns 0 for success, non-zero for failure.
1256 */
1257int
1258mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1259 *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1260{
1261 Mpi2ConfigRequest_t mpi_request;
1262 int r;
1263
1264 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1265 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1266 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1267 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1268 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1269 mpi_request.Header.PageNumber = 0;
1270 mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1271 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1272 r = _config_request(ioc, &mpi_request, mpi_reply,
1273 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1274 if (r)
1275 goto out;
1276
1277 mpi_request.PageAddress = cpu_to_le32(form | handle);
1278 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1279 r = _config_request(ioc, &mpi_request, mpi_reply,
1280 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1281 sizeof(*config_page));
1282 out:
1283 return r;
1284}
1285
1286/**
1287 * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1288 * @ioc: per adapter object
1289 * @mpi_reply: reply mf payload returned from firmware
1290 * @config_page: contents of the config page
1291 * @phy_number: phy number
1292 * Context: sleep.
1293 *
1294 * Returns 0 for success, non-zero for failure.
1295 */
1296int
1297mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1298 *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1299{
1300 Mpi2ConfigRequest_t mpi_request;
1301 int r;
1302
1303 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1304 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1305 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1306 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1307 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1308 mpi_request.Header.PageNumber = 0;
1309 mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1310 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1311 r = _config_request(ioc, &mpi_request, mpi_reply,
1312 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1313 if (r)
1314 goto out;
1315
1316 mpi_request.PageAddress =
1317 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1318 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1319 r = _config_request(ioc, &mpi_request, mpi_reply,
1320 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1321 sizeof(*config_page));
1322 out:
1323 return r;
1324}
1325
1326/**
1327 * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1328 * @ioc: per adapter object
1329 * @mpi_reply: reply mf payload returned from firmware
1330 * @config_page: contents of the config page
1331 * @phy_number: phy number
1332 * Context: sleep.
1333 *
1334 * Returns 0 for success, non-zero for failure.
1335 */
1336int
1337mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1338 *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1339{
1340 Mpi2ConfigRequest_t mpi_request;
1341 int r;
1342
1343 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1344 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1345 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1346 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1347 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1348 mpi_request.Header.PageNumber = 1;
1349 mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1350 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1351 r = _config_request(ioc, &mpi_request, mpi_reply,
1352 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1353 if (r)
1354 goto out;
1355
1356 mpi_request.PageAddress =
1357 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1358 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1359 r = _config_request(ioc, &mpi_request, mpi_reply,
1360 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1361 sizeof(*config_page));
1362 out:
1363 return r;
1364}
1365
1366/**
1367 * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1368 * @ioc: per adapter object
1369 * @mpi_reply: reply mf payload returned from firmware
1370 * @config_page: contents of the config page
1371 * @form: GET_NEXT_HANDLE or HANDLE
1372 * @handle: volume handle
1373 * Context: sleep.
1374 *
1375 * Returns 0 for success, non-zero for failure.
1376 */
1377int
1378mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1379 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1380 u32 handle)
1381{
1382 Mpi2ConfigRequest_t mpi_request;
1383 int r;
1384
1385 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1386 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1387 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1388 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1389 mpi_request.Header.PageNumber = 1;
1390 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1391 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1392 r = _config_request(ioc, &mpi_request, mpi_reply,
1393 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1394 if (r)
1395 goto out;
1396
1397 mpi_request.PageAddress = cpu_to_le32(form | handle);
1398 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1399 r = _config_request(ioc, &mpi_request, mpi_reply,
1400 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1401 sizeof(*config_page));
1402 out:
1403 return r;
1404}
1405
1406/**
1407 * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1408 * @ioc: per adapter object
1409 * @handle: volume handle
1410 * @num_pds: returns pds count
1411 * Context: sleep.
1412 *
1413 * Returns 0 for success, non-zero for failure.
1414 */
1415int
1416mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1417 u8 *num_pds)
1418{
1419 Mpi2ConfigRequest_t mpi_request;
1420 Mpi2RaidVolPage0_t config_page;
1421 Mpi2ConfigReply_t mpi_reply;
1422 int r;
1423 u16 ioc_status;
1424
1425 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1426 *num_pds = 0;
1427 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1428 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1429 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1430 mpi_request.Header.PageNumber = 0;
1431 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1432 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1433 r = _config_request(ioc, &mpi_request, &mpi_reply,
1434 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1435 if (r)
1436 goto out;
1437
1438 mpi_request.PageAddress =
1439 cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1440 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1441 r = _config_request(ioc, &mpi_request, &mpi_reply,
1442 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1443 sizeof(Mpi2RaidVolPage0_t));
1444 if (!r) {
1445 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1446 MPI2_IOCSTATUS_MASK;
1447 if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1448 *num_pds = config_page.NumPhysDisks;
1449 }
1450
1451 out:
1452 return r;
1453}
1454
1455/**
1456 * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1457 * @ioc: per adapter object
1458 * @mpi_reply: reply mf payload returned from firmware
1459 * @config_page: contents of the config page
1460 * @form: GET_NEXT_HANDLE or HANDLE
1461 * @handle: volume handle
1462 * @sz: size of buffer passed in config_page
1463 * Context: sleep.
1464 *
1465 * Returns 0 for success, non-zero for failure.
1466 */
1467int
1468mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1469 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1470 u32 handle, u16 sz)
1471{
1472 Mpi2ConfigRequest_t mpi_request;
1473 int r;
1474
1475 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1476 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1477 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1478 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1479 mpi_request.Header.PageNumber = 0;
1480 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1481 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1482 r = _config_request(ioc, &mpi_request, mpi_reply,
1483 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1484 if (r)
1485 goto out;
1486
1487 mpi_request.PageAddress = cpu_to_le32(form | handle);
1488 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1489 r = _config_request(ioc, &mpi_request, mpi_reply,
1490 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1491 out:
1492 return r;
1493}
1494
1495/**
1496 * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1497 * @ioc: per adapter object
1498 * @mpi_reply: reply mf payload returned from firmware
1499 * @config_page: contents of the config page
1500 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1501 * @form_specific: specific to the form
1502 * Context: sleep.
1503 *
1504 * Returns 0 for success, non-zero for failure.
1505 */
1506int
1507mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1508 *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1509 u32 form_specific)
1510{
1511 Mpi2ConfigRequest_t mpi_request;
1512 int r;
1513
1514 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1515 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1516 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1517 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1518 mpi_request.Header.PageNumber = 0;
1519 mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1520 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1521 r = _config_request(ioc, &mpi_request, mpi_reply,
1522 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1523 if (r)
1524 goto out;
1525
1526 mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1527 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1528 r = _config_request(ioc, &mpi_request, mpi_reply,
1529 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1530 sizeof(*config_page));
1531 out:
1532 return r;
1533}
1534
1535/**
1536 * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
1537 * raid components
1538 * @ioc: per adapter object
1539 * @pd_handle: phys disk handle
1540 * @volume_handle: volume handle
1541 * Context: sleep.
1542 *
1543 * Returns 0 for success, non-zero for failure.
1544 */
1545int
1546mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
1547 u16 *volume_handle)
1548{
1549 Mpi2RaidConfigurationPage0_t *config_page = NULL;
1550 Mpi2ConfigRequest_t mpi_request;
1551 Mpi2ConfigReply_t mpi_reply;
1552 int r, i, config_page_sz;
1553 u16 ioc_status;
1554 int config_num;
1555 u16 element_type;
1556 u16 phys_disk_dev_handle;
1557
1558 *volume_handle = 0;
1559 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1560 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1561 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1562 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1563 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1564 mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1565 mpi_request.Header.PageNumber = 0;
1566 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1567 r = _config_request(ioc, &mpi_request, &mpi_reply,
1568 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1569 if (r)
1570 goto out;
1571
1572 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1573 config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1574 config_page = kmalloc(config_page_sz, GFP_KERNEL);
1575 if (!config_page) {
1576 r = -1;
1577 goto out;
1578 }
1579
1580 config_num = 0xff;
1581 while (1) {
1582 mpi_request.PageAddress = cpu_to_le32(config_num +
1583 MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1584 r = _config_request(ioc, &mpi_request, &mpi_reply,
1585 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1586 config_page_sz);
1587 if (r)
1588 goto out;
1589 r = -1;
1590 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1591 MPI2_IOCSTATUS_MASK;
1592 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1593 goto out;
1594 for (i = 0; i < config_page->NumElements; i++) {
1595 element_type = le16_to_cpu(config_page->
1596 ConfigElement[i].ElementFlags) &
1597 MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1598 if (element_type ==
1599 MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1600 element_type ==
1601 MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1602 phys_disk_dev_handle =
1603 le16_to_cpu(config_page->ConfigElement[i].
1604 PhysDiskDevHandle);
1605 if (phys_disk_dev_handle == pd_handle) {
1606 *volume_handle =
1607 le16_to_cpu(config_page->
1608 ConfigElement[i].VolDevHandle);
1609 r = 0;
1610 goto out;
1611 }
1612 } else if (element_type ==
1613 MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1614 *volume_handle = 0;
1615 r = 0;
1616 goto out;
1617 }
1618 }
1619 config_num = config_page->ConfigNum;
1620 }
1621 out:
1622 kfree(config_page);
1623 return r;
1624}
1625
1626/**
1627 * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
1628 * @ioc: per adapter object
1629 * @volume_handle: volume handle
1630 * @wwid: volume wwid
1631 * Context: sleep.
1632 *
1633 * Returns 0 for success, non-zero for failure.
1634 */
1635int
1636mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
1637 u64 *wwid)
1638{
1639 Mpi2ConfigReply_t mpi_reply;
1640 Mpi2RaidVolPage1_t raid_vol_pg1;
1641
1642 *wwid = 0;
1643 if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1644 &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1645 volume_handle))) {
1646 *wwid = le64_to_cpu(raid_vol_pg1.WWID);
1647 return 0;
1648 } else
1649 return -1;
1650}