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