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