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