GNU Linux-libre 6.8.9-gnu
[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                 if (r == -ETIME)
364                         issue_host_reset = 1;
365                 goto free_mem;
366         }
367
368         smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
369         if (!smid) {
370                 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
371                 ioc->config_cmds.status = MPT3_CMD_NOT_USED;
372                 r = -EAGAIN;
373                 goto free_mem;
374         }
375
376         r = 0;
377         memset(ioc->config_cmds.reply, 0, sizeof(Mpi2ConfigReply_t));
378         ioc->config_cmds.status = MPT3_CMD_PENDING;
379         config_request = mpt3sas_base_get_msg_frame(ioc, smid);
380         ioc->config_cmds.smid = smid;
381         memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
382         if (ioc->logging_level & MPT_DEBUG_CONFIG)
383                 _config_display_some_debug(ioc, smid, "config_request", NULL);
384         init_completion(&ioc->config_cmds.done);
385         ioc->put_smid_default(ioc, smid);
386         wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ);
387         if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
388                 if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
389                         _config_display_some_debug(ioc,
390                             smid, "config_request", NULL);
391                 ioc_err(ioc, "%s: command timeout\n", __func__);
392                 mpt3sas_base_check_cmd_timeout(ioc, ioc->config_cmds.status,
393                                 mpi_request, sizeof(Mpi2ConfigRequest_t) / 4);
394                 retry_count++;
395                 if (ioc->config_cmds.smid == smid)
396                         mpt3sas_base_free_smid(ioc, smid);
397                 if (ioc->config_cmds.status & MPT3_CMD_RESET)
398                         goto retry_config;
399                 if (ioc->shost_recovery || ioc->pci_error_recovery) {
400                         issue_host_reset = 0;
401                         r = -EFAULT;
402                 } else
403                         issue_host_reset = 1;
404                 goto free_mem;
405         }
406
407         if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
408                 memcpy(mpi_reply, ioc->config_cmds.reply,
409                     sizeof(Mpi2ConfigReply_t));
410
411                 /* Reply Frame Sanity Checks to workaround FW issues */
412                 if ((mpi_request->Header.PageType & 0xF) !=
413                     (mpi_reply->Header.PageType & 0xF)) {
414                         if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
415                                 _config_display_some_debug(ioc,
416                                     smid, "config_request", NULL);
417                         _debug_dump_mf(mpi_request, ioc->request_sz/4);
418                         _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
419                         panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
420                               ioc->name, __func__,
421                               mpi_request->Header.PageType & 0xF,
422                               mpi_reply->Header.PageType & 0xF);
423                 }
424
425                 if (((mpi_request->Header.PageType & 0xF) ==
426                     MPI2_CONFIG_PAGETYPE_EXTENDED) &&
427                     mpi_request->ExtPageType != mpi_reply->ExtPageType) {
428                         if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
429                                 _config_display_some_debug(ioc,
430                                     smid, "config_request", NULL);
431                         _debug_dump_mf(mpi_request, ioc->request_sz/4);
432                         _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
433                         panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
434                               ioc->name, __func__,
435                               mpi_request->ExtPageType,
436                               mpi_reply->ExtPageType);
437                 }
438                 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
439                     & MPI2_IOCSTATUS_MASK;
440         }
441
442         if (retry_count)
443                 ioc_info(ioc, "%s: retry (%d) completed!!\n",
444                          __func__, retry_count);
445
446         if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
447             config_page && mpi_request->Action ==
448             MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
449                 u8 *p = (u8 *)mem.page;
450
451                 /* Config Page Sanity Checks to workaround FW issues */
452                 if (p) {
453                         if ((mpi_request->Header.PageType & 0xF) !=
454                             (p[3] & 0xF)) {
455                                 if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
456                                         _config_display_some_debug(ioc,
457                                             smid, "config_request", NULL);
458                                 _debug_dump_mf(mpi_request, ioc->request_sz/4);
459                                 _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
460                                 _debug_dump_config(p, min_t(u16, mem.sz,
461                                     config_page_sz)/4);
462                                 panic("%s: %s: Firmware BUG: config page mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
463                                       ioc->name, __func__,
464                                       mpi_request->Header.PageType & 0xF,
465                                       p[3] & 0xF);
466                         }
467
468                         if (((mpi_request->Header.PageType & 0xF) ==
469                             MPI2_CONFIG_PAGETYPE_EXTENDED) &&
470                             (mpi_request->ExtPageType != p[6])) {
471                                 if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
472                                         _config_display_some_debug(ioc,
473                                             smid, "config_request", NULL);
474                                 _debug_dump_mf(mpi_request, ioc->request_sz/4);
475                                 _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
476                                 _debug_dump_config(p, min_t(u16, mem.sz,
477                                     config_page_sz)/4);
478                                 panic("%s: %s: Firmware BUG: config page mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
479                                       ioc->name, __func__,
480                                       mpi_request->ExtPageType, p[6]);
481                         }
482                 }
483                 memcpy(config_page, mem.page, min_t(u16, mem.sz,
484                     config_page_sz));
485         }
486
487  free_mem:
488         if (config_page)
489                 _config_free_config_dma_memory(ioc, &mem);
490  out:
491         ioc->config_cmds.status = MPT3_CMD_NOT_USED;
492         mutex_unlock(&ioc->config_cmds.mutex);
493
494         if (issue_host_reset) {
495                 if (ioc->drv_internal_flags & MPT_DRV_INTERNAL_FIRST_PE_ISSUED) {
496                         mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
497                         r = -EFAULT;
498                 } else {
499                         if (mpt3sas_base_check_for_fault_and_issue_reset(ioc))
500                                 return -EFAULT;
501                         r = -EAGAIN;
502                 }
503         }
504         return r;
505 }
506
507 /**
508  * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
509  * @ioc: per adapter object
510  * @mpi_reply: reply mf payload returned from firmware
511  * @config_page: contents of the config page
512  * Context: sleep.
513  *
514  * Return: 0 for success, non-zero for failure.
515  */
516 int
517 mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
518         Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
519 {
520         Mpi2ConfigRequest_t mpi_request;
521         int r;
522
523         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
524         mpi_request.Function = MPI2_FUNCTION_CONFIG;
525         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
526         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
527         mpi_request.Header.PageNumber = 0;
528         mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
529         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
530         r = _config_request(ioc, &mpi_request, mpi_reply,
531             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
532         if (r)
533                 goto out;
534
535         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
536         r = _config_request(ioc, &mpi_request, mpi_reply,
537             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
538             sizeof(*config_page));
539  out:
540         return r;
541 }
542
543 /**
544  * mpt3sas_config_get_manufacturing_pg1 - obtain manufacturing page 1
545  * @ioc: per adapter object
546  * @mpi_reply: reply mf payload returned from firmware
547  * @config_page: contents of the config page
548  * Context: sleep.
549  *
550  * Return: 0 for success, non-zero for failure.
551  */
552 int
553 mpt3sas_config_get_manufacturing_pg1(struct MPT3SAS_ADAPTER *ioc,
554         Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage1_t *config_page)
555 {
556         Mpi2ConfigRequest_t mpi_request;
557         int r;
558
559         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
560         mpi_request.Function = MPI2_FUNCTION_CONFIG;
561         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
562         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
563         mpi_request.Header.PageNumber = 1;
564         mpi_request.Header.PageVersion = MPI2_MANUFACTURING1_PAGEVERSION;
565         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
566         r = _config_request(ioc, &mpi_request, mpi_reply,
567                 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
568         if (r)
569                 goto out;
570
571         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
572         r = _config_request(ioc, &mpi_request, mpi_reply,
573                 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
574                 sizeof(*config_page));
575  out:
576         return r;
577 }
578
579 /**
580  * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
581  * @ioc: per adapter object
582  * @mpi_reply: reply mf payload returned from firmware
583  * @config_page: contents of the config page
584  * @sz: size of buffer passed in config_page
585  * Context: sleep.
586  *
587  * Return: 0 for success, non-zero for failure.
588  */
589 int
590 mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
591         Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
592         u16 sz)
593 {
594         Mpi2ConfigRequest_t mpi_request;
595         int r;
596
597         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
598         mpi_request.Function = MPI2_FUNCTION_CONFIG;
599         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
600         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
601         mpi_request.Header.PageNumber = 7;
602         mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
603         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
604         r = _config_request(ioc, &mpi_request, mpi_reply,
605             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
606         if (r)
607                 goto out;
608
609         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
610         r = _config_request(ioc, &mpi_request, mpi_reply,
611             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
612             sz);
613  out:
614         return r;
615 }
616
617 /**
618  * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
619  * @ioc: per adapter object
620  * @mpi_reply: reply mf payload returned from firmware
621  * @config_page: contents of the config page
622  * Context: sleep.
623  *
624  * Return: 0 for success, non-zero for failure.
625  */
626 int
627 mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
628         Mpi2ConfigReply_t *mpi_reply,
629         struct Mpi2ManufacturingPage10_t *config_page)
630 {
631         Mpi2ConfigRequest_t mpi_request;
632         int r;
633
634         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
635         mpi_request.Function = MPI2_FUNCTION_CONFIG;
636         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
637         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
638         mpi_request.Header.PageNumber = 10;
639         mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
640         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
641         r = _config_request(ioc, &mpi_request, mpi_reply,
642             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
643         if (r)
644                 goto out;
645
646         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
647         r = _config_request(ioc, &mpi_request, mpi_reply,
648             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
649             sizeof(*config_page));
650  out:
651         return r;
652 }
653
654 /**
655  * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
656  * @ioc: per adapter object
657  * @mpi_reply: reply mf payload returned from firmware
658  * @config_page: contents of the config page
659  * Context: sleep.
660  *
661  * Return: 0 for success, non-zero for failure.
662  */
663 int
664 mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
665         Mpi2ConfigReply_t *mpi_reply,
666         struct Mpi2ManufacturingPage11_t *config_page)
667 {
668         Mpi2ConfigRequest_t mpi_request;
669         int r;
670
671         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
672         mpi_request.Function = MPI2_FUNCTION_CONFIG;
673         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
674         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
675         mpi_request.Header.PageNumber = 11;
676         mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
677         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
678         r = _config_request(ioc, &mpi_request, mpi_reply,
679             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
680         if (r)
681                 goto out;
682
683         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
684         r = _config_request(ioc, &mpi_request, mpi_reply,
685             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
686             sizeof(*config_page));
687  out:
688         return r;
689 }
690
691 /**
692  * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
693  * @ioc: per adapter object
694  * @mpi_reply: reply mf payload returned from firmware
695  * @config_page: contents of the config page
696  * Context: sleep.
697  *
698  * Return: 0 for success, non-zero for failure.
699  */
700 int
701 mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
702         Mpi2ConfigReply_t *mpi_reply,
703         struct Mpi2ManufacturingPage11_t *config_page)
704 {
705         Mpi2ConfigRequest_t mpi_request;
706         int r;
707
708         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
709         mpi_request.Function = MPI2_FUNCTION_CONFIG;
710         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
711         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
712         mpi_request.Header.PageNumber = 11;
713         mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
714         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
715         r = _config_request(ioc, &mpi_request, mpi_reply,
716             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
717         if (r)
718                 goto out;
719
720         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
721         r = _config_request(ioc, &mpi_request, mpi_reply,
722             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
723             sizeof(*config_page));
724  out:
725         return r;
726 }
727
728 /**
729  * mpt3sas_config_get_bios_pg2 - obtain bios page 2
730  * @ioc: per adapter object
731  * @mpi_reply: reply mf payload returned from firmware
732  * @config_page: contents of the config page
733  * Context: sleep.
734  *
735  * Return: 0 for success, non-zero for failure.
736  */
737 int
738 mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
739         Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
740 {
741         Mpi2ConfigRequest_t mpi_request;
742         int r;
743
744         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
745         mpi_request.Function = MPI2_FUNCTION_CONFIG;
746         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
747         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
748         mpi_request.Header.PageNumber = 2;
749         mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
750         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
751         r = _config_request(ioc, &mpi_request, mpi_reply,
752             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
753         if (r)
754                 goto out;
755
756         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
757         r = _config_request(ioc, &mpi_request, mpi_reply,
758             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
759             sizeof(*config_page));
760  out:
761         return r;
762 }
763
764 /**
765  * mpt3sas_config_get_bios_pg3 - obtain bios page 3
766  * @ioc: per adapter object
767  * @mpi_reply: reply mf payload returned from firmware
768  * @config_page: contents of the config page
769  * Context: sleep.
770  *
771  * Return: 0 for success, non-zero for failure.
772  */
773 int
774 mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
775         *mpi_reply, Mpi2BiosPage3_t *config_page)
776 {
777         Mpi2ConfigRequest_t mpi_request;
778         int r;
779
780         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
781         mpi_request.Function = MPI2_FUNCTION_CONFIG;
782         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
783         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
784         mpi_request.Header.PageNumber = 3;
785         mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
786         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
787         r = _config_request(ioc, &mpi_request, mpi_reply,
788             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
789         if (r)
790                 goto out;
791
792         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
793         r = _config_request(ioc, &mpi_request, mpi_reply,
794             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
795             sizeof(*config_page));
796
797  out:
798         return r;
799 }
800
801 /**
802  * mpt3sas_config_set_bios_pg4 - write out bios page 4
803  * @ioc: per adapter object
804  * @mpi_reply: reply mf payload returned from firmware
805  * @config_page: contents of the config page
806  * @sz_config_pg: sizeof the config page
807  * Context: sleep.
808  *
809  * Return: 0 for success, non-zero for failure.
810  */
811 int
812 mpt3sas_config_set_bios_pg4(struct MPT3SAS_ADAPTER *ioc,
813         Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage4_t *config_page,
814         int sz_config_pg)
815 {
816         Mpi2ConfigRequest_t mpi_request;
817         int r;
818
819         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
820
821         mpi_request.Function = MPI2_FUNCTION_CONFIG;
822         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
823         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
824         mpi_request.Header.PageNumber = 4;
825         mpi_request.Header.PageVersion = MPI2_BIOSPAGE4_PAGEVERSION;
826
827         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
828
829         r = _config_request(ioc, &mpi_request, mpi_reply,
830                 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
831         if (r)
832                 goto out;
833
834         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
835         r = _config_request(ioc, &mpi_request, mpi_reply,
836                 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
837                 sz_config_pg);
838  out:
839         return r;
840 }
841
842 /**
843  * mpt3sas_config_get_bios_pg4 - read bios page 4
844  * @ioc: per adapter object
845  * @mpi_reply: reply mf payload returned from firmware
846  * @config_page: contents of the config page
847  * @sz_config_pg: sizeof the config page
848  * Context: sleep.
849  *
850  * Return: 0 for success, non-zero for failure.
851  */
852 int
853 mpt3sas_config_get_bios_pg4(struct MPT3SAS_ADAPTER *ioc,
854         Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage4_t *config_page,
855         int sz_config_pg)
856 {
857         Mpi2ConfigRequest_t mpi_request;
858         int r;
859
860         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
861         mpi_request.Function = MPI2_FUNCTION_CONFIG;
862         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
863         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
864         mpi_request.Header.PageNumber = 4;
865         mpi_request.Header.PageVersion =  MPI2_BIOSPAGE4_PAGEVERSION;
866         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
867         r = _config_request(ioc, &mpi_request, mpi_reply,
868                 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
869         if (r)
870                 goto out;
871
872         /*
873          * The sizeof the page is variable. Allow for just the
874          * size to be returned
875          */
876         if (config_page && sz_config_pg) {
877                 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
878
879                 r = _config_request(ioc, &mpi_request, mpi_reply,
880                         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
881                         sz_config_pg);
882         }
883
884 out:
885         return r;
886 }
887
888 /**
889  * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
890  * @ioc: per adapter object
891  * @mpi_reply: reply mf payload returned from firmware
892  * @config_page: contents of the config page
893  * Context: sleep.
894  *
895  * Return: 0 for success, non-zero for failure.
896  */
897 int
898 mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
899         Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
900 {
901         Mpi2ConfigRequest_t mpi_request;
902         int r;
903
904         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
905         mpi_request.Function = MPI2_FUNCTION_CONFIG;
906         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
907         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
908         mpi_request.Header.PageNumber = 0;
909         mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
910         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
911         r = _config_request(ioc, &mpi_request, mpi_reply,
912             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
913         if (r)
914                 goto out;
915
916         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
917         r = _config_request(ioc, &mpi_request, mpi_reply,
918             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
919             sizeof(*config_page));
920  out:
921         return r;
922 }
923
924 /**
925  * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
926  * @ioc: per adapter object
927  * @mpi_reply: reply mf payload returned from firmware
928  * @config_page: contents of the config page
929  * Context: sleep.
930  *
931  * Return: 0 for success, non-zero for failure.
932  */
933 int
934 mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
935         Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
936 {
937         Mpi2ConfigRequest_t mpi_request;
938         int r;
939
940         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
941         mpi_request.Function = MPI2_FUNCTION_CONFIG;
942         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
943         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
944         mpi_request.Header.PageNumber = 1;
945         mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
946         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
947         r = _config_request(ioc, &mpi_request, mpi_reply,
948             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
949         if (r)
950                 goto out;
951
952         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
953         r = _config_request(ioc, &mpi_request, mpi_reply,
954             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
955             sizeof(*config_page));
956  out:
957         return r;
958 }
959
960 /**
961  * mpt3sas_config_set_iounit_pg1 - set iounit page 1
962  * @ioc: per adapter object
963  * @mpi_reply: reply mf payload returned from firmware
964  * @config_page: contents of the config page
965  * Context: sleep.
966  *
967  * Return: 0 for success, non-zero for failure.
968  */
969 int
970 mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
971         Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
972 {
973         Mpi2ConfigRequest_t mpi_request;
974         int r;
975
976         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
977         mpi_request.Function = MPI2_FUNCTION_CONFIG;
978         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
979         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
980         mpi_request.Header.PageNumber = 1;
981         mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
982         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
983         r = _config_request(ioc, &mpi_request, mpi_reply,
984             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
985         if (r)
986                 goto out;
987
988         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
989         r = _config_request(ioc, &mpi_request, mpi_reply,
990             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
991             sizeof(*config_page));
992  out:
993         return r;
994 }
995
996 /**
997  * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
998  * @ioc: per adapter object
999  * @mpi_reply: reply mf payload returned from firmware
1000  * @config_page: contents of the config page
1001  * @sz: size of buffer passed in config_page
1002  * Context: sleep.
1003  *
1004  * Return: 0 for success, non-zero for failure.
1005  */
1006 int
1007 mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
1008         Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
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_IO_UNIT;
1017         mpi_request.Header.PageNumber = 3;
1018         mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
1019         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1020         r = _config_request(ioc, &mpi_request, mpi_reply,
1021             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1022         if (r)
1023                 goto out;
1024
1025         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1026         r = _config_request(ioc, &mpi_request, mpi_reply,
1027             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1028  out:
1029         return r;
1030 }
1031
1032 /**
1033  * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
1034  * @ioc: per adapter object
1035  * @mpi_reply: reply mf payload returned from firmware
1036  * @config_page: contents of the config page
1037  * Context: sleep.
1038  *
1039  * Return: 0 for success, non-zero for failure.
1040  */
1041 int
1042 mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
1043         Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
1044 {
1045         Mpi2ConfigRequest_t mpi_request;
1046         int r;
1047
1048         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1049         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1050         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1051         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
1052         mpi_request.Header.PageNumber = 8;
1053         mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
1054         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1055         r = _config_request(ioc, &mpi_request, mpi_reply,
1056             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1057         if (r)
1058                 goto out;
1059
1060         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1061         r = _config_request(ioc, &mpi_request, mpi_reply,
1062             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1063             sizeof(*config_page));
1064  out:
1065         return r;
1066 }
1067
1068 /**
1069  * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
1070  * @ioc: per adapter object
1071  * @mpi_reply: reply mf payload returned from firmware
1072  * @config_page: contents of the config page
1073  * Context: sleep.
1074  *
1075  * Return: 0 for success, non-zero for failure.
1076  */
1077 int
1078 mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
1079         Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
1080 {
1081         Mpi2ConfigRequest_t mpi_request;
1082         int r;
1083
1084         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1085         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1086         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1087         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
1088         mpi_request.Header.PageNumber = 8;
1089         mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
1090         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1091         r = _config_request(ioc, &mpi_request, mpi_reply,
1092             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1093         if (r)
1094                 goto out;
1095
1096         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1097         r = _config_request(ioc, &mpi_request, mpi_reply,
1098             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1099             sizeof(*config_page));
1100  out:
1101         return r;
1102 }
1103 /**
1104  * mpt3sas_config_get_ioc_pg1 - obtain ioc page 1
1105  * @ioc: per adapter object
1106  * @mpi_reply: reply mf payload returned from firmware
1107  * @config_page: contents of the config page
1108  * Context: sleep.
1109  *
1110  * Return: 0 for success, non-zero for failure.
1111  */
1112 int
1113 mpt3sas_config_get_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
1114         Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
1115 {
1116         Mpi2ConfigRequest_t mpi_request;
1117         int r;
1118
1119         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1120         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1121         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1122         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
1123         mpi_request.Header.PageNumber = 1;
1124         mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
1125         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1126         r = _config_request(ioc, &mpi_request, mpi_reply,
1127             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1128         if (r)
1129                 goto out;
1130
1131         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1132         r = _config_request(ioc, &mpi_request, mpi_reply,
1133             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1134             sizeof(*config_page));
1135  out:
1136         return r;
1137 }
1138
1139 /**
1140  * mpt3sas_config_set_ioc_pg1 - modify ioc page 1
1141  * @ioc: per adapter object
1142  * @mpi_reply: reply mf payload returned from firmware
1143  * @config_page: contents of the config page
1144  * Context: sleep.
1145  *
1146  * Return: 0 for success, non-zero for failure.
1147  */
1148 int
1149 mpt3sas_config_set_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
1150         Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
1151 {
1152         Mpi2ConfigRequest_t mpi_request;
1153         int r;
1154
1155         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1156         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1157         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1158         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
1159         mpi_request.Header.PageNumber = 1;
1160         mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
1161         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1162         r = _config_request(ioc, &mpi_request, mpi_reply,
1163             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1164         if (r)
1165                 goto out;
1166
1167         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1168         r = _config_request(ioc, &mpi_request, mpi_reply,
1169             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1170             sizeof(*config_page));
1171  out:
1172         return r;
1173 }
1174
1175 /**
1176  * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
1177  * @ioc: per adapter object
1178  * @mpi_reply: reply mf payload returned from firmware
1179  * @config_page: contents of the config page
1180  * @form: GET_NEXT_HANDLE or HANDLE
1181  * @handle: device handle
1182  * Context: sleep.
1183  *
1184  * Return: 0 for success, non-zero for failure.
1185  */
1186 int
1187 mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1188         Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
1189         u32 form, u32 handle)
1190 {
1191         Mpi2ConfigRequest_t mpi_request;
1192         int r;
1193
1194         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1195         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1196         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1197         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1198         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1199         mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
1200         mpi_request.Header.PageNumber = 0;
1201         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1202         r = _config_request(ioc, &mpi_request, mpi_reply,
1203             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1204         if (r)
1205                 goto out;
1206
1207         mpi_request.PageAddress = cpu_to_le32(form | handle);
1208         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1209         r = _config_request(ioc, &mpi_request, mpi_reply,
1210             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1211             sizeof(*config_page));
1212  out:
1213         return r;
1214 }
1215
1216 /**
1217  * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
1218  * @ioc: per adapter object
1219  * @mpi_reply: reply mf payload returned from firmware
1220  * @config_page: contents of the config page
1221  * @form: GET_NEXT_HANDLE or HANDLE
1222  * @handle: device handle
1223  * Context: sleep.
1224  *
1225  * Return: 0 for success, non-zero for failure.
1226  */
1227 int
1228 mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1229         Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1230         u32 form, u32 handle)
1231 {
1232         Mpi2ConfigRequest_t mpi_request;
1233         int r;
1234
1235         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1236         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1237         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1238         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1239         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1240         mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1241         mpi_request.Header.PageNumber = 1;
1242         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1243         r = _config_request(ioc, &mpi_request, mpi_reply,
1244             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1245         if (r)
1246                 goto out;
1247
1248         mpi_request.PageAddress = cpu_to_le32(form | handle);
1249         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1250         r = _config_request(ioc, &mpi_request, mpi_reply,
1251             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1252             sizeof(*config_page));
1253  out:
1254         return r;
1255 }
1256
1257 /**
1258  * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
1259  * @ioc: per adapter object
1260  * @mpi_reply: reply mf payload returned from firmware
1261  * @config_page: contents of the config page
1262  * @form: GET_NEXT_HANDLE or HANDLE
1263  * @handle: device handle
1264  * Context: sleep.
1265  *
1266  * Return: 0 for success, non-zero for failure.
1267  */
1268 int
1269 mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1270         Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
1271         u32 form, u32 handle)
1272 {
1273         Mpi2ConfigRequest_t mpi_request;
1274         int r;
1275
1276         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1277         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1278         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1279         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1280         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1281         mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
1282         mpi_request.Header.PageNumber = 0;
1283         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1284         r = _config_request(ioc, &mpi_request, mpi_reply,
1285                         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1286         if (r)
1287                 goto out;
1288
1289         mpi_request.PageAddress = cpu_to_le32(form | handle);
1290         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1291         r = _config_request(ioc, &mpi_request, mpi_reply,
1292                         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1293                         sizeof(*config_page));
1294 out:
1295         return r;
1296 }
1297
1298 /**
1299  * mpt3sas_config_get_pcie_iounit_pg1 - obtain pcie iounit page 1
1300  * @ioc: per adapter object
1301  * @mpi_reply: reply mf payload returned from firmware
1302  * @config_page: contents of the config page
1303  * @sz: size of buffer passed in config_page
1304  * Context: sleep.
1305  *
1306  * Returns 0 for success, non-zero for failure.
1307  */
1308 int
1309 mpt3sas_config_get_pcie_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1310         Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeIOUnitPage1_t *config_page,
1311         u16 sz)
1312 {
1313         Mpi2ConfigRequest_t mpi_request;
1314         int r;
1315
1316         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1317         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1318         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1319         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1320         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT;
1321         mpi_request.Header.PageVersion = MPI26_PCIEIOUNITPAGE1_PAGEVERSION;
1322         mpi_request.Header.PageNumber = 1;
1323         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1324         r = _config_request(ioc, &mpi_request, mpi_reply,
1325             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1326         if (r)
1327                 goto out;
1328         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1329         r = _config_request(ioc, &mpi_request, mpi_reply,
1330             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1331 out:
1332         return r;
1333 }
1334
1335 /**
1336  * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
1337  * @ioc: per adapter object
1338  * @mpi_reply: reply mf payload returned from firmware
1339  * @config_page: contents of the config page
1340  * @form: GET_NEXT_HANDLE or HANDLE
1341  * @handle: device handle
1342  * Context: sleep.
1343  *
1344  * Return: 0 for success, non-zero for failure.
1345  */
1346 int
1347 mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
1348         Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
1349         u32 form, u32 handle)
1350 {
1351         Mpi2ConfigRequest_t mpi_request;
1352         int r;
1353
1354         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1355         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1356         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1357         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1358         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1359         mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
1360         mpi_request.Header.PageNumber = 2;
1361         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1362         r = _config_request(ioc, &mpi_request, mpi_reply,
1363                         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1364         if (r)
1365                 goto out;
1366
1367         mpi_request.PageAddress = cpu_to_le32(form | handle);
1368         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1369         r = _config_request(ioc, &mpi_request, mpi_reply,
1370                         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1371                         sizeof(*config_page));
1372 out:
1373         return r;
1374 }
1375
1376 /**
1377  * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1378  * @ioc: per adapter object
1379  * @num_phys: pointer returned with the number of phys
1380  * Context: sleep.
1381  *
1382  * Return: 0 for success, non-zero for failure.
1383  */
1384 int
1385 mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1386 {
1387         Mpi2ConfigRequest_t mpi_request;
1388         int r;
1389         u16 ioc_status;
1390         Mpi2ConfigReply_t mpi_reply;
1391         Mpi2SasIOUnitPage0_t config_page;
1392
1393         *num_phys = 0;
1394         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1395         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1396         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1397         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1398         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1399         mpi_request.Header.PageNumber = 0;
1400         mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1401         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1402         r = _config_request(ioc, &mpi_request, &mpi_reply,
1403             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1404         if (r)
1405                 goto out;
1406
1407         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1408         r = _config_request(ioc, &mpi_request, &mpi_reply,
1409             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1410             sizeof(Mpi2SasIOUnitPage0_t));
1411         if (!r) {
1412                 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1413                     MPI2_IOCSTATUS_MASK;
1414                 if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1415                         *num_phys = config_page.NumPhys;
1416         }
1417  out:
1418         return r;
1419 }
1420
1421 /**
1422  * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1423  * @ioc: per adapter object
1424  * @mpi_reply: reply mf payload returned from firmware
1425  * @config_page: contents of the config page
1426  * @sz: size of buffer passed in config_page
1427  * Context: sleep.
1428  *
1429  * Calling function should call config_get_number_hba_phys prior to
1430  * this function, so enough memory is allocated for config_page.
1431  *
1432  * Return: 0 for success, non-zero for failure.
1433  */
1434 int
1435 mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1436         Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1437         u16 sz)
1438 {
1439         Mpi2ConfigRequest_t mpi_request;
1440         int r;
1441
1442         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1443         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1444         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1445         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1446         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1447         mpi_request.Header.PageNumber = 0;
1448         mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1449         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1450         r = _config_request(ioc, &mpi_request, mpi_reply,
1451             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1452         if (r)
1453                 goto out;
1454
1455         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1456         r = _config_request(ioc, &mpi_request, mpi_reply,
1457             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1458  out:
1459         return r;
1460 }
1461
1462 /**
1463  * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1464  * @ioc: per adapter object
1465  * @mpi_reply: reply mf payload returned from firmware
1466  * @config_page: contents of the config page
1467  * @sz: size of buffer passed in config_page
1468  * Context: sleep.
1469  *
1470  * Calling function should call config_get_number_hba_phys prior to
1471  * this function, so enough memory is allocated for config_page.
1472  *
1473  * Return: 0 for success, non-zero for failure.
1474  */
1475 int
1476 mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1477         Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1478         u16 sz)
1479 {
1480         Mpi2ConfigRequest_t mpi_request;
1481         int r;
1482
1483         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1484         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1485         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1486         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1487         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1488         mpi_request.Header.PageNumber = 1;
1489         mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1490         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1491         r = _config_request(ioc, &mpi_request, mpi_reply,
1492             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1493         if (r)
1494                 goto out;
1495
1496         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1497         r = _config_request(ioc, &mpi_request, mpi_reply,
1498             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1499  out:
1500         return r;
1501 }
1502
1503 /**
1504  * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1505  * @ioc: per adapter object
1506  * @mpi_reply: reply mf payload returned from firmware
1507  * @config_page: contents of the config page
1508  * @sz: size of buffer passed in config_page
1509  * Context: sleep.
1510  *
1511  * Calling function should call config_get_number_hba_phys prior to
1512  * this function, so enough memory is allocated for config_page.
1513  *
1514  * Return: 0 for success, non-zero for failure.
1515  */
1516 int
1517 mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1518         Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1519         u16 sz)
1520 {
1521         Mpi2ConfigRequest_t mpi_request;
1522         int r;
1523
1524         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1525         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1526         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1527         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1528         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1529         mpi_request.Header.PageNumber = 1;
1530         mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1531         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1532         r = _config_request(ioc, &mpi_request, mpi_reply,
1533             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1534         if (r)
1535                 goto out;
1536
1537         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1538         _config_request(ioc, &mpi_request, mpi_reply,
1539             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1540         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1541         r = _config_request(ioc, &mpi_request, mpi_reply,
1542             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1543  out:
1544         return r;
1545 }
1546
1547 /**
1548  * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1549  * @ioc: per adapter object
1550  * @mpi_reply: reply mf payload returned from firmware
1551  * @config_page: contents of the config page
1552  * @form: GET_NEXT_HANDLE or HANDLE
1553  * @handle: expander handle
1554  * Context: sleep.
1555  *
1556  * Return: 0 for success, non-zero for failure.
1557  */
1558 int
1559 mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1560         *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1561 {
1562         Mpi2ConfigRequest_t mpi_request;
1563         int r;
1564
1565         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1566         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1567         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1568         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1569         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1570         mpi_request.Header.PageNumber = 0;
1571         mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1572         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1573         r = _config_request(ioc, &mpi_request, mpi_reply,
1574             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1575         if (r)
1576                 goto out;
1577
1578         mpi_request.PageAddress = cpu_to_le32(form | handle);
1579         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1580         r = _config_request(ioc, &mpi_request, mpi_reply,
1581             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1582             sizeof(*config_page));
1583  out:
1584         return r;
1585 }
1586
1587 /**
1588  * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1589  * @ioc: per adapter object
1590  * @mpi_reply: reply mf payload returned from firmware
1591  * @config_page: contents of the config page
1592  * @phy_number: phy number
1593  * @handle: expander handle
1594  * Context: sleep.
1595  *
1596  * Return: 0 for success, non-zero for failure.
1597  */
1598 int
1599 mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1600         *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1601         u16 handle)
1602 {
1603         Mpi2ConfigRequest_t mpi_request;
1604         int r;
1605
1606         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1607         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1608         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1609         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1610         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1611         mpi_request.Header.PageNumber = 1;
1612         mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1613         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1614         r = _config_request(ioc, &mpi_request, mpi_reply,
1615             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1616         if (r)
1617                 goto out;
1618
1619         mpi_request.PageAddress =
1620             cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1621             (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1622         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1623         r = _config_request(ioc, &mpi_request, mpi_reply,
1624             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1625             sizeof(*config_page));
1626  out:
1627         return r;
1628 }
1629
1630 /**
1631  * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1632  * @ioc: per adapter object
1633  * @mpi_reply: reply mf payload returned from firmware
1634  * @config_page: contents of the config page
1635  * @form: GET_NEXT_HANDLE or HANDLE
1636  * @handle: expander handle
1637  * Context: sleep.
1638  *
1639  * Return: 0 for success, non-zero for failure.
1640  */
1641 int
1642 mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1643         *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1644 {
1645         Mpi2ConfigRequest_t mpi_request;
1646         int r;
1647
1648         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1649         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1650         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1651         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1652         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1653         mpi_request.Header.PageNumber = 0;
1654         mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1655         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1656         r = _config_request(ioc, &mpi_request, mpi_reply,
1657             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1658         if (r)
1659                 goto out;
1660
1661         mpi_request.PageAddress = cpu_to_le32(form | handle);
1662         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1663         r = _config_request(ioc, &mpi_request, mpi_reply,
1664             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1665             sizeof(*config_page));
1666  out:
1667         return r;
1668 }
1669
1670 /**
1671  * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1672  * @ioc: per adapter object
1673  * @mpi_reply: reply mf payload returned from firmware
1674  * @config_page: contents of the config page
1675  * @phy_number: phy number
1676  * Context: sleep.
1677  *
1678  * Return: 0 for success, non-zero for failure.
1679  */
1680 int
1681 mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1682         *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1683 {
1684         Mpi2ConfigRequest_t mpi_request;
1685         int r;
1686
1687         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1688         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1689         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1690         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1691         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1692         mpi_request.Header.PageNumber = 0;
1693         mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1694         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1695         r = _config_request(ioc, &mpi_request, mpi_reply,
1696             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1697         if (r)
1698                 goto out;
1699
1700         mpi_request.PageAddress =
1701             cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1702         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1703         r = _config_request(ioc, &mpi_request, mpi_reply,
1704             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1705             sizeof(*config_page));
1706  out:
1707         return r;
1708 }
1709
1710 /**
1711  * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1712  * @ioc: per adapter object
1713  * @mpi_reply: reply mf payload returned from firmware
1714  * @config_page: contents of the config page
1715  * @phy_number: phy number
1716  * Context: sleep.
1717  *
1718  * Return: 0 for success, non-zero for failure.
1719  */
1720 int
1721 mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1722         *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1723 {
1724         Mpi2ConfigRequest_t mpi_request;
1725         int r;
1726
1727         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1728         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1729         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1730         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1731         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1732         mpi_request.Header.PageNumber = 1;
1733         mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1734         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1735         r = _config_request(ioc, &mpi_request, mpi_reply,
1736             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1737         if (r)
1738                 goto out;
1739
1740         mpi_request.PageAddress =
1741             cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1742         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1743         r = _config_request(ioc, &mpi_request, mpi_reply,
1744             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1745             sizeof(*config_page));
1746  out:
1747         return r;
1748 }
1749
1750 /**
1751  * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1752  * @ioc: per adapter object
1753  * @mpi_reply: reply mf payload returned from firmware
1754  * @config_page: contents of the config page
1755  * @form: GET_NEXT_HANDLE or HANDLE
1756  * @handle: volume handle
1757  * Context: sleep.
1758  *
1759  * Return: 0 for success, non-zero for failure.
1760  */
1761 int
1762 mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1763         Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1764         u32 handle)
1765 {
1766         Mpi2ConfigRequest_t mpi_request;
1767         int r;
1768
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_RAID_VOLUME;
1773         mpi_request.Header.PageNumber = 1;
1774         mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1775         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1776         r = _config_request(ioc, &mpi_request, mpi_reply,
1777             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1778         if (r)
1779                 goto out;
1780
1781         mpi_request.PageAddress = cpu_to_le32(form | handle);
1782         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1783         r = _config_request(ioc, &mpi_request, mpi_reply,
1784             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1785             sizeof(*config_page));
1786  out:
1787         return r;
1788 }
1789
1790 /**
1791  * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1792  * @ioc: per adapter object
1793  * @handle: volume handle
1794  * @num_pds: returns pds count
1795  * Context: sleep.
1796  *
1797  * Return: 0 for success, non-zero for failure.
1798  */
1799 int
1800 mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1801         u8 *num_pds)
1802 {
1803         Mpi2ConfigRequest_t mpi_request;
1804         Mpi2RaidVolPage0_t config_page;
1805         Mpi2ConfigReply_t mpi_reply;
1806         int r;
1807         u16 ioc_status;
1808
1809         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1810         *num_pds = 0;
1811         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1812         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1813         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1814         mpi_request.Header.PageNumber = 0;
1815         mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1816         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1817         r = _config_request(ioc, &mpi_request, &mpi_reply,
1818             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1819         if (r)
1820                 goto out;
1821
1822         mpi_request.PageAddress =
1823             cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1824         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1825         r = _config_request(ioc, &mpi_request, &mpi_reply,
1826             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1827             sizeof(Mpi2RaidVolPage0_t));
1828         if (!r) {
1829                 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1830                     MPI2_IOCSTATUS_MASK;
1831                 if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1832                         *num_pds = config_page.NumPhysDisks;
1833         }
1834
1835  out:
1836         return r;
1837 }
1838
1839 /**
1840  * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1841  * @ioc: per adapter object
1842  * @mpi_reply: reply mf payload returned from firmware
1843  * @config_page: contents of the config page
1844  * @form: GET_NEXT_HANDLE or HANDLE
1845  * @handle: volume handle
1846  * @sz: size of buffer passed in config_page
1847  * Context: sleep.
1848  *
1849  * Return: 0 for success, non-zero for failure.
1850  */
1851 int
1852 mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1853         Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1854         u32 handle, u16 sz)
1855 {
1856         Mpi2ConfigRequest_t mpi_request;
1857         int r;
1858
1859         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1860         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1861         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1862         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1863         mpi_request.Header.PageNumber = 0;
1864         mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1865         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1866         r = _config_request(ioc, &mpi_request, mpi_reply,
1867             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1868         if (r)
1869                 goto out;
1870
1871         mpi_request.PageAddress = cpu_to_le32(form | handle);
1872         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1873         r = _config_request(ioc, &mpi_request, mpi_reply,
1874             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1875  out:
1876         return r;
1877 }
1878
1879 /**
1880  * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1881  * @ioc: per adapter object
1882  * @mpi_reply: reply mf payload returned from firmware
1883  * @config_page: contents of the config page
1884  * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1885  * @form_specific: specific to the form
1886  * Context: sleep.
1887  *
1888  * Return: 0 for success, non-zero for failure.
1889  */
1890 int
1891 mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1892         *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1893         u32 form_specific)
1894 {
1895         Mpi2ConfigRequest_t mpi_request;
1896         int r;
1897
1898         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1899         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1900         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1901         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1902         mpi_request.Header.PageNumber = 0;
1903         mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1904         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1905         r = _config_request(ioc, &mpi_request, mpi_reply,
1906             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1907         if (r)
1908                 goto out;
1909
1910         mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1911         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1912         r = _config_request(ioc, &mpi_request, mpi_reply,
1913             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1914             sizeof(*config_page));
1915  out:
1916         return r;
1917 }
1918
1919 /**
1920  * mpt3sas_config_get_driver_trigger_pg0 - obtain driver trigger page 0
1921  * @ioc: per adapter object
1922  * @mpi_reply: reply mf payload returned from firmware
1923  * @config_page: contents of the config page
1924  * Context: sleep.
1925  *
1926  * Returns 0 for success, non-zero for failure.
1927  */
1928 int
1929 mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1930         Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1931 {
1932         Mpi2ConfigRequest_t mpi_request;
1933         int r;
1934
1935         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1936         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1937         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1938         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1939         mpi_request.ExtPageType =
1940             MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1941         mpi_request.Header.PageNumber = 0;
1942         mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1943         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1944         r = _config_request(ioc, &mpi_request, mpi_reply,
1945             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1946         if (r)
1947                 goto out;
1948
1949         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1950         r = _config_request(ioc, &mpi_request, mpi_reply,
1951             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1952             sizeof(*config_page));
1953  out:
1954         return r;
1955 }
1956
1957 /**
1958  * _config_set_driver_trigger_pg0 - write driver trigger page 0
1959  * @ioc: per adapter object
1960  * @mpi_reply: reply mf payload returned from firmware
1961  * @config_page: contents of the config page
1962  * Context: sleep.
1963  *
1964  * Returns 0 for success, non-zero for failure.
1965  */
1966 static int
1967 _config_set_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1968         Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1969 {
1970         Mpi2ConfigRequest_t mpi_request;
1971         int r;
1972
1973         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1974         mpi_request.Function = MPI2_FUNCTION_CONFIG;
1975         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1976         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1977         mpi_request.ExtPageType =
1978             MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1979         mpi_request.Header.PageNumber = 0;
1980         mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1981         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1982         r = _config_request(ioc, &mpi_request, mpi_reply,
1983             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1984         if (r)
1985                 goto out;
1986
1987         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1988         _config_request(ioc, &mpi_request, mpi_reply,
1989             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1990             sizeof(*config_page));
1991         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1992         r = _config_request(ioc, &mpi_request, mpi_reply,
1993             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1994             sizeof(*config_page));
1995  out:
1996         return r;
1997 }
1998
1999 /**
2000  * mpt3sas_config_update_driver_trigger_pg0 - update driver trigger page 0
2001  * @ioc: per adapter object
2002  * @trigger_flag: trigger type bit map
2003  * @set: set ot clear trigger values
2004  * Context: sleep.
2005  *
2006  * Returns 0 for success, non-zero for failure.
2007  */
2008 static int
2009 mpt3sas_config_update_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
2010         u16 trigger_flag, bool set)
2011 {
2012         Mpi26DriverTriggerPage0_t tg_pg0;
2013         Mpi2ConfigReply_t mpi_reply;
2014         int rc;
2015         u16 flags, ioc_status;
2016
2017         rc = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
2018         if (rc)
2019                 return rc;
2020         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2021             MPI2_IOCSTATUS_MASK;
2022         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2023                 dcprintk(ioc,
2024                     ioc_err(ioc,
2025                     "%s: Failed to get trigger pg0, ioc_status(0x%04x)\n",
2026                     __func__, ioc_status));
2027                 return -EFAULT;
2028         }
2029
2030         if (set)
2031                 flags = le16_to_cpu(tg_pg0.TriggerFlags) | trigger_flag;
2032         else
2033                 flags = le16_to_cpu(tg_pg0.TriggerFlags) & ~trigger_flag;
2034
2035         tg_pg0.TriggerFlags = cpu_to_le16(flags);
2036
2037         rc = _config_set_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
2038         if (rc)
2039                 return rc;
2040         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2041             MPI2_IOCSTATUS_MASK;
2042         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2043                 dcprintk(ioc,
2044                     ioc_err(ioc,
2045                     "%s: Failed to update trigger pg0, ioc_status(0x%04x)\n",
2046                     __func__, ioc_status));
2047                 return -EFAULT;
2048         }
2049
2050         return 0;
2051 }
2052
2053 /**
2054  * mpt3sas_config_get_driver_trigger_pg1 - obtain driver trigger page 1
2055  * @ioc: per adapter object
2056  * @mpi_reply: reply mf payload returned from firmware
2057  * @config_page: contents of the config page
2058  * Context: sleep.
2059  *
2060  * Returns 0 for success, non-zero for failure.
2061  */
2062 int
2063 mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
2064         Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
2065 {
2066         Mpi2ConfigRequest_t mpi_request;
2067         int r;
2068
2069         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2070         mpi_request.Function = MPI2_FUNCTION_CONFIG;
2071         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2072         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2073         mpi_request.ExtPageType =
2074             MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2075         mpi_request.Header.PageNumber = 1;
2076         mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
2077         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2078         r = _config_request(ioc, &mpi_request, mpi_reply,
2079             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2080         if (r)
2081                 goto out;
2082
2083         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2084         r = _config_request(ioc, &mpi_request, mpi_reply,
2085             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2086             sizeof(*config_page));
2087  out:
2088         return r;
2089 }
2090
2091 /**
2092  * _config_set_driver_trigger_pg1 - write driver trigger page 1
2093  * @ioc: per adapter object
2094  * @mpi_reply: reply mf payload returned from firmware
2095  * @config_page: contents of the config page
2096  * Context: sleep.
2097  *
2098  * Returns 0 for success, non-zero for failure.
2099  */
2100 static int
2101 _config_set_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
2102         Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
2103 {
2104         Mpi2ConfigRequest_t mpi_request;
2105         int r;
2106
2107         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2108         mpi_request.Function = MPI2_FUNCTION_CONFIG;
2109         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2110         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2111         mpi_request.ExtPageType =
2112             MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2113         mpi_request.Header.PageNumber = 1;
2114         mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
2115         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2116         r = _config_request(ioc, &mpi_request, mpi_reply,
2117             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2118         if (r)
2119                 goto out;
2120
2121         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2122         _config_request(ioc, &mpi_request, mpi_reply,
2123             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2124             sizeof(*config_page));
2125         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2126         r = _config_request(ioc, &mpi_request, mpi_reply,
2127             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2128             sizeof(*config_page));
2129  out:
2130         return r;
2131 }
2132
2133 /**
2134  * mpt3sas_config_update_driver_trigger_pg1 - update driver trigger page 1
2135  * @ioc: per adapter object
2136  * @master_tg: Master trigger bit map
2137  * @set: set ot clear trigger values
2138  * Context: sleep.
2139  *
2140  * Returns 0 for success, non-zero for failure.
2141  */
2142 int
2143 mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
2144         struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set)
2145 {
2146         Mpi26DriverTriggerPage1_t tg_pg1;
2147         Mpi2ConfigReply_t mpi_reply;
2148         int rc;
2149         u16 ioc_status;
2150
2151         rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2152             MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, set);
2153         if (rc)
2154                 return rc;
2155
2156         rc = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
2157         if (rc)
2158                 goto out;
2159
2160         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2161             MPI2_IOCSTATUS_MASK;
2162         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2163                 dcprintk(ioc,
2164                     ioc_err(ioc,
2165                     "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
2166                     __func__, ioc_status));
2167                 rc = -EFAULT;
2168                 goto out;
2169         }
2170
2171         if (set) {
2172                 tg_pg1.NumMasterTrigger = cpu_to_le16(1);
2173                 tg_pg1.MasterTriggers[0].MasterTriggerFlags = cpu_to_le32(
2174                     master_tg->MasterData);
2175         } else {
2176                 tg_pg1.NumMasterTrigger = 0;
2177                 tg_pg1.MasterTriggers[0].MasterTriggerFlags = 0;
2178         }
2179
2180         rc = _config_set_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
2181         if (rc)
2182                 goto out;
2183
2184         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2185             MPI2_IOCSTATUS_MASK;
2186         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2187                 dcprintk(ioc,
2188                     ioc_err(ioc,
2189                     "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
2190                     __func__, ioc_status));
2191                 rc = -EFAULT;
2192                 goto out;
2193         }
2194
2195         return 0;
2196
2197 out:
2198         mpt3sas_config_update_driver_trigger_pg0(ioc,
2199             MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, !set);
2200
2201         return rc;
2202 }
2203
2204 /**
2205  * mpt3sas_config_get_driver_trigger_pg2 - obtain driver trigger page 2
2206  * @ioc: per adapter object
2207  * @mpi_reply: reply mf payload returned from firmware
2208  * @config_page: contents of the config page
2209  * Context: sleep.
2210  *
2211  * Returns 0 for success, non-zero for failure.
2212  */
2213 int
2214 mpt3sas_config_get_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2215         Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2216 {
2217         Mpi2ConfigRequest_t mpi_request;
2218         int r;
2219
2220         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2221         mpi_request.Function = MPI2_FUNCTION_CONFIG;
2222         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2223         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2224         mpi_request.ExtPageType =
2225             MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2226         mpi_request.Header.PageNumber = 2;
2227         mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2228         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2229         r = _config_request(ioc, &mpi_request, mpi_reply,
2230             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2231         if (r)
2232                 goto out;
2233
2234         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2235         r = _config_request(ioc, &mpi_request, mpi_reply,
2236             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2237             sizeof(*config_page));
2238  out:
2239         return r;
2240 }
2241
2242 /**
2243  * _config_set_driver_trigger_pg2 - write driver trigger page 2
2244  * @ioc: per adapter object
2245  * @mpi_reply: reply mf payload returned from firmware
2246  * @config_page: contents of the config page
2247  * Context: sleep.
2248  *
2249  * Returns 0 for success, non-zero for failure.
2250  */
2251 static int
2252 _config_set_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2253         Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2254 {
2255         Mpi2ConfigRequest_t mpi_request;
2256         int r;
2257
2258         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2259         mpi_request.Function = MPI2_FUNCTION_CONFIG;
2260         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2261         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2262         mpi_request.ExtPageType =
2263             MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2264         mpi_request.Header.PageNumber = 2;
2265         mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2266         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2267         r = _config_request(ioc, &mpi_request, mpi_reply,
2268             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2269         if (r)
2270                 goto out;
2271
2272         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2273         _config_request(ioc, &mpi_request, mpi_reply,
2274             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2275             sizeof(*config_page));
2276         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2277         r = _config_request(ioc, &mpi_request, mpi_reply,
2278             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2279             sizeof(*config_page));
2280  out:
2281         return r;
2282 }
2283
2284 /**
2285  * mpt3sas_config_update_driver_trigger_pg2 - update driver trigger page 2
2286  * @ioc: per adapter object
2287  * @event_tg: list of Event Triggers
2288  * @set: set ot clear trigger values
2289  * Context: sleep.
2290  *
2291  * Returns 0 for success, non-zero for failure.
2292  */
2293 int
2294 mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2295         struct SL_WH_EVENT_TRIGGERS_T *event_tg, bool set)
2296 {
2297         Mpi26DriverTriggerPage2_t tg_pg2;
2298         Mpi2ConfigReply_t mpi_reply;
2299         int rc, i, count;
2300         u16 ioc_status;
2301
2302         rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2303             MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, set);
2304         if (rc)
2305                 return rc;
2306
2307         rc = mpt3sas_config_get_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2308         if (rc)
2309                 goto out;
2310
2311         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2312             MPI2_IOCSTATUS_MASK;
2313         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2314                 dcprintk(ioc,
2315                     ioc_err(ioc,
2316                     "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2317                     __func__, ioc_status));
2318                 rc = -EFAULT;
2319                 goto out;
2320         }
2321
2322         if (set) {
2323                 count = event_tg->ValidEntries;
2324                 tg_pg2.NumMPIEventTrigger = cpu_to_le16(count);
2325                 for (i = 0; i < count; i++) {
2326                         tg_pg2.MPIEventTriggers[i].MPIEventCode =
2327                             cpu_to_le16(
2328                             event_tg->EventTriggerEntry[i].EventValue);
2329                         tg_pg2.MPIEventTriggers[i].MPIEventCodeSpecific =
2330                             cpu_to_le16(
2331                             event_tg->EventTriggerEntry[i].LogEntryQualifier);
2332                 }
2333         } else {
2334                 tg_pg2.NumMPIEventTrigger = 0;
2335                 memset(&tg_pg2.MPIEventTriggers[0], 0,
2336                     NUM_VALID_ENTRIES * sizeof(
2337                     MPI26_DRIVER_MPI_EVENT_TRIGGER_ENTRY));
2338         }
2339
2340         rc = _config_set_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2341         if (rc)
2342                 goto out;
2343
2344         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2345             MPI2_IOCSTATUS_MASK;
2346         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2347                 dcprintk(ioc,
2348                     ioc_err(ioc,
2349                     "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2350                     __func__, ioc_status));
2351                 rc = -EFAULT;
2352                 goto out;
2353         }
2354
2355         return 0;
2356
2357 out:
2358         mpt3sas_config_update_driver_trigger_pg0(ioc,
2359             MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, !set);
2360
2361         return rc;
2362 }
2363
2364 /**
2365  * mpt3sas_config_get_driver_trigger_pg3 - obtain driver trigger page 3
2366  * @ioc: per adapter object
2367  * @mpi_reply: reply mf payload returned from firmware
2368  * @config_page: contents of the config page
2369  * Context: sleep.
2370  *
2371  * Returns 0 for success, non-zero for failure.
2372  */
2373 int
2374 mpt3sas_config_get_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2375         Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2376 {
2377         Mpi2ConfigRequest_t mpi_request;
2378         int r;
2379
2380         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2381         mpi_request.Function = MPI2_FUNCTION_CONFIG;
2382         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2383         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2384         mpi_request.ExtPageType =
2385             MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2386         mpi_request.Header.PageNumber = 3;
2387         mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2388         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2389         r = _config_request(ioc, &mpi_request, mpi_reply,
2390             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2391         if (r)
2392                 goto out;
2393
2394         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2395         r = _config_request(ioc, &mpi_request, mpi_reply,
2396             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2397             sizeof(*config_page));
2398  out:
2399         return r;
2400 }
2401
2402 /**
2403  * _config_set_driver_trigger_pg3 - write driver trigger page 3
2404  * @ioc: per adapter object
2405  * @mpi_reply: reply mf payload returned from firmware
2406  * @config_page: contents of the config page
2407  * Context: sleep.
2408  *
2409  * Returns 0 for success, non-zero for failure.
2410  */
2411 static int
2412 _config_set_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2413         Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2414 {
2415         Mpi2ConfigRequest_t mpi_request;
2416         int r;
2417
2418         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2419         mpi_request.Function = MPI2_FUNCTION_CONFIG;
2420         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2421         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2422         mpi_request.ExtPageType =
2423             MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2424         mpi_request.Header.PageNumber = 3;
2425         mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2426         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2427         r = _config_request(ioc, &mpi_request, mpi_reply,
2428             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2429         if (r)
2430                 goto out;
2431
2432         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2433         _config_request(ioc, &mpi_request, mpi_reply,
2434             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2435             sizeof(*config_page));
2436         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2437         r = _config_request(ioc, &mpi_request, mpi_reply,
2438             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2439             sizeof(*config_page));
2440  out:
2441         return r;
2442 }
2443
2444 /**
2445  * mpt3sas_config_update_driver_trigger_pg3 - update driver trigger page 3
2446  * @ioc: per adapter object
2447  * @scsi_tg: scsi trigger list
2448  * @set: set ot clear trigger values
2449  * Context: sleep.
2450  *
2451  * Returns 0 for success, non-zero for failure.
2452  */
2453 int
2454 mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2455         struct SL_WH_SCSI_TRIGGERS_T *scsi_tg, bool set)
2456 {
2457         Mpi26DriverTriggerPage3_t tg_pg3;
2458         Mpi2ConfigReply_t mpi_reply;
2459         int rc, i, count;
2460         u16 ioc_status;
2461
2462         rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2463             MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, set);
2464         if (rc)
2465                 return rc;
2466
2467         rc = mpt3sas_config_get_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2468         if (rc)
2469                 goto out;
2470
2471         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2472             MPI2_IOCSTATUS_MASK;
2473         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2474                 dcprintk(ioc,
2475                     ioc_err(ioc,
2476                     "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2477                     __func__, ioc_status));
2478                 return -EFAULT;
2479         }
2480
2481         if (set) {
2482                 count = scsi_tg->ValidEntries;
2483                 tg_pg3.NumSCSISenseTrigger = cpu_to_le16(count);
2484                 for (i = 0; i < count; i++) {
2485                         tg_pg3.SCSISenseTriggers[i].ASCQ =
2486                             scsi_tg->SCSITriggerEntry[i].ASCQ;
2487                         tg_pg3.SCSISenseTriggers[i].ASC =
2488                             scsi_tg->SCSITriggerEntry[i].ASC;
2489                         tg_pg3.SCSISenseTriggers[i].SenseKey =
2490                             scsi_tg->SCSITriggerEntry[i].SenseKey;
2491                 }
2492         } else {
2493                 tg_pg3.NumSCSISenseTrigger = 0;
2494                 memset(&tg_pg3.SCSISenseTriggers[0], 0,
2495                     NUM_VALID_ENTRIES * sizeof(
2496                     MPI26_DRIVER_SCSI_SENSE_TRIGGER_ENTRY));
2497         }
2498
2499         rc = _config_set_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2500         if (rc)
2501                 goto out;
2502
2503         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2504             MPI2_IOCSTATUS_MASK;
2505         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2506                 dcprintk(ioc,
2507                     ioc_err(ioc,
2508                     "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2509                      __func__, ioc_status));
2510                 return -EFAULT;
2511         }
2512
2513         return 0;
2514 out:
2515         mpt3sas_config_update_driver_trigger_pg0(ioc,
2516             MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, !set);
2517
2518         return rc;
2519 }
2520
2521 /**
2522  * mpt3sas_config_get_driver_trigger_pg4 - obtain driver trigger page 4
2523  * @ioc: per adapter object
2524  * @mpi_reply: reply mf payload returned from firmware
2525  * @config_page: contents of the config page
2526  * Context: sleep.
2527  *
2528  * Returns 0 for success, non-zero for failure.
2529  */
2530 int
2531 mpt3sas_config_get_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2532         Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2533 {
2534         Mpi2ConfigRequest_t mpi_request;
2535         int r;
2536
2537         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2538         mpi_request.Function = MPI2_FUNCTION_CONFIG;
2539         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2540         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2541         mpi_request.ExtPageType =
2542             MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2543         mpi_request.Header.PageNumber = 4;
2544         mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2545         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2546         r = _config_request(ioc, &mpi_request, mpi_reply,
2547             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2548         if (r)
2549                 goto out;
2550
2551         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2552         r = _config_request(ioc, &mpi_request, mpi_reply,
2553             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2554             sizeof(*config_page));
2555  out:
2556         return r;
2557 }
2558
2559 /**
2560  * _config_set_driver_trigger_pg4 - write driver trigger page 4
2561  * @ioc: per adapter object
2562  * @mpi_reply: reply mf payload returned from firmware
2563  * @config_page: contents of the config page
2564  * Context: sleep.
2565  *
2566  * Returns 0 for success, non-zero for failure.
2567  */
2568 static int
2569 _config_set_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2570         Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2571 {
2572         Mpi2ConfigRequest_t mpi_request;
2573         int r;
2574
2575         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2576         mpi_request.Function = MPI2_FUNCTION_CONFIG;
2577         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2578         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2579         mpi_request.ExtPageType =
2580             MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2581         mpi_request.Header.PageNumber = 4;
2582         mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2583         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2584         r = _config_request(ioc, &mpi_request, mpi_reply,
2585             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2586         if (r)
2587                 goto out;
2588
2589         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2590         _config_request(ioc, &mpi_request, mpi_reply,
2591             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2592             sizeof(*config_page));
2593         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2594         r = _config_request(ioc, &mpi_request, mpi_reply,
2595             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2596             sizeof(*config_page));
2597  out:
2598         return r;
2599 }
2600
2601 /**
2602  * mpt3sas_config_update_driver_trigger_pg4 - update driver trigger page 4
2603  * @ioc: per adapter object
2604  * @mpi_tg: mpi trigger list
2605  * @set: set ot clear trigger values
2606  * Context: sleep.
2607  *
2608  * Returns 0 for success, non-zero for failure.
2609  */
2610 int
2611 mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2612         struct SL_WH_MPI_TRIGGERS_T *mpi_tg, bool set)
2613 {
2614         Mpi26DriverTriggerPage4_t tg_pg4;
2615         Mpi2ConfigReply_t mpi_reply;
2616         int rc, i, count;
2617         u16 ioc_status;
2618
2619         rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2620             MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, set);
2621         if (rc)
2622                 return rc;
2623
2624         rc = mpt3sas_config_get_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2625         if (rc)
2626                 goto out;
2627
2628         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2629             MPI2_IOCSTATUS_MASK;
2630         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2631                 dcprintk(ioc,
2632                     ioc_err(ioc,
2633                     "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2634                     __func__, ioc_status));
2635                 rc = -EFAULT;
2636                 goto out;
2637         }
2638
2639         if (set) {
2640                 count = mpi_tg->ValidEntries;
2641                 tg_pg4.NumIOCStatusLogInfoTrigger = cpu_to_le16(count);
2642                 for (i = 0; i < count; i++) {
2643                         tg_pg4.IOCStatusLoginfoTriggers[i].IOCStatus =
2644                             cpu_to_le16(mpi_tg->MPITriggerEntry[i].IOCStatus);
2645                         tg_pg4.IOCStatusLoginfoTriggers[i].LogInfo =
2646                             cpu_to_le32(mpi_tg->MPITriggerEntry[i].IocLogInfo);
2647                 }
2648         } else {
2649                 tg_pg4.NumIOCStatusLogInfoTrigger = 0;
2650                 memset(&tg_pg4.IOCStatusLoginfoTriggers[0], 0,
2651                     NUM_VALID_ENTRIES * sizeof(
2652                     MPI26_DRIVER_IOCSTATUS_LOGINFO_TRIGGER_ENTRY));
2653         }
2654
2655         rc = _config_set_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2656         if (rc)
2657                 goto out;
2658
2659         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2660             MPI2_IOCSTATUS_MASK;
2661         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2662                 dcprintk(ioc,
2663                     ioc_err(ioc,
2664                     "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2665                     __func__, ioc_status));
2666                 rc = -EFAULT;
2667                 goto out;
2668         }
2669
2670         return 0;
2671
2672 out:
2673         mpt3sas_config_update_driver_trigger_pg0(ioc,
2674             MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, !set);
2675
2676         return rc;
2677 }
2678
2679 /**
2680  * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
2681  * raid components
2682  * @ioc: per adapter object
2683  * @pd_handle: phys disk handle
2684  * @volume_handle: volume handle
2685  * Context: sleep.
2686  *
2687  * Return: 0 for success, non-zero for failure.
2688  */
2689 int
2690 mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
2691         u16 *volume_handle)
2692 {
2693         Mpi2RaidConfigurationPage0_t *config_page = NULL;
2694         Mpi2ConfigRequest_t mpi_request;
2695         Mpi2ConfigReply_t mpi_reply;
2696         int r, i, config_page_sz;
2697         u16 ioc_status;
2698         int config_num;
2699         u16 element_type;
2700         u16 phys_disk_dev_handle;
2701
2702         *volume_handle = 0;
2703         memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2704         mpi_request.Function = MPI2_FUNCTION_CONFIG;
2705         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2706         mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2707         mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
2708         mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
2709         mpi_request.Header.PageNumber = 0;
2710         ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2711         r = _config_request(ioc, &mpi_request, &mpi_reply,
2712             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2713         if (r)
2714                 goto out;
2715
2716         mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2717         config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
2718         config_page = kmalloc(config_page_sz, GFP_KERNEL);
2719         if (!config_page) {
2720                 r = -1;
2721                 goto out;
2722         }
2723
2724         config_num = 0xff;
2725         while (1) {
2726                 mpi_request.PageAddress = cpu_to_le32(config_num +
2727                     MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
2728                 r = _config_request(ioc, &mpi_request, &mpi_reply,
2729                     MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2730                     config_page_sz);
2731                 if (r)
2732                         goto out;
2733                 r = -1;
2734                 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2735                     MPI2_IOCSTATUS_MASK;
2736                 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
2737                         goto out;
2738                 for (i = 0; i < config_page->NumElements; i++) {
2739                         element_type = le16_to_cpu(config_page->
2740                             ConfigElement[i].ElementFlags) &
2741                             MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
2742                         if (element_type ==
2743                             MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
2744                             element_type ==
2745                             MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
2746                                 phys_disk_dev_handle =
2747                                     le16_to_cpu(config_page->ConfigElement[i].
2748                                     PhysDiskDevHandle);
2749                                 if (phys_disk_dev_handle == pd_handle) {
2750                                         *volume_handle =
2751                                             le16_to_cpu(config_page->
2752                                             ConfigElement[i].VolDevHandle);
2753                                         r = 0;
2754                                         goto out;
2755                                 }
2756                         } else if (element_type ==
2757                             MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
2758                                 *volume_handle = 0;
2759                                 r = 0;
2760                                 goto out;
2761                         }
2762                 }
2763                 config_num = config_page->ConfigNum;
2764         }
2765  out:
2766         kfree(config_page);
2767         return r;
2768 }
2769
2770 /**
2771  * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
2772  * @ioc: per adapter object
2773  * @volume_handle: volume handle
2774  * @wwid: volume wwid
2775  * Context: sleep.
2776  *
2777  * Return: 0 for success, non-zero for failure.
2778  */
2779 int
2780 mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
2781         u64 *wwid)
2782 {
2783         Mpi2ConfigReply_t mpi_reply;
2784         Mpi2RaidVolPage1_t raid_vol_pg1;
2785
2786         *wwid = 0;
2787         if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
2788             &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
2789             volume_handle))) {
2790                 *wwid = le64_to_cpu(raid_vol_pg1.WWID);
2791                 return 0;
2792         } else
2793                 return -1;
2794 }