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