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_iounit_pg1 - obtain pcie iounit page 1
1173 * @ioc: per adapter object
1174 * @mpi_reply: reply mf payload returned from firmware
1175 * @config_page: contents of the config page
1176 * @sz: size of buffer passed in config_page
1177 * Context: sleep.
1178 *
1179 * Returns 0 for success, non-zero for failure.
1180 */
1181int
1182mpt3sas_config_get_pcie_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1183        Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeIOUnitPage1_t *config_page,
1184        u16 sz)
1185{
1186        Mpi2ConfigRequest_t mpi_request;
1187        int r;
1188
1189        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1190        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1191        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1192        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1193        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT;
1194        mpi_request.Header.PageVersion = MPI26_PCIEIOUNITPAGE1_PAGEVERSION;
1195        mpi_request.Header.PageNumber = 1;
1196        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1197        r = _config_request(ioc, &mpi_request, mpi_reply,
1198            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1199        if (r)
1200                goto out;
1201        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1202        r = _config_request(ioc, &mpi_request, mpi_reply,
1203            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1204out:
1205        return r;
1206}
1207
1208/**
1209 * mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
1210 * @ioc: per adapter object
1211 * @mpi_reply: reply mf payload returned from firmware
1212 * @config_page: contents of the config page
1213 * @form: GET_NEXT_HANDLE or HANDLE
1214 * @handle: device handle
1215 * Context: sleep.
1216 *
1217 * Return: 0 for success, non-zero for failure.
1218 */
1219int
1220mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
1221        Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
1222        u32 form, u32 handle)
1223{
1224        Mpi2ConfigRequest_t mpi_request;
1225        int r;
1226
1227        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1228        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1229        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1230        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1231        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1232        mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
1233        mpi_request.Header.PageNumber = 2;
1234        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1235        r = _config_request(ioc, &mpi_request, mpi_reply,
1236                        MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1237        if (r)
1238                goto out;
1239
1240        mpi_request.PageAddress = cpu_to_le32(form | handle);
1241        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1242        r = _config_request(ioc, &mpi_request, mpi_reply,
1243                        MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1244                        sizeof(*config_page));
1245out:
1246        return r;
1247}
1248
1249/**
1250 * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1251 * @ioc: per adapter object
1252 * @num_phys: pointer returned with the number of phys
1253 * Context: sleep.
1254 *
1255 * Return: 0 for success, non-zero for failure.
1256 */
1257int
1258mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1259{
1260        Mpi2ConfigRequest_t mpi_request;
1261        int r;
1262        u16 ioc_status;
1263        Mpi2ConfigReply_t mpi_reply;
1264        Mpi2SasIOUnitPage0_t config_page;
1265
1266        *num_phys = 0;
1267        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1268        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1269        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1270        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1271        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1272        mpi_request.Header.PageNumber = 0;
1273        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1274        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1275        r = _config_request(ioc, &mpi_request, &mpi_reply,
1276            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1277        if (r)
1278                goto out;
1279
1280        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1281        r = _config_request(ioc, &mpi_request, &mpi_reply,
1282            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1283            sizeof(Mpi2SasIOUnitPage0_t));
1284        if (!r) {
1285                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1286                    MPI2_IOCSTATUS_MASK;
1287                if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1288                        *num_phys = config_page.NumPhys;
1289        }
1290 out:
1291        return r;
1292}
1293
1294/**
1295 * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1296 * @ioc: per adapter object
1297 * @mpi_reply: reply mf payload returned from firmware
1298 * @config_page: contents of the config page
1299 * @sz: size of buffer passed in config_page
1300 * Context: sleep.
1301 *
1302 * Calling function should call config_get_number_hba_phys prior to
1303 * this function, so enough memory is allocated for config_page.
1304 *
1305 * Return: 0 for success, non-zero for failure.
1306 */
1307int
1308mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1309        Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1310        u16 sz)
1311{
1312        Mpi2ConfigRequest_t mpi_request;
1313        int r;
1314
1315        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1316        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1317        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1318        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1319        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1320        mpi_request.Header.PageNumber = 0;
1321        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1322        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1323        r = _config_request(ioc, &mpi_request, mpi_reply,
1324            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1325        if (r)
1326                goto out;
1327
1328        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1329        r = _config_request(ioc, &mpi_request, mpi_reply,
1330            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1331 out:
1332        return r;
1333}
1334
1335/**
1336 * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1337 * @ioc: per adapter object
1338 * @mpi_reply: reply mf payload returned from firmware
1339 * @config_page: contents of the config page
1340 * @sz: size of buffer passed in config_page
1341 * Context: sleep.
1342 *
1343 * Calling function should call config_get_number_hba_phys prior to
1344 * this function, so enough memory is allocated for config_page.
1345 *
1346 * Return: 0 for success, non-zero for failure.
1347 */
1348int
1349mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1350        Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1351        u16 sz)
1352{
1353        Mpi2ConfigRequest_t mpi_request;
1354        int r;
1355
1356        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1357        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1358        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1359        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1360        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1361        mpi_request.Header.PageNumber = 1;
1362        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1363        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1364        r = _config_request(ioc, &mpi_request, mpi_reply,
1365            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1366        if (r)
1367                goto out;
1368
1369        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1370        r = _config_request(ioc, &mpi_request, mpi_reply,
1371            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1372 out:
1373        return r;
1374}
1375
1376/**
1377 * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1378 * @ioc: per adapter object
1379 * @mpi_reply: reply mf payload returned from firmware
1380 * @config_page: contents of the config page
1381 * @sz: size of buffer passed in config_page
1382 * Context: sleep.
1383 *
1384 * Calling function should call config_get_number_hba_phys prior to
1385 * this function, so enough memory is allocated for config_page.
1386 *
1387 * Return: 0 for success, non-zero for failure.
1388 */
1389int
1390mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1391        Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1392        u16 sz)
1393{
1394        Mpi2ConfigRequest_t mpi_request;
1395        int r;
1396
1397        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1398        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1399        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1400        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1401        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1402        mpi_request.Header.PageNumber = 1;
1403        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1404        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1405        r = _config_request(ioc, &mpi_request, mpi_reply,
1406            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1407        if (r)
1408                goto out;
1409
1410        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1411        _config_request(ioc, &mpi_request, mpi_reply,
1412            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1413        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1414        r = _config_request(ioc, &mpi_request, mpi_reply,
1415            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1416 out:
1417        return r;
1418}
1419
1420/**
1421 * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1422 * @ioc: per adapter object
1423 * @mpi_reply: reply mf payload returned from firmware
1424 * @config_page: contents of the config page
1425 * @form: GET_NEXT_HANDLE or HANDLE
1426 * @handle: expander handle
1427 * Context: sleep.
1428 *
1429 * Return: 0 for success, non-zero for failure.
1430 */
1431int
1432mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1433        *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1434{
1435        Mpi2ConfigRequest_t mpi_request;
1436        int r;
1437
1438        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1439        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1440        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1441        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1442        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1443        mpi_request.Header.PageNumber = 0;
1444        mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1445        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1446        r = _config_request(ioc, &mpi_request, mpi_reply,
1447            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1448        if (r)
1449                goto out;
1450
1451        mpi_request.PageAddress = cpu_to_le32(form | handle);
1452        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1453        r = _config_request(ioc, &mpi_request, mpi_reply,
1454            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1455            sizeof(*config_page));
1456 out:
1457        return r;
1458}
1459
1460/**
1461 * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1462 * @ioc: per adapter object
1463 * @mpi_reply: reply mf payload returned from firmware
1464 * @config_page: contents of the config page
1465 * @phy_number: phy number
1466 * @handle: expander handle
1467 * Context: sleep.
1468 *
1469 * Return: 0 for success, non-zero for failure.
1470 */
1471int
1472mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1473        *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1474        u16 handle)
1475{
1476        Mpi2ConfigRequest_t mpi_request;
1477        int r;
1478
1479        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1480        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1481        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1482        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1483        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1484        mpi_request.Header.PageNumber = 1;
1485        mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1486        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1487        r = _config_request(ioc, &mpi_request, mpi_reply,
1488            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1489        if (r)
1490                goto out;
1491
1492        mpi_request.PageAddress =
1493            cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1494            (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1495        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1496        r = _config_request(ioc, &mpi_request, mpi_reply,
1497            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1498            sizeof(*config_page));
1499 out:
1500        return r;
1501}
1502
1503/**
1504 * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1505 * @ioc: per adapter object
1506 * @mpi_reply: reply mf payload returned from firmware
1507 * @config_page: contents of the config page
1508 * @form: GET_NEXT_HANDLE or HANDLE
1509 * @handle: expander handle
1510 * Context: sleep.
1511 *
1512 * Return: 0 for success, non-zero for failure.
1513 */
1514int
1515mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1516        *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1517{
1518        Mpi2ConfigRequest_t mpi_request;
1519        int r;
1520
1521        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1522        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1523        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1524        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1525        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1526        mpi_request.Header.PageNumber = 0;
1527        mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1528        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1529        r = _config_request(ioc, &mpi_request, mpi_reply,
1530            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1531        if (r)
1532                goto out;
1533
1534        mpi_request.PageAddress = cpu_to_le32(form | handle);
1535        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1536        r = _config_request(ioc, &mpi_request, mpi_reply,
1537            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1538            sizeof(*config_page));
1539 out:
1540        return r;
1541}
1542
1543/**
1544 * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1545 * @ioc: per adapter object
1546 * @mpi_reply: reply mf payload returned from firmware
1547 * @config_page: contents of the config page
1548 * @phy_number: phy number
1549 * Context: sleep.
1550 *
1551 * Return: 0 for success, non-zero for failure.
1552 */
1553int
1554mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1555        *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1556{
1557        Mpi2ConfigRequest_t mpi_request;
1558        int r;
1559
1560        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1561        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1562        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1563        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1564        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1565        mpi_request.Header.PageNumber = 0;
1566        mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1567        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1568        r = _config_request(ioc, &mpi_request, mpi_reply,
1569            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1570        if (r)
1571                goto out;
1572
1573        mpi_request.PageAddress =
1574            cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1575        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1576        r = _config_request(ioc, &mpi_request, mpi_reply,
1577            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1578            sizeof(*config_page));
1579 out:
1580        return r;
1581}
1582
1583/**
1584 * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1585 * @ioc: per adapter object
1586 * @mpi_reply: reply mf payload returned from firmware
1587 * @config_page: contents of the config page
1588 * @phy_number: phy number
1589 * Context: sleep.
1590 *
1591 * Return: 0 for success, non-zero for failure.
1592 */
1593int
1594mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1595        *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1596{
1597        Mpi2ConfigRequest_t mpi_request;
1598        int r;
1599
1600        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1601        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1602        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1603        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1604        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1605        mpi_request.Header.PageNumber = 1;
1606        mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1607        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1608        r = _config_request(ioc, &mpi_request, mpi_reply,
1609            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1610        if (r)
1611                goto out;
1612
1613        mpi_request.PageAddress =
1614            cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1615        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1616        r = _config_request(ioc, &mpi_request, mpi_reply,
1617            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1618            sizeof(*config_page));
1619 out:
1620        return r;
1621}
1622
1623/**
1624 * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1625 * @ioc: per adapter object
1626 * @mpi_reply: reply mf payload returned from firmware
1627 * @config_page: contents of the config page
1628 * @form: GET_NEXT_HANDLE or HANDLE
1629 * @handle: volume handle
1630 * Context: sleep.
1631 *
1632 * Return: 0 for success, non-zero for failure.
1633 */
1634int
1635mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1636        Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1637        u32 handle)
1638{
1639        Mpi2ConfigRequest_t mpi_request;
1640        int r;
1641
1642        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1643        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1644        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1645        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1646        mpi_request.Header.PageNumber = 1;
1647        mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1648        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1649        r = _config_request(ioc, &mpi_request, mpi_reply,
1650            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1651        if (r)
1652                goto out;
1653
1654        mpi_request.PageAddress = cpu_to_le32(form | handle);
1655        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1656        r = _config_request(ioc, &mpi_request, mpi_reply,
1657            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1658            sizeof(*config_page));
1659 out:
1660        return r;
1661}
1662
1663/**
1664 * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1665 * @ioc: per adapter object
1666 * @handle: volume handle
1667 * @num_pds: returns pds count
1668 * Context: sleep.
1669 *
1670 * Return: 0 for success, non-zero for failure.
1671 */
1672int
1673mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1674        u8 *num_pds)
1675{
1676        Mpi2ConfigRequest_t mpi_request;
1677        Mpi2RaidVolPage0_t config_page;
1678        Mpi2ConfigReply_t mpi_reply;
1679        int r;
1680        u16 ioc_status;
1681
1682        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1683        *num_pds = 0;
1684        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1685        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1686        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1687        mpi_request.Header.PageNumber = 0;
1688        mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1689        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1690        r = _config_request(ioc, &mpi_request, &mpi_reply,
1691            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1692        if (r)
1693                goto out;
1694
1695        mpi_request.PageAddress =
1696            cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1697        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1698        r = _config_request(ioc, &mpi_request, &mpi_reply,
1699            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1700            sizeof(Mpi2RaidVolPage0_t));
1701        if (!r) {
1702                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1703                    MPI2_IOCSTATUS_MASK;
1704                if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1705                        *num_pds = config_page.NumPhysDisks;
1706        }
1707
1708 out:
1709        return r;
1710}
1711
1712/**
1713 * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1714 * @ioc: per adapter object
1715 * @mpi_reply: reply mf payload returned from firmware
1716 * @config_page: contents of the config page
1717 * @form: GET_NEXT_HANDLE or HANDLE
1718 * @handle: volume handle
1719 * @sz: size of buffer passed in config_page
1720 * Context: sleep.
1721 *
1722 * Return: 0 for success, non-zero for failure.
1723 */
1724int
1725mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1726        Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1727        u32 handle, u16 sz)
1728{
1729        Mpi2ConfigRequest_t mpi_request;
1730        int r;
1731
1732        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1733        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1734        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1735        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1736        mpi_request.Header.PageNumber = 0;
1737        mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1738        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1739        r = _config_request(ioc, &mpi_request, mpi_reply,
1740            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1741        if (r)
1742                goto out;
1743
1744        mpi_request.PageAddress = cpu_to_le32(form | handle);
1745        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1746        r = _config_request(ioc, &mpi_request, mpi_reply,
1747            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1748 out:
1749        return r;
1750}
1751
1752/**
1753 * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1754 * @ioc: per adapter object
1755 * @mpi_reply: reply mf payload returned from firmware
1756 * @config_page: contents of the config page
1757 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1758 * @form_specific: specific to the form
1759 * Context: sleep.
1760 *
1761 * Return: 0 for success, non-zero for failure.
1762 */
1763int
1764mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1765        *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1766        u32 form_specific)
1767{
1768        Mpi2ConfigRequest_t mpi_request;
1769        int r;
1770
1771        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1772        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1773        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1774        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1775        mpi_request.Header.PageNumber = 0;
1776        mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1777        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1778        r = _config_request(ioc, &mpi_request, mpi_reply,
1779            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1780        if (r)
1781                goto out;
1782
1783        mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1784        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1785        r = _config_request(ioc, &mpi_request, mpi_reply,
1786            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1787            sizeof(*config_page));
1788 out:
1789        return r;
1790}
1791
1792/**
1793 * mpt3sas_config_get_driver_trigger_pg0 - obtain driver trigger page 0
1794 * @ioc: per adapter object
1795 * @mpi_reply: reply mf payload returned from firmware
1796 * @config_page: contents of the config page
1797 * Context: sleep.
1798 *
1799 * Returns 0 for success, non-zero for failure.
1800 */
1801int
1802mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1803        Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1804{
1805        Mpi2ConfigRequest_t mpi_request;
1806        int r;
1807
1808        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1809        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1810        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1811        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1812        mpi_request.ExtPageType =
1813            MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1814        mpi_request.Header.PageNumber = 0;
1815        mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1816        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1817        r = _config_request(ioc, &mpi_request, mpi_reply,
1818            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1819        if (r)
1820                goto out;
1821
1822        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1823        r = _config_request(ioc, &mpi_request, mpi_reply,
1824            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1825            sizeof(*config_page));
1826 out:
1827        return r;
1828}
1829
1830/**
1831 * _config_set_driver_trigger_pg0 - write driver trigger page 0
1832 * @ioc: per adapter object
1833 * @mpi_reply: reply mf payload returned from firmware
1834 * @config_page: contents of the config page
1835 * Context: sleep.
1836 *
1837 * Returns 0 for success, non-zero for failure.
1838 */
1839static int
1840_config_set_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1841        Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page)
1842{
1843        Mpi2ConfigRequest_t mpi_request;
1844        int r;
1845
1846        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1847        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1848        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1849        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1850        mpi_request.ExtPageType =
1851            MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1852        mpi_request.Header.PageNumber = 0;
1853        mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION;
1854        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1855        r = _config_request(ioc, &mpi_request, mpi_reply,
1856            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1857        if (r)
1858                goto out;
1859
1860        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1861        _config_request(ioc, &mpi_request, mpi_reply,
1862            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1863            sizeof(*config_page));
1864        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1865        r = _config_request(ioc, &mpi_request, mpi_reply,
1866            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1867            sizeof(*config_page));
1868 out:
1869        return r;
1870}
1871
1872/**
1873 * mpt3sas_config_update_driver_trigger_pg0 - update driver trigger page 0
1874 * @ioc: per adapter object
1875 * @trigger_flag: trigger type bit map
1876 * @set: set ot clear trigger values
1877 * Context: sleep.
1878 *
1879 * Returns 0 for success, non-zero for failure.
1880 */
1881static int
1882mpt3sas_config_update_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc,
1883        u16 trigger_flag, bool set)
1884{
1885        Mpi26DriverTriggerPage0_t tg_pg0;
1886        Mpi2ConfigReply_t mpi_reply;
1887        int rc;
1888        u16 flags, ioc_status;
1889
1890        rc = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
1891        if (rc)
1892                return rc;
1893        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1894            MPI2_IOCSTATUS_MASK;
1895        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1896                dcprintk(ioc,
1897                    ioc_err(ioc,
1898                    "%s: Failed to get trigger pg0, ioc_status(0x%04x)\n",
1899                    __func__, ioc_status));
1900                return -EFAULT;
1901        }
1902
1903        if (set)
1904                flags = le16_to_cpu(tg_pg0.TriggerFlags) | trigger_flag;
1905        else
1906                flags = le16_to_cpu(tg_pg0.TriggerFlags) & ~trigger_flag;
1907
1908        tg_pg0.TriggerFlags = cpu_to_le16(flags);
1909
1910        rc = _config_set_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0);
1911        if (rc)
1912                return rc;
1913        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1914            MPI2_IOCSTATUS_MASK;
1915        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1916                dcprintk(ioc,
1917                    ioc_err(ioc,
1918                    "%s: Failed to update trigger pg0, ioc_status(0x%04x)\n",
1919                    __func__, ioc_status));
1920                return -EFAULT;
1921        }
1922
1923        return 0;
1924}
1925
1926/**
1927 * mpt3sas_config_get_driver_trigger_pg1 - obtain driver trigger page 1
1928 * @ioc: per adapter object
1929 * @mpi_reply: reply mf payload returned from firmware
1930 * @config_page: contents of the config page
1931 * Context: sleep.
1932 *
1933 * Returns 0 for success, non-zero for failure.
1934 */
1935int
1936mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
1937        Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
1938{
1939        Mpi2ConfigRequest_t mpi_request;
1940        int r;
1941
1942        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1943        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1944        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1945        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1946        mpi_request.ExtPageType =
1947            MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1948        mpi_request.Header.PageNumber = 1;
1949        mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
1950        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1951        r = _config_request(ioc, &mpi_request, mpi_reply,
1952            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1953        if (r)
1954                goto out;
1955
1956        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1957        r = _config_request(ioc, &mpi_request, mpi_reply,
1958            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1959            sizeof(*config_page));
1960 out:
1961        return r;
1962}
1963
1964/**
1965 * _config_set_driver_trigger_pg1 - write driver trigger page 1
1966 * @ioc: per adapter object
1967 * @mpi_reply: reply mf payload returned from firmware
1968 * @config_page: contents of the config page
1969 * Context: sleep.
1970 *
1971 * Returns 0 for success, non-zero for failure.
1972 */
1973static int
1974_config_set_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
1975        Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page)
1976{
1977        Mpi2ConfigRequest_t mpi_request;
1978        int r;
1979
1980        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1981        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1982        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1983        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1984        mpi_request.ExtPageType =
1985            MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
1986        mpi_request.Header.PageNumber = 1;
1987        mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION;
1988        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1989        r = _config_request(ioc, &mpi_request, mpi_reply,
1990            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1991        if (r)
1992                goto out;
1993
1994        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1995        _config_request(ioc, &mpi_request, mpi_reply,
1996            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1997            sizeof(*config_page));
1998        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1999        r = _config_request(ioc, &mpi_request, mpi_reply,
2000            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2001            sizeof(*config_page));
2002 out:
2003        return r;
2004}
2005
2006/**
2007 * mpt3sas_config_update_driver_trigger_pg1 - update driver trigger page 1
2008 * @ioc: per adapter object
2009 * @master_tg: Master trigger bit map
2010 * @set: set ot clear trigger values
2011 * Context: sleep.
2012 *
2013 * Returns 0 for success, non-zero for failure.
2014 */
2015int
2016mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc,
2017        struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set)
2018{
2019        Mpi26DriverTriggerPage1_t tg_pg1;
2020        Mpi2ConfigReply_t mpi_reply;
2021        int rc;
2022        u16 ioc_status;
2023
2024        rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2025            MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, set);
2026        if (rc)
2027                return rc;
2028
2029        rc = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
2030        if (rc)
2031                goto out;
2032
2033        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2034            MPI2_IOCSTATUS_MASK;
2035        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2036                dcprintk(ioc,
2037                    ioc_err(ioc,
2038                    "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
2039                    __func__, ioc_status));
2040                rc = -EFAULT;
2041                goto out;
2042        }
2043
2044        if (set) {
2045                tg_pg1.NumMasterTrigger = cpu_to_le16(1);
2046                tg_pg1.MasterTriggers[0].MasterTriggerFlags = cpu_to_le32(
2047                    master_tg->MasterData);
2048        } else {
2049                tg_pg1.NumMasterTrigger = 0;
2050                tg_pg1.MasterTriggers[0].MasterTriggerFlags = 0;
2051        }
2052
2053        rc = _config_set_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1);
2054        if (rc)
2055                goto out;
2056
2057        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2058            MPI2_IOCSTATUS_MASK;
2059        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2060                dcprintk(ioc,
2061                    ioc_err(ioc,
2062                    "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n",
2063                    __func__, ioc_status));
2064                rc = -EFAULT;
2065                goto out;
2066        }
2067
2068        return 0;
2069
2070out:
2071        mpt3sas_config_update_driver_trigger_pg0(ioc,
2072            MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, !set);
2073
2074        return rc;
2075}
2076
2077/**
2078 * mpt3sas_config_get_driver_trigger_pg2 - obtain driver trigger page 2
2079 * @ioc: per adapter object
2080 * @mpi_reply: reply mf payload returned from firmware
2081 * @config_page: contents of the config page
2082 * Context: sleep.
2083 *
2084 * Returns 0 for success, non-zero for failure.
2085 */
2086int
2087mpt3sas_config_get_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2088        Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2089{
2090        Mpi2ConfigRequest_t mpi_request;
2091        int r;
2092
2093        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2094        mpi_request.Function = MPI2_FUNCTION_CONFIG;
2095        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2096        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2097        mpi_request.ExtPageType =
2098            MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2099        mpi_request.Header.PageNumber = 2;
2100        mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2101        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2102        r = _config_request(ioc, &mpi_request, mpi_reply,
2103            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2104        if (r)
2105                goto out;
2106
2107        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2108        r = _config_request(ioc, &mpi_request, mpi_reply,
2109            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2110            sizeof(*config_page));
2111 out:
2112        return r;
2113}
2114
2115/**
2116 * _config_set_driver_trigger_pg2 - write driver trigger page 2
2117 * @ioc: per adapter object
2118 * @mpi_reply: reply mf payload returned from firmware
2119 * @config_page: contents of the config page
2120 * Context: sleep.
2121 *
2122 * Returns 0 for success, non-zero for failure.
2123 */
2124static int
2125_config_set_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2126        Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page)
2127{
2128        Mpi2ConfigRequest_t mpi_request;
2129        int r;
2130
2131        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2132        mpi_request.Function = MPI2_FUNCTION_CONFIG;
2133        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2134        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2135        mpi_request.ExtPageType =
2136            MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2137        mpi_request.Header.PageNumber = 2;
2138        mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION;
2139        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2140        r = _config_request(ioc, &mpi_request, mpi_reply,
2141            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2142        if (r)
2143                goto out;
2144
2145        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2146        _config_request(ioc, &mpi_request, mpi_reply,
2147            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2148            sizeof(*config_page));
2149        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2150        r = _config_request(ioc, &mpi_request, mpi_reply,
2151            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2152            sizeof(*config_page));
2153 out:
2154        return r;
2155}
2156
2157/**
2158 * mpt3sas_config_update_driver_trigger_pg2 - update driver trigger page 2
2159 * @ioc: per adapter object
2160 * @event_tg: list of Event Triggers
2161 * @set: set ot clear trigger values
2162 * Context: sleep.
2163 *
2164 * Returns 0 for success, non-zero for failure.
2165 */
2166int
2167mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc,
2168        struct SL_WH_EVENT_TRIGGERS_T *event_tg, bool set)
2169{
2170        Mpi26DriverTriggerPage2_t tg_pg2;
2171        Mpi2ConfigReply_t mpi_reply;
2172        int rc, i, count;
2173        u16 ioc_status;
2174
2175        rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2176            MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, set);
2177        if (rc)
2178                return rc;
2179
2180        rc = mpt3sas_config_get_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2181        if (rc)
2182                goto out;
2183
2184        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2185            MPI2_IOCSTATUS_MASK;
2186        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2187                dcprintk(ioc,
2188                    ioc_err(ioc,
2189                    "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2190                    __func__, ioc_status));
2191                rc = -EFAULT;
2192                goto out;
2193        }
2194
2195        if (set) {
2196                count = event_tg->ValidEntries;
2197                tg_pg2.NumMPIEventTrigger = cpu_to_le16(count);
2198                for (i = 0; i < count; i++) {
2199                        tg_pg2.MPIEventTriggers[i].MPIEventCode =
2200                            cpu_to_le16(
2201                            event_tg->EventTriggerEntry[i].EventValue);
2202                        tg_pg2.MPIEventTriggers[i].MPIEventCodeSpecific =
2203                            cpu_to_le16(
2204                            event_tg->EventTriggerEntry[i].LogEntryQualifier);
2205                }
2206        } else {
2207                tg_pg2.NumMPIEventTrigger = 0;
2208                memset(&tg_pg2.MPIEventTriggers[0], 0,
2209                    NUM_VALID_ENTRIES * sizeof(
2210                    MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY));
2211        }
2212
2213        rc = _config_set_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2);
2214        if (rc)
2215                goto out;
2216
2217        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2218            MPI2_IOCSTATUS_MASK;
2219        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2220                dcprintk(ioc,
2221                    ioc_err(ioc,
2222                    "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n",
2223                    __func__, ioc_status));
2224                rc = -EFAULT;
2225                goto out;
2226        }
2227
2228        return 0;
2229
2230out:
2231        mpt3sas_config_update_driver_trigger_pg0(ioc,
2232            MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, !set);
2233
2234        return rc;
2235}
2236
2237/**
2238 * mpt3sas_config_get_driver_trigger_pg3 - obtain driver trigger page 3
2239 * @ioc: per adapter object
2240 * @mpi_reply: reply mf payload returned from firmware
2241 * @config_page: contents of the config page
2242 * Context: sleep.
2243 *
2244 * Returns 0 for success, non-zero for failure.
2245 */
2246int
2247mpt3sas_config_get_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2248        Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2249{
2250        Mpi2ConfigRequest_t mpi_request;
2251        int r;
2252
2253        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2254        mpi_request.Function = MPI2_FUNCTION_CONFIG;
2255        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2256        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2257        mpi_request.ExtPageType =
2258            MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2259        mpi_request.Header.PageNumber = 3;
2260        mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2261        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2262        r = _config_request(ioc, &mpi_request, mpi_reply,
2263            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2264        if (r)
2265                goto out;
2266
2267        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2268        r = _config_request(ioc, &mpi_request, mpi_reply,
2269            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2270            sizeof(*config_page));
2271 out:
2272        return r;
2273}
2274
2275/**
2276 * _config_set_driver_trigger_pg3 - write driver trigger page 3
2277 * @ioc: per adapter object
2278 * @mpi_reply: reply mf payload returned from firmware
2279 * @config_page: contents of the config page
2280 * Context: sleep.
2281 *
2282 * Returns 0 for success, non-zero for failure.
2283 */
2284static int
2285_config_set_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2286        Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page)
2287{
2288        Mpi2ConfigRequest_t mpi_request;
2289        int r;
2290
2291        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2292        mpi_request.Function = MPI2_FUNCTION_CONFIG;
2293        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2294        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2295        mpi_request.ExtPageType =
2296            MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2297        mpi_request.Header.PageNumber = 3;
2298        mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION;
2299        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2300        r = _config_request(ioc, &mpi_request, mpi_reply,
2301            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2302        if (r)
2303                goto out;
2304
2305        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2306        _config_request(ioc, &mpi_request, mpi_reply,
2307            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2308            sizeof(*config_page));
2309        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2310        r = _config_request(ioc, &mpi_request, mpi_reply,
2311            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2312            sizeof(*config_page));
2313 out:
2314        return r;
2315}
2316
2317/**
2318 * mpt3sas_config_update_driver_trigger_pg3 - update driver trigger page 3
2319 * @ioc: per adapter object
2320 * @scsi_tg: scsi trigger list
2321 * @set: set ot clear trigger values
2322 * Context: sleep.
2323 *
2324 * Returns 0 for success, non-zero for failure.
2325 */
2326int
2327mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc,
2328        struct SL_WH_SCSI_TRIGGERS_T *scsi_tg, bool set)
2329{
2330        Mpi26DriverTriggerPage3_t tg_pg3;
2331        Mpi2ConfigReply_t mpi_reply;
2332        int rc, i, count;
2333        u16 ioc_status;
2334
2335        rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2336            MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, set);
2337        if (rc)
2338                return rc;
2339
2340        rc = mpt3sas_config_get_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2341        if (rc)
2342                goto out;
2343
2344        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2345            MPI2_IOCSTATUS_MASK;
2346        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2347                dcprintk(ioc,
2348                    ioc_err(ioc,
2349                    "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2350                    __func__, ioc_status));
2351                return -EFAULT;
2352        }
2353
2354        if (set) {
2355                count = scsi_tg->ValidEntries;
2356                tg_pg3.NumSCSISenseTrigger = cpu_to_le16(count);
2357                for (i = 0; i < count; i++) {
2358                        tg_pg3.SCSISenseTriggers[i].ASCQ =
2359                            scsi_tg->SCSITriggerEntry[i].ASCQ;
2360                        tg_pg3.SCSISenseTriggers[i].ASC =
2361                            scsi_tg->SCSITriggerEntry[i].ASC;
2362                        tg_pg3.SCSISenseTriggers[i].SenseKey =
2363                            scsi_tg->SCSITriggerEntry[i].SenseKey;
2364                }
2365        } else {
2366                tg_pg3.NumSCSISenseTrigger = 0;
2367                memset(&tg_pg3.SCSISenseTriggers[0], 0,
2368                    NUM_VALID_ENTRIES * sizeof(
2369                    MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY));
2370        }
2371
2372        rc = _config_set_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3);
2373        if (rc)
2374                goto out;
2375
2376        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2377            MPI2_IOCSTATUS_MASK;
2378        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2379                dcprintk(ioc,
2380                    ioc_err(ioc,
2381                    "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n",
2382                     __func__, ioc_status));
2383                return -EFAULT;
2384        }
2385
2386        return 0;
2387out:
2388        mpt3sas_config_update_driver_trigger_pg0(ioc,
2389            MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, !set);
2390
2391        return rc;
2392}
2393
2394/**
2395 * mpt3sas_config_get_driver_trigger_pg4 - obtain driver trigger page 4
2396 * @ioc: per adapter object
2397 * @mpi_reply: reply mf payload returned from firmware
2398 * @config_page: contents of the config page
2399 * Context: sleep.
2400 *
2401 * Returns 0 for success, non-zero for failure.
2402 */
2403int
2404mpt3sas_config_get_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2405        Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2406{
2407        Mpi2ConfigRequest_t mpi_request;
2408        int r;
2409
2410        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2411        mpi_request.Function = MPI2_FUNCTION_CONFIG;
2412        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2413        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2414        mpi_request.ExtPageType =
2415            MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2416        mpi_request.Header.PageNumber = 4;
2417        mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2418        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2419        r = _config_request(ioc, &mpi_request, mpi_reply,
2420            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2421        if (r)
2422                goto out;
2423
2424        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2425        r = _config_request(ioc, &mpi_request, mpi_reply,
2426            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2427            sizeof(*config_page));
2428 out:
2429        return r;
2430}
2431
2432/**
2433 * _config_set_driver_trigger_pg4 - write driver trigger page 4
2434 * @ioc: per adapter object
2435 * @mpi_reply: reply mf payload returned from firmware
2436 * @config_page: contents of the config page
2437 * Context: sleep.
2438 *
2439 * Returns 0 for success, non-zero for failure.
2440 */
2441static int
2442_config_set_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2443        Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page)
2444{
2445        Mpi2ConfigRequest_t mpi_request;
2446        int r;
2447
2448        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2449        mpi_request.Function = MPI2_FUNCTION_CONFIG;
2450        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2451        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2452        mpi_request.ExtPageType =
2453            MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER;
2454        mpi_request.Header.PageNumber = 4;
2455        mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION;
2456        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2457        r = _config_request(ioc, &mpi_request, mpi_reply,
2458            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2459        if (r)
2460                goto out;
2461
2462        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2463        _config_request(ioc, &mpi_request, mpi_reply,
2464            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2465            sizeof(*config_page));
2466        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
2467        r = _config_request(ioc, &mpi_request, mpi_reply,
2468            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2469            sizeof(*config_page));
2470 out:
2471        return r;
2472}
2473
2474/**
2475 * mpt3sas_config_update_driver_trigger_pg4 - update driver trigger page 4
2476 * @ioc: per adapter object
2477 * @mpi_tg: mpi trigger list
2478 * @set: set ot clear trigger values
2479 * Context: sleep.
2480 *
2481 * Returns 0 for success, non-zero for failure.
2482 */
2483int
2484mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc,
2485        struct SL_WH_MPI_TRIGGERS_T *mpi_tg, bool set)
2486{
2487        Mpi26DriverTriggerPage4_t tg_pg4;
2488        Mpi2ConfigReply_t mpi_reply;
2489        int rc, i, count;
2490        u16 ioc_status;
2491
2492        rc = mpt3sas_config_update_driver_trigger_pg0(ioc,
2493            MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, set);
2494        if (rc)
2495                return rc;
2496
2497        rc = mpt3sas_config_get_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2498        if (rc)
2499                goto out;
2500
2501        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2502            MPI2_IOCSTATUS_MASK;
2503        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2504                dcprintk(ioc,
2505                    ioc_err(ioc,
2506                    "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2507                    __func__, ioc_status));
2508                rc = -EFAULT;
2509                goto out;
2510        }
2511
2512        if (set) {
2513                count = mpi_tg->ValidEntries;
2514                tg_pg4.NumIOCStatusLogInfoTrigger = cpu_to_le16(count);
2515                for (i = 0; i < count; i++) {
2516                        tg_pg4.IOCStatusLoginfoTriggers[i].IOCStatus =
2517                            cpu_to_le16(mpi_tg->MPITriggerEntry[i].IOCStatus);
2518                        tg_pg4.IOCStatusLoginfoTriggers[i].LogInfo =
2519                            cpu_to_le32(mpi_tg->MPITriggerEntry[i].IocLogInfo);
2520                }
2521        } else {
2522                tg_pg4.NumIOCStatusLogInfoTrigger = 0;
2523                memset(&tg_pg4.IOCStatusLoginfoTriggers[0], 0,
2524                    NUM_VALID_ENTRIES * sizeof(
2525                    MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY));
2526        }
2527
2528        rc = _config_set_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4);
2529        if (rc)
2530                goto out;
2531
2532        ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2533            MPI2_IOCSTATUS_MASK;
2534        if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2535                dcprintk(ioc,
2536                    ioc_err(ioc,
2537                    "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n",
2538                    __func__, ioc_status));
2539                rc = -EFAULT;
2540                goto out;
2541        }
2542
2543        return 0;
2544
2545out:
2546        mpt3sas_config_update_driver_trigger_pg0(ioc,
2547            MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, !set);
2548
2549        return rc;
2550}
2551
2552/**
2553 * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
2554 * raid components
2555 * @ioc: per adapter object
2556 * @pd_handle: phys disk handle
2557 * @volume_handle: volume handle
2558 * Context: sleep.
2559 *
2560 * Return: 0 for success, non-zero for failure.
2561 */
2562int
2563mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
2564        u16 *volume_handle)
2565{
2566        Mpi2RaidConfigurationPage0_t *config_page = NULL;
2567        Mpi2ConfigRequest_t mpi_request;
2568        Mpi2ConfigReply_t mpi_reply;
2569        int r, i, config_page_sz;
2570        u16 ioc_status;
2571        int config_num;
2572        u16 element_type;
2573        u16 phys_disk_dev_handle;
2574
2575        *volume_handle = 0;
2576        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
2577        mpi_request.Function = MPI2_FUNCTION_CONFIG;
2578        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
2579        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
2580        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
2581        mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
2582        mpi_request.Header.PageNumber = 0;
2583        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
2584        r = _config_request(ioc, &mpi_request, &mpi_reply,
2585            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
2586        if (r)
2587                goto out;
2588
2589        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
2590        config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
2591        config_page = kmalloc(config_page_sz, GFP_KERNEL);
2592        if (!config_page) {
2593                r = -1;
2594                goto out;
2595        }
2596
2597        config_num = 0xff;
2598        while (1) {
2599                mpi_request.PageAddress = cpu_to_le32(config_num +
2600                    MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
2601                r = _config_request(ioc, &mpi_request, &mpi_reply,
2602                    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
2603                    config_page_sz);
2604                if (r)
2605                        goto out;
2606                r = -1;
2607                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2608                    MPI2_IOCSTATUS_MASK;
2609                if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
2610                        goto out;
2611                for (i = 0; i < config_page->NumElements; i++) {
2612                        element_type = le16_to_cpu(config_page->
2613                            ConfigElement[i].ElementFlags) &
2614                            MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
2615                        if (element_type ==
2616                            MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
2617                            element_type ==
2618                            MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
2619                                phys_disk_dev_handle =
2620                                    le16_to_cpu(config_page->ConfigElement[i].
2621                                    PhysDiskDevHandle);
2622                                if (phys_disk_dev_handle == pd_handle) {
2623                                        *volume_handle =
2624                                            le16_to_cpu(config_page->
2625                                            ConfigElement[i].VolDevHandle);
2626                                        r = 0;
2627                                        goto out;
2628                                }
2629                        } else if (element_type ==
2630                            MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
2631                                *volume_handle = 0;
2632                                r = 0;
2633                                goto out;
2634                        }
2635                }
2636                config_num = config_page->ConfigNum;
2637        }
2638 out:
2639        kfree(config_page);
2640        return r;
2641}
2642
2643/**
2644 * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
2645 * @ioc: per adapter object
2646 * @volume_handle: volume handle
2647 * @wwid: volume wwid
2648 * Context: sleep.
2649 *
2650 * Return: 0 for success, non-zero for failure.
2651 */
2652int
2653mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
2654        u64 *wwid)
2655{
2656        Mpi2ConfigReply_t mpi_reply;
2657        Mpi2RaidVolPage1_t raid_vol_pg1;
2658
2659        *wwid = 0;
2660        if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
2661            &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
2662            volume_handle))) {
2663                *wwid = le64_to_cpu(raid_vol_pg1.WWID);
2664                return 0;
2665        } else
2666                return -1;
2667}
2668