root/drivers/scsi/mpt3sas/mpt3sas_config.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _config_display_some_debug
  2. _config_alloc_config_dma_memory
  3. _config_free_config_dma_memory
  4. mpt3sas_config_done
  5. _config_request
  6. mpt3sas_config_get_manufacturing_pg0
  7. mpt3sas_config_get_manufacturing_pg7
  8. mpt3sas_config_get_manufacturing_pg10
  9. mpt3sas_config_get_manufacturing_pg11
  10. mpt3sas_config_set_manufacturing_pg11
  11. mpt3sas_config_get_bios_pg2
  12. mpt3sas_config_get_bios_pg3
  13. mpt3sas_config_get_iounit_pg0
  14. mpt3sas_config_get_iounit_pg1
  15. mpt3sas_config_set_iounit_pg1
  16. mpt3sas_config_get_iounit_pg3
  17. mpt3sas_config_get_iounit_pg8
  18. mpt3sas_config_get_ioc_pg8
  19. mpt3sas_config_get_ioc_pg1
  20. mpt3sas_config_set_ioc_pg1
  21. mpt3sas_config_get_sas_device_pg0
  22. mpt3sas_config_get_sas_device_pg1
  23. mpt3sas_config_get_pcie_device_pg0
  24. mpt3sas_config_get_pcie_device_pg2
  25. mpt3sas_config_get_number_hba_phys
  26. mpt3sas_config_get_sas_iounit_pg0
  27. mpt3sas_config_get_sas_iounit_pg1
  28. mpt3sas_config_set_sas_iounit_pg1
  29. mpt3sas_config_get_expander_pg0
  30. mpt3sas_config_get_expander_pg1
  31. mpt3sas_config_get_enclosure_pg0
  32. mpt3sas_config_get_phy_pg0
  33. mpt3sas_config_get_phy_pg1
  34. mpt3sas_config_get_raid_volume_pg1
  35. mpt3sas_config_get_number_pds
  36. mpt3sas_config_get_raid_volume_pg0
  37. mpt3sas_config_get_phys_disk_pg0
  38. mpt3sas_config_get_volume_handle
  39. mpt3sas_config_get_volume_wwid

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

/* [<][>][^][v][top][bottom][index][help] */