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