blob: 022f27f3ef6e5da90250a6892cd126a7562bba80 [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)
Calvin Owens98c56ad2016-07-28 21:38:21 -0700494 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530495 return r;
496}
497
498/**
499 * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
500 * @ioc: per adapter object
501 * @mpi_reply: reply mf payload returned from firmware
502 * @config_page: contents of the config page
503 * Context: sleep.
504 *
505 * Returns 0 for success, non-zero for failure.
506 */
507int
508mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
509 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
510{
511 Mpi2ConfigRequest_t mpi_request;
512 int r;
513
514 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
515 mpi_request.Function = MPI2_FUNCTION_CONFIG;
516 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
517 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
518 mpi_request.Header.PageNumber = 0;
519 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
520 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
521 r = _config_request(ioc, &mpi_request, mpi_reply,
522 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
523 if (r)
524 goto out;
525
526 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
527 r = _config_request(ioc, &mpi_request, mpi_reply,
528 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
529 sizeof(*config_page));
530 out:
531 return r;
532}
533
534/**
535 * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
536 * @ioc: per adapter object
537 * @mpi_reply: reply mf payload returned from firmware
538 * @config_page: contents of the config page
539 * @sz: size of buffer passed in config_page
540 * Context: sleep.
541 *
542 * Returns 0 for success, non-zero for failure.
543 */
544int
545mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
546 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
547 u16 sz)
548{
549 Mpi2ConfigRequest_t mpi_request;
550 int r;
551
552 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
553 mpi_request.Function = MPI2_FUNCTION_CONFIG;
554 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
555 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
556 mpi_request.Header.PageNumber = 7;
557 mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
558 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
559 r = _config_request(ioc, &mpi_request, mpi_reply,
560 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
561 if (r)
562 goto out;
563
564 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
565 r = _config_request(ioc, &mpi_request, mpi_reply,
566 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
567 sz);
568 out:
569 return r;
570}
571
572/**
573 * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
574 * @ioc: per adapter object
575 * @mpi_reply: reply mf payload returned from firmware
576 * @config_page: contents of the config page
577 * Context: sleep.
578 *
579 * Returns 0 for success, non-zero for failure.
580 */
581int
582mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
583 Mpi2ConfigReply_t *mpi_reply,
584 struct Mpi2ManufacturingPage10_t *config_page)
585{
586 Mpi2ConfigRequest_t mpi_request;
587 int r;
588
589 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
590 mpi_request.Function = MPI2_FUNCTION_CONFIG;
591 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
592 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
593 mpi_request.Header.PageNumber = 10;
594 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
595 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
596 r = _config_request(ioc, &mpi_request, mpi_reply,
597 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
598 if (r)
599 goto out;
600
601 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
602 r = _config_request(ioc, &mpi_request, mpi_reply,
603 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
604 sizeof(*config_page));
605 out:
606 return r;
607}
608
609/**
610 * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
611 * @ioc: per adapter object
612 * @mpi_reply: reply mf payload returned from firmware
613 * @config_page: contents of the config page
614 * Context: sleep.
615 *
616 * Returns 0 for success, non-zero for failure.
617 */
618int
619mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
620 Mpi2ConfigReply_t *mpi_reply,
621 struct Mpi2ManufacturingPage11_t *config_page)
622{
623 Mpi2ConfigRequest_t mpi_request;
624 int r;
625
626 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
627 mpi_request.Function = MPI2_FUNCTION_CONFIG;
628 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
629 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
630 mpi_request.Header.PageNumber = 11;
631 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
632 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
633 r = _config_request(ioc, &mpi_request, mpi_reply,
634 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
635 if (r)
636 goto out;
637
638 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
639 r = _config_request(ioc, &mpi_request, mpi_reply,
640 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
641 sizeof(*config_page));
642 out:
643 return r;
644}
645
646/**
647 * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
648 * @ioc: per adapter object
649 * @mpi_reply: reply mf payload returned from firmware
650 * @config_page: contents of the config page
651 * Context: sleep.
652 *
653 * Returns 0 for success, non-zero for failure.
654 */
655int
656mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
657 Mpi2ConfigReply_t *mpi_reply,
658 struct Mpi2ManufacturingPage11_t *config_page)
659{
660 Mpi2ConfigRequest_t mpi_request;
661 int r;
662
663 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
664 mpi_request.Function = MPI2_FUNCTION_CONFIG;
665 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
666 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
667 mpi_request.Header.PageNumber = 11;
668 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
669 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
670 r = _config_request(ioc, &mpi_request, mpi_reply,
671 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
672 if (r)
673 goto out;
674
675 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
676 r = _config_request(ioc, &mpi_request, mpi_reply,
677 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
678 sizeof(*config_page));
679 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
680 r = _config_request(ioc, &mpi_request, mpi_reply,
681 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
682 sizeof(*config_page));
683 out:
684 return r;
685}
686
687/**
688 * mpt3sas_config_get_bios_pg2 - obtain bios page 2
689 * @ioc: per adapter object
690 * @mpi_reply: reply mf payload returned from firmware
691 * @config_page: contents of the config page
692 * Context: sleep.
693 *
694 * Returns 0 for success, non-zero for failure.
695 */
696int
697mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
698 Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
699{
700 Mpi2ConfigRequest_t mpi_request;
701 int r;
702
703 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
704 mpi_request.Function = MPI2_FUNCTION_CONFIG;
705 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
706 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
707 mpi_request.Header.PageNumber = 2;
708 mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
709 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
710 r = _config_request(ioc, &mpi_request, mpi_reply,
711 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
712 if (r)
713 goto out;
714
715 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
716 r = _config_request(ioc, &mpi_request, mpi_reply,
717 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
718 sizeof(*config_page));
719 out:
720 return r;
721}
722
723/**
724 * mpt3sas_config_get_bios_pg3 - obtain bios page 3
725 * @ioc: per adapter object
726 * @mpi_reply: reply mf payload returned from firmware
727 * @config_page: contents of the config page
728 * Context: sleep.
729 *
730 * Returns 0 for success, non-zero for failure.
731 */
732int
733mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
734 *mpi_reply, Mpi2BiosPage3_t *config_page)
735{
736 Mpi2ConfigRequest_t mpi_request;
737 int r;
738
739 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
740 mpi_request.Function = MPI2_FUNCTION_CONFIG;
741 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
742 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
743 mpi_request.Header.PageNumber = 3;
744 mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
745 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
746 r = _config_request(ioc, &mpi_request, mpi_reply,
747 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
748 if (r)
749 goto out;
750
751 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
752 r = _config_request(ioc, &mpi_request, mpi_reply,
753 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
754 sizeof(*config_page));
755 out:
756 return r;
757}
758
759/**
760 * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
761 * @ioc: per adapter object
762 * @mpi_reply: reply mf payload returned from firmware
763 * @config_page: contents of the config page
764 * Context: sleep.
765 *
766 * Returns 0 for success, non-zero for failure.
767 */
768int
769mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
770 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
771{
772 Mpi2ConfigRequest_t mpi_request;
773 int r;
774
775 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
776 mpi_request.Function = MPI2_FUNCTION_CONFIG;
777 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
778 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
779 mpi_request.Header.PageNumber = 0;
780 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
781 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
782 r = _config_request(ioc, &mpi_request, mpi_reply,
783 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
784 if (r)
785 goto out;
786
787 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
788 r = _config_request(ioc, &mpi_request, mpi_reply,
789 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
790 sizeof(*config_page));
791 out:
792 return r;
793}
794
795/**
796 * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
797 * @ioc: per adapter object
798 * @mpi_reply: reply mf payload returned from firmware
799 * @config_page: contents of the config page
800 * Context: sleep.
801 *
802 * Returns 0 for success, non-zero for failure.
803 */
804int
805mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
806 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
807{
808 Mpi2ConfigRequest_t mpi_request;
809 int r;
810
811 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
812 mpi_request.Function = MPI2_FUNCTION_CONFIG;
813 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
814 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
815 mpi_request.Header.PageNumber = 1;
816 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
817 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
818 r = _config_request(ioc, &mpi_request, mpi_reply,
819 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
820 if (r)
821 goto out;
822
823 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
824 r = _config_request(ioc, &mpi_request, mpi_reply,
825 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
826 sizeof(*config_page));
827 out:
828 return r;
829}
830
831/**
832 * mpt3sas_config_set_iounit_pg1 - set iounit page 1
833 * @ioc: per adapter object
834 * @mpi_reply: reply mf payload returned from firmware
835 * @config_page: contents of the config page
836 * Context: sleep.
837 *
838 * Returns 0 for success, non-zero for failure.
839 */
840int
841mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
842 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
843{
844 Mpi2ConfigRequest_t mpi_request;
845 int r;
846
847 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
848 mpi_request.Function = MPI2_FUNCTION_CONFIG;
849 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
850 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
851 mpi_request.Header.PageNumber = 1;
852 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
853 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
854 r = _config_request(ioc, &mpi_request, mpi_reply,
855 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
856 if (r)
857 goto out;
858
859 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
860 r = _config_request(ioc, &mpi_request, mpi_reply,
861 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
862 sizeof(*config_page));
863 out:
864 return r;
865}
866
Sreekanth Reddy42263092015-11-11 17:30:29 +0530867/**
868 * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
869 * @ioc: per adapter object
870 * @mpi_reply: reply mf payload returned from firmware
871 * @config_page: contents of the config page
872 * @sz: size of buffer passed in config_page
873 * Context: sleep.
874 *
875 * Returns 0 for success, non-zero for failure.
876 */
877int
878mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
879 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
880{
881 Mpi2ConfigRequest_t mpi_request;
882 int r;
883
884 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
885 mpi_request.Function = MPI2_FUNCTION_CONFIG;
886 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
887 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
888 mpi_request.Header.PageNumber = 3;
889 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
890 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
891 r = _config_request(ioc, &mpi_request, mpi_reply,
892 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
893 if (r)
894 goto out;
895
896 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
897 r = _config_request(ioc, &mpi_request, mpi_reply,
898 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
899 out:
900 return r;
901}
Sreekanth Reddy42263092015-11-11 17:30:29 +0530902
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530903/**
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +0530904 * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
905 * @ioc: per adapter object
906 * @mpi_reply: reply mf payload returned from firmware
907 * @config_page: contents of the config page
908 * Context: sleep.
909 *
910 * Returns 0 for success, non-zero for failure.
911 */
912int
913mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
914 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
915{
916 Mpi2ConfigRequest_t mpi_request;
917 int r;
918
919 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
920 mpi_request.Function = MPI2_FUNCTION_CONFIG;
921 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
922 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
923 mpi_request.Header.PageNumber = 8;
924 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
925 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
926 r = _config_request(ioc, &mpi_request, mpi_reply,
927 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
928 if (r)
929 goto out;
930
931 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
932 r = _config_request(ioc, &mpi_request, mpi_reply,
933 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
934 sizeof(*config_page));
935 out:
936 return r;
937}
938
939/**
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530940 * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
941 * @ioc: per adapter object
942 * @mpi_reply: reply mf payload returned from firmware
943 * @config_page: contents of the config page
944 * Context: sleep.
945 *
946 * Returns 0 for success, non-zero for failure.
947 */
948int
949mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
950 Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
951{
952 Mpi2ConfigRequest_t mpi_request;
953 int r;
954
955 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
956 mpi_request.Function = MPI2_FUNCTION_CONFIG;
957 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
958 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
959 mpi_request.Header.PageNumber = 8;
960 mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
961 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
962 r = _config_request(ioc, &mpi_request, mpi_reply,
963 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
964 if (r)
965 goto out;
966
967 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
968 r = _config_request(ioc, &mpi_request, mpi_reply,
969 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
970 sizeof(*config_page));
971 out:
972 return r;
973}
974
975/**
976 * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
977 * @ioc: per adapter object
978 * @mpi_reply: reply mf payload returned from firmware
979 * @config_page: contents of the config page
980 * @form: GET_NEXT_HANDLE or HANDLE
981 * @handle: device handle
982 * Context: sleep.
983 *
984 * Returns 0 for success, non-zero for failure.
985 */
986int
987mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
988 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
989 u32 form, u32 handle)
990{
991 Mpi2ConfigRequest_t mpi_request;
992 int r;
993
994 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
995 mpi_request.Function = MPI2_FUNCTION_CONFIG;
996 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
997 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
998 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
999 mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
1000 mpi_request.Header.PageNumber = 0;
1001 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1002 r = _config_request(ioc, &mpi_request, mpi_reply,
1003 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1004 if (r)
1005 goto out;
1006
1007 mpi_request.PageAddress = cpu_to_le32(form | handle);
1008 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1009 r = _config_request(ioc, &mpi_request, mpi_reply,
1010 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1011 sizeof(*config_page));
1012 out:
1013 return r;
1014}
1015
1016/**
1017 * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
1018 * @ioc: per adapter object
1019 * @mpi_reply: reply mf payload returned from firmware
1020 * @config_page: contents of the config page
1021 * @form: GET_NEXT_HANDLE or HANDLE
1022 * @handle: device handle
1023 * Context: sleep.
1024 *
1025 * Returns 0 for success, non-zero for failure.
1026 */
1027int
1028mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1029 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1030 u32 form, u32 handle)
1031{
1032 Mpi2ConfigRequest_t mpi_request;
1033 int r;
1034
1035 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1036 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1037 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1038 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1039 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1040 mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1041 mpi_request.Header.PageNumber = 1;
1042 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1043 r = _config_request(ioc, &mpi_request, mpi_reply,
1044 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1045 if (r)
1046 goto out;
1047
1048 mpi_request.PageAddress = cpu_to_le32(form | handle);
1049 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1050 r = _config_request(ioc, &mpi_request, mpi_reply,
1051 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1052 sizeof(*config_page));
1053 out:
1054 return r;
1055}
1056
1057/**
1058 * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1059 * @ioc: per adapter object
1060 * @num_phys: pointer returned with the number of phys
1061 * Context: sleep.
1062 *
1063 * Returns 0 for success, non-zero for failure.
1064 */
1065int
1066mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1067{
1068 Mpi2ConfigRequest_t mpi_request;
1069 int r;
1070 u16 ioc_status;
1071 Mpi2ConfigReply_t mpi_reply;
1072 Mpi2SasIOUnitPage0_t config_page;
1073
1074 *num_phys = 0;
1075 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1076 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1077 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1078 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1079 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1080 mpi_request.Header.PageNumber = 0;
1081 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1082 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1083 r = _config_request(ioc, &mpi_request, &mpi_reply,
1084 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1085 if (r)
1086 goto out;
1087
1088 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1089 r = _config_request(ioc, &mpi_request, &mpi_reply,
1090 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1091 sizeof(Mpi2SasIOUnitPage0_t));
1092 if (!r) {
1093 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1094 MPI2_IOCSTATUS_MASK;
1095 if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1096 *num_phys = config_page.NumPhys;
1097 }
1098 out:
1099 return r;
1100}
1101
1102/**
1103 * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1104 * @ioc: per adapter object
1105 * @mpi_reply: reply mf payload returned from firmware
1106 * @config_page: contents of the config page
1107 * @sz: size of buffer passed in config_page
1108 * Context: sleep.
1109 *
1110 * Calling function should call config_get_number_hba_phys prior to
1111 * this function, so enough memory is allocated for config_page.
1112 *
1113 * Returns 0 for success, non-zero for failure.
1114 */
1115int
1116mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1117 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1118 u16 sz)
1119{
1120 Mpi2ConfigRequest_t mpi_request;
1121 int r;
1122
1123 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1124 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1125 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1126 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1127 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1128 mpi_request.Header.PageNumber = 0;
1129 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1130 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1131 r = _config_request(ioc, &mpi_request, mpi_reply,
1132 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1133 if (r)
1134 goto out;
1135
1136 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1137 r = _config_request(ioc, &mpi_request, mpi_reply,
1138 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1139 out:
1140 return r;
1141}
1142
1143/**
1144 * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1145 * @ioc: per adapter object
1146 * @mpi_reply: reply mf payload returned from firmware
1147 * @config_page: contents of the config page
1148 * @sz: size of buffer passed in config_page
1149 * Context: sleep.
1150 *
1151 * Calling function should call config_get_number_hba_phys prior to
1152 * this function, so enough memory is allocated for config_page.
1153 *
1154 * Returns 0 for success, non-zero for failure.
1155 */
1156int
1157mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1158 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1159 u16 sz)
1160{
1161 Mpi2ConfigRequest_t mpi_request;
1162 int r;
1163
1164 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1165 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1166 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1167 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1168 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1169 mpi_request.Header.PageNumber = 1;
1170 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1171 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1172 r = _config_request(ioc, &mpi_request, mpi_reply,
1173 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1174 if (r)
1175 goto out;
1176
1177 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1178 r = _config_request(ioc, &mpi_request, mpi_reply,
1179 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1180 out:
1181 return r;
1182}
1183
1184/**
1185 * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1186 * @ioc: per adapter object
1187 * @mpi_reply: reply mf payload returned from firmware
1188 * @config_page: contents of the config page
1189 * @sz: size of buffer passed in config_page
1190 * Context: sleep.
1191 *
1192 * Calling function should call config_get_number_hba_phys prior to
1193 * this function, so enough memory is allocated for config_page.
1194 *
1195 * Returns 0 for success, non-zero for failure.
1196 */
1197int
1198mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1199 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1200 u16 sz)
1201{
1202 Mpi2ConfigRequest_t mpi_request;
1203 int r;
1204
1205 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1206 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1207 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1208 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1209 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1210 mpi_request.Header.PageNumber = 1;
1211 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1212 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1213 r = _config_request(ioc, &mpi_request, mpi_reply,
1214 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1215 if (r)
1216 goto out;
1217
1218 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1219 _config_request(ioc, &mpi_request, mpi_reply,
1220 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1221 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1222 r = _config_request(ioc, &mpi_request, mpi_reply,
1223 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1224 out:
1225 return r;
1226}
1227
1228/**
1229 * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1230 * @ioc: per adapter object
1231 * @mpi_reply: reply mf payload returned from firmware
1232 * @config_page: contents of the config page
1233 * @form: GET_NEXT_HANDLE or HANDLE
1234 * @handle: expander handle
1235 * Context: sleep.
1236 *
1237 * Returns 0 for success, non-zero for failure.
1238 */
1239int
1240mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1241 *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1242{
1243 Mpi2ConfigRequest_t mpi_request;
1244 int r;
1245
1246 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1247 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1248 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1249 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1250 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1251 mpi_request.Header.PageNumber = 0;
1252 mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1253 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1254 r = _config_request(ioc, &mpi_request, mpi_reply,
1255 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1256 if (r)
1257 goto out;
1258
1259 mpi_request.PageAddress = cpu_to_le32(form | handle);
1260 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1261 r = _config_request(ioc, &mpi_request, mpi_reply,
1262 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1263 sizeof(*config_page));
1264 out:
1265 return r;
1266}
1267
1268/**
1269 * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1270 * @ioc: per adapter object
1271 * @mpi_reply: reply mf payload returned from firmware
1272 * @config_page: contents of the config page
1273 * @phy_number: phy number
1274 * @handle: expander handle
1275 * Context: sleep.
1276 *
1277 * Returns 0 for success, non-zero for failure.
1278 */
1279int
1280mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1281 *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1282 u16 handle)
1283{
1284 Mpi2ConfigRequest_t mpi_request;
1285 int r;
1286
1287 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1288 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1289 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1290 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1291 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1292 mpi_request.Header.PageNumber = 1;
1293 mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1294 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1295 r = _config_request(ioc, &mpi_request, mpi_reply,
1296 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1297 if (r)
1298 goto out;
1299
1300 mpi_request.PageAddress =
1301 cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1302 (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1303 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1304 r = _config_request(ioc, &mpi_request, mpi_reply,
1305 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1306 sizeof(*config_page));
1307 out:
1308 return r;
1309}
1310
1311/**
1312 * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1313 * @ioc: per adapter object
1314 * @mpi_reply: reply mf payload returned from firmware
1315 * @config_page: contents of the config page
1316 * @form: GET_NEXT_HANDLE or HANDLE
1317 * @handle: expander handle
1318 * Context: sleep.
1319 *
1320 * Returns 0 for success, non-zero for failure.
1321 */
1322int
1323mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1324 *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1325{
1326 Mpi2ConfigRequest_t mpi_request;
1327 int r;
1328
1329 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1330 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1331 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1332 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1333 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1334 mpi_request.Header.PageNumber = 0;
1335 mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1336 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1337 r = _config_request(ioc, &mpi_request, mpi_reply,
1338 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1339 if (r)
1340 goto out;
1341
1342 mpi_request.PageAddress = cpu_to_le32(form | handle);
1343 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1344 r = _config_request(ioc, &mpi_request, mpi_reply,
1345 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1346 sizeof(*config_page));
1347 out:
1348 return r;
1349}
1350
1351/**
1352 * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1353 * @ioc: per adapter object
1354 * @mpi_reply: reply mf payload returned from firmware
1355 * @config_page: contents of the config page
1356 * @phy_number: phy number
1357 * Context: sleep.
1358 *
1359 * Returns 0 for success, non-zero for failure.
1360 */
1361int
1362mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1363 *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1364{
1365 Mpi2ConfigRequest_t mpi_request;
1366 int r;
1367
1368 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1369 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1370 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1371 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1372 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1373 mpi_request.Header.PageNumber = 0;
1374 mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1375 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1376 r = _config_request(ioc, &mpi_request, mpi_reply,
1377 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1378 if (r)
1379 goto out;
1380
1381 mpi_request.PageAddress =
1382 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1383 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1384 r = _config_request(ioc, &mpi_request, mpi_reply,
1385 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1386 sizeof(*config_page));
1387 out:
1388 return r;
1389}
1390
1391/**
1392 * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1393 * @ioc: per adapter object
1394 * @mpi_reply: reply mf payload returned from firmware
1395 * @config_page: contents of the config page
1396 * @phy_number: phy number
1397 * Context: sleep.
1398 *
1399 * Returns 0 for success, non-zero for failure.
1400 */
1401int
1402mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1403 *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1404{
1405 Mpi2ConfigRequest_t mpi_request;
1406 int r;
1407
1408 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1409 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1410 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1411 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1412 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1413 mpi_request.Header.PageNumber = 1;
1414 mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1415 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1416 r = _config_request(ioc, &mpi_request, mpi_reply,
1417 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1418 if (r)
1419 goto out;
1420
1421 mpi_request.PageAddress =
1422 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1423 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1424 r = _config_request(ioc, &mpi_request, mpi_reply,
1425 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1426 sizeof(*config_page));
1427 out:
1428 return r;
1429}
1430
1431/**
1432 * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1433 * @ioc: per adapter object
1434 * @mpi_reply: reply mf payload returned from firmware
1435 * @config_page: contents of the config page
1436 * @form: GET_NEXT_HANDLE or HANDLE
1437 * @handle: volume handle
1438 * Context: sleep.
1439 *
1440 * Returns 0 for success, non-zero for failure.
1441 */
1442int
1443mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1444 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1445 u32 handle)
1446{
1447 Mpi2ConfigRequest_t mpi_request;
1448 int r;
1449
1450 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1451 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1452 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1453 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1454 mpi_request.Header.PageNumber = 1;
1455 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1456 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1457 r = _config_request(ioc, &mpi_request, mpi_reply,
1458 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1459 if (r)
1460 goto out;
1461
1462 mpi_request.PageAddress = cpu_to_le32(form | handle);
1463 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1464 r = _config_request(ioc, &mpi_request, mpi_reply,
1465 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1466 sizeof(*config_page));
1467 out:
1468 return r;
1469}
1470
1471/**
1472 * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1473 * @ioc: per adapter object
1474 * @handle: volume handle
1475 * @num_pds: returns pds count
1476 * Context: sleep.
1477 *
1478 * Returns 0 for success, non-zero for failure.
1479 */
1480int
1481mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1482 u8 *num_pds)
1483{
1484 Mpi2ConfigRequest_t mpi_request;
1485 Mpi2RaidVolPage0_t config_page;
1486 Mpi2ConfigReply_t mpi_reply;
1487 int r;
1488 u16 ioc_status;
1489
1490 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1491 *num_pds = 0;
1492 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1493 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1494 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1495 mpi_request.Header.PageNumber = 0;
1496 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1497 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1498 r = _config_request(ioc, &mpi_request, &mpi_reply,
1499 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1500 if (r)
1501 goto out;
1502
1503 mpi_request.PageAddress =
1504 cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1505 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1506 r = _config_request(ioc, &mpi_request, &mpi_reply,
1507 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1508 sizeof(Mpi2RaidVolPage0_t));
1509 if (!r) {
1510 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1511 MPI2_IOCSTATUS_MASK;
1512 if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1513 *num_pds = config_page.NumPhysDisks;
1514 }
1515
1516 out:
1517 return r;
1518}
1519
1520/**
1521 * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1522 * @ioc: per adapter object
1523 * @mpi_reply: reply mf payload returned from firmware
1524 * @config_page: contents of the config page
1525 * @form: GET_NEXT_HANDLE or HANDLE
1526 * @handle: volume handle
1527 * @sz: size of buffer passed in config_page
1528 * Context: sleep.
1529 *
1530 * Returns 0 for success, non-zero for failure.
1531 */
1532int
1533mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1534 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1535 u32 handle, u16 sz)
1536{
1537 Mpi2ConfigRequest_t mpi_request;
1538 int r;
1539
1540 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1541 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1542 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1543 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1544 mpi_request.Header.PageNumber = 0;
1545 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1546 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1547 r = _config_request(ioc, &mpi_request, mpi_reply,
1548 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1549 if (r)
1550 goto out;
1551
1552 mpi_request.PageAddress = cpu_to_le32(form | handle);
1553 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1554 r = _config_request(ioc, &mpi_request, mpi_reply,
1555 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1556 out:
1557 return r;
1558}
1559
1560/**
1561 * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1562 * @ioc: per adapter object
1563 * @mpi_reply: reply mf payload returned from firmware
1564 * @config_page: contents of the config page
1565 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1566 * @form_specific: specific to the form
1567 * Context: sleep.
1568 *
1569 * Returns 0 for success, non-zero for failure.
1570 */
1571int
1572mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1573 *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1574 u32 form_specific)
1575{
1576 Mpi2ConfigRequest_t mpi_request;
1577 int r;
1578
1579 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1580 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1581 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1582 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1583 mpi_request.Header.PageNumber = 0;
1584 mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1585 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1586 r = _config_request(ioc, &mpi_request, mpi_reply,
1587 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1588 if (r)
1589 goto out;
1590
1591 mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1592 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1593 r = _config_request(ioc, &mpi_request, mpi_reply,
1594 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1595 sizeof(*config_page));
1596 out:
1597 return r;
1598}
1599
1600/**
1601 * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
1602 * raid components
1603 * @ioc: per adapter object
1604 * @pd_handle: phys disk handle
1605 * @volume_handle: volume handle
1606 * Context: sleep.
1607 *
1608 * Returns 0 for success, non-zero for failure.
1609 */
1610int
1611mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
1612 u16 *volume_handle)
1613{
1614 Mpi2RaidConfigurationPage0_t *config_page = NULL;
1615 Mpi2ConfigRequest_t mpi_request;
1616 Mpi2ConfigReply_t mpi_reply;
1617 int r, i, config_page_sz;
1618 u16 ioc_status;
1619 int config_num;
1620 u16 element_type;
1621 u16 phys_disk_dev_handle;
1622
1623 *volume_handle = 0;
1624 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1625 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1626 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1627 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1628 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1629 mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1630 mpi_request.Header.PageNumber = 0;
1631 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1632 r = _config_request(ioc, &mpi_request, &mpi_reply,
1633 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1634 if (r)
1635 goto out;
1636
1637 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1638 config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1639 config_page = kmalloc(config_page_sz, GFP_KERNEL);
1640 if (!config_page) {
1641 r = -1;
1642 goto out;
1643 }
1644
1645 config_num = 0xff;
1646 while (1) {
1647 mpi_request.PageAddress = cpu_to_le32(config_num +
1648 MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1649 r = _config_request(ioc, &mpi_request, &mpi_reply,
1650 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1651 config_page_sz);
1652 if (r)
1653 goto out;
1654 r = -1;
1655 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1656 MPI2_IOCSTATUS_MASK;
1657 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1658 goto out;
1659 for (i = 0; i < config_page->NumElements; i++) {
1660 element_type = le16_to_cpu(config_page->
1661 ConfigElement[i].ElementFlags) &
1662 MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1663 if (element_type ==
1664 MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1665 element_type ==
1666 MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1667 phys_disk_dev_handle =
1668 le16_to_cpu(config_page->ConfigElement[i].
1669 PhysDiskDevHandle);
1670 if (phys_disk_dev_handle == pd_handle) {
1671 *volume_handle =
1672 le16_to_cpu(config_page->
1673 ConfigElement[i].VolDevHandle);
1674 r = 0;
1675 goto out;
1676 }
1677 } else if (element_type ==
1678 MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1679 *volume_handle = 0;
1680 r = 0;
1681 goto out;
1682 }
1683 }
1684 config_num = config_page->ConfigNum;
1685 }
1686 out:
1687 kfree(config_page);
1688 return r;
1689}
1690
1691/**
1692 * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
1693 * @ioc: per adapter object
1694 * @volume_handle: volume handle
1695 * @wwid: volume wwid
1696 * Context: sleep.
1697 *
1698 * Returns 0 for success, non-zero for failure.
1699 */
1700int
1701mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
1702 u64 *wwid)
1703{
1704 Mpi2ConfigReply_t mpi_reply;
1705 Mpi2RaidVolPage1_t raid_vol_pg1;
1706
1707 *wwid = 0;
1708 if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1709 &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1710 volume_handle))) {
1711 *wwid = le64_to_cpu(raid_vol_pg1.WWID);
1712 return 0;
1713 } else
1714 return -1;
1715}