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