Merge branch 'nfs-for-2.6.32'
[pandora-kernel.git] / drivers / scsi / mpt2sas / mpt2sas_config.c
1 /*
2  * This module provides common API for accessing firmware configuration pages
3  *
4  * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
5  * Copyright (C) 2007-2008  LSI Corporation
6  *  (mailto:DL-MPTFusionLinux@lsi.com)
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * NO WARRANTY
19  * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
20  * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
21  * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
23  * solely responsible for determining the appropriateness of using and
24  * distributing the Program and assumes all risks associated with its
25  * exercise of rights under this Agreement, including but not limited to
26  * the risks and costs of program errors, damage to or loss of data,
27  * programs or equipment, and unavailability or interruption of operations.
28
29  * DISCLAIMER OF LIABILITY
30  * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
31  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
33  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35  * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
36  * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
37
38  * You should have received a copy of the GNU General Public License
39  * along with this program; if not, write to the Free Software
40  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
41  * USA.
42  */
43
44 #include <linux/version.h>
45 #include <linux/module.h>
46 #include <linux/kernel.h>
47 #include <linux/init.h>
48 #include <linux/errno.h>
49 #include <linux/blkdev.h>
50 #include <linux/sched.h>
51 #include <linux/workqueue.h>
52 #include <linux/delay.h>
53 #include <linux/pci.h>
54
55 #include "mpt2sas_base.h"
56
57 /* local definitions */
58
59 /* Timeout for config page request (in seconds) */
60 #define MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT 15
61
62 /* Common sgl flags for READING a config page. */
63 #define MPT2_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
64     MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
65     | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT)
66
67 /* Common sgl flags for WRITING a config page. */
68 #define MPT2_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
69     MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
70     | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \
71     << MPI2_SGE_FLAGS_SHIFT)
72
73 /**
74  * struct config_request - obtain dma memory via routine
75  * @config_page_sz: size
76  * @config_page: virt pointer
77  * @config_page_dma: phys pointer
78  *
79  */
80 struct 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  */
98 static 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  */
189 void
190 mpt2sas_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  */
229 static 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_host_reset = 0;
240         u16 wait_state_count;
241
242         mutex_lock(&ioc->config_cmds.mutex);
243         if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) {
244                 printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n",
245                     ioc->name, __func__);
246                 mutex_unlock(&ioc->config_cmds.mutex);
247                 return -EAGAIN;
248         }
249         retry_count = 0;
250
251  retry_config:
252         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         }
258         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__);
265                         r = -EFAULT;
266                         goto out;
267                 }
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__);
282                 r = -EAGAIN;
283                 goto out;
284         }
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);
303                 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;
312         }
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__);
319 out:
320         ioc->config_cmds.status = MPT2_CMD_NOT_USED;
321         mutex_unlock(&ioc->config_cmds.mutex);
322         if (issue_host_reset)
323                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
324                     FORCE_BIG_HAMMER);
325         return r;
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  */
337 static 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  */
359 static 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  */
376 int
377 mpt2sas_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         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:
425         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  */
437 int
438 mpt2sas_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
445         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:
486         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  */
498 int
499 mpt2sas_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
506         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:
547         return r;
548 }
549
550 /**
551  * mpt2sas_config_get_iounit_pg0 - obtain iounit page 0
552  * @ioc: per adapter object
553  * @mpi_reply: reply mf payload returned from firmware
554  * @config_page: contents of the config page
555  * Context: sleep.
556  *
557  * Returns 0 for success, non-zero for failure.
558  */
559 int
560 mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc,
561     Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
562 {
563         Mpi2ConfigRequest_t mpi_request;
564         int r;
565         struct config_request mem;
566
567         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:
608         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  */
620 int
621 mpt2sas_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
628         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:
669         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  */
681 int
682 mpt2sas_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
689         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:
730         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  */
742 int
743 mpt2sas_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
750         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:
791         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  */
805 int
806 mpt2sas_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
813         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:
857         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  */
871 int
872 mpt2sas_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
879         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:
923         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  */
934 int
935 mpt2sas_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
944         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:
992         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  */
1008 int
1009 mpt2sas_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;
1015         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:
1057         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  */
1073 int
1074 mpt2sas_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
1081         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:
1123         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  */
1137 int
1138 mpt2sas_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
1145         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:
1189         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  */
1203 int
1204 mpt2sas_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
1212         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:
1258         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  */
1272 int
1273 mpt2sas_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
1280         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:
1324         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  */
1337 int
1338 mpt2sas_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
1345         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:
1390         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  */
1403 int
1404 mpt2sas_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
1411         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:
1456         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  */
1470 int
1471 mpt2sas_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
1479         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:
1521         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  */
1533 int
1534 mpt2sas_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
1544         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:
1591         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  */
1606 int
1607 mpt2sas_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
1615         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:
1656         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  */
1670 int
1671 mpt2sas_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
1679         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:
1721         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  */
1733 int
1734 mpt2sas_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
1744         *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:
1807         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  */
1819 int
1820 mpt2sas_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 }