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