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