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