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