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