Merge branch 'stable/for-linus-5.2' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.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 = "manufacturing";
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                 case MPI2_CONFIG_EXTPAGETYPE_SAS_PORT:
154                         desc = "sas_port";
155                         break;
156                 case MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING:
157                         desc = "ext_manufacturing";
158                         break;
159                 case MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT:
160                         desc = "pcie_io_unit";
161                         break;
162                 case MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH:
163                         desc = "pcie_switch";
164                         break;
165                 case MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE:
166                         desc = "pcie_device";
167                         break;
168                 case MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK:
169                         desc = "pcie_link";
170                         break;
171                 }
172                 break;
173         }
174
175         if (!desc)
176                 return;
177
178         ioc_info(ioc, "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n",
179                  calling_function_name, desc,
180                  mpi_request->Header.PageNumber, mpi_request->Action,
181                  le32_to_cpu(mpi_request->PageAddress), smid);
182
183         if (!mpi_reply)
184                 return;
185
186         if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
187                 ioc_info(ioc, "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
188                          le16_to_cpu(mpi_reply->IOCStatus),
189                          le32_to_cpu(mpi_reply->IOCLogInfo));
190 }
191
192 /**
193  * _config_alloc_config_dma_memory - obtain physical memory
194  * @ioc: per adapter object
195  * @mem: struct config_request
196  *
197  * A wrapper for obtaining dma-able memory for config page request.
198  *
199  * Return: 0 for success, non-zero for failure.
200  */
201 static int
202 _config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
203         struct config_request *mem)
204 {
205         int r = 0;
206
207         if (mem->sz > ioc->config_page_sz) {
208                 mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
209                     &mem->page_dma, GFP_KERNEL);
210                 if (!mem->page) {
211                         ioc_err(ioc, "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n",
212                                 __func__, mem->sz);
213                         r = -ENOMEM;
214                 }
215         } else { /* use tmp buffer if less than 512 bytes */
216                 mem->page = ioc->config_page;
217                 mem->page_dma = ioc->config_page_dma;
218         }
219         ioc->config_vaddr = mem->page;
220         return r;
221 }
222
223 /**
224  * _config_free_config_dma_memory - wrapper to free the memory
225  * @ioc: per adapter object
226  * @mem: struct config_request
227  *
228  * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
229  *
230  * Return: 0 for success, non-zero for failure.
231  */
232 static void
233 _config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
234         struct config_request *mem)
235 {
236         if (mem->sz > ioc->config_page_sz)
237                 dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
238                     mem->page_dma);
239 }
240
241 /**
242  * mpt3sas_config_done - config page completion routine
243  * @ioc: per adapter object
244  * @smid: system request message index
245  * @msix_index: MSIX table index supplied by the OS
246  * @reply: reply message frame(lower 32bit addr)
247  * Context: none.
248  *
249  * The callback handler when using _config_request.
250  *
251  * Return: 1 meaning mf should be freed from _base_interrupt
252  *         0 means the mf is freed from this function.
253  */
254 u8
255 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
256         u32 reply)
257 {
258         MPI2DefaultReply_t *mpi_reply;
259
260         if (ioc->config_cmds.status == MPT3_CMD_NOT_USED)
261                 return 1;
262         if (ioc->config_cmds.smid != smid)
263                 return 1;
264         ioc->config_cmds.status |= MPT3_CMD_COMPLETE;
265         mpi_reply =  mpt3sas_base_get_reply_virt_addr(ioc, reply);
266         if (mpi_reply) {
267                 ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID;
268                 memcpy(ioc->config_cmds.reply, mpi_reply,
269                     mpi_reply->MsgLength*4);
270         }
271         ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
272         _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
273         ioc->config_cmds.smid = USHRT_MAX;
274         complete(&ioc->config_cmds.done);
275         return 1;
276 }
277
278 /**
279  * _config_request - main routine for sending config page requests
280  * @ioc: per adapter object
281  * @mpi_request: request message frame
282  * @mpi_reply: reply mf payload returned from firmware
283  * @timeout: timeout in seconds
284  * @config_page: contents of the config page
285  * @config_page_sz: size of config page
286  * Context: sleep
287  *
288  * A generic API for config page requests to firmware.
289  *
290  * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling
291  * this API.
292  *
293  * The callback index is set inside `ioc->config_cb_idx.
294  *
295  * Return: 0 for success, non-zero for failure.
296  */
297 static int
298 _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
299         *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
300         void *config_page, u16 config_page_sz)
301 {
302         u16 smid;
303         Mpi2ConfigRequest_t *config_request;
304         int r;
305         u8 retry_count, issue_host_reset = 0;
306         struct config_request mem;
307         u32 ioc_status = UINT_MAX;
308
309         mutex_lock(&ioc->config_cmds.mutex);
310         if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
311                 ioc_err(ioc, "%s: config_cmd in use\n", __func__);
312                 mutex_unlock(&ioc->config_cmds.mutex);
313                 return -EAGAIN;
314         }
315
316         retry_count = 0;
317         memset(&mem, 0, sizeof(struct config_request));
318
319         mpi_request->VF_ID = 0; /* TODO */
320         mpi_request->VP_ID = 0;
321
322         if (config_page) {
323                 mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
324                 mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
325                 mpi_request->Header.PageType = mpi_reply->Header.PageType;
326                 mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
327                 mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
328                 mpi_request->ExtPageType = mpi_reply->ExtPageType;
329                 if (mpi_request->Header.PageLength)
330                         mem.sz = mpi_request->Header.PageLength * 4;
331                 else
332                         mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
333                 r = _config_alloc_config_dma_memory(ioc, &mem);
334                 if (r != 0)
335                         goto out;
336                 if (mpi_request->Action ==
337                     MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
338                     mpi_request->Action ==
339                     MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
340                         ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
341                             MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
342                             mem.page_dma);
343                         memcpy(mem.page, config_page, min_t(u16, mem.sz,
344                             config_page_sz));
345                 } else {
346                         memset(config_page, 0, config_page_sz);
347                         ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
348                             MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
349                         memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
350                 }
351         }
352
353  retry_config:
354         if (retry_count) {
355                 if (retry_count > 2) { /* attempt only 2 retries */
356                         r = -EFAULT;
357                         goto free_mem;
358                 }
359                 ioc_info(ioc, "%s: attempting retry (%d)\n",
360                          __func__, retry_count);
361         }
362
363         r = mpt3sas_wait_for_ioc(ioc, MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT);
364         if (r)
365                 goto free_mem;
366
367         smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
368         if (!smid) {
369                 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
370                 ioc->config_cmds.status = MPT3_CMD_NOT_USED;
371                 r = -EAGAIN;
372                 goto free_mem;
373         }
374
375         r = 0;
376         memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
377         ioc->config_cmds.status = MPT3_CMD_PENDING;
378         config_request = mpt3sas_base_get_msg_frame(ioc, smid);
379         ioc->config_cmds.smid = smid;
380         memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
381         _config_display_some_debug(ioc, smid, "config_request", NULL);
382         init_completion(&ioc->config_cmds.done);
383         mpt3sas_base_put_smid_default(ioc, smid);
384         wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ);
385         if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
386                 mpt3sas_base_check_cmd_timeout(ioc,
387                         ioc->config_cmds.status, mpi_request,
388                         sizeof(Mpi2ConfigRequest_t)/4);
389                 retry_count++;
390                 if (ioc->config_cmds.smid == smid)
391                         mpt3sas_base_free_smid(ioc, smid);
392                 if ((ioc->shost_recovery) || (ioc->config_cmds.status &
393                     MPT3_CMD_RESET) || ioc->pci_error_recovery)
394                         goto retry_config;
395                 issue_host_reset = 1;
396                 r = -EFAULT;
397                 goto free_mem;
398         }
399
400         if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
401                 memcpy(mpi_reply, ioc->config_cmds.reply,
402                     sizeof(Mpi2ConfigReply_t));
403
404                 /* Reply Frame Sanity Checks to workaround FW issues */
405                 if ((mpi_request->Header.PageType & 0xF) !=
406                     (mpi_reply->Header.PageType & 0xF)) {
407                         _debug_dump_mf(mpi_request, ioc->request_sz/4);
408                         _debug_dump_reply(mpi_reply, ioc->request_sz/4);
409                         panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
410                               ioc->name, __func__,
411                               mpi_request->Header.PageType & 0xF,
412                               mpi_reply->Header.PageType & 0xF);
413                 }
414
415                 if (((mpi_request->Header.PageType & 0xF) ==
416                     MPI2_CONFIG_PAGETYPE_EXTENDED) &&
417                     mpi_request->ExtPageType != mpi_reply->ExtPageType) {
418                         _debug_dump_mf(mpi_request, ioc->request_sz/4);
419                         _debug_dump_reply(mpi_reply, ioc->request_sz/4);
420                         panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
421                               ioc->name, __func__,
422                               mpi_request->ExtPageType,
423                               mpi_reply->ExtPageType);
424                 }
425                 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
426                     & MPI2_IOCSTATUS_MASK;
427         }
428
429         if (retry_count)
430                 ioc_info(ioc, "%s: retry (%d) completed!!\n",
431                          __func__, retry_count);
432
433         if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
434             config_page && mpi_request->Action ==
435             MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
436                 u8 *p = (u8 *)mem.page;
437
438                 /* Config Page Sanity Checks to workaround FW issues */
439                 if (p) {
440                         if ((mpi_request->Header.PageType & 0xF) !=
441                             (p[3] & 0xF)) {
442                                 _debug_dump_mf(mpi_request, ioc->request_sz/4);
443                                 _debug_dump_reply(mpi_reply, ioc->request_sz/4);
444                                 _debug_dump_config(p, min_t(u16, mem.sz,
445                                     config_page_sz)/4);
446                                 panic("%s: %s: Firmware BUG: config page mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
447                                       ioc->name, __func__,
448                                       mpi_request->Header.PageType & 0xF,
449                                       p[3] & 0xF);
450                         }
451
452                         if (((mpi_request->Header.PageType & 0xF) ==
453                             MPI2_CONFIG_PAGETYPE_EXTENDED) &&
454                             (mpi_request->ExtPageType != p[6])) {
455                                 _debug_dump_mf(mpi_request, ioc->request_sz/4);
456                                 _debug_dump_reply(mpi_reply, ioc->request_sz/4);
457                                 _debug_dump_config(p, min_t(u16, mem.sz,
458                                     config_page_sz)/4);
459                                 panic("%s: %s: Firmware BUG: config page mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
460                                       ioc->name, __func__,
461                                       mpi_request->ExtPageType, p[6]);
462                         }
463                 }
464                 memcpy(config_page, mem.page, min_t(u16, mem.sz,
465                     config_page_sz));
466         }
467
468  free_mem:
469         if (config_page)
470                 _config_free_config_dma_memory(ioc, &mem);
471  out:
472         ioc->config_cmds.status = MPT3_CMD_NOT_USED;
473         mutex_unlock(&ioc->config_cmds.mutex);
474
475         if (issue_host_reset)
476                 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
477         return r;
478 }
479
480 /**
481  * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
482  * @ioc: per adapter object
483  * @mpi_reply: reply mf payload returned from firmware
484  * @config_page: contents of the config page
485  * Context: sleep.
486  *
487  * Return: 0 for success, non-zero for failure.
488  */
489 int
490 mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
491         Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
492 {
493         Mpi2ConfigRequest_t mpi_request;
494         int r;
495
496         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
497         mpi_request.Function = MPI2_FUNCTION_CONFIG;
498         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
499         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
500         mpi_request.Header.PageNumber = 0;
501         mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
502         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
503         r = _config_request(ioc, &mpi_request, mpi_reply,
504             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
505         if (r)
506                 goto out;
507
508         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
509         r = _config_request(ioc, &mpi_request, mpi_reply,
510             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
511             sizeof(*config_page));
512  out:
513         return r;
514 }
515
516 /**
517  * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
518  * @ioc: per adapter object
519  * @mpi_reply: reply mf payload returned from firmware
520  * @config_page: contents of the config page
521  * @sz: size of buffer passed in config_page
522  * Context: sleep.
523  *
524  * Return: 0 for success, non-zero for failure.
525  */
526 int
527 mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
528         Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
529         u16 sz)
530 {
531         Mpi2ConfigRequest_t mpi_request;
532         int r;
533
534         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
535         mpi_request.Function = MPI2_FUNCTION_CONFIG;
536         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
537         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
538         mpi_request.Header.PageNumber = 7;
539         mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
540         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
541         r = _config_request(ioc, &mpi_request, mpi_reply,
542             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
543         if (r)
544                 goto out;
545
546         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
547         r = _config_request(ioc, &mpi_request, mpi_reply,
548             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
549             sz);
550  out:
551         return r;
552 }
553
554 /**
555  * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
556  * @ioc: per adapter object
557  * @mpi_reply: reply mf payload returned from firmware
558  * @config_page: contents of the config page
559  * Context: sleep.
560  *
561  * Return: 0 for success, non-zero for failure.
562  */
563 int
564 mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
565         Mpi2ConfigReply_t *mpi_reply,
566         struct Mpi2ManufacturingPage10_t *config_page)
567 {
568         Mpi2ConfigRequest_t mpi_request;
569         int r;
570
571         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
572         mpi_request.Function = MPI2_FUNCTION_CONFIG;
573         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
574         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
575         mpi_request.Header.PageNumber = 10;
576         mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
577         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
578         r = _config_request(ioc, &mpi_request, mpi_reply,
579             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
580         if (r)
581                 goto out;
582
583         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
584         r = _config_request(ioc, &mpi_request, mpi_reply,
585             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
586             sizeof(*config_page));
587  out:
588         return r;
589 }
590
591 /**
592  * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
593  * @ioc: per adapter object
594  * @mpi_reply: reply mf payload returned from firmware
595  * @config_page: contents of the config page
596  * Context: sleep.
597  *
598  * Return: 0 for success, non-zero for failure.
599  */
600 int
601 mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
602         Mpi2ConfigReply_t *mpi_reply,
603         struct Mpi2ManufacturingPage11_t *config_page)
604 {
605         Mpi2ConfigRequest_t mpi_request;
606         int r;
607
608         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
609         mpi_request.Function = MPI2_FUNCTION_CONFIG;
610         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
611         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
612         mpi_request.Header.PageNumber = 11;
613         mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
614         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
615         r = _config_request(ioc, &mpi_request, mpi_reply,
616             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
617         if (r)
618                 goto out;
619
620         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
621         r = _config_request(ioc, &mpi_request, mpi_reply,
622             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
623             sizeof(*config_page));
624  out:
625         return r;
626 }
627
628 /**
629  * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
630  * @ioc: per adapter object
631  * @mpi_reply: reply mf payload returned from firmware
632  * @config_page: contents of the config page
633  * Context: sleep.
634  *
635  * Return: 0 for success, non-zero for failure.
636  */
637 int
638 mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
639         Mpi2ConfigReply_t *mpi_reply,
640         struct Mpi2ManufacturingPage11_t *config_page)
641 {
642         Mpi2ConfigRequest_t mpi_request;
643         int r;
644
645         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
646         mpi_request.Function = MPI2_FUNCTION_CONFIG;
647         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
648         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
649         mpi_request.Header.PageNumber = 11;
650         mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
651         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
652         r = _config_request(ioc, &mpi_request, mpi_reply,
653             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
654         if (r)
655                 goto out;
656
657         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
658         r = _config_request(ioc, &mpi_request, mpi_reply,
659             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
660             sizeof(*config_page));
661  out:
662         return r;
663 }
664
665 /**
666  * mpt3sas_config_get_bios_pg2 - obtain bios page 2
667  * @ioc: per adapter object
668  * @mpi_reply: reply mf payload returned from firmware
669  * @config_page: contents of the config page
670  * Context: sleep.
671  *
672  * Return: 0 for success, non-zero for failure.
673  */
674 int
675 mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
676         Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
677 {
678         Mpi2ConfigRequest_t mpi_request;
679         int r;
680
681         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
682         mpi_request.Function = MPI2_FUNCTION_CONFIG;
683         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
684         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
685         mpi_request.Header.PageNumber = 2;
686         mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
687         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
688         r = _config_request(ioc, &mpi_request, mpi_reply,
689             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
690         if (r)
691                 goto out;
692
693         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
694         r = _config_request(ioc, &mpi_request, mpi_reply,
695             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
696             sizeof(*config_page));
697  out:
698         return r;
699 }
700
701 /**
702  * mpt3sas_config_get_bios_pg3 - obtain bios page 3
703  * @ioc: per adapter object
704  * @mpi_reply: reply mf payload returned from firmware
705  * @config_page: contents of the config page
706  * Context: sleep.
707  *
708  * Return: 0 for success, non-zero for failure.
709  */
710 int
711 mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
712         *mpi_reply, Mpi2BiosPage3_t *config_page)
713 {
714         Mpi2ConfigRequest_t mpi_request;
715         int r;
716
717         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
718         mpi_request.Function = MPI2_FUNCTION_CONFIG;
719         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
720         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
721         mpi_request.Header.PageNumber = 3;
722         mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
723         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
724         r = _config_request(ioc, &mpi_request, mpi_reply,
725             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
726         if (r)
727                 goto out;
728
729         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
730         r = _config_request(ioc, &mpi_request, mpi_reply,
731             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
732             sizeof(*config_page));
733  out:
734         return r;
735 }
736
737 /**
738  * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
739  * @ioc: per adapter object
740  * @mpi_reply: reply mf payload returned from firmware
741  * @config_page: contents of the config page
742  * Context: sleep.
743  *
744  * Return: 0 for success, non-zero for failure.
745  */
746 int
747 mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
748         Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
749 {
750         Mpi2ConfigRequest_t mpi_request;
751         int r;
752
753         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
754         mpi_request.Function = MPI2_FUNCTION_CONFIG;
755         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
756         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
757         mpi_request.Header.PageNumber = 0;
758         mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
759         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
760         r = _config_request(ioc, &mpi_request, mpi_reply,
761             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
762         if (r)
763                 goto out;
764
765         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
766         r = _config_request(ioc, &mpi_request, mpi_reply,
767             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
768             sizeof(*config_page));
769  out:
770         return r;
771 }
772
773 /**
774  * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
775  * @ioc: per adapter object
776  * @mpi_reply: reply mf payload returned from firmware
777  * @config_page: contents of the config page
778  * Context: sleep.
779  *
780  * Return: 0 for success, non-zero for failure.
781  */
782 int
783 mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
784         Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
785 {
786         Mpi2ConfigRequest_t mpi_request;
787         int r;
788
789         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
790         mpi_request.Function = MPI2_FUNCTION_CONFIG;
791         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
792         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
793         mpi_request.Header.PageNumber = 1;
794         mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
795         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
796         r = _config_request(ioc, &mpi_request, mpi_reply,
797             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
798         if (r)
799                 goto out;
800
801         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
802         r = _config_request(ioc, &mpi_request, mpi_reply,
803             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
804             sizeof(*config_page));
805  out:
806         return r;
807 }
808
809 /**
810  * mpt3sas_config_set_iounit_pg1 - set iounit page 1
811  * @ioc: per adapter object
812  * @mpi_reply: reply mf payload returned from firmware
813  * @config_page: contents of the config page
814  * Context: sleep.
815  *
816  * Return: 0 for success, non-zero for failure.
817  */
818 int
819 mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
820         Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
821 {
822         Mpi2ConfigRequest_t mpi_request;
823         int r;
824
825         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
826         mpi_request.Function = MPI2_FUNCTION_CONFIG;
827         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
828         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
829         mpi_request.Header.PageNumber = 1;
830         mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
831         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
832         r = _config_request(ioc, &mpi_request, mpi_reply,
833             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
834         if (r)
835                 goto out;
836
837         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
838         r = _config_request(ioc, &mpi_request, mpi_reply,
839             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
840             sizeof(*config_page));
841  out:
842         return r;
843 }
844
845 /**
846  * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
847  * @ioc: per adapter object
848  * @mpi_reply: reply mf payload returned from firmware
849  * @config_page: contents of the config page
850  * @sz: size of buffer passed in config_page
851  * Context: sleep.
852  *
853  * Return: 0 for success, non-zero for failure.
854  */
855 int
856 mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
857         Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
858 {
859         Mpi2ConfigRequest_t mpi_request;
860         int r;
861
862         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
863         mpi_request.Function = MPI2_FUNCTION_CONFIG;
864         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
865         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
866         mpi_request.Header.PageNumber = 3;
867         mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
868         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
869         r = _config_request(ioc, &mpi_request, mpi_reply,
870             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
871         if (r)
872                 goto out;
873
874         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
875         r = _config_request(ioc, &mpi_request, mpi_reply,
876             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
877  out:
878         return r;
879 }
880
881 /**
882  * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
883  * @ioc: per adapter object
884  * @mpi_reply: reply mf payload returned from firmware
885  * @config_page: contents of the config page
886  * Context: sleep.
887  *
888  * Return: 0 for success, non-zero for failure.
889  */
890 int
891 mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
892         Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
893 {
894         Mpi2ConfigRequest_t mpi_request;
895         int r;
896
897         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
898         mpi_request.Function = MPI2_FUNCTION_CONFIG;
899         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
900         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
901         mpi_request.Header.PageNumber = 8;
902         mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
903         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
904         r = _config_request(ioc, &mpi_request, mpi_reply,
905             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
906         if (r)
907                 goto out;
908
909         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
910         r = _config_request(ioc, &mpi_request, mpi_reply,
911             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
912             sizeof(*config_page));
913  out:
914         return r;
915 }
916
917 /**
918  * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
919  * @ioc: per adapter object
920  * @mpi_reply: reply mf payload returned from firmware
921  * @config_page: contents of the config page
922  * Context: sleep.
923  *
924  * Return: 0 for success, non-zero for failure.
925  */
926 int
927 mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
928         Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
929 {
930         Mpi2ConfigRequest_t mpi_request;
931         int r;
932
933         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
934         mpi_request.Function = MPI2_FUNCTION_CONFIG;
935         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
936         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
937         mpi_request.Header.PageNumber = 8;
938         mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
939         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
940         r = _config_request(ioc, &mpi_request, mpi_reply,
941             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
942         if (r)
943                 goto out;
944
945         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
946         r = _config_request(ioc, &mpi_request, mpi_reply,
947             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
948             sizeof(*config_page));
949  out:
950         return r;
951 }
952
953 /**
954  * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
955  * @ioc: per adapter object
956  * @mpi_reply: reply mf payload returned from firmware
957  * @config_page: contents of the config page
958  * @form: GET_NEXT_HANDLE or HANDLE
959  * @handle: device handle
960  * Context: sleep.
961  *
962  * Return: 0 for success, non-zero for failure.
963  */
964 int
965 mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
966         Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
967         u32 form, u32 handle)
968 {
969         Mpi2ConfigRequest_t mpi_request;
970         int r;
971
972         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
973         mpi_request.Function = MPI2_FUNCTION_CONFIG;
974         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
975         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
976         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
977         mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
978         mpi_request.Header.PageNumber = 0;
979         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
980         r = _config_request(ioc, &mpi_request, mpi_reply,
981             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
982         if (r)
983                 goto out;
984
985         mpi_request.PageAddress = cpu_to_le32(form | handle);
986         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
987         r = _config_request(ioc, &mpi_request, mpi_reply,
988             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
989             sizeof(*config_page));
990  out:
991         return r;
992 }
993
994 /**
995  * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
996  * @ioc: per adapter object
997  * @mpi_reply: reply mf payload returned from firmware
998  * @config_page: contents of the config page
999  * @form: GET_NEXT_HANDLE or HANDLE
1000  * @handle: device handle
1001  * Context: sleep.
1002  *
1003  * Return: 0 for success, non-zero for failure.
1004  */
1005 int
1006 mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1007         Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1008         u32 form, u32 handle)
1009 {
1010         Mpi2ConfigRequest_t mpi_request;
1011         int r;
1012
1013         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1014         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1015         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1016         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1017         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1018         mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1019         mpi_request.Header.PageNumber = 1;
1020         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1021         r = _config_request(ioc, &mpi_request, mpi_reply,
1022             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1023         if (r)
1024                 goto out;
1025
1026         mpi_request.PageAddress = cpu_to_le32(form | handle);
1027         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1028         r = _config_request(ioc, &mpi_request, mpi_reply,
1029             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1030             sizeof(*config_page));
1031  out:
1032         return r;
1033 }
1034
1035 /**
1036  * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
1037  * @ioc: per adapter object
1038  * @mpi_reply: reply mf payload returned from firmware
1039  * @config_page: contents of the config page
1040  * @form: GET_NEXT_HANDLE or HANDLE
1041  * @handle: device handle
1042  * Context: sleep.
1043  *
1044  * Return: 0 for success, non-zero for failure.
1045  */
1046 int
1047 mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1048         Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
1049         u32 form, u32 handle)
1050 {
1051         Mpi2ConfigRequest_t mpi_request;
1052         int r;
1053
1054         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1055         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1056         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1057         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1058         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1059         mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
1060         mpi_request.Header.PageNumber = 0;
1061         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1062         r = _config_request(ioc, &mpi_request, mpi_reply,
1063                         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1064         if (r)
1065                 goto out;
1066
1067         mpi_request.PageAddress = cpu_to_le32(form | handle);
1068         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1069         r = _config_request(ioc, &mpi_request, mpi_reply,
1070                         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1071                         sizeof(*config_page));
1072 out:
1073         return r;
1074 }
1075
1076 /**
1077  * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
1078  * @ioc: per adapter object
1079  * @mpi_reply: reply mf payload returned from firmware
1080  * @config_page: contents of the config page
1081  * @form: GET_NEXT_HANDLE or HANDLE
1082  * @handle: device handle
1083  * Context: sleep.
1084  *
1085  * Return: 0 for success, non-zero for failure.
1086  */
1087 int
1088 mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
1089         Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
1090         u32 form, u32 handle)
1091 {
1092         Mpi2ConfigRequest_t mpi_request;
1093         int r;
1094
1095         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1096         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1097         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1098         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1099         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1100         mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
1101         mpi_request.Header.PageNumber = 2;
1102         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1103         r = _config_request(ioc, &mpi_request, mpi_reply,
1104                         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1105         if (r)
1106                 goto out;
1107
1108         mpi_request.PageAddress = cpu_to_le32(form | handle);
1109         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1110         r = _config_request(ioc, &mpi_request, mpi_reply,
1111                         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1112                         sizeof(*config_page));
1113 out:
1114         return r;
1115 }
1116
1117 /**
1118  * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1119  * @ioc: per adapter object
1120  * @num_phys: pointer returned with the number of phys
1121  * Context: sleep.
1122  *
1123  * Return: 0 for success, non-zero for failure.
1124  */
1125 int
1126 mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1127 {
1128         Mpi2ConfigRequest_t mpi_request;
1129         int r;
1130         u16 ioc_status;
1131         Mpi2ConfigReply_t mpi_reply;
1132         Mpi2SasIOUnitPage0_t config_page;
1133
1134         *num_phys = 0;
1135         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1136         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1137         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1138         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1139         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1140         mpi_request.Header.PageNumber = 0;
1141         mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1142         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1143         r = _config_request(ioc, &mpi_request, &mpi_reply,
1144             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1145         if (r)
1146                 goto out;
1147
1148         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1149         r = _config_request(ioc, &mpi_request, &mpi_reply,
1150             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1151             sizeof(Mpi2SasIOUnitPage0_t));
1152         if (!r) {
1153                 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1154                     MPI2_IOCSTATUS_MASK;
1155                 if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1156                         *num_phys = config_page.NumPhys;
1157         }
1158  out:
1159         return r;
1160 }
1161
1162 /**
1163  * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1164  * @ioc: per adapter object
1165  * @mpi_reply: reply mf payload returned from firmware
1166  * @config_page: contents of the config page
1167  * @sz: size of buffer passed in config_page
1168  * Context: sleep.
1169  *
1170  * Calling function should call config_get_number_hba_phys prior to
1171  * this function, so enough memory is allocated for config_page.
1172  *
1173  * Return: 0 for success, non-zero for failure.
1174  */
1175 int
1176 mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1177         Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1178         u16 sz)
1179 {
1180         Mpi2ConfigRequest_t mpi_request;
1181         int r;
1182
1183         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1184         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1185         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1186         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1187         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1188         mpi_request.Header.PageNumber = 0;
1189         mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1190         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1191         r = _config_request(ioc, &mpi_request, mpi_reply,
1192             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1193         if (r)
1194                 goto out;
1195
1196         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1197         r = _config_request(ioc, &mpi_request, mpi_reply,
1198             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1199  out:
1200         return r;
1201 }
1202
1203 /**
1204  * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1205  * @ioc: per adapter object
1206  * @mpi_reply: reply mf payload returned from firmware
1207  * @config_page: contents of the config page
1208  * @sz: size of buffer passed in config_page
1209  * Context: sleep.
1210  *
1211  * Calling function should call config_get_number_hba_phys prior to
1212  * this function, so enough memory is allocated for config_page.
1213  *
1214  * Return: 0 for success, non-zero for failure.
1215  */
1216 int
1217 mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1218         Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1219         u16 sz)
1220 {
1221         Mpi2ConfigRequest_t mpi_request;
1222         int r;
1223
1224         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1225         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1226         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1227         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1228         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1229         mpi_request.Header.PageNumber = 1;
1230         mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1231         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1232         r = _config_request(ioc, &mpi_request, mpi_reply,
1233             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1234         if (r)
1235                 goto out;
1236
1237         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1238         r = _config_request(ioc, &mpi_request, mpi_reply,
1239             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1240  out:
1241         return r;
1242 }
1243
1244 /**
1245  * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1246  * @ioc: per adapter object
1247  * @mpi_reply: reply mf payload returned from firmware
1248  * @config_page: contents of the config page
1249  * @sz: size of buffer passed in config_page
1250  * Context: sleep.
1251  *
1252  * Calling function should call config_get_number_hba_phys prior to
1253  * this function, so enough memory is allocated for config_page.
1254  *
1255  * Return: 0 for success, non-zero for failure.
1256  */
1257 int
1258 mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1259         Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1260         u16 sz)
1261 {
1262         Mpi2ConfigRequest_t mpi_request;
1263         int r;
1264
1265         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1266         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1267         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1268         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1269         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1270         mpi_request.Header.PageNumber = 1;
1271         mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1272         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1273         r = _config_request(ioc, &mpi_request, mpi_reply,
1274             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1275         if (r)
1276                 goto out;
1277
1278         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1279         _config_request(ioc, &mpi_request, mpi_reply,
1280             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1281         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1282         r = _config_request(ioc, &mpi_request, mpi_reply,
1283             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1284  out:
1285         return r;
1286 }
1287
1288 /**
1289  * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1290  * @ioc: per adapter object
1291  * @mpi_reply: reply mf payload returned from firmware
1292  * @config_page: contents of the config page
1293  * @form: GET_NEXT_HANDLE or HANDLE
1294  * @handle: expander handle
1295  * Context: sleep.
1296  *
1297  * Return: 0 for success, non-zero for failure.
1298  */
1299 int
1300 mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1301         *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1302 {
1303         Mpi2ConfigRequest_t mpi_request;
1304         int r;
1305
1306         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1307         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1308         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1309         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1310         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1311         mpi_request.Header.PageNumber = 0;
1312         mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1313         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1314         r = _config_request(ioc, &mpi_request, mpi_reply,
1315             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1316         if (r)
1317                 goto out;
1318
1319         mpi_request.PageAddress = cpu_to_le32(form | handle);
1320         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1321         r = _config_request(ioc, &mpi_request, mpi_reply,
1322             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1323             sizeof(*config_page));
1324  out:
1325         return r;
1326 }
1327
1328 /**
1329  * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1330  * @ioc: per adapter object
1331  * @mpi_reply: reply mf payload returned from firmware
1332  * @config_page: contents of the config page
1333  * @phy_number: phy number
1334  * @handle: expander handle
1335  * Context: sleep.
1336  *
1337  * Return: 0 for success, non-zero for failure.
1338  */
1339 int
1340 mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1341         *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1342         u16 handle)
1343 {
1344         Mpi2ConfigRequest_t mpi_request;
1345         int r;
1346
1347         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1348         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1349         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1350         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1351         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1352         mpi_request.Header.PageNumber = 1;
1353         mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1354         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1355         r = _config_request(ioc, &mpi_request, mpi_reply,
1356             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1357         if (r)
1358                 goto out;
1359
1360         mpi_request.PageAddress =
1361             cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1362             (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1363         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1364         r = _config_request(ioc, &mpi_request, mpi_reply,
1365             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1366             sizeof(*config_page));
1367  out:
1368         return r;
1369 }
1370
1371 /**
1372  * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1373  * @ioc: per adapter object
1374  * @mpi_reply: reply mf payload returned from firmware
1375  * @config_page: contents of the config page
1376  * @form: GET_NEXT_HANDLE or HANDLE
1377  * @handle: expander handle
1378  * Context: sleep.
1379  *
1380  * Return: 0 for success, non-zero for failure.
1381  */
1382 int
1383 mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1384         *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1385 {
1386         Mpi2ConfigRequest_t mpi_request;
1387         int r;
1388
1389         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1390         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1391         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1392         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1393         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1394         mpi_request.Header.PageNumber = 0;
1395         mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1396         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1397         r = _config_request(ioc, &mpi_request, mpi_reply,
1398             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1399         if (r)
1400                 goto out;
1401
1402         mpi_request.PageAddress = cpu_to_le32(form | handle);
1403         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1404         r = _config_request(ioc, &mpi_request, mpi_reply,
1405             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1406             sizeof(*config_page));
1407  out:
1408         return r;
1409 }
1410
1411 /**
1412  * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1413  * @ioc: per adapter object
1414  * @mpi_reply: reply mf payload returned from firmware
1415  * @config_page: contents of the config page
1416  * @phy_number: phy number
1417  * Context: sleep.
1418  *
1419  * Return: 0 for success, non-zero for failure.
1420  */
1421 int
1422 mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1423         *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1424 {
1425         Mpi2ConfigRequest_t mpi_request;
1426         int r;
1427
1428         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1429         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1430         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1431         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1432         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1433         mpi_request.Header.PageNumber = 0;
1434         mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1435         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1436         r = _config_request(ioc, &mpi_request, mpi_reply,
1437             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1438         if (r)
1439                 goto out;
1440
1441         mpi_request.PageAddress =
1442             cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1443         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1444         r = _config_request(ioc, &mpi_request, mpi_reply,
1445             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1446             sizeof(*config_page));
1447  out:
1448         return r;
1449 }
1450
1451 /**
1452  * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1453  * @ioc: per adapter object
1454  * @mpi_reply: reply mf payload returned from firmware
1455  * @config_page: contents of the config page
1456  * @phy_number: phy number
1457  * Context: sleep.
1458  *
1459  * Return: 0 for success, non-zero for failure.
1460  */
1461 int
1462 mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1463         *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1464 {
1465         Mpi2ConfigRequest_t mpi_request;
1466         int r;
1467
1468         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1469         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1470         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1471         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1472         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1473         mpi_request.Header.PageNumber = 1;
1474         mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1475         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1476         r = _config_request(ioc, &mpi_request, mpi_reply,
1477             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1478         if (r)
1479                 goto out;
1480
1481         mpi_request.PageAddress =
1482             cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1483         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1484         r = _config_request(ioc, &mpi_request, mpi_reply,
1485             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1486             sizeof(*config_page));
1487  out:
1488         return r;
1489 }
1490
1491 /**
1492  * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1493  * @ioc: per adapter object
1494  * @mpi_reply: reply mf payload returned from firmware
1495  * @config_page: contents of the config page
1496  * @form: GET_NEXT_HANDLE or HANDLE
1497  * @handle: volume handle
1498  * Context: sleep.
1499  *
1500  * Return: 0 for success, non-zero for failure.
1501  */
1502 int
1503 mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1504         Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1505         u32 handle)
1506 {
1507         Mpi2ConfigRequest_t mpi_request;
1508         int r;
1509
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         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1517         r = _config_request(ioc, &mpi_request, mpi_reply,
1518             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
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         r = _config_request(ioc, &mpi_request, mpi_reply,
1525             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1526             sizeof(*config_page));
1527  out:
1528         return r;
1529 }
1530
1531 /**
1532  * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1533  * @ioc: per adapter object
1534  * @handle: volume handle
1535  * @num_pds: returns pds count
1536  * Context: sleep.
1537  *
1538  * Return: 0 for success, non-zero for failure.
1539  */
1540 int
1541 mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1542         u8 *num_pds)
1543 {
1544         Mpi2ConfigRequest_t mpi_request;
1545         Mpi2RaidVolPage0_t config_page;
1546         Mpi2ConfigReply_t mpi_reply;
1547         int r;
1548         u16 ioc_status;
1549
1550         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1551         *num_pds = 0;
1552         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1553         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1554         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1555         mpi_request.Header.PageNumber = 0;
1556         mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1557         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1558         r = _config_request(ioc, &mpi_request, &mpi_reply,
1559             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1560         if (r)
1561                 goto out;
1562
1563         mpi_request.PageAddress =
1564             cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1565         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1566         r = _config_request(ioc, &mpi_request, &mpi_reply,
1567             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1568             sizeof(Mpi2RaidVolPage0_t));
1569         if (!r) {
1570                 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1571                     MPI2_IOCSTATUS_MASK;
1572                 if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1573                         *num_pds = config_page.NumPhysDisks;
1574         }
1575
1576  out:
1577         return r;
1578 }
1579
1580 /**
1581  * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1582  * @ioc: per adapter object
1583  * @mpi_reply: reply mf payload returned from firmware
1584  * @config_page: contents of the config page
1585  * @form: GET_NEXT_HANDLE or HANDLE
1586  * @handle: volume handle
1587  * @sz: size of buffer passed in config_page
1588  * Context: sleep.
1589  *
1590  * Return: 0 for success, non-zero for failure.
1591  */
1592 int
1593 mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1594         Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1595         u32 handle, u16 sz)
1596 {
1597         Mpi2ConfigRequest_t mpi_request;
1598         int r;
1599
1600         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1601         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1602         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1603         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1604         mpi_request.Header.PageNumber = 0;
1605         mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1606         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1607         r = _config_request(ioc, &mpi_request, mpi_reply,
1608             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1609         if (r)
1610                 goto out;
1611
1612         mpi_request.PageAddress = cpu_to_le32(form | handle);
1613         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1614         r = _config_request(ioc, &mpi_request, mpi_reply,
1615             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1616  out:
1617         return r;
1618 }
1619
1620 /**
1621  * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1622  * @ioc: per adapter object
1623  * @mpi_reply: reply mf payload returned from firmware
1624  * @config_page: contents of the config page
1625  * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1626  * @form_specific: specific to the form
1627  * Context: sleep.
1628  *
1629  * Return: 0 for success, non-zero for failure.
1630  */
1631 int
1632 mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1633         *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1634         u32 form_specific)
1635 {
1636         Mpi2ConfigRequest_t mpi_request;
1637         int r;
1638
1639         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1640         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1641         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1642         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1643         mpi_request.Header.PageNumber = 0;
1644         mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1645         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1646         r = _config_request(ioc, &mpi_request, mpi_reply,
1647             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1648         if (r)
1649                 goto out;
1650
1651         mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1652         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1653         r = _config_request(ioc, &mpi_request, mpi_reply,
1654             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1655             sizeof(*config_page));
1656  out:
1657         return r;
1658 }
1659
1660 /**
1661  * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
1662  * raid components
1663  * @ioc: per adapter object
1664  * @pd_handle: phys disk handle
1665  * @volume_handle: volume handle
1666  * Context: sleep.
1667  *
1668  * Return: 0 for success, non-zero for failure.
1669  */
1670 int
1671 mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
1672         u16 *volume_handle)
1673 {
1674         Mpi2RaidConfigurationPage0_t *config_page = NULL;
1675         Mpi2ConfigRequest_t mpi_request;
1676         Mpi2ConfigReply_t mpi_reply;
1677         int r, i, config_page_sz;
1678         u16 ioc_status;
1679         int config_num;
1680         u16 element_type;
1681         u16 phys_disk_dev_handle;
1682
1683         *volume_handle = 0;
1684         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1685         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1686         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1687         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1688         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1689         mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1690         mpi_request.Header.PageNumber = 0;
1691         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1692         r = _config_request(ioc, &mpi_request, &mpi_reply,
1693             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1694         if (r)
1695                 goto out;
1696
1697         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1698         config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1699         config_page = kmalloc(config_page_sz, GFP_KERNEL);
1700         if (!config_page) {
1701                 r = -1;
1702                 goto out;
1703         }
1704
1705         config_num = 0xff;
1706         while (1) {
1707                 mpi_request.PageAddress = cpu_to_le32(config_num +
1708                     MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1709                 r = _config_request(ioc, &mpi_request, &mpi_reply,
1710                     MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1711                     config_page_sz);
1712                 if (r)
1713                         goto out;
1714                 r = -1;
1715                 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1716                     MPI2_IOCSTATUS_MASK;
1717                 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1718                         goto out;
1719                 for (i = 0; i < config_page->NumElements; i++) {
1720                         element_type = le16_to_cpu(config_page->
1721                             ConfigElement[i].ElementFlags) &
1722                             MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1723                         if (element_type ==
1724                             MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1725                             element_type ==
1726                             MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1727                                 phys_disk_dev_handle =
1728                                     le16_to_cpu(config_page->ConfigElement[i].
1729                                     PhysDiskDevHandle);
1730                                 if (phys_disk_dev_handle == pd_handle) {
1731                                         *volume_handle =
1732                                             le16_to_cpu(config_page->
1733                                             ConfigElement[i].VolDevHandle);
1734                                         r = 0;
1735                                         goto out;
1736                                 }
1737                         } else if (element_type ==
1738                             MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1739                                 *volume_handle = 0;
1740                                 r = 0;
1741                                 goto out;
1742                         }
1743                 }
1744                 config_num = config_page->ConfigNum;
1745         }
1746  out:
1747         kfree(config_page);
1748         return r;
1749 }
1750
1751 /**
1752  * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
1753  * @ioc: per adapter object
1754  * @volume_handle: volume handle
1755  * @wwid: volume wwid
1756  * Context: sleep.
1757  *
1758  * Return: 0 for success, non-zero for failure.
1759  */
1760 int
1761 mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
1762         u64 *wwid)
1763 {
1764         Mpi2ConfigReply_t mpi_reply;
1765         Mpi2RaidVolPage1_t raid_vol_pg1;
1766
1767         *wwid = 0;
1768         if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1769             &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1770             volume_handle))) {
1771                 *wwid = le64_to_cpu(raid_vol_pg1.WWID);
1772                 return 0;
1773         } else
1774                 return -1;
1775 }