blob: 1c6658c60239a2ce0fde2d608cbb48abc0abae02 [file] [log] [blame]
Eric Moore635374e2009-03-09 01:21:12 -06001/*
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:
Kashyap, Desai6bd4e1e2009-08-07 19:37:14 +0530250 if (retry_count) {
251 if (retry_count > 2) /* attempt only 2 retries */
252 return -EFAULT;
253 printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n",
254 ioc->name, __func__, retry_count);
255 }
Eric Moore635374e2009-03-09 01:21:12 -0600256 wait_state_count = 0;
257 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
258 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
259 if (wait_state_count++ == MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT) {
260 printk(MPT2SAS_ERR_FMT
261 "%s: failed due to ioc not operational\n",
262 ioc->name, __func__);
263 ioc->config_cmds.status = MPT2_CMD_NOT_USED;
264 return -EFAULT;
265 }
266 ssleep(1);
267 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
268 printk(MPT2SAS_INFO_FMT "%s: waiting for "
269 "operational state(count=%d)\n", ioc->name,
270 __func__, wait_state_count);
271 }
272 if (wait_state_count)
273 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
274 ioc->name, __func__);
275
276 smid = mpt2sas_base_get_smid(ioc, ioc->config_cb_idx);
277 if (!smid) {
278 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
279 ioc->name, __func__);
280 ioc->config_cmds.status = MPT2_CMD_NOT_USED;
281 return -EAGAIN;
282 }
283
284 r = 0;
285 memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
286 ioc->config_cmds.status = MPT2_CMD_PENDING;
287 config_request = mpt2sas_base_get_msg_frame(ioc, smid);
288 ioc->config_cmds.smid = smid;
289 memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
290#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
291 _config_display_some_debug(ioc, smid, "config_request", NULL);
292#endif
293 mpt2sas_base_put_smid_default(ioc, smid, config_request->VF_ID);
294 timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
295 timeout*HZ);
296 if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) {
297 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
298 ioc->name, __func__);
299 _debug_dump_mf(mpi_request,
300 sizeof(Mpi2ConfigRequest_t)/4);
301 if (!(ioc->config_cmds.status & MPT2_CMD_RESET))
302 issue_reset = 1;
303 goto issue_host_reset;
304 }
305 if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID)
306 memcpy(mpi_reply, ioc->config_cmds.reply,
307 sizeof(Mpi2ConfigReply_t));
308 if (retry_count)
309 printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n",
310 ioc->name, __func__);
311 ioc->config_cmds.status = MPT2_CMD_NOT_USED;
312 return r;
313
314 issue_host_reset:
315 if (issue_reset)
316 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
317 FORCE_BIG_HAMMER);
318 ioc->config_cmds.status = MPT2_CMD_NOT_USED;
319 if (!retry_count) {
320 printk(MPT2SAS_INFO_FMT "%s: attempting retry\n",
321 ioc->name, __func__);
322 retry_count++;
323 goto retry_config;
324 }
325 return -EFAULT;
326}
327
328/**
329 * _config_alloc_config_dma_memory - obtain physical memory
330 * @ioc: per adapter object
331 * @mem: struct config_request
332 *
333 * A wrapper for obtaining dma-able memory for config page request.
334 *
335 * Returns 0 for success, non-zero for failure.
336 */
337static int
338_config_alloc_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
339 struct config_request *mem)
340{
341 int r = 0;
342
343 mem->config_page = pci_alloc_consistent(ioc->pdev, mem->config_page_sz,
344 &mem->config_page_dma);
345 if (!mem->config_page)
346 r = -ENOMEM;
347 return r;
348}
349
350/**
351 * _config_free_config_dma_memory - wrapper to free the memory
352 * @ioc: per adapter object
353 * @mem: struct config_request
354 *
355 * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
356 *
357 * Returns 0 for success, non-zero for failure.
358 */
359static void
360_config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
361 struct config_request *mem)
362{
363 pci_free_consistent(ioc->pdev, mem->config_page_sz, mem->config_page,
364 mem->config_page_dma);
365}
366
367/**
368 * mpt2sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
369 * @ioc: per adapter object
370 * @mpi_reply: reply mf payload returned from firmware
371 * @config_page: contents of the config page
372 * Context: sleep.
373 *
374 * Returns 0 for success, non-zero for failure.
375 */
376int
377mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
378 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
379{
380 Mpi2ConfigRequest_t mpi_request;
381 int r;
382 struct config_request mem;
383
384 mutex_lock(&ioc->config_cmds.mutex);
385 memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t));
386 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
387 mpi_request.Function = MPI2_FUNCTION_CONFIG;
388 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
389 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
390 mpi_request.Header.PageNumber = 0;
391 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
392 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
393 r = _config_request(ioc, &mpi_request, mpi_reply,
394 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
395 if (r)
396 goto out;
397
398 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
399 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
400 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
401 mpi_request.Header.PageType = mpi_reply->Header.PageType;
402 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
403 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
404 if (mem.config_page_sz > ioc->config_page_sz) {
405 r = _config_alloc_config_dma_memory(ioc, &mem);
406 if (r)
407 goto out;
408 } else {
409 mem.config_page_dma = ioc->config_page_dma;
410 mem.config_page = ioc->config_page;
411 }
412 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
413 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
414 mem.config_page_dma);
415 r = _config_request(ioc, &mpi_request, mpi_reply,
416 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
417 if (!r)
418 memcpy(config_page, mem.config_page,
419 min_t(u16, mem.config_page_sz,
420 sizeof(Mpi2ManufacturingPage0_t)));
421
422 if (mem.config_page_sz > ioc->config_page_sz)
423 _config_free_config_dma_memory(ioc, &mem);
424
425 out:
426 mutex_unlock(&ioc->config_cmds.mutex);
427 return r;
428}
429
430/**
431 * mpt2sas_config_get_bios_pg2 - obtain bios page 2
432 * @ioc: per adapter object
433 * @mpi_reply: reply mf payload returned from firmware
434 * @config_page: contents of the config page
435 * Context: sleep.
436 *
437 * Returns 0 for success, non-zero for failure.
438 */
439int
440mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc,
441 Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
442{
443 Mpi2ConfigRequest_t mpi_request;
444 int r;
445 struct config_request mem;
446
447 mutex_lock(&ioc->config_cmds.mutex);
448 memset(config_page, 0, sizeof(Mpi2BiosPage2_t));
449 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
450 mpi_request.Function = MPI2_FUNCTION_CONFIG;
451 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
452 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
453 mpi_request.Header.PageNumber = 2;
454 mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
455 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
456 r = _config_request(ioc, &mpi_request, mpi_reply,
457 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
458 if (r)
459 goto out;
460
461 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
462 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
463 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
464 mpi_request.Header.PageType = mpi_reply->Header.PageType;
465 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
466 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
467 if (mem.config_page_sz > ioc->config_page_sz) {
468 r = _config_alloc_config_dma_memory(ioc, &mem);
469 if (r)
470 goto out;
471 } else {
472 mem.config_page_dma = ioc->config_page_dma;
473 mem.config_page = ioc->config_page;
474 }
475 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
476 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
477 mem.config_page_dma);
478 r = _config_request(ioc, &mpi_request, mpi_reply,
479 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
480 if (!r)
481 memcpy(config_page, mem.config_page,
482 min_t(u16, mem.config_page_sz,
483 sizeof(Mpi2BiosPage2_t)));
484
485 if (mem.config_page_sz > ioc->config_page_sz)
486 _config_free_config_dma_memory(ioc, &mem);
487
488 out:
489 mutex_unlock(&ioc->config_cmds.mutex);
490 return r;
491}
492
493/**
494 * mpt2sas_config_get_bios_pg3 - obtain bios page 3
495 * @ioc: per adapter object
496 * @mpi_reply: reply mf payload returned from firmware
497 * @config_page: contents of the config page
498 * Context: sleep.
499 *
500 * Returns 0 for success, non-zero for failure.
501 */
502int
503mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
504 *mpi_reply, Mpi2BiosPage3_t *config_page)
505{
506 Mpi2ConfigRequest_t mpi_request;
507 int r;
508 struct config_request mem;
509
510 mutex_lock(&ioc->config_cmds.mutex);
511 memset(config_page, 0, sizeof(Mpi2BiosPage3_t));
512 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
513 mpi_request.Function = MPI2_FUNCTION_CONFIG;
514 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
515 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
516 mpi_request.Header.PageNumber = 3;
517 mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
518 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
519 r = _config_request(ioc, &mpi_request, mpi_reply,
520 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
521 if (r)
522 goto out;
523
524 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
525 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
526 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
527 mpi_request.Header.PageType = mpi_reply->Header.PageType;
528 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
529 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
530 if (mem.config_page_sz > ioc->config_page_sz) {
531 r = _config_alloc_config_dma_memory(ioc, &mem);
532 if (r)
533 goto out;
534 } else {
535 mem.config_page_dma = ioc->config_page_dma;
536 mem.config_page = ioc->config_page;
537 }
538 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
539 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
540 mem.config_page_dma);
541 r = _config_request(ioc, &mpi_request, mpi_reply,
542 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
543 if (!r)
544 memcpy(config_page, mem.config_page,
545 min_t(u16, mem.config_page_sz,
546 sizeof(Mpi2BiosPage3_t)));
547
548 if (mem.config_page_sz > ioc->config_page_sz)
549 _config_free_config_dma_memory(ioc, &mem);
550
551 out:
552 mutex_unlock(&ioc->config_cmds.mutex);
553 return r;
554}
555
556/**
557 * mpt2sas_config_get_iounit_pg0 - obtain iounit page 0
558 * @ioc: per adapter object
559 * @mpi_reply: reply mf payload returned from firmware
560 * @config_page: contents of the config page
561 * Context: sleep.
562 *
563 * Returns 0 for success, non-zero for failure.
564 */
565int
566mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc,
567 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
568{
569 Mpi2ConfigRequest_t mpi_request;
570 int r;
571 struct config_request mem;
572
573 mutex_lock(&ioc->config_cmds.mutex);
574 memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t));
575 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
576 mpi_request.Function = MPI2_FUNCTION_CONFIG;
577 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
578 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
579 mpi_request.Header.PageNumber = 0;
580 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
581 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
582 r = _config_request(ioc, &mpi_request, mpi_reply,
583 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
584 if (r)
585 goto out;
586
587 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
588 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
589 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
590 mpi_request.Header.PageType = mpi_reply->Header.PageType;
591 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
592 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
593 if (mem.config_page_sz > ioc->config_page_sz) {
594 r = _config_alloc_config_dma_memory(ioc, &mem);
595 if (r)
596 goto out;
597 } else {
598 mem.config_page_dma = ioc->config_page_dma;
599 mem.config_page = ioc->config_page;
600 }
601 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
602 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
603 mem.config_page_dma);
604 r = _config_request(ioc, &mpi_request, mpi_reply,
605 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
606 if (!r)
607 memcpy(config_page, mem.config_page,
608 min_t(u16, mem.config_page_sz,
609 sizeof(Mpi2IOUnitPage0_t)));
610
611 if (mem.config_page_sz > ioc->config_page_sz)
612 _config_free_config_dma_memory(ioc, &mem);
613
614 out:
615 mutex_unlock(&ioc->config_cmds.mutex);
616 return r;
617}
618
619/**
620 * mpt2sas_config_get_iounit_pg1 - obtain iounit page 1
621 * @ioc: per adapter object
622 * @mpi_reply: reply mf payload returned from firmware
623 * @config_page: contents of the config page
624 * Context: sleep.
625 *
626 * Returns 0 for success, non-zero for failure.
627 */
628int
629mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
630 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
631{
632 Mpi2ConfigRequest_t mpi_request;
633 int r;
634 struct config_request mem;
635
636 mutex_lock(&ioc->config_cmds.mutex);
637 memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t));
638 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
639 mpi_request.Function = MPI2_FUNCTION_CONFIG;
640 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
641 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
642 mpi_request.Header.PageNumber = 1;
643 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
644 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
645 r = _config_request(ioc, &mpi_request, mpi_reply,
646 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
647 if (r)
648 goto out;
649
650 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
651 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
652 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
653 mpi_request.Header.PageType = mpi_reply->Header.PageType;
654 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
655 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
656 if (mem.config_page_sz > ioc->config_page_sz) {
657 r = _config_alloc_config_dma_memory(ioc, &mem);
658 if (r)
659 goto out;
660 } else {
661 mem.config_page_dma = ioc->config_page_dma;
662 mem.config_page = ioc->config_page;
663 }
664 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
665 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
666 mem.config_page_dma);
667 r = _config_request(ioc, &mpi_request, mpi_reply,
668 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
669 if (!r)
670 memcpy(config_page, mem.config_page,
671 min_t(u16, mem.config_page_sz,
672 sizeof(Mpi2IOUnitPage1_t)));
673
674 if (mem.config_page_sz > ioc->config_page_sz)
675 _config_free_config_dma_memory(ioc, &mem);
676
677 out:
678 mutex_unlock(&ioc->config_cmds.mutex);
679 return r;
680}
681
682/**
683 * mpt2sas_config_set_iounit_pg1 - set iounit page 1
684 * @ioc: per adapter object
685 * @mpi_reply: reply mf payload returned from firmware
686 * @config_page: contents of the config page
687 * Context: sleep.
688 *
689 * Returns 0 for success, non-zero for failure.
690 */
691int
692mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
693 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t config_page)
694{
695 Mpi2ConfigRequest_t mpi_request;
696 int r;
697 struct config_request mem;
698
699 mutex_lock(&ioc->config_cmds.mutex);
700 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
701 mpi_request.Function = MPI2_FUNCTION_CONFIG;
702 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
703 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
704 mpi_request.Header.PageNumber = 1;
705 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
706 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
707 r = _config_request(ioc, &mpi_request, mpi_reply,
708 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
709 if (r)
710 goto out;
711
712 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
713 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
714 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
715 mpi_request.Header.PageType = mpi_reply->Header.PageType;
716 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
717 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
718 if (mem.config_page_sz > ioc->config_page_sz) {
719 r = _config_alloc_config_dma_memory(ioc, &mem);
720 if (r)
721 goto out;
722 } else {
723 mem.config_page_dma = ioc->config_page_dma;
724 mem.config_page = ioc->config_page;
725 }
726
727 memset(mem.config_page, 0, mem.config_page_sz);
728 memcpy(mem.config_page, &config_page,
729 sizeof(Mpi2IOUnitPage1_t));
730
731 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
732 MPT2_CONFIG_COMMON_WRITE_SGLFLAGS | mem.config_page_sz,
733 mem.config_page_dma);
734 r = _config_request(ioc, &mpi_request, mpi_reply,
735 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
736
737 if (mem.config_page_sz > ioc->config_page_sz)
738 _config_free_config_dma_memory(ioc, &mem);
739
740 out:
741 mutex_unlock(&ioc->config_cmds.mutex);
742 return r;
743}
744
745/**
746 * mpt2sas_config_get_ioc_pg8 - obtain ioc page 8
747 * @ioc: per adapter object
748 * @mpi_reply: reply mf payload returned from firmware
749 * @config_page: contents of the config page
750 * Context: sleep.
751 *
752 * Returns 0 for success, non-zero for failure.
753 */
754int
755mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc,
756 Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
757{
758 Mpi2ConfigRequest_t mpi_request;
759 int r;
760 struct config_request mem;
761
762 mutex_lock(&ioc->config_cmds.mutex);
763 memset(config_page, 0, sizeof(Mpi2IOCPage8_t));
764 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
765 mpi_request.Function = MPI2_FUNCTION_CONFIG;
766 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
767 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
768 mpi_request.Header.PageNumber = 8;
769 mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
770 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
771 r = _config_request(ioc, &mpi_request, mpi_reply,
772 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
773 if (r)
774 goto out;
775
776 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
777 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
778 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
779 mpi_request.Header.PageType = mpi_reply->Header.PageType;
780 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
781 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
782 if (mem.config_page_sz > ioc->config_page_sz) {
783 r = _config_alloc_config_dma_memory(ioc, &mem);
784 if (r)
785 goto out;
786 } else {
787 mem.config_page_dma = ioc->config_page_dma;
788 mem.config_page = ioc->config_page;
789 }
790 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
791 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
792 mem.config_page_dma);
793 r = _config_request(ioc, &mpi_request, mpi_reply,
794 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
795 if (!r)
796 memcpy(config_page, mem.config_page,
797 min_t(u16, mem.config_page_sz,
798 sizeof(Mpi2IOCPage8_t)));
799
800 if (mem.config_page_sz > ioc->config_page_sz)
801 _config_free_config_dma_memory(ioc, &mem);
802
803 out:
804 mutex_unlock(&ioc->config_cmds.mutex);
805 return r;
806}
807
808/**
809 * mpt2sas_config_get_sas_device_pg0 - obtain sas device page 0
810 * @ioc: per adapter object
811 * @mpi_reply: reply mf payload returned from firmware
812 * @config_page: contents of the config page
813 * @form: GET_NEXT_HANDLE or HANDLE
814 * @handle: device handle
815 * Context: sleep.
816 *
817 * Returns 0 for success, non-zero for failure.
818 */
819int
820mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
821 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle)
822{
823 Mpi2ConfigRequest_t mpi_request;
824 int r;
825 struct config_request mem;
826
827 mutex_lock(&ioc->config_cmds.mutex);
828 memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t));
829 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
830 mpi_request.Function = MPI2_FUNCTION_CONFIG;
831 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
832 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
833 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
834 mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
835 mpi_request.Header.PageNumber = 0;
836 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
837 r = _config_request(ioc, &mpi_request, mpi_reply,
838 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
839 if (r)
840 goto out;
841
842 mpi_request.PageAddress = cpu_to_le32(form | handle);
843 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
844 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
845 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
846 mpi_request.Header.PageType = mpi_reply->Header.PageType;
847 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
848 mpi_request.ExtPageType = mpi_reply->ExtPageType;
849 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
850 if (mem.config_page_sz > ioc->config_page_sz) {
851 r = _config_alloc_config_dma_memory(ioc, &mem);
852 if (r)
853 goto out;
854 } else {
855 mem.config_page_dma = ioc->config_page_dma;
856 mem.config_page = ioc->config_page;
857 }
858 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
859 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
860 mem.config_page_dma);
861 r = _config_request(ioc, &mpi_request, mpi_reply,
862 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
863 if (!r)
864 memcpy(config_page, mem.config_page,
865 min_t(u16, mem.config_page_sz,
866 sizeof(Mpi2SasDevicePage0_t)));
867
868 if (mem.config_page_sz > ioc->config_page_sz)
869 _config_free_config_dma_memory(ioc, &mem);
870
871 out:
872 mutex_unlock(&ioc->config_cmds.mutex);
873 return r;
874}
875
876/**
877 * mpt2sas_config_get_sas_device_pg1 - obtain sas device page 1
878 * @ioc: per adapter object
879 * @mpi_reply: reply mf payload returned from firmware
880 * @config_page: contents of the config page
881 * @form: GET_NEXT_HANDLE or HANDLE
882 * @handle: device handle
883 * Context: sleep.
884 *
885 * Returns 0 for success, non-zero for failure.
886 */
887int
888mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
889 *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle)
890{
891 Mpi2ConfigRequest_t mpi_request;
892 int r;
893 struct config_request mem;
894
895 mutex_lock(&ioc->config_cmds.mutex);
896 memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t));
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_EXTENDED;
901 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
902 mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
903 mpi_request.Header.PageNumber = 1;
904 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
905 r = _config_request(ioc, &mpi_request, mpi_reply,
906 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
907 if (r)
908 goto out;
909
910 mpi_request.PageAddress = cpu_to_le32(form | handle);
911 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
912 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
913 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
914 mpi_request.Header.PageType = mpi_reply->Header.PageType;
915 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
916 mpi_request.ExtPageType = mpi_reply->ExtPageType;
917 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
918 if (mem.config_page_sz > ioc->config_page_sz) {
919 r = _config_alloc_config_dma_memory(ioc, &mem);
920 if (r)
921 goto out;
922 } else {
923 mem.config_page_dma = ioc->config_page_dma;
924 mem.config_page = ioc->config_page;
925 }
926 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
927 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
928 mem.config_page_dma);
929 r = _config_request(ioc, &mpi_request, mpi_reply,
930 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
931 if (!r)
932 memcpy(config_page, mem.config_page,
933 min_t(u16, mem.config_page_sz,
934 sizeof(Mpi2SasDevicePage1_t)));
935
936 if (mem.config_page_sz > ioc->config_page_sz)
937 _config_free_config_dma_memory(ioc, &mem);
938
939 out:
940 mutex_unlock(&ioc->config_cmds.mutex);
941 return r;
942}
943
944/**
945 * mpt2sas_config_get_number_hba_phys - obtain number of phys on the host
946 * @ioc: per adapter object
947 * @num_phys: pointer returned with the number of phys
948 * Context: sleep.
949 *
950 * Returns 0 for success, non-zero for failure.
951 */
952int
953mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys)
954{
955 Mpi2ConfigRequest_t mpi_request;
956 int r;
957 struct config_request mem;
958 u16 ioc_status;
959 Mpi2ConfigReply_t mpi_reply;
960 Mpi2SasIOUnitPage0_t config_page;
961
962 mutex_lock(&ioc->config_cmds.mutex);
963 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
964 mpi_request.Function = MPI2_FUNCTION_CONFIG;
965 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
966 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
967 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
968 mpi_request.Header.PageNumber = 0;
969 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
970 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
971 r = _config_request(ioc, &mpi_request, &mpi_reply,
972 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
973 if (r)
974 goto out;
975
976 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
977 mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion;
978 mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber;
979 mpi_request.Header.PageType = mpi_reply.Header.PageType;
980 mpi_request.ExtPageLength = mpi_reply.ExtPageLength;
981 mpi_request.ExtPageType = mpi_reply.ExtPageType;
982 mem.config_page_sz = le16_to_cpu(mpi_reply.ExtPageLength) * 4;
983 if (mem.config_page_sz > ioc->config_page_sz) {
984 r = _config_alloc_config_dma_memory(ioc, &mem);
985 if (r)
986 goto out;
987 } else {
988 mem.config_page_dma = ioc->config_page_dma;
989 mem.config_page = ioc->config_page;
990 }
991 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
992 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
993 mem.config_page_dma);
994 r = _config_request(ioc, &mpi_request, &mpi_reply,
995 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
996 if (!r) {
997 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
998 MPI2_IOCSTATUS_MASK;
999 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1000 memcpy(&config_page, mem.config_page,
1001 min_t(u16, mem.config_page_sz,
1002 sizeof(Mpi2SasIOUnitPage0_t)));
1003 *num_phys = config_page.NumPhys;
1004 }
1005 }
1006
1007 if (mem.config_page_sz > ioc->config_page_sz)
1008 _config_free_config_dma_memory(ioc, &mem);
1009
1010 out:
1011 mutex_unlock(&ioc->config_cmds.mutex);
1012 return r;
1013}
1014
1015/**
1016 * mpt2sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1017 * @ioc: per adapter object
1018 * @mpi_reply: reply mf payload returned from firmware
1019 * @config_page: contents of the config page
1020 * @sz: size of buffer passed in config_page
1021 * Context: sleep.
1022 *
1023 * Calling function should call config_get_number_hba_phys prior to
1024 * this function, so enough memory is allocated for config_page.
1025 *
1026 * Returns 0 for success, non-zero for failure.
1027 */
1028int
1029mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1030 *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz)
1031{
1032 Mpi2ConfigRequest_t mpi_request;
1033 int r;
1034 struct config_request mem;
1035
1036 mutex_lock(&ioc->config_cmds.mutex);
1037 memset(config_page, 0, sz);
1038 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1039 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1040 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1041 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1042 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1043 mpi_request.Header.PageNumber = 0;
1044 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1045 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1046 r = _config_request(ioc, &mpi_request, mpi_reply,
1047 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1048 if (r)
1049 goto out;
1050
1051 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1052 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1053 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1054 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1055 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1056 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1057 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1058 if (mem.config_page_sz > ioc->config_page_sz) {
1059 r = _config_alloc_config_dma_memory(ioc, &mem);
1060 if (r)
1061 goto out;
1062 } else {
1063 mem.config_page_dma = ioc->config_page_dma;
1064 mem.config_page = ioc->config_page;
1065 }
1066 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1067 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1068 mem.config_page_dma);
1069 r = _config_request(ioc, &mpi_request, mpi_reply,
1070 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1071 if (!r)
1072 memcpy(config_page, mem.config_page,
1073 min_t(u16, sz, mem.config_page_sz));
1074
1075 if (mem.config_page_sz > ioc->config_page_sz)
1076 _config_free_config_dma_memory(ioc, &mem);
1077
1078 out:
1079 mutex_unlock(&ioc->config_cmds.mutex);
1080 return r;
1081}
1082
1083/**
1084 * mpt2sas_config_get_sas_iounit_pg1 - obtain sas iounit page 0
1085 * @ioc: per adapter object
1086 * @mpi_reply: reply mf payload returned from firmware
1087 * @config_page: contents of the config page
1088 * @sz: size of buffer passed in config_page
1089 * Context: sleep.
1090 *
1091 * Calling function should call config_get_number_hba_phys prior to
1092 * this function, so enough memory is allocated for config_page.
1093 *
1094 * Returns 0 for success, non-zero for failure.
1095 */
1096int
1097mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1098 *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz)
1099{
1100 Mpi2ConfigRequest_t mpi_request;
1101 int r;
1102 struct config_request mem;
1103
1104 mutex_lock(&ioc->config_cmds.mutex);
1105 memset(config_page, 0, sz);
1106 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1107 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1108 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1109 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1110 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1111 mpi_request.Header.PageNumber = 1;
1112 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1113 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1114 r = _config_request(ioc, &mpi_request, mpi_reply,
1115 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1116 if (r)
1117 goto out;
1118
1119 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1120 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1121 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1122 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1123 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1124 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1125 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1126 if (mem.config_page_sz > ioc->config_page_sz) {
1127 r = _config_alloc_config_dma_memory(ioc, &mem);
1128 if (r)
1129 goto out;
1130 } else {
1131 mem.config_page_dma = ioc->config_page_dma;
1132 mem.config_page = ioc->config_page;
1133 }
1134 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1135 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1136 mem.config_page_dma);
1137 r = _config_request(ioc, &mpi_request, mpi_reply,
1138 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1139 if (!r)
1140 memcpy(config_page, mem.config_page,
1141 min_t(u16, sz, mem.config_page_sz));
1142
1143 if (mem.config_page_sz > ioc->config_page_sz)
1144 _config_free_config_dma_memory(ioc, &mem);
1145
1146 out:
1147 mutex_unlock(&ioc->config_cmds.mutex);
1148 return r;
1149}
1150
1151/**
1152 * mpt2sas_config_get_expander_pg0 - obtain expander page 0
1153 * @ioc: per adapter object
1154 * @mpi_reply: reply mf payload returned from firmware
1155 * @config_page: contents of the config page
1156 * @form: GET_NEXT_HANDLE or HANDLE
1157 * @handle: expander handle
1158 * Context: sleep.
1159 *
1160 * Returns 0 for success, non-zero for failure.
1161 */
1162int
1163mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1164 *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1165{
1166 Mpi2ConfigRequest_t mpi_request;
1167 int r;
1168 struct config_request mem;
1169
1170 mutex_lock(&ioc->config_cmds.mutex);
1171 memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t));
1172 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1173 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1174 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1175 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1176 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1177 mpi_request.Header.PageNumber = 0;
1178 mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1179 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1180 r = _config_request(ioc, &mpi_request, mpi_reply,
1181 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1182 if (r)
1183 goto out;
1184
1185 mpi_request.PageAddress = cpu_to_le32(form | handle);
1186 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1187 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1188 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1189 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1190 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1191 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1192 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1193 if (mem.config_page_sz > ioc->config_page_sz) {
1194 r = _config_alloc_config_dma_memory(ioc, &mem);
1195 if (r)
1196 goto out;
1197 } else {
1198 mem.config_page_dma = ioc->config_page_dma;
1199 mem.config_page = ioc->config_page;
1200 }
1201 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1202 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1203 mem.config_page_dma);
1204 r = _config_request(ioc, &mpi_request, mpi_reply,
1205 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1206 if (!r)
1207 memcpy(config_page, mem.config_page,
1208 min_t(u16, mem.config_page_sz,
1209 sizeof(Mpi2ExpanderPage0_t)));
1210
1211 if (mem.config_page_sz > ioc->config_page_sz)
1212 _config_free_config_dma_memory(ioc, &mem);
1213
1214 out:
1215 mutex_unlock(&ioc->config_cmds.mutex);
1216 return r;
1217}
1218
1219/**
1220 * mpt2sas_config_get_expander_pg1 - obtain expander page 1
1221 * @ioc: per adapter object
1222 * @mpi_reply: reply mf payload returned from firmware
1223 * @config_page: contents of the config page
1224 * @phy_number: phy number
1225 * @handle: expander handle
1226 * Context: sleep.
1227 *
1228 * Returns 0 for success, non-zero for failure.
1229 */
1230int
1231mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1232 *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1233 u16 handle)
1234{
1235 Mpi2ConfigRequest_t mpi_request;
1236 int r;
1237 struct config_request mem;
1238
1239 mutex_lock(&ioc->config_cmds.mutex);
1240 memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t));
1241 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1242 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1243 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1244 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1245 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1246 mpi_request.Header.PageNumber = 1;
1247 mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1248 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1249 r = _config_request(ioc, &mpi_request, mpi_reply,
1250 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1251 if (r)
1252 goto out;
1253
1254 mpi_request.PageAddress =
1255 cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1256 (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1257 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1258 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1259 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1260 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1261 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1262 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1263 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1264 if (mem.config_page_sz > ioc->config_page_sz) {
1265 r = _config_alloc_config_dma_memory(ioc, &mem);
1266 if (r)
1267 goto out;
1268 } else {
1269 mem.config_page_dma = ioc->config_page_dma;
1270 mem.config_page = ioc->config_page;
1271 }
1272 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1273 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1274 mem.config_page_dma);
1275 r = _config_request(ioc, &mpi_request, mpi_reply,
1276 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1277 if (!r)
1278 memcpy(config_page, mem.config_page,
1279 min_t(u16, mem.config_page_sz,
1280 sizeof(Mpi2ExpanderPage1_t)));
1281
1282 if (mem.config_page_sz > ioc->config_page_sz)
1283 _config_free_config_dma_memory(ioc, &mem);
1284
1285 out:
1286 mutex_unlock(&ioc->config_cmds.mutex);
1287 return r;
1288}
1289
1290/**
1291 * mpt2sas_config_get_enclosure_pg0 - obtain enclosure page 0
1292 * @ioc: per adapter object
1293 * @mpi_reply: reply mf payload returned from firmware
1294 * @config_page: contents of the config page
1295 * @form: GET_NEXT_HANDLE or HANDLE
1296 * @handle: expander handle
1297 * Context: sleep.
1298 *
1299 * Returns 0 for success, non-zero for failure.
1300 */
1301int
1302mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1303 *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1304{
1305 Mpi2ConfigRequest_t mpi_request;
1306 int r;
1307 struct config_request mem;
1308
1309 mutex_lock(&ioc->config_cmds.mutex);
1310 memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t));
1311 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1312 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1313 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1314 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1315 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1316 mpi_request.Header.PageNumber = 0;
1317 mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1318 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1319 r = _config_request(ioc, &mpi_request, mpi_reply,
1320 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1321 if (r)
1322 goto out;
1323
1324 mpi_request.PageAddress = cpu_to_le32(form | handle);
1325 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1326 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1327 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1328 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1329 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1330 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1331 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1332 if (mem.config_page_sz > ioc->config_page_sz) {
1333 r = _config_alloc_config_dma_memory(ioc, &mem);
1334 if (r)
1335 goto out;
1336 } else {
1337 mem.config_page_dma = ioc->config_page_dma;
1338 mem.config_page = ioc->config_page;
1339 }
1340 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1341 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1342 mem.config_page_dma);
1343 r = _config_request(ioc, &mpi_request, mpi_reply,
1344 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1345 if (!r)
1346 memcpy(config_page, mem.config_page,
1347 min_t(u16, mem.config_page_sz,
1348 sizeof(Mpi2SasEnclosurePage0_t)));
1349
1350 if (mem.config_page_sz > ioc->config_page_sz)
1351 _config_free_config_dma_memory(ioc, &mem);
1352
1353 out:
1354 mutex_unlock(&ioc->config_cmds.mutex);
1355 return r;
1356}
1357
1358/**
1359 * mpt2sas_config_get_phy_pg0 - obtain phy page 0
1360 * @ioc: per adapter object
1361 * @mpi_reply: reply mf payload returned from firmware
1362 * @config_page: contents of the config page
1363 * @phy_number: phy number
1364 * Context: sleep.
1365 *
1366 * Returns 0 for success, non-zero for failure.
1367 */
1368int
1369mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1370 *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1371{
1372 Mpi2ConfigRequest_t mpi_request;
1373 int r;
1374 struct config_request mem;
1375
1376 mutex_lock(&ioc->config_cmds.mutex);
1377 memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t));
1378 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1379 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1380 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1381 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1382 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1383 mpi_request.Header.PageNumber = 0;
1384 mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1385 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1386 r = _config_request(ioc, &mpi_request, mpi_reply,
1387 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1388 if (r)
1389 goto out;
1390
1391 mpi_request.PageAddress =
1392 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1393 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1394 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1395 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1396 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1397 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1398 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1399 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1400 if (mem.config_page_sz > ioc->config_page_sz) {
1401 r = _config_alloc_config_dma_memory(ioc, &mem);
1402 if (r)
1403 goto out;
1404 } else {
1405 mem.config_page_dma = ioc->config_page_dma;
1406 mem.config_page = ioc->config_page;
1407 }
1408 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1409 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1410 mem.config_page_dma);
1411 r = _config_request(ioc, &mpi_request, mpi_reply,
1412 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1413 if (!r)
1414 memcpy(config_page, mem.config_page,
1415 min_t(u16, mem.config_page_sz,
1416 sizeof(Mpi2SasPhyPage0_t)));
1417
1418 if (mem.config_page_sz > ioc->config_page_sz)
1419 _config_free_config_dma_memory(ioc, &mem);
1420
1421 out:
1422 mutex_unlock(&ioc->config_cmds.mutex);
1423 return r;
1424}
1425
1426/**
1427 * mpt2sas_config_get_phy_pg1 - obtain phy page 1
1428 * @ioc: per adapter object
1429 * @mpi_reply: reply mf payload returned from firmware
1430 * @config_page: contents of the config page
1431 * @phy_number: phy number
1432 * Context: sleep.
1433 *
1434 * Returns 0 for success, non-zero for failure.
1435 */
1436int
1437mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1438 *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1439{
1440 Mpi2ConfigRequest_t mpi_request;
1441 int r;
1442 struct config_request mem;
1443
1444 mutex_lock(&ioc->config_cmds.mutex);
1445 memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t));
1446 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1447 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1448 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1449 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1450 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1451 mpi_request.Header.PageNumber = 1;
1452 mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1453 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1454 r = _config_request(ioc, &mpi_request, mpi_reply,
1455 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1456 if (r)
1457 goto out;
1458
1459 mpi_request.PageAddress =
1460 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1461 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1462 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1463 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1464 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1465 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1466 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1467 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1468 if (mem.config_page_sz > ioc->config_page_sz) {
1469 r = _config_alloc_config_dma_memory(ioc, &mem);
1470 if (r)
1471 goto out;
1472 } else {
1473 mem.config_page_dma = ioc->config_page_dma;
1474 mem.config_page = ioc->config_page;
1475 }
1476 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1477 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1478 mem.config_page_dma);
1479 r = _config_request(ioc, &mpi_request, mpi_reply,
1480 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1481 if (!r)
1482 memcpy(config_page, mem.config_page,
1483 min_t(u16, mem.config_page_sz,
1484 sizeof(Mpi2SasPhyPage1_t)));
1485
1486 if (mem.config_page_sz > ioc->config_page_sz)
1487 _config_free_config_dma_memory(ioc, &mem);
1488
1489 out:
1490 mutex_unlock(&ioc->config_cmds.mutex);
1491 return r;
1492}
1493
1494/**
1495 * mpt2sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1496 * @ioc: per adapter object
1497 * @mpi_reply: reply mf payload returned from firmware
1498 * @config_page: contents of the config page
1499 * @form: GET_NEXT_HANDLE or HANDLE
1500 * @handle: volume handle
1501 * Context: sleep.
1502 *
1503 * Returns 0 for success, non-zero for failure.
1504 */
1505int
1506mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc,
1507 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1508 u32 handle)
1509{
1510 Mpi2ConfigRequest_t mpi_request;
1511 int r;
1512 struct config_request mem;
1513
1514 mutex_lock(&ioc->config_cmds.mutex);
1515 memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t));
1516 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1517 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1518 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1519 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1520 mpi_request.Header.PageNumber = 1;
1521 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1522 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1523 r = _config_request(ioc, &mpi_request, mpi_reply,
1524 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1525 if (r)
1526 goto out;
1527
1528 mpi_request.PageAddress = cpu_to_le32(form | handle);
1529 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1530 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1531 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1532 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1533 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
1534 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
1535 if (mem.config_page_sz > ioc->config_page_sz) {
1536 r = _config_alloc_config_dma_memory(ioc, &mem);
1537 if (r)
1538 goto out;
1539 } else {
1540 mem.config_page_dma = ioc->config_page_dma;
1541 mem.config_page = ioc->config_page;
1542 }
1543 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1544 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1545 mem.config_page_dma);
1546 r = _config_request(ioc, &mpi_request, mpi_reply,
1547 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1548 if (!r)
1549 memcpy(config_page, mem.config_page,
1550 min_t(u16, mem.config_page_sz,
1551 sizeof(Mpi2RaidVolPage1_t)));
1552
1553 if (mem.config_page_sz > ioc->config_page_sz)
1554 _config_free_config_dma_memory(ioc, &mem);
1555
1556 out:
1557 mutex_unlock(&ioc->config_cmds.mutex);
1558 return r;
1559}
1560
1561/**
1562 * mpt2sas_config_get_number_pds - obtain number of phys disk assigned to volume
1563 * @ioc: per adapter object
1564 * @handle: volume handle
1565 * @num_pds: returns pds count
1566 * Context: sleep.
1567 *
1568 * Returns 0 for success, non-zero for failure.
1569 */
1570int
1571mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle,
1572 u8 *num_pds)
1573{
1574 Mpi2ConfigRequest_t mpi_request;
1575 Mpi2RaidVolPage0_t *config_page;
1576 Mpi2ConfigReply_t mpi_reply;
1577 int r;
1578 struct config_request mem;
1579 u16 ioc_status;
1580
1581 mutex_lock(&ioc->config_cmds.mutex);
1582 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1583 *num_pds = 0;
1584 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1585 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1586 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1587 mpi_request.Header.PageNumber = 0;
1588 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1589 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1590 r = _config_request(ioc, &mpi_request, &mpi_reply,
1591 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1592 if (r)
1593 goto out;
1594
1595 mpi_request.PageAddress =
1596 cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1597 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1598 mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion;
1599 mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber;
1600 mpi_request.Header.PageType = mpi_reply.Header.PageType;
1601 mpi_request.Header.PageLength = mpi_reply.Header.PageLength;
1602 mem.config_page_sz = le16_to_cpu(mpi_reply.Header.PageLength) * 4;
1603 if (mem.config_page_sz > ioc->config_page_sz) {
1604 r = _config_alloc_config_dma_memory(ioc, &mem);
1605 if (r)
1606 goto out;
1607 } else {
1608 mem.config_page_dma = ioc->config_page_dma;
1609 mem.config_page = ioc->config_page;
1610 }
1611 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1612 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1613 mem.config_page_dma);
1614 r = _config_request(ioc, &mpi_request, &mpi_reply,
1615 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1616 if (!r) {
1617 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1618 MPI2_IOCSTATUS_MASK;
1619 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1620 config_page = mem.config_page;
1621 *num_pds = config_page->NumPhysDisks;
1622 }
1623 }
1624
1625 if (mem.config_page_sz > ioc->config_page_sz)
1626 _config_free_config_dma_memory(ioc, &mem);
1627
1628 out:
1629 mutex_unlock(&ioc->config_cmds.mutex);
1630 return r;
1631}
1632
1633/**
1634 * mpt2sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1635 * @ioc: per adapter object
1636 * @mpi_reply: reply mf payload returned from firmware
1637 * @config_page: contents of the config page
1638 * @form: GET_NEXT_HANDLE or HANDLE
1639 * @handle: volume handle
1640 * @sz: size of buffer passed in config_page
1641 * Context: sleep.
1642 *
1643 * Returns 0 for success, non-zero for failure.
1644 */
1645int
1646mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc,
1647 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1648 u32 handle, u16 sz)
1649{
1650 Mpi2ConfigRequest_t mpi_request;
1651 int r;
1652 struct config_request mem;
1653
1654 mutex_lock(&ioc->config_cmds.mutex);
1655 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1656 memset(config_page, 0, sz);
1657 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1658 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1659 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1660 mpi_request.Header.PageNumber = 0;
1661 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1662 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1663 r = _config_request(ioc, &mpi_request, mpi_reply,
1664 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1665 if (r)
1666 goto out;
1667
1668 mpi_request.PageAddress = cpu_to_le32(form | handle);
1669 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1670 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1671 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1672 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1673 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
1674 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
1675 if (mem.config_page_sz > ioc->config_page_sz) {
1676 r = _config_alloc_config_dma_memory(ioc, &mem);
1677 if (r)
1678 goto out;
1679 } else {
1680 mem.config_page_dma = ioc->config_page_dma;
1681 mem.config_page = ioc->config_page;
1682 }
1683 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1684 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1685 mem.config_page_dma);
1686 r = _config_request(ioc, &mpi_request, mpi_reply,
1687 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1688 if (!r)
1689 memcpy(config_page, mem.config_page,
1690 min_t(u16, sz, mem.config_page_sz));
1691
1692 if (mem.config_page_sz > ioc->config_page_sz)
1693 _config_free_config_dma_memory(ioc, &mem);
1694
1695 out:
1696 mutex_unlock(&ioc->config_cmds.mutex);
1697 return r;
1698}
1699
1700/**
1701 * mpt2sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1702 * @ioc: per adapter object
1703 * @mpi_reply: reply mf payload returned from firmware
1704 * @config_page: contents of the config page
1705 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1706 * @form_specific: specific to the form
1707 * Context: sleep.
1708 *
1709 * Returns 0 for success, non-zero for failure.
1710 */
1711int
1712mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1713 *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1714 u32 form_specific)
1715{
1716 Mpi2ConfigRequest_t mpi_request;
1717 int r;
1718 struct config_request mem;
1719
1720 mutex_lock(&ioc->config_cmds.mutex);
1721 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1722 memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t));
1723 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1724 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1725 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1726 mpi_request.Header.PageNumber = 0;
1727 mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1728 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1729 r = _config_request(ioc, &mpi_request, mpi_reply,
1730 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1731 if (r)
1732 goto out;
1733
1734 mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1735 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1736 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1737 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1738 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1739 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
1740 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
1741 if (mem.config_page_sz > ioc->config_page_sz) {
1742 r = _config_alloc_config_dma_memory(ioc, &mem);
1743 if (r)
1744 goto out;
1745 } else {
1746 mem.config_page_dma = ioc->config_page_dma;
1747 mem.config_page = ioc->config_page;
1748 }
1749 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1750 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1751 mem.config_page_dma);
1752 r = _config_request(ioc, &mpi_request, mpi_reply,
1753 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1754 if (!r)
1755 memcpy(config_page, mem.config_page,
1756 min_t(u16, mem.config_page_sz,
1757 sizeof(Mpi2RaidPhysDiskPage0_t)));
1758
1759 if (mem.config_page_sz > ioc->config_page_sz)
1760 _config_free_config_dma_memory(ioc, &mem);
1761
1762 out:
1763 mutex_unlock(&ioc->config_cmds.mutex);
1764 return r;
1765}
1766
1767/**
1768 * mpt2sas_config_get_volume_handle - returns volume handle for give hidden raid components
1769 * @ioc: per adapter object
1770 * @pd_handle: phys disk handle
1771 * @volume_handle: volume handle
1772 * Context: sleep.
1773 *
1774 * Returns 0 for success, non-zero for failure.
1775 */
1776int
1777mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
1778 u16 *volume_handle)
1779{
1780 Mpi2RaidConfigurationPage0_t *config_page;
1781 Mpi2ConfigRequest_t mpi_request;
1782 Mpi2ConfigReply_t mpi_reply;
1783 int r, i;
1784 struct config_request mem;
1785 u16 ioc_status;
1786
1787 mutex_lock(&ioc->config_cmds.mutex);
1788 *volume_handle = 0;
1789 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1790 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1791 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1792 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1793 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1794 mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1795 mpi_request.Header.PageNumber = 0;
1796 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1797 r = _config_request(ioc, &mpi_request, &mpi_reply,
1798 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1799 if (r)
1800 goto out;
1801
1802 mpi_request.PageAddress =
1803 cpu_to_le32(MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG);
1804 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1805 mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion;
1806 mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber;
1807 mpi_request.Header.PageType = mpi_reply.Header.PageType;
1808 mpi_request.ExtPageLength = mpi_reply.ExtPageLength;
1809 mpi_request.ExtPageType = mpi_reply.ExtPageType;
1810 mem.config_page_sz = le16_to_cpu(mpi_reply.ExtPageLength) * 4;
1811 if (mem.config_page_sz > ioc->config_page_sz) {
1812 r = _config_alloc_config_dma_memory(ioc, &mem);
1813 if (r)
1814 goto out;
1815 } else {
1816 mem.config_page_dma = ioc->config_page_dma;
1817 mem.config_page = ioc->config_page;
1818 }
1819 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1820 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1821 mem.config_page_dma);
1822 r = _config_request(ioc, &mpi_request, &mpi_reply,
1823 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1824 if (r)
1825 goto out;
1826
1827 r = -1;
1828 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
1829 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1830 goto done;
1831 config_page = mem.config_page;
1832 for (i = 0; i < config_page->NumElements; i++) {
1833 if ((config_page->ConfigElement[i].ElementFlags &
1834 MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE) !=
1835 MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT)
1836 continue;
1837 if (config_page->ConfigElement[i].PhysDiskDevHandle ==
1838 pd_handle) {
1839 *volume_handle = le16_to_cpu(config_page->
1840 ConfigElement[i].VolDevHandle);
1841 r = 0;
1842 goto done;
1843 }
1844 }
1845
1846 done:
1847 if (mem.config_page_sz > ioc->config_page_sz)
1848 _config_free_config_dma_memory(ioc, &mem);
1849
1850 out:
1851 mutex_unlock(&ioc->config_cmds.mutex);
1852 return r;
1853}
1854
1855/**
1856 * mpt2sas_config_get_volume_wwid - returns wwid given the volume handle
1857 * @ioc: per adapter object
1858 * @volume_handle: volume handle
1859 * @wwid: volume wwid
1860 * Context: sleep.
1861 *
1862 * Returns 0 for success, non-zero for failure.
1863 */
1864int
1865mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
1866 u64 *wwid)
1867{
1868 Mpi2ConfigReply_t mpi_reply;
1869 Mpi2RaidVolPage1_t raid_vol_pg1;
1870
1871 *wwid = 0;
1872 if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1873 &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1874 volume_handle))) {
1875 *wwid = le64_to_cpu(raid_vol_pg1.WWID);
1876 return 0;
1877 } else
1878 return -1;
1879}