Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This module provides common API for accessing firmware configuration pages
0003  *
0004  * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c
0005  * Copyright (C) 2012-2014  LSI Corporation
0006  * Copyright (C) 2013-2014 Avago Technologies
0007  *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
0008  *
0009  * This program is free software; you can redistribute it and/or
0010  * modify it under the terms of the GNU General Public License
0011  * as published by the Free Software Foundation; either version 2
0012  * of the License, or (at your option) any later version.
0013  *
0014  * This program is distributed in the hope that it will be useful,
0015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017  * GNU General Public License for more details.
0018  *
0019  * NO WARRANTY
0020  * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
0021  * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
0022  * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
0023  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
0024  * solely responsible for determining the appropriateness of using and
0025  * distributing the Program and assumes all risks associated with its
0026  * exercise of rights under this Agreement, including but not limited to
0027  * the risks and costs of program errors, damage to or loss of data,
0028  * programs or equipment, and unavailability or interruption of operations.
0029 
0030  * DISCLAIMER OF LIABILITY
0031  * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
0032  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0033  * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
0034  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
0035  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
0036  * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
0037  * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
0038 
0039  * You should have received a copy of the GNU General Public License
0040  * along with this program; if not, write to the Free Software
0041  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
0042  * USA.
0043  */
0044 
0045 #include <linux/module.h>
0046 #include <linux/kernel.h>
0047 #include <linux/init.h>
0048 #include <linux/errno.h>
0049 #include <linux/blkdev.h>
0050 #include <linux/sched.h>
0051 #include <linux/workqueue.h>
0052 #include <linux/delay.h>
0053 #include <linux/pci.h>
0054 
0055 #include "mpt3sas_base.h"
0056 
0057 /* local definitions */
0058 
0059 /* Timeout for config page request (in seconds) */
0060 #define MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT 15
0061 
0062 /* Common sgl flags for READING a config page. */
0063 #define MPT3_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
0064     MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
0065     | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT)
0066 
0067 /* Common sgl flags for WRITING a config page. */
0068 #define MPT3_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
0069     MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
0070     | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \
0071     << MPI2_SGE_FLAGS_SHIFT)
0072 
0073 /**
0074  * struct config_request - obtain dma memory via routine
0075  * @sz: size
0076  * @page: virt pointer
0077  * @page_dma: phys pointer
0078  *
0079  */
0080 struct config_request {
0081     u16         sz;
0082     void            *page;
0083     dma_addr_t      page_dma;
0084 };
0085 
0086 /**
0087  * _config_display_some_debug - debug routine
0088  * @ioc: per adapter object
0089  * @smid: system request message index
0090  * @calling_function_name: string pass from calling function
0091  * @mpi_reply: reply message frame
0092  * Context: none.
0093  *
0094  * Function for displaying debug info helpful when debugging issues
0095  * in this module.
0096  */
0097 static void
0098 _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
0099     char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
0100 {
0101     Mpi2ConfigRequest_t *mpi_request;
0102     char *desc = NULL;
0103 
0104     mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
0105     switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
0106     case MPI2_CONFIG_PAGETYPE_IO_UNIT:
0107         desc = "io_unit";
0108         break;
0109     case MPI2_CONFIG_PAGETYPE_IOC:
0110         desc = "ioc";
0111         break;
0112     case MPI2_CONFIG_PAGETYPE_BIOS:
0113         desc = "bios";
0114         break;
0115     case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
0116         desc = "raid_volume";
0117         break;
0118     case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
0119         desc = "manufacturing";
0120         break;
0121     case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
0122         desc = "physdisk";
0123         break;
0124     case MPI2_CONFIG_PAGETYPE_EXTENDED:
0125         switch (mpi_request->ExtPageType) {
0126         case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
0127             desc = "sas_io_unit";
0128             break;
0129         case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
0130             desc = "sas_expander";
0131             break;
0132         case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
0133             desc = "sas_device";
0134             break;
0135         case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
0136             desc = "sas_phy";
0137             break;
0138         case MPI2_CONFIG_EXTPAGETYPE_LOG:
0139             desc = "log";
0140             break;
0141         case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
0142             desc = "enclosure";
0143             break;
0144         case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
0145             desc = "raid_config";
0146             break;
0147         case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
0148             desc = "driver_mapping";
0149             break;
0150         case MPI2_CONFIG_EXTPAGETYPE_SAS_PORT:
0151             desc = "sas_port";
0152             break;
0153         case MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING:
0154             desc = "ext_manufacturing";
0155             break;
0156         case MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT:
0157             desc = "pcie_io_unit";
0158             break;
0159         case MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH:
0160             desc = "pcie_switch";
0161             break;
0162         case MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE:
0163             desc = "pcie_device";
0164             break;
0165         case MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK:
0166             desc = "pcie_link";
0167             break;
0168         }
0169         break;
0170     }
0171 
0172     if (!desc)
0173         return;
0174 
0175     ioc_info(ioc, "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n",
0176          calling_function_name, desc,
0177          mpi_request->Header.PageNumber, mpi_request->Action,
0178          le32_to_cpu(mpi_request->PageAddress), smid);
0179 
0180     if (!mpi_reply)
0181         return;
0182 
0183     if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
0184         ioc_info(ioc, "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
0185              le16_to_cpu(mpi_reply->IOCStatus),
0186              le32_to_cpu(mpi_reply->IOCLogInfo));
0187 }
0188 
0189 /**
0190  * _config_alloc_config_dma_memory - obtain physical memory
0191  * @ioc: per adapter object
0192  * @mem: struct config_request
0193  *
0194  * A wrapper for obtaining dma-able memory for config page request.
0195  *
0196  * Return: 0 for success, non-zero for failure.
0197  */
0198 static int
0199 _config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
0200     struct config_request *mem)
0201 {
0202     int r = 0;
0203 
0204     if (mem->sz > ioc->config_page_sz) {
0205         mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
0206             &mem->page_dma, GFP_KERNEL);
0207         if (!mem->page) {
0208             ioc_err(ioc, "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n",
0209                 __func__, mem->sz);
0210             r = -ENOMEM;
0211         }
0212     } else { /* use tmp buffer if less than 512 bytes */
0213         mem->page = ioc->config_page;
0214         mem->page_dma = ioc->config_page_dma;
0215     }
0216     ioc->config_vaddr = mem->page;
0217     return r;
0218 }
0219 
0220 /**
0221  * _config_free_config_dma_memory - wrapper to free the memory
0222  * @ioc: per adapter object
0223  * @mem: struct config_request
0224  *
0225  * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
0226  *
0227  * Return: 0 for success, non-zero for failure.
0228  */
0229 static void
0230 _config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
0231     struct config_request *mem)
0232 {
0233     if (mem->sz > ioc->config_page_sz)
0234         dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
0235             mem->page_dma);
0236 }
0237 
0238 /**
0239  * mpt3sas_config_done - config page completion routine
0240  * @ioc: per adapter object
0241  * @smid: system request message index
0242  * @msix_index: MSIX table index supplied by the OS
0243  * @reply: reply message frame(lower 32bit addr)
0244  * Context: none.
0245  *
0246  * The callback handler when using _config_request.
0247  *
0248  * Return: 1 meaning mf should be freed from _base_interrupt
0249  *         0 means the mf is freed from this function.
0250  */
0251 u8
0252 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
0253     u32 reply)
0254 {
0255     MPI2DefaultReply_t *mpi_reply;
0256 
0257     if (ioc->config_cmds.status == MPT3_CMD_NOT_USED)
0258         return 1;
0259     if (ioc->config_cmds.smid != smid)
0260         return 1;
0261     ioc->config_cmds.status |= MPT3_CMD_COMPLETE;
0262     mpi_reply =  mpt3sas_base_get_reply_virt_addr(ioc, reply);
0263     if (mpi_reply) {
0264         ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID;
0265         memcpy(ioc->config_cmds.reply, mpi_reply,
0266             mpi_reply->MsgLength*4);
0267     }
0268     ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
0269     if (ioc->logging_level & MPT_DEBUG_CONFIG)
0270         _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
0271     ioc->config_cmds.smid = USHRT_MAX;
0272     complete(&ioc->config_cmds.done);
0273     return 1;
0274 }
0275 
0276 /**
0277  * _config_request - main routine for sending config page requests
0278  * @ioc: per adapter object
0279  * @mpi_request: request message frame
0280  * @mpi_reply: reply mf payload returned from firmware
0281  * @timeout: timeout in seconds
0282  * @config_page: contents of the config page
0283  * @config_page_sz: size of config page
0284  * Context: sleep
0285  *
0286  * A generic API for config page requests to firmware.
0287  *
0288  * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling
0289  * this API.
0290  *
0291  * The callback index is set inside `ioc->config_cb_idx.
0292  *
0293  * Return: 0 for success, non-zero for failure.
0294  */
0295 static int
0296 _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
0297     *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
0298     void *config_page, u16 config_page_sz)
0299 {
0300     u16 smid;
0301     Mpi2ConfigRequest_t *config_request;
0302     int r;
0303     u8 retry_count, issue_host_reset = 0;
0304     struct config_request mem;
0305     u32 ioc_status = UINT_MAX;
0306 
0307     mutex_lock(&ioc->config_cmds.mutex);
0308     if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
0309         ioc_err(ioc, "%s: config_cmd in use\n", __func__);
0310         mutex_unlock(&ioc->config_cmds.mutex);
0311         return -EAGAIN;
0312     }
0313 
0314     retry_count = 0;
0315     memset(&mem, 0, sizeof(struct config_request));
0316 
0317     mpi_request->VF_ID = 0; /* TODO */
0318     mpi_request->VP_ID = 0;
0319 
0320     if (config_page) {
0321         mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
0322         mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
0323         mpi_request->Header.PageType = mpi_reply->Header.PageType;
0324         mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
0325         mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
0326         mpi_request->ExtPageType = mpi_reply->ExtPageType;
0327         if (mpi_request->Header.PageLength)
0328             mem.sz = mpi_request->Header.PageLength * 4;
0329         else
0330             mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
0331         r = _config_alloc_config_dma_memory(ioc, &mem);
0332         if (r != 0)
0333             goto out;
0334         if (mpi_request->Action ==
0335             MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
0336             mpi_request->Action ==
0337             MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
0338             ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
0339                 MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
0340                 mem.page_dma);
0341             memcpy(mem.page, config_page, min_t(u16, mem.sz,
0342                 config_page_sz));
0343         } else {
0344             memset(config_page, 0, config_page_sz);
0345             ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
0346                 MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
0347             memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
0348         }
0349     }
0350 
0351  retry_config:
0352     if (retry_count) {
0353         if (retry_count > 2) { /* attempt only 2 retries */
0354             r = -EFAULT;
0355             goto free_mem;
0356         }
0357         ioc_info(ioc, "%s: attempting retry (%d)\n",
0358              __func__, retry_count);
0359     }
0360 
0361     r = mpt3sas_wait_for_ioc(ioc, MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT);
0362     if (r) {
0363         if (r == -ETIME)
0364             issue_host_reset = 1;
0365         goto free_mem;
0366     }
0367 
0368     smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
0369     if (!smid) {
0370         ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
0371         ioc->config_cmds.status = MPT3_CMD_NOT_USED;
0372         r = -EAGAIN;
0373         goto free_mem;
0374     }
0375 
0376     r = 0;
0377     memset(ioc->config_cmds.reply, 0, sizeof(Mpi2ConfigReply_t));
0378     ioc->config_cmds.status = MPT3_CMD_PENDING;
0379     config_request = mpt3sas_base_get_msg_frame(ioc, smid);
0380     ioc->config_cmds.smid = smid;
0381     memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
0382     if (ioc->logging_level & MPT_DEBUG_CONFIG)
0383         _config_display_some_debug(ioc, smid, "config_request", NULL);
0384     init_completion(&ioc->config_cmds.done);
0385     ioc->put_smid_default(ioc, smid);
0386     wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ);
0387     if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
0388         if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
0389             _config_display_some_debug(ioc,
0390                 smid, "config_request", NULL);
0391         ioc_err(ioc, "%s: command timeout\n", __func__);
0392         mpt3sas_base_check_cmd_timeout(ioc, ioc->config_cmds.status,
0393                 mpi_request, sizeof(Mpi2ConfigRequest_t) / 4);
0394         retry_count++;
0395         if (ioc->config_cmds.smid == smid)
0396             mpt3sas_base_free_smid(ioc, smid);
0397         if (ioc->config_cmds.status & MPT3_CMD_RESET)
0398             goto retry_config;
0399         if (ioc->shost_recovery || ioc->pci_error_recovery) {
0400             issue_host_reset = 0;
0401             r = -EFAULT;
0402         } else
0403             issue_host_reset = 1;
0404         goto free_mem;
0405     }
0406 
0407     if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
0408         memcpy(mpi_reply, ioc->config_cmds.reply,
0409             sizeof(Mpi2ConfigReply_t));
0410 
0411         /* Reply Frame Sanity Checks to workaround FW issues */
0412         if ((mpi_request->Header.PageType & 0xF) !=
0413             (mpi_reply->Header.PageType & 0xF)) {
0414             if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
0415                 _config_display_some_debug(ioc,
0416                     smid, "config_request", NULL);
0417             _debug_dump_mf(mpi_request, ioc->request_sz/4);
0418             _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
0419             panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
0420                   ioc->name, __func__,
0421                   mpi_request->Header.PageType & 0xF,
0422                   mpi_reply->Header.PageType & 0xF);
0423         }
0424 
0425         if (((mpi_request->Header.PageType & 0xF) ==
0426             MPI2_CONFIG_PAGETYPE_EXTENDED) &&
0427             mpi_request->ExtPageType != mpi_reply->ExtPageType) {
0428             if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
0429                 _config_display_some_debug(ioc,
0430                     smid, "config_request", NULL);
0431             _debug_dump_mf(mpi_request, ioc->request_sz/4);
0432             _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
0433             panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
0434                   ioc->name, __func__,
0435                   mpi_request->ExtPageType,
0436                   mpi_reply->ExtPageType);
0437         }
0438         ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
0439             & MPI2_IOCSTATUS_MASK;
0440     }
0441 
0442     if (retry_count)
0443         ioc_info(ioc, "%s: retry (%d) completed!!\n",
0444              __func__, retry_count);
0445 
0446     if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
0447         config_page && mpi_request->Action ==
0448         MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
0449         u8 *p = (u8 *)mem.page;
0450 
0451         /* Config Page Sanity Checks to workaround FW issues */
0452         if (p) {
0453             if ((mpi_request->Header.PageType & 0xF) !=
0454                 (p[3] & 0xF)) {
0455                 if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
0456                     _config_display_some_debug(ioc,
0457                         smid, "config_request", NULL);
0458                 _debug_dump_mf(mpi_request, ioc->request_sz/4);
0459                 _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
0460                 _debug_dump_config(p, min_t(u16, mem.sz,
0461                     config_page_sz)/4);
0462                 panic("%s: %s: Firmware BUG: config page mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
0463                       ioc->name, __func__,
0464                       mpi_request->Header.PageType & 0xF,
0465                       p[3] & 0xF);
0466             }
0467 
0468             if (((mpi_request->Header.PageType & 0xF) ==
0469                 MPI2_CONFIG_PAGETYPE_EXTENDED) &&
0470                 (mpi_request->ExtPageType != p[6])) {
0471                 if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
0472                     _config_display_some_debug(ioc,
0473                         smid, "config_request", NULL);
0474                 _debug_dump_mf(mpi_request, ioc->request_sz/4);
0475                 _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
0476                 _debug_dump_config(p, min_t(u16, mem.sz,
0477                     config_page_sz)/4);
0478                 panic("%s: %s: Firmware BUG: config page mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
0479                       ioc->name, __func__,
0480                       mpi_request->ExtPageType, p[6]);
0481             }
0482         }
0483         memcpy(config_page, mem.page, min_t(u16, mem.sz,
0484             config_page_sz));
0485     }
0486 
0487  free_mem:
0488     if (config_page)
0489         _config_free_config_dma_memory(ioc, &mem);
0490  out:
0491     ioc->config_cmds.status = MPT3_CMD_NOT_USED;
0492     mutex_unlock(&ioc->config_cmds.mutex);
0493 
0494     if (issue_host_reset) {
0495         if (ioc->drv_internal_flags & MPT_DRV_INTERNAL_FIRST_PE_ISSUED) {
0496             mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
0497             r = -EFAULT;
0498         } else {
0499             if (mpt3sas_base_check_for_fault_and_issue_reset(ioc))
0500                 return -EFAULT;
0501             r = -EAGAIN;
0502         }
0503     }
0504     return r;
0505 }
0506 
0507 /**
0508  * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
0509  * @ioc: per adapter object
0510  * @mpi_reply: reply mf payload returned from firmware
0511  * @config_page: contents of the config page
0512  * Context: sleep.
0513  *
0514  * Return: 0 for success, non-zero for failure.
0515  */
0516 int
0517 mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
0518     Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
0519 {
0520     Mpi2ConfigRequest_t mpi_request;
0521     int r;
0522 
0523     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0524     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0525     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0526     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
0527     mpi_request.Header.PageNumber = 0;
0528     mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
0529     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0530     r = _config_request(ioc, &mpi_request, mpi_reply,
0531         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0532     if (r)
0533         goto out;
0534 
0535     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
0536     r = _config_request(ioc, &mpi_request, mpi_reply,
0537         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0538         sizeof(*config_page));
0539  out:
0540     return r;
0541 }
0542 
0543 /**
0544  * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
0545  * @ioc: per adapter object
0546  * @mpi_reply: reply mf payload returned from firmware
0547  * @config_page: contents of the config page
0548  * @sz: size of buffer passed in config_page
0549  * Context: sleep.
0550  *
0551  * Return: 0 for success, non-zero for failure.
0552  */
0553 int
0554 mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
0555     Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
0556     u16 sz)
0557 {
0558     Mpi2ConfigRequest_t mpi_request;
0559     int r;
0560 
0561     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0562     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0563     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0564     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
0565     mpi_request.Header.PageNumber = 7;
0566     mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
0567     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0568     r = _config_request(ioc, &mpi_request, mpi_reply,
0569         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0570     if (r)
0571         goto out;
0572 
0573     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
0574     r = _config_request(ioc, &mpi_request, mpi_reply,
0575         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0576         sz);
0577  out:
0578     return r;
0579 }
0580 
0581 /**
0582  * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
0583  * @ioc: per adapter object
0584  * @mpi_reply: reply mf payload returned from firmware
0585  * @config_page: contents of the config page
0586  * Context: sleep.
0587  *
0588  * Return: 0 for success, non-zero for failure.
0589  */
0590 int
0591 mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
0592     Mpi2ConfigReply_t *mpi_reply,
0593     struct Mpi2ManufacturingPage10_t *config_page)
0594 {
0595     Mpi2ConfigRequest_t mpi_request;
0596     int r;
0597 
0598     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0599     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0600     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0601     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
0602     mpi_request.Header.PageNumber = 10;
0603     mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
0604     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0605     r = _config_request(ioc, &mpi_request, mpi_reply,
0606         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0607     if (r)
0608         goto out;
0609 
0610     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
0611     r = _config_request(ioc, &mpi_request, mpi_reply,
0612         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0613         sizeof(*config_page));
0614  out:
0615     return r;
0616 }
0617 
0618 /**
0619  * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
0620  * @ioc: per adapter object
0621  * @mpi_reply: reply mf payload returned from firmware
0622  * @config_page: contents of the config page
0623  * Context: sleep.
0624  *
0625  * Return: 0 for success, non-zero for failure.
0626  */
0627 int
0628 mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
0629     Mpi2ConfigReply_t *mpi_reply,
0630     struct Mpi2ManufacturingPage11_t *config_page)
0631 {
0632     Mpi2ConfigRequest_t mpi_request;
0633     int r;
0634 
0635     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0636     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0637     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0638     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
0639     mpi_request.Header.PageNumber = 11;
0640     mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
0641     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0642     r = _config_request(ioc, &mpi_request, mpi_reply,
0643         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0644     if (r)
0645         goto out;
0646 
0647     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
0648     r = _config_request(ioc, &mpi_request, mpi_reply,
0649         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0650         sizeof(*config_page));
0651  out:
0652     return r;
0653 }
0654 
0655 /**
0656  * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
0657  * @ioc: per adapter object
0658  * @mpi_reply: reply mf payload returned from firmware
0659  * @config_page: contents of the config page
0660  * Context: sleep.
0661  *
0662  * Return: 0 for success, non-zero for failure.
0663  */
0664 int
0665 mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
0666     Mpi2ConfigReply_t *mpi_reply,
0667     struct Mpi2ManufacturingPage11_t *config_page)
0668 {
0669     Mpi2ConfigRequest_t mpi_request;
0670     int r;
0671 
0672     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0673     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0674     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0675     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
0676     mpi_request.Header.PageNumber = 11;
0677     mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
0678     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0679     r = _config_request(ioc, &mpi_request, mpi_reply,
0680         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0681     if (r)
0682         goto out;
0683 
0684     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
0685     r = _config_request(ioc, &mpi_request, mpi_reply,
0686         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0687         sizeof(*config_page));
0688  out:
0689     return r;
0690 }
0691 
0692 /**
0693  * mpt3sas_config_get_bios_pg2 - obtain bios page 2
0694  * @ioc: per adapter object
0695  * @mpi_reply: reply mf payload returned from firmware
0696  * @config_page: contents of the config page
0697  * Context: sleep.
0698  *
0699  * Return: 0 for success, non-zero for failure.
0700  */
0701 int
0702 mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
0703     Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
0704 {
0705     Mpi2ConfigRequest_t mpi_request;
0706     int r;
0707 
0708     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0709     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0710     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0711     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
0712     mpi_request.Header.PageNumber = 2;
0713     mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
0714     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0715     r = _config_request(ioc, &mpi_request, mpi_reply,
0716         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0717     if (r)
0718         goto out;
0719 
0720     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
0721     r = _config_request(ioc, &mpi_request, mpi_reply,
0722         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0723         sizeof(*config_page));
0724  out:
0725     return r;
0726 }
0727 
0728 /**
0729  * mpt3sas_config_get_bios_pg3 - obtain bios page 3
0730  * @ioc: per adapter object
0731  * @mpi_reply: reply mf payload returned from firmware
0732  * @config_page: contents of the config page
0733  * Context: sleep.
0734  *
0735  * Return: 0 for success, non-zero for failure.
0736  */
0737 int
0738 mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
0739     *mpi_reply, Mpi2BiosPage3_t *config_page)
0740 {
0741     Mpi2ConfigRequest_t mpi_request;
0742     int r;
0743 
0744     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0745     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0746     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0747     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
0748     mpi_request.Header.PageNumber = 3;
0749     mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
0750     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0751     r = _config_request(ioc, &mpi_request, mpi_reply,
0752         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0753     if (r)
0754         goto out;
0755 
0756     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
0757     r = _config_request(ioc, &mpi_request, mpi_reply,
0758         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0759         sizeof(*config_page));
0760  out:
0761     return r;
0762 }
0763 
0764 /**
0765  * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
0766  * @ioc: per adapter object
0767  * @mpi_reply: reply mf payload returned from firmware
0768  * @config_page: contents of the config page
0769  * Context: sleep.
0770  *
0771  * Return: 0 for success, non-zero for failure.
0772  */
0773 int
0774 mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
0775     Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
0776 {
0777     Mpi2ConfigRequest_t mpi_request;
0778     int r;
0779 
0780     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0781     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0782     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0783     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
0784     mpi_request.Header.PageNumber = 0;
0785     mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
0786     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0787     r = _config_request(ioc, &mpi_request, mpi_reply,
0788         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0789     if (r)
0790         goto out;
0791 
0792     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
0793     r = _config_request(ioc, &mpi_request, mpi_reply,
0794         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0795         sizeof(*config_page));
0796  out:
0797     return r;
0798 }
0799 
0800 /**
0801  * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
0802  * @ioc: per adapter object
0803  * @mpi_reply: reply mf payload returned from firmware
0804  * @config_page: contents of the config page
0805  * Context: sleep.
0806  *
0807  * Return: 0 for success, non-zero for failure.
0808  */
0809 int
0810 mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
0811     Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
0812 {
0813     Mpi2ConfigRequest_t mpi_request;
0814     int r;
0815 
0816     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0817     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0818     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0819     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
0820     mpi_request.Header.PageNumber = 1;
0821     mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
0822     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0823     r = _config_request(ioc, &mpi_request, mpi_reply,
0824         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0825     if (r)
0826         goto out;
0827 
0828     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
0829     r = _config_request(ioc, &mpi_request, mpi_reply,
0830         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0831         sizeof(*config_page));
0832  out:
0833     return r;
0834 }
0835 
0836 /**
0837  * mpt3sas_config_set_iounit_pg1 - set iounit page 1
0838  * @ioc: per adapter object
0839  * @mpi_reply: reply mf payload returned from firmware
0840  * @config_page: contents of the config page
0841  * Context: sleep.
0842  *
0843  * Return: 0 for success, non-zero for failure.
0844  */
0845 int
0846 mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
0847     Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
0848 {
0849     Mpi2ConfigRequest_t mpi_request;
0850     int r;
0851 
0852     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0853     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0854     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0855     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
0856     mpi_request.Header.PageNumber = 1;
0857     mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
0858     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0859     r = _config_request(ioc, &mpi_request, mpi_reply,
0860         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0861     if (r)
0862         goto out;
0863 
0864     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
0865     r = _config_request(ioc, &mpi_request, mpi_reply,
0866         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0867         sizeof(*config_page));
0868  out:
0869     return r;
0870 }
0871 
0872 /**
0873  * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
0874  * @ioc: per adapter object
0875  * @mpi_reply: reply mf payload returned from firmware
0876  * @config_page: contents of the config page
0877  * @sz: size of buffer passed in config_page
0878  * Context: sleep.
0879  *
0880  * Return: 0 for success, non-zero for failure.
0881  */
0882 int
0883 mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
0884     Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
0885 {
0886     Mpi2ConfigRequest_t mpi_request;
0887     int r;
0888 
0889     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0890     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0891     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0892     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
0893     mpi_request.Header.PageNumber = 3;
0894     mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
0895     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0896     r = _config_request(ioc, &mpi_request, mpi_reply,
0897         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0898     if (r)
0899         goto out;
0900 
0901     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
0902     r = _config_request(ioc, &mpi_request, mpi_reply,
0903         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
0904  out:
0905     return r;
0906 }
0907 
0908 /**
0909  * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
0910  * @ioc: per adapter object
0911  * @mpi_reply: reply mf payload returned from firmware
0912  * @config_page: contents of the config page
0913  * Context: sleep.
0914  *
0915  * Return: 0 for success, non-zero for failure.
0916  */
0917 int
0918 mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
0919     Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
0920 {
0921     Mpi2ConfigRequest_t mpi_request;
0922     int r;
0923 
0924     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0925     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0926     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0927     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
0928     mpi_request.Header.PageNumber = 8;
0929     mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
0930     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0931     r = _config_request(ioc, &mpi_request, mpi_reply,
0932         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0933     if (r)
0934         goto out;
0935 
0936     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
0937     r = _config_request(ioc, &mpi_request, mpi_reply,
0938         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0939         sizeof(*config_page));
0940  out:
0941     return r;
0942 }
0943 
0944 /**
0945  * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
0946  * @ioc: per adapter object
0947  * @mpi_reply: reply mf payload returned from firmware
0948  * @config_page: contents of the config page
0949  * Context: sleep.
0950  *
0951  * Return: 0 for success, non-zero for failure.
0952  */
0953 int
0954 mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
0955     Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
0956 {
0957     Mpi2ConfigRequest_t mpi_request;
0958     int r;
0959 
0960     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0961     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0962     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0963     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
0964     mpi_request.Header.PageNumber = 8;
0965     mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
0966     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
0967     r = _config_request(ioc, &mpi_request, mpi_reply,
0968         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
0969     if (r)
0970         goto out;
0971 
0972     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
0973     r = _config_request(ioc, &mpi_request, mpi_reply,
0974         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
0975         sizeof(*config_page));
0976  out:
0977     return r;
0978 }
0979 /**
0980  * mpt3sas_config_get_ioc_pg1 - obtain ioc page 1
0981  * @ioc: per adapter object
0982  * @mpi_reply: reply mf payload returned from firmware
0983  * @config_page: contents of the config page
0984  * Context: sleep.
0985  *
0986  * Return: 0 for success, non-zero for failure.
0987  */
0988 int
0989 mpt3sas_config_get_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
0990     Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
0991 {
0992     Mpi2ConfigRequest_t mpi_request;
0993     int r;
0994 
0995     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
0996     mpi_request.Function = MPI2_FUNCTION_CONFIG;
0997     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
0998     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
0999     mpi_request.Header.PageNumber = 1;
1000     mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
1001     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1002     r = _config_request(ioc, &mpi_request, mpi_reply,
1003         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1004     if (r)
1005         goto out;
1006 
1007     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1008     r = _config_request(ioc, &mpi_request, mpi_reply,
1009         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1010         sizeof(*config_page));
1011  out:
1012     return r;
1013 }
1014 
1015 /**
1016  * mpt3sas_config_set_ioc_pg1 - modify ioc page 1
1017  * @ioc: per adapter object
1018  * @mpi_reply: reply mf payload returned from firmware
1019  * @config_page: contents of the config page
1020  * Context: sleep.
1021  *
1022  * Return: 0 for success, non-zero for failure.
1023  */
1024 int
1025 mpt3sas_config_set_ioc_pg1(struct MPT3SAS_ADAPTER *ioc,
1026     Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage1_t *config_page)
1027 {
1028     Mpi2ConfigRequest_t mpi_request;
1029     int r;
1030 
1031     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1032     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1033     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1034     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
1035     mpi_request.Header.PageNumber = 1;
1036     mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
1037     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1038     r = _config_request(ioc, &mpi_request, mpi_reply,
1039         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1040     if (r)
1041         goto out;
1042 
1043     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1044     r = _config_request(ioc, &mpi_request, mpi_reply,
1045         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1046         sizeof(*config_page));
1047  out:
1048     return r;
1049 }
1050 
1051 /**
1052  * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
1053  * @ioc: per adapter object
1054  * @mpi_reply: reply mf payload returned from firmware
1055  * @config_page: contents of the config page
1056  * @form: GET_NEXT_HANDLE or HANDLE
1057  * @handle: device handle
1058  * Context: sleep.
1059  *
1060  * Return: 0 for success, non-zero for failure.
1061  */
1062 int
1063 mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1064     Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
1065     u32 form, u32 handle)
1066 {
1067     Mpi2ConfigRequest_t mpi_request;
1068     int r;
1069 
1070     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1071     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1072     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1073     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1074     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1075     mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
1076     mpi_request.Header.PageNumber = 0;
1077     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1078     r = _config_request(ioc, &mpi_request, mpi_reply,
1079         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1080     if (r)
1081         goto out;
1082 
1083     mpi_request.PageAddress = cpu_to_le32(form | handle);
1084     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1085     r = _config_request(ioc, &mpi_request, mpi_reply,
1086         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1087         sizeof(*config_page));
1088  out:
1089     return r;
1090 }
1091 
1092 /**
1093  * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
1094  * @ioc: per adapter object
1095  * @mpi_reply: reply mf payload returned from firmware
1096  * @config_page: contents of the config page
1097  * @form: GET_NEXT_HANDLE or HANDLE
1098  * @handle: device handle
1099  * Context: sleep.
1100  *
1101  * Return: 0 for success, non-zero for failure.
1102  */
1103 int
1104 mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1105     Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1106     u32 form, u32 handle)
1107 {
1108     Mpi2ConfigRequest_t mpi_request;
1109     int r;
1110 
1111     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1112     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1113     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1114     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1115     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1116     mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1117     mpi_request.Header.PageNumber = 1;
1118     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1119     r = _config_request(ioc, &mpi_request, mpi_reply,
1120         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1121     if (r)
1122         goto out;
1123 
1124     mpi_request.PageAddress = cpu_to_le32(form | handle);
1125     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1126     r = _config_request(ioc, &mpi_request, mpi_reply,
1127         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1128         sizeof(*config_page));
1129  out:
1130     return r;
1131 }
1132 
1133 /**
1134  * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
1135  * @ioc: per adapter object
1136  * @mpi_reply: reply mf payload returned from firmware
1137  * @config_page: contents of the config page
1138  * @form: GET_NEXT_HANDLE or HANDLE
1139  * @handle: device handle
1140  * Context: sleep.
1141  *
1142  * Return: 0 for success, non-zero for failure.
1143  */
1144 int
1145 mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1146     Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
1147     u32 form, u32 handle)
1148 {
1149     Mpi2ConfigRequest_t mpi_request;
1150     int r;
1151 
1152     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1153     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1154     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1155     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1156     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1157     mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
1158     mpi_request.Header.PageNumber = 0;
1159     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1160     r = _config_request(ioc, &mpi_request, mpi_reply,
1161             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1162     if (r)
1163         goto out;
1164 
1165     mpi_request.PageAddress = cpu_to_le32(form | handle);
1166     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1167     r = _config_request(ioc, &mpi_request, mpi_reply,
1168             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1169             sizeof(*config_page));
1170 out:
1171     return r;
1172 }
1173 
1174 /**
1175  * mpt3sas_config_get_pcie_iounit_pg1 - obtain pcie iounit page 1
1176  * @ioc: per adapter object
1177  * @mpi_reply: reply mf payload returned from firmware
1178  * @config_page: contents of the config page
1179  * @sz: size of buffer passed in config_page
1180  * Context: sleep.
1181  *
1182  * Returns 0 for success, non-zero for failure.
1183  */
1184 int
1185 mpt3sas_config_get_pcie_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1186     Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeIOUnitPage1_t *config_page,
1187     u16 sz)
1188 {
1189     Mpi2ConfigRequest_t mpi_request;
1190     int r;
1191 
1192     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1193     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1194     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1195     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1196     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT;
1197     mpi_request.Header.PageVersion = MPI26_PCIEIOUNITPAGE1_PAGEVERSION;
1198     mpi_request.Header.PageNumber = 1;
1199     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1200     r = _config_request(ioc, &mpi_request, mpi_reply,
1201         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1202     if (r)
1203         goto out;
1204     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1205     r = _config_request(ioc, &mpi_request, mpi_reply,
1206         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1207 out:
1208     return r;
1209 }
1210 
1211 /**
1212  * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
1213  * @ioc: per adapter object
1214  * @mpi_reply: reply mf payload returned from firmware
1215  * @config_page: contents of the config page
1216  * @form: GET_NEXT_HANDLE or HANDLE
1217  * @handle: device handle
1218  * Context: sleep.
1219  *
1220  * Return: 0 for success, non-zero for failure.
1221  */
1222 int
1223 mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
1224     Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
1225     u32 form, u32 handle)
1226 {
1227     Mpi2ConfigRequest_t mpi_request;
1228     int r;
1229 
1230     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1231     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1232     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1233     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1234     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1235     mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
1236     mpi_request.Header.PageNumber = 2;
1237     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1238     r = _config_request(ioc, &mpi_request, mpi_reply,
1239             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1240     if (r)
1241         goto out;
1242 
1243     mpi_request.PageAddress = cpu_to_le32(form | handle);
1244     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1245     r = _config_request(ioc, &mpi_request, mpi_reply,
1246             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1247             sizeof(*config_page));
1248 out:
1249     return r;
1250 }
1251 
1252 /**
1253  * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1254  * @ioc: per adapter object
1255  * @num_phys: pointer returned with the number of phys
1256  * Context: sleep.
1257  *
1258  * Return: 0 for success, non-zero for failure.
1259  */
1260 int
1261 mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1262 {
1263     Mpi2ConfigRequest_t mpi_request;
1264     int r;
1265     u16 ioc_status;
1266     Mpi2ConfigReply_t mpi_reply;
1267     Mpi2SasIOUnitPage0_t config_page;
1268 
1269     *num_phys = 0;
1270     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1271     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1272     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1273     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1274     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1275     mpi_request.Header.PageNumber = 0;
1276     mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1277     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1278     r = _config_request(ioc, &mpi_request, &mpi_reply,
1279         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1280     if (r)
1281         goto out;
1282 
1283     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1284     r = _config_request(ioc, &mpi_request, &mpi_reply,
1285         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1286         sizeof(Mpi2SasIOUnitPage0_t));
1287     if (!r) {
1288         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1289             MPI2_IOCSTATUS_MASK;
1290         if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1291             *num_phys = config_page.NumPhys;
1292     }
1293  out:
1294     return r;
1295 }
1296 
1297 /**
1298  * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1299  * @ioc: per adapter object
1300  * @mpi_reply: reply mf payload returned from firmware
1301  * @config_page: contents of the config page
1302  * @sz: size of buffer passed in config_page
1303  * Context: sleep.
1304  *
1305  * Calling function should call config_get_number_hba_phys prior to
1306  * this function, so enough memory is allocated for config_page.
1307  *
1308  * Return: 0 for success, non-zero for failure.
1309  */
1310 int
1311 mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1312     Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1313     u16 sz)
1314 {
1315     Mpi2ConfigRequest_t mpi_request;
1316     int r;
1317 
1318     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1319     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1320     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1321     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1322     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1323     mpi_request.Header.PageNumber = 0;
1324     mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1325     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1326     r = _config_request(ioc, &mpi_request, mpi_reply,
1327         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1328     if (r)
1329         goto out;
1330 
1331     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1332     r = _config_request(ioc, &mpi_request, mpi_reply,
1333         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1334  out:
1335     return r;
1336 }
1337 
1338 /**
1339  * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1340  * @ioc: per adapter object
1341  * @mpi_reply: reply mf payload returned from firmware
1342  * @config_page: contents of the config page
1343  * @sz: size of buffer passed in config_page
1344  * Context: sleep.
1345  *
1346  * Calling function should call config_get_number_hba_phys prior to
1347  * this function, so enough memory is allocated for config_page.
1348  *
1349  * Return: 0 for success, non-zero for failure.
1350  */
1351 int
1352 mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1353     Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1354     u16 sz)
1355 {
1356     Mpi2ConfigRequest_t mpi_request;
1357     int r;
1358 
1359     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1360     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1361     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1362     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1363     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1364     mpi_request.Header.PageNumber = 1;
1365     mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1366     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1367     r = _config_request(ioc, &mpi_request, mpi_reply,
1368         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1369     if (r)
1370         goto out;
1371 
1372     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1373     r = _config_request(ioc, &mpi_request, mpi_reply,
1374         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1375  out:
1376     return r;
1377 }
1378 
1379 /**
1380  * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1381  * @ioc: per adapter object
1382  * @mpi_reply: reply mf payload returned from firmware
1383  * @config_page: contents of the config page
1384  * @sz: size of buffer passed in config_page
1385  * Context: sleep.
1386  *
1387  * Calling function should call config_get_number_hba_phys prior to
1388  * this function, so enough memory is allocated for config_page.
1389  *
1390  * Return: 0 for success, non-zero for failure.
1391  */
1392 int
1393 mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1394     Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1395     u16 sz)
1396 {
1397     Mpi2ConfigRequest_t mpi_request;
1398     int r;
1399 
1400     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1401     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1402     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1403     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1404     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1405     mpi_request.Header.PageNumber = 1;
1406     mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1407     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1408     r = _config_request(ioc, &mpi_request, mpi_reply,
1409         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1410     if (r)
1411         goto out;
1412 
1413     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1414     _config_request(ioc, &mpi_request, mpi_reply,
1415         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1416     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1417     r = _config_request(ioc, &mpi_request, mpi_reply,
1418         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1419  out:
1420     return r;
1421 }
1422 
1423 /**
1424  * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1425  * @ioc: per adapter object
1426  * @mpi_reply: reply mf payload returned from firmware
1427  * @config_page: contents of the config page
1428  * @form: GET_NEXT_HANDLE or HANDLE
1429  * @handle: expander handle
1430  * Context: sleep.
1431  *
1432  * Return: 0 for success, non-zero for failure.
1433  */
1434 int
1435 mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1436     *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1437 {
1438     Mpi2ConfigRequest_t mpi_request;
1439     int r;
1440 
1441     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1442     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1443     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1444     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1445     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1446     mpi_request.Header.PageNumber = 0;
1447     mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1448     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1449     r = _config_request(ioc, &mpi_request, mpi_reply,
1450         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1451     if (r)
1452         goto out;
1453 
1454     mpi_request.PageAddress = cpu_to_le32(form | handle);
1455     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1456     r = _config_request(ioc, &mpi_request, mpi_reply,
1457         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1458         sizeof(*config_page));
1459  out:
1460     return r;
1461 }
1462 
1463 /**
1464  * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1465  * @ioc: per adapter object
1466  * @mpi_reply: reply mf payload returned from firmware
1467  * @config_page: contents of the config page
1468  * @phy_number: phy number
1469  * @handle: expander handle
1470  * Context: sleep.
1471  *
1472  * Return: 0 for success, non-zero for failure.
1473  */
1474 int
1475 mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1476     *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1477     u16 handle)
1478 {
1479     Mpi2ConfigRequest_t mpi_request;
1480     int r;
1481 
1482     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1483     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1484     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1485     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1486     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1487     mpi_request.Header.PageNumber = 1;
1488     mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1489     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1490     r = _config_request(ioc, &mpi_request, mpi_reply,
1491         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1492     if (r)
1493         goto out;
1494 
1495     mpi_request.PageAddress =
1496         cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1497         (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1498     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1499     r = _config_request(ioc, &mpi_request, mpi_reply,
1500         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1501         sizeof(*config_page));
1502  out:
1503     return r;
1504 }
1505 
1506 /**
1507  * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1508  * @ioc: per adapter object
1509  * @mpi_reply: reply mf payload returned from firmware
1510  * @config_page: contents of the config page
1511  * @form: GET_NEXT_HANDLE or HANDLE
1512  * @handle: expander handle
1513  * Context: sleep.
1514  *
1515  * Return: 0 for success, non-zero for failure.
1516  */
1517 int
1518 mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1519     *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1520 {
1521     Mpi2ConfigRequest_t mpi_request;
1522     int r;
1523 
1524     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1525     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1526     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1527     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1528     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1529     mpi_request.Header.PageNumber = 0;
1530     mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1531     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1532     r = _config_request(ioc, &mpi_request, mpi_reply,
1533         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1534     if (r)
1535         goto out;
1536 
1537     mpi_request.PageAddress = cpu_to_le32(form | handle);
1538     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1539     r = _config_request(ioc, &mpi_request, mpi_reply,
1540         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1541         sizeof(*config_page));
1542  out:
1543     return r;
1544 }
1545 
1546 /**
1547  * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1548  * @ioc: per adapter object
1549  * @mpi_reply: reply mf payload returned from firmware
1550  * @config_page: contents of the config page
1551  * @phy_number: phy number
1552  * Context: sleep.
1553  *
1554  * Return: 0 for success, non-zero for failure.
1555  */
1556 int
1557 mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1558     *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1559 {
1560     Mpi2ConfigRequest_t mpi_request;
1561     int r;
1562 
1563     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1564     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1565     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1566     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1567     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1568     mpi_request.Header.PageNumber = 0;
1569     mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1570     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1571     r = _config_request(ioc, &mpi_request, mpi_reply,
1572         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1573     if (r)
1574         goto out;
1575 
1576     mpi_request.PageAddress =
1577         cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1578     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1579     r = _config_request(ioc, &mpi_request, mpi_reply,
1580         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1581         sizeof(*config_page));
1582  out:
1583     return r;
1584 }
1585 
1586 /**
1587  * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1588  * @ioc: per adapter object
1589  * @mpi_reply: reply mf payload returned from firmware
1590  * @config_page: contents of the config page
1591  * @phy_number: phy number
1592  * Context: sleep.
1593  *
1594  * Return: 0 for success, non-zero for failure.
1595  */
1596 int
1597 mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1598     *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1599 {
1600     Mpi2ConfigRequest_t mpi_request;
1601     int r;
1602 
1603     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1604     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1605     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1606     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1607     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1608     mpi_request.Header.PageNumber = 1;
1609     mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1610     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1611     r = _config_request(ioc, &mpi_request, mpi_reply,
1612         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1613     if (r)
1614         goto out;
1615 
1616     mpi_request.PageAddress =
1617         cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1618     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1619     r = _config_request(ioc, &mpi_request, mpi_reply,
1620         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1621         sizeof(*config_page));
1622  out:
1623     return r;
1624 }
1625 
1626 /**
1627  * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1628  * @ioc: per adapter object
1629  * @mpi_reply: reply mf payload returned from firmware
1630  * @config_page: contents of the config page
1631  * @form: GET_NEXT_HANDLE or HANDLE
1632  * @handle: volume handle
1633  * Context: sleep.
1634  *
1635  * Return: 0 for success, non-zero for failure.
1636  */
1637 int
1638 mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1639     Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1640     u32 handle)
1641 {
1642     Mpi2ConfigRequest_t mpi_request;
1643     int r;
1644 
1645     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1646     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1647     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1648     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1649     mpi_request.Header.PageNumber = 1;
1650     mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1651     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1652     r = _config_request(ioc, &mpi_request, mpi_reply,
1653         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1654     if (r)
1655         goto out;
1656 
1657     mpi_request.PageAddress = cpu_to_le32(form | handle);
1658     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1659     r = _config_request(ioc, &mpi_request, mpi_reply,
1660         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1661         sizeof(*config_page));
1662  out:
1663     return r;
1664 }
1665 
1666 /**
1667  * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1668  * @ioc: per adapter object
1669  * @handle: volume handle
1670  * @num_pds: returns pds count
1671  * Context: sleep.
1672  *
1673  * Return: 0 for success, non-zero for failure.
1674  */
1675 int
1676 mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1677     u8 *num_pds)
1678 {
1679     Mpi2ConfigRequest_t mpi_request;
1680     Mpi2RaidVolPage0_t config_page;
1681     Mpi2ConfigReply_t mpi_reply;
1682     int r;
1683     u16 ioc_status;
1684 
1685     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1686     *num_pds = 0;
1687     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1688     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1689     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1690     mpi_request.Header.PageNumber = 0;
1691     mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1692     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1693     r = _config_request(ioc, &mpi_request, &mpi_reply,
1694         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1695     if (r)
1696         goto out;
1697 
1698     mpi_request.PageAddress =
1699         cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1700     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1701     r = _config_request(ioc, &mpi_request, &mpi_reply,
1702         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1703         sizeof(Mpi2RaidVolPage0_t));
1704     if (!r) {
1705         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1706             MPI2_IOCSTATUS_MASK;
1707         if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1708             *num_pds = config_page.NumPhysDisks;
1709     }
1710 
1711  out:
1712     return r;
1713 }
1714 
1715 /**
1716  * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1717  * @ioc: per adapter object
1718  * @mpi_reply: reply mf payload returned from firmware
1719  * @config_page: contents of the config page
1720  * @form: GET_NEXT_HANDLE or HANDLE
1721  * @handle: volume handle
1722  * @sz: size of buffer passed in config_page
1723  * Context: sleep.
1724  *
1725  * Return: 0 for success, non-zero for failure.
1726  */
1727 int
1728 mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1729     Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1730     u32 handle, u16 sz)
1731 {
1732     Mpi2ConfigRequest_t mpi_request;
1733     int r;
1734 
1735     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1736     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1737     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1738     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1739     mpi_request.Header.PageNumber = 0;
1740     mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1741     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1742     r = _config_request(ioc, &mpi_request, mpi_reply,
1743         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1744     if (r)
1745         goto out;
1746 
1747     mpi_request.PageAddress = cpu_to_le32(form | handle);
1748     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1749     r = _config_request(ioc, &mpi_request, mpi_reply,
1750         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1751  out:
1752     return r;
1753 }
1754 
1755 /**
1756  * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1757  * @ioc: per adapter object
1758  * @mpi_reply: reply mf payload returned from firmware
1759  * @config_page: contents of the config page
1760  * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1761  * @form_specific: specific to the form
1762  * Context: sleep.
1763  *
1764  * Return: 0 for success, non-zero for failure.
1765  */
1766 int
1767 mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1768     *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1769     u32 form_specific)
1770 {
1771     Mpi2ConfigRequest_t mpi_request;
1772     int r;
1773 
1774     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1775     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1776     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1777     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1778     mpi_request.Header.PageNumber = 0;
1779     mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1780     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1781     r = _config_request(ioc, &mpi_request, mpi_reply,
1782         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1783     if (r)
1784         goto out;
1785 
1786     mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1787     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1788     r = _config_request(ioc, &mpi_request, mpi_reply,
1789         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1790         sizeof(*config_page));
1791  out:
1792     return r;
1793 }
1794 
1795 /**
1796  * mpt3sas_config_get_driver_trigger_pg0 - obtain driver trigger page 0
1797  * @ioc: per adapter object
1798  * @mpi_reply: reply mf payload returned from firmware
1799  * @config_page: contents of the config page
1800  * Context: sleep.
1801  *
1802  * Returns 0 for success, non-zero for failure.
1803  */
1804 int
1805 mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1806     Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1807 {
1808     Mpi2ConfigRequest_t mpi_request;
1809     int r;
1810 
1811     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1812     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1813     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1814     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1815     mpi_request.ExtPageType =
1816         MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1817     mpi_request.Header.PageNumber = 0;
1818     mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1819     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1820     r = _config_request(ioc, &mpi_request, mpi_reply,
1821         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1822     if (r)
1823         goto out;
1824 
1825     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1826     r = _config_request(ioc, &mpi_request, mpi_reply,
1827         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1828         sizeof(*config_page));
1829  out:
1830     return r;
1831 }
1832 
1833 /**
1834  * _config_set_driver_trigger_pg0 - write driver trigger page 0
1835  * @ioc: per adapter object
1836  * @mpi_reply: reply mf payload returned from firmware
1837  * @config_page: contents of the config page
1838  * Context: sleep.
1839  *
1840  * Returns 0 for success, non-zero for failure.
1841  */
1842 static int
1843 _config_set_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1844     Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1845 {
1846     Mpi2ConfigRequest_t mpi_request;
1847     int r;
1848 
1849     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1850     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1851     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1852     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1853     mpi_request.ExtPageType =
1854         MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1855     mpi_request.Header.PageNumber = 0;
1856     mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1857     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1858     r = _config_request(ioc, &mpi_request, mpi_reply,
1859         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1860     if (r)
1861         goto out;
1862 
1863     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1864     _config_request(ioc, &mpi_request, mpi_reply,
1865         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1866         sizeof(*config_page));
1867     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1868     r = _config_request(ioc, &mpi_request, mpi_reply,
1869         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1870         sizeof(*config_page));
1871  out:
1872     return r;
1873 }
1874 
1875 /**
1876  * mpt3sas_config_update_driver_trigger_pg0 - update driver trigger page 0
1877  * @ioc: per adapter object
1878  * @trigger_flag: trigger type bit map
1879  * @set: set ot clear trigger values
1880  * Context: sleep.
1881  *
1882  * Returns 0 for success, non-zero for failure.
1883  */
1884 static int
1885 mpt3sas_config_update_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1886     u16 trigger_flag, bool set)
1887 {
1888     Mpi26DriverTriggerPage0_t tg_pg0;
1889     Mpi2ConfigReply_t mpi_reply;
1890     int rc;
1891     u16 flags, ioc_status;
1892 
1893     rc = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
1894     if (rc)
1895         return rc;
1896     ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1897         MPI2_IOCSTATUS_MASK;
1898     if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1899         dcprintk(ioc,
1900             ioc_err(ioc,
1901             "%s: Failed to get trigger pg0, ioc_status(0x%04x)\n",
1902             __func__, ioc_status));
1903         return -EFAULT;
1904     }
1905 
1906     if (set)
1907         flags = le16_to_cpu(tg_pg0.TriggerFlags) | trigger_flag;
1908     else
1909         flags = le16_to_cpu(tg_pg0.TriggerFlags) & ~trigger_flag;
1910 
1911     tg_pg0.TriggerFlags = cpu_to_le16(flags);
1912 
1913     rc = _config_set_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
1914     if (rc)
1915         return rc;
1916     ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1917         MPI2_IOCSTATUS_MASK;
1918     if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1919         dcprintk(ioc,
1920             ioc_err(ioc,
1921             "%s: Failed to update trigger pg0, ioc_status(0x%04x)\n",
1922             __func__, ioc_status));
1923         return -EFAULT;
1924     }
1925 
1926     return 0;
1927 }
1928 
1929 /**
1930  * mpt3sas_config_get_driver_trigger_pg1 - obtain driver trigger page 1
1931  * @ioc: per adapter object
1932  * @mpi_reply: reply mf payload returned from firmware
1933  * @config_page: contents of the config page
1934  * Context: sleep.
1935  *
1936  * Returns 0 for success, non-zero for failure.
1937  */
1938 int
1939 mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
1940     Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
1941 {
1942     Mpi2ConfigRequest_t mpi_request;
1943     int r;
1944 
1945     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1946     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1947     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1948     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1949     mpi_request.ExtPageType =
1950         MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1951     mpi_request.Header.PageNumber = 1;
1952     mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
1953     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1954     r = _config_request(ioc, &mpi_request, mpi_reply,
1955         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1956     if (r)
1957         goto out;
1958 
1959     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1960     r = _config_request(ioc, &mpi_request, mpi_reply,
1961         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1962         sizeof(*config_page));
1963  out:
1964     return r;
1965 }
1966 
1967 /**
1968  * _config_set_driver_trigger_pg1 - write driver trigger page 1
1969  * @ioc: per adapter object
1970  * @mpi_reply: reply mf payload returned from firmware
1971  * @config_page: contents of the config page
1972  * Context: sleep.
1973  *
1974  * Returns 0 for success, non-zero for failure.
1975  */
1976 static int
1977 _config_set_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
1978     Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
1979 {
1980     Mpi2ConfigRequest_t mpi_request;
1981     int r;
1982 
1983     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1984     mpi_request.Function = MPI2_FUNCTION_CONFIG;
1985     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1986     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1987     mpi_request.ExtPageType =
1988         MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1989     mpi_request.Header.PageNumber = 1;
1990     mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
1991     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1992     r = _config_request(ioc, &mpi_request, mpi_reply,
1993         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1994     if (r)
1995         goto out;
1996 
1997     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1998     _config_request(ioc, &mpi_request, mpi_reply,
1999         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2000         sizeof(*config_page));
2001     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2002     r = _config_request(ioc, &mpi_request, mpi_reply,
2003         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2004         sizeof(*config_page));
2005  out:
2006     return r;
2007 }
2008 
2009 /**
2010  * mpt3sas_config_update_driver_trigger_pg1 - update driver trigger page 1
2011  * @ioc: per adapter object
2012  * @master_tg: Master trigger bit map
2013  * @set: set ot clear trigger values
2014  * Context: sleep.
2015  *
2016  * Returns 0 for success, non-zero for failure.
2017  */
2018 int
2019 mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
2020     struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set)
2021 {
2022     Mpi26DriverTriggerPage1_t tg_pg1;
2023     Mpi2ConfigReply_t mpi_reply;
2024     int rc;
2025     u16 ioc_status;
2026 
2027     rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2028         MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, set);
2029     if (rc)
2030         return rc;
2031 
2032     rc = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
2033     if (rc)
2034         goto out;
2035 
2036     ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2037         MPI2_IOCSTATUS_MASK;
2038     if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2039         dcprintk(ioc,
2040             ioc_err(ioc,
2041             "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
2042             __func__, ioc_status));
2043         rc = -EFAULT;
2044         goto out;
2045     }
2046 
2047     if (set) {
2048         tg_pg1.NumMasterTrigger = cpu_to_le16(1);
2049         tg_pg1.MasterTriggers[0].MasterTriggerFlags = cpu_to_le32(
2050             master_tg->MasterData);
2051     } else {
2052         tg_pg1.NumMasterTrigger = 0;
2053         tg_pg1.MasterTriggers[0].MasterTriggerFlags = 0;
2054     }
2055 
2056     rc = _config_set_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
2057     if (rc)
2058         goto out;
2059 
2060     ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2061         MPI2_IOCSTATUS_MASK;
2062     if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2063         dcprintk(ioc,
2064             ioc_err(ioc,
2065             "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
2066             __func__, ioc_status));
2067         rc = -EFAULT;
2068         goto out;
2069     }
2070 
2071     return 0;
2072 
2073 out:
2074     mpt3sas_config_update_driver_trigger_pg0(ioc,
2075         MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, !set);
2076 
2077     return rc;
2078 }
2079 
2080 /**
2081  * mpt3sas_config_get_driver_trigger_pg2 - obtain driver trigger page 2
2082  * @ioc: per adapter object
2083  * @mpi_reply: reply mf payload returned from firmware
2084  * @config_page: contents of the config page
2085  * Context: sleep.
2086  *
2087  * Returns 0 for success, non-zero for failure.
2088  */
2089 int
2090 mpt3sas_config_get_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2091     Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2092 {
2093     Mpi2ConfigRequest_t mpi_request;
2094     int r;
2095 
2096     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2097     mpi_request.Function = MPI2_FUNCTION_CONFIG;
2098     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2099     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2100     mpi_request.ExtPageType =
2101         MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2102     mpi_request.Header.PageNumber = 2;
2103     mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2104     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2105     r = _config_request(ioc, &mpi_request, mpi_reply,
2106         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2107     if (r)
2108         goto out;
2109 
2110     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2111     r = _config_request(ioc, &mpi_request, mpi_reply,
2112         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2113         sizeof(*config_page));
2114  out:
2115     return r;
2116 }
2117 
2118 /**
2119  * _config_set_driver_trigger_pg2 - write driver trigger page 2
2120  * @ioc: per adapter object
2121  * @mpi_reply: reply mf payload returned from firmware
2122  * @config_page: contents of the config page
2123  * Context: sleep.
2124  *
2125  * Returns 0 for success, non-zero for failure.
2126  */
2127 static int
2128 _config_set_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2129     Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2130 {
2131     Mpi2ConfigRequest_t mpi_request;
2132     int r;
2133 
2134     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2135     mpi_request.Function = MPI2_FUNCTION_CONFIG;
2136     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2137     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2138     mpi_request.ExtPageType =
2139         MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2140     mpi_request.Header.PageNumber = 2;
2141     mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2142     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2143     r = _config_request(ioc, &mpi_request, mpi_reply,
2144         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2145     if (r)
2146         goto out;
2147 
2148     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2149     _config_request(ioc, &mpi_request, mpi_reply,
2150         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2151         sizeof(*config_page));
2152     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2153     r = _config_request(ioc, &mpi_request, mpi_reply,
2154         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2155         sizeof(*config_page));
2156  out:
2157     return r;
2158 }
2159 
2160 /**
2161  * mpt3sas_config_update_driver_trigger_pg2 - update driver trigger page 2
2162  * @ioc: per adapter object
2163  * @event_tg: list of Event Triggers
2164  * @set: set ot clear trigger values
2165  * Context: sleep.
2166  *
2167  * Returns 0 for success, non-zero for failure.
2168  */
2169 int
2170 mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2171     struct SL_WH_EVENT_TRIGGERS_T *event_tg, bool set)
2172 {
2173     Mpi26DriverTriggerPage2_t tg_pg2;
2174     Mpi2ConfigReply_t mpi_reply;
2175     int rc, i, count;
2176     u16 ioc_status;
2177 
2178     rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2179         MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, set);
2180     if (rc)
2181         return rc;
2182 
2183     rc = mpt3sas_config_get_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2184     if (rc)
2185         goto out;
2186 
2187     ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2188         MPI2_IOCSTATUS_MASK;
2189     if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2190         dcprintk(ioc,
2191             ioc_err(ioc,
2192             "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2193             __func__, ioc_status));
2194         rc = -EFAULT;
2195         goto out;
2196     }
2197 
2198     if (set) {
2199         count = event_tg->ValidEntries;
2200         tg_pg2.NumMPIEventTrigger = cpu_to_le16(count);
2201         for (i = 0; i < count; i++) {
2202             tg_pg2.MPIEventTriggers[i].MPIEventCode =
2203                 cpu_to_le16(
2204                 event_tg->EventTriggerEntry[i].EventValue);
2205             tg_pg2.MPIEventTriggers[i].MPIEventCodeSpecific =
2206                 cpu_to_le16(
2207                 event_tg->EventTriggerEntry[i].LogEntryQualifier);
2208         }
2209     } else {
2210         tg_pg2.NumMPIEventTrigger = 0;
2211         memset(&tg_pg2.MPIEventTriggers[0], 0,
2212             NUM_VALID_ENTRIES * sizeof(
2213             MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY));
2214     }
2215 
2216     rc = _config_set_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2217     if (rc)
2218         goto out;
2219 
2220     ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2221         MPI2_IOCSTATUS_MASK;
2222     if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2223         dcprintk(ioc,
2224             ioc_err(ioc,
2225             "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2226             __func__, ioc_status));
2227         rc = -EFAULT;
2228         goto out;
2229     }
2230 
2231     return 0;
2232 
2233 out:
2234     mpt3sas_config_update_driver_trigger_pg0(ioc,
2235         MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, !set);
2236 
2237     return rc;
2238 }
2239 
2240 /**
2241  * mpt3sas_config_get_driver_trigger_pg3 - obtain driver trigger page 3
2242  * @ioc: per adapter object
2243  * @mpi_reply: reply mf payload returned from firmware
2244  * @config_page: contents of the config page
2245  * Context: sleep.
2246  *
2247  * Returns 0 for success, non-zero for failure.
2248  */
2249 int
2250 mpt3sas_config_get_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2251     Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2252 {
2253     Mpi2ConfigRequest_t mpi_request;
2254     int r;
2255 
2256     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2257     mpi_request.Function = MPI2_FUNCTION_CONFIG;
2258     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2259     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2260     mpi_request.ExtPageType =
2261         MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2262     mpi_request.Header.PageNumber = 3;
2263     mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2264     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2265     r = _config_request(ioc, &mpi_request, mpi_reply,
2266         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2267     if (r)
2268         goto out;
2269 
2270     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2271     r = _config_request(ioc, &mpi_request, mpi_reply,
2272         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2273         sizeof(*config_page));
2274  out:
2275     return r;
2276 }
2277 
2278 /**
2279  * _config_set_driver_trigger_pg3 - write driver trigger page 3
2280  * @ioc: per adapter object
2281  * @mpi_reply: reply mf payload returned from firmware
2282  * @config_page: contents of the config page
2283  * Context: sleep.
2284  *
2285  * Returns 0 for success, non-zero for failure.
2286  */
2287 static int
2288 _config_set_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2289     Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2290 {
2291     Mpi2ConfigRequest_t mpi_request;
2292     int r;
2293 
2294     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2295     mpi_request.Function = MPI2_FUNCTION_CONFIG;
2296     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2297     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2298     mpi_request.ExtPageType =
2299         MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2300     mpi_request.Header.PageNumber = 3;
2301     mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2302     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2303     r = _config_request(ioc, &mpi_request, mpi_reply,
2304         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2305     if (r)
2306         goto out;
2307 
2308     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2309     _config_request(ioc, &mpi_request, mpi_reply,
2310         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2311         sizeof(*config_page));
2312     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2313     r = _config_request(ioc, &mpi_request, mpi_reply,
2314         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2315         sizeof(*config_page));
2316  out:
2317     return r;
2318 }
2319 
2320 /**
2321  * mpt3sas_config_update_driver_trigger_pg3 - update driver trigger page 3
2322  * @ioc: per adapter object
2323  * @scsi_tg: scsi trigger list
2324  * @set: set ot clear trigger values
2325  * Context: sleep.
2326  *
2327  * Returns 0 for success, non-zero for failure.
2328  */
2329 int
2330 mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2331     struct SL_WH_SCSI_TRIGGERS_T *scsi_tg, bool set)
2332 {
2333     Mpi26DriverTriggerPage3_t tg_pg3;
2334     Mpi2ConfigReply_t mpi_reply;
2335     int rc, i, count;
2336     u16 ioc_status;
2337 
2338     rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2339         MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, set);
2340     if (rc)
2341         return rc;
2342 
2343     rc = mpt3sas_config_get_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2344     if (rc)
2345         goto out;
2346 
2347     ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2348         MPI2_IOCSTATUS_MASK;
2349     if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2350         dcprintk(ioc,
2351             ioc_err(ioc,
2352             "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2353             __func__, ioc_status));
2354         return -EFAULT;
2355     }
2356 
2357     if (set) {
2358         count = scsi_tg->ValidEntries;
2359         tg_pg3.NumSCSISenseTrigger = cpu_to_le16(count);
2360         for (i = 0; i < count; i++) {
2361             tg_pg3.SCSISenseTriggers[i].ASCQ =
2362                 scsi_tg->SCSITriggerEntry[i].ASCQ;
2363             tg_pg3.SCSISenseTriggers[i].ASC =
2364                 scsi_tg->SCSITriggerEntry[i].ASC;
2365             tg_pg3.SCSISenseTriggers[i].SenseKey =
2366                 scsi_tg->SCSITriggerEntry[i].SenseKey;
2367         }
2368     } else {
2369         tg_pg3.NumSCSISenseTrigger = 0;
2370         memset(&tg_pg3.SCSISenseTriggers[0], 0,
2371             NUM_VALID_ENTRIES * sizeof(
2372             MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY));
2373     }
2374 
2375     rc = _config_set_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2376     if (rc)
2377         goto out;
2378 
2379     ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2380         MPI2_IOCSTATUS_MASK;
2381     if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2382         dcprintk(ioc,
2383             ioc_err(ioc,
2384             "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2385              __func__, ioc_status));
2386         return -EFAULT;
2387     }
2388 
2389     return 0;
2390 out:
2391     mpt3sas_config_update_driver_trigger_pg0(ioc,
2392         MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, !set);
2393 
2394     return rc;
2395 }
2396 
2397 /**
2398  * mpt3sas_config_get_driver_trigger_pg4 - obtain driver trigger page 4
2399  * @ioc: per adapter object
2400  * @mpi_reply: reply mf payload returned from firmware
2401  * @config_page: contents of the config page
2402  * Context: sleep.
2403  *
2404  * Returns 0 for success, non-zero for failure.
2405  */
2406 int
2407 mpt3sas_config_get_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2408     Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2409 {
2410     Mpi2ConfigRequest_t mpi_request;
2411     int r;
2412 
2413     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2414     mpi_request.Function = MPI2_FUNCTION_CONFIG;
2415     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2416     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2417     mpi_request.ExtPageType =
2418         MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2419     mpi_request.Header.PageNumber = 4;
2420     mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2421     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2422     r = _config_request(ioc, &mpi_request, mpi_reply,
2423         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2424     if (r)
2425         goto out;
2426 
2427     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2428     r = _config_request(ioc, &mpi_request, mpi_reply,
2429         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2430         sizeof(*config_page));
2431  out:
2432     return r;
2433 }
2434 
2435 /**
2436  * _config_set_driver_trigger_pg4 - write driver trigger page 4
2437  * @ioc: per adapter object
2438  * @mpi_reply: reply mf payload returned from firmware
2439  * @config_page: contents of the config page
2440  * Context: sleep.
2441  *
2442  * Returns 0 for success, non-zero for failure.
2443  */
2444 static int
2445 _config_set_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2446     Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2447 {
2448     Mpi2ConfigRequest_t mpi_request;
2449     int r;
2450 
2451     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2452     mpi_request.Function = MPI2_FUNCTION_CONFIG;
2453     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2454     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2455     mpi_request.ExtPageType =
2456         MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2457     mpi_request.Header.PageNumber = 4;
2458     mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2459     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2460     r = _config_request(ioc, &mpi_request, mpi_reply,
2461         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2462     if (r)
2463         goto out;
2464 
2465     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2466     _config_request(ioc, &mpi_request, mpi_reply,
2467         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2468         sizeof(*config_page));
2469     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2470     r = _config_request(ioc, &mpi_request, mpi_reply,
2471         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2472         sizeof(*config_page));
2473  out:
2474     return r;
2475 }
2476 
2477 /**
2478  * mpt3sas_config_update_driver_trigger_pg4 - update driver trigger page 4
2479  * @ioc: per adapter object
2480  * @mpi_tg: mpi trigger list
2481  * @set: set ot clear trigger values
2482  * Context: sleep.
2483  *
2484  * Returns 0 for success, non-zero for failure.
2485  */
2486 int
2487 mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2488     struct SL_WH_MPI_TRIGGERS_T *mpi_tg, bool set)
2489 {
2490     Mpi26DriverTriggerPage4_t tg_pg4;
2491     Mpi2ConfigReply_t mpi_reply;
2492     int rc, i, count;
2493     u16 ioc_status;
2494 
2495     rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2496         MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, set);
2497     if (rc)
2498         return rc;
2499 
2500     rc = mpt3sas_config_get_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2501     if (rc)
2502         goto out;
2503 
2504     ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2505         MPI2_IOCSTATUS_MASK;
2506     if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2507         dcprintk(ioc,
2508             ioc_err(ioc,
2509             "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2510             __func__, ioc_status));
2511         rc = -EFAULT;
2512         goto out;
2513     }
2514 
2515     if (set) {
2516         count = mpi_tg->ValidEntries;
2517         tg_pg4.NumIOCStatusLogInfoTrigger = cpu_to_le16(count);
2518         for (i = 0; i < count; i++) {
2519             tg_pg4.IOCStatusLoginfoTriggers[i].IOCStatus =
2520                 cpu_to_le16(mpi_tg->MPITriggerEntry[i].IOCStatus);
2521             tg_pg4.IOCStatusLoginfoTriggers[i].LogInfo =
2522                 cpu_to_le32(mpi_tg->MPITriggerEntry[i].IocLogInfo);
2523         }
2524     } else {
2525         tg_pg4.NumIOCStatusLogInfoTrigger = 0;
2526         memset(&tg_pg4.IOCStatusLoginfoTriggers[0], 0,
2527             NUM_VALID_ENTRIES * sizeof(
2528             MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY));
2529     }
2530 
2531     rc = _config_set_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2532     if (rc)
2533         goto out;
2534 
2535     ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2536         MPI2_IOCSTATUS_MASK;
2537     if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2538         dcprintk(ioc,
2539             ioc_err(ioc,
2540             "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2541             __func__, ioc_status));
2542         rc = -EFAULT;
2543         goto out;
2544     }
2545 
2546     return 0;
2547 
2548 out:
2549     mpt3sas_config_update_driver_trigger_pg0(ioc,
2550         MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, !set);
2551 
2552     return rc;
2553 }
2554 
2555 /**
2556  * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
2557  * raid components
2558  * @ioc: per adapter object
2559  * @pd_handle: phys disk handle
2560  * @volume_handle: volume handle
2561  * Context: sleep.
2562  *
2563  * Return: 0 for success, non-zero for failure.
2564  */
2565 int
2566 mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
2567     u16 *volume_handle)
2568 {
2569     Mpi2RaidConfigurationPage0_t *config_page = NULL;
2570     Mpi2ConfigRequest_t mpi_request;
2571     Mpi2ConfigReply_t mpi_reply;
2572     int r, i, config_page_sz;
2573     u16 ioc_status;
2574     int config_num;
2575     u16 element_type;
2576     u16 phys_disk_dev_handle;
2577 
2578     *volume_handle = 0;
2579     memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2580     mpi_request.Function = MPI2_FUNCTION_CONFIG;
2581     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2582     mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2583     mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
2584     mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
2585     mpi_request.Header.PageNumber = 0;
2586     ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2587     r = _config_request(ioc, &mpi_request, &mpi_reply,
2588         MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2589     if (r)
2590         goto out;
2591 
2592     mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2593     config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
2594     config_page = kmalloc(config_page_sz, GFP_KERNEL);
2595     if (!config_page) {
2596         r = -1;
2597         goto out;
2598     }
2599 
2600     config_num = 0xff;
2601     while (1) {
2602         mpi_request.PageAddress = cpu_to_le32(config_num +
2603             MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
2604         r = _config_request(ioc, &mpi_request, &mpi_reply,
2605             MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2606             config_page_sz);
2607         if (r)
2608             goto out;
2609         r = -1;
2610         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2611             MPI2_IOCSTATUS_MASK;
2612         if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
2613             goto out;
2614         for (i = 0; i < config_page->NumElements; i++) {
2615             element_type = le16_to_cpu(config_page->
2616                 ConfigElement[i].ElementFlags) &
2617                 MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
2618             if (element_type ==
2619                 MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
2620                 element_type ==
2621                 MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
2622                 phys_disk_dev_handle =
2623                     le16_to_cpu(config_page->ConfigElement[i].
2624                     PhysDiskDevHandle);
2625                 if (phys_disk_dev_handle == pd_handle) {
2626                     *volume_handle =
2627                         le16_to_cpu(config_page->
2628                         ConfigElement[i].VolDevHandle);
2629                     r = 0;
2630                     goto out;
2631                 }
2632             } else if (element_type ==
2633                 MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
2634                 *volume_handle = 0;
2635                 r = 0;
2636                 goto out;
2637             }
2638         }
2639         config_num = config_page->ConfigNum;
2640     }
2641  out:
2642     kfree(config_page);
2643     return r;
2644 }
2645 
2646 /**
2647  * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
2648  * @ioc: per adapter object
2649  * @volume_handle: volume handle
2650  * @wwid: volume wwid
2651  * Context: sleep.
2652  *
2653  * Return: 0 for success, non-zero for failure.
2654  */
2655 int
2656 mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
2657     u64 *wwid)
2658 {
2659     Mpi2ConfigReply_t mpi_reply;
2660     Mpi2RaidVolPage1_t raid_vol_pg1;
2661 
2662     *wwid = 0;
2663     if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
2664         &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
2665         volume_handle))) {
2666         *wwid = le64_to_cpu(raid_vol_pg1.WWID);
2667         return 0;
2668     } else
2669         return -1;
2670 }