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        if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
 105                return;
 106
 107        mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
 108        switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
 109        case MPI2_CONFIG_PAGETYPE_IO_UNIT:
 110                desc = "io_unit";
 111                break;
 112        case MPI2_CONFIG_PAGETYPE_IOC:
 113                desc = "ioc";
 114                break;
 115        case MPI2_CONFIG_PAGETYPE_BIOS:
 116                desc = "bios";
 117                break;
 118        case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
 119                desc = "raid_volume";
 120                break;
 121        case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
 122                desc = "manufaucturing";
 123                break;
 124        case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
 125                desc = "physdisk";
 126                break;
 127        case MPI2_CONFIG_PAGETYPE_EXTENDED:
 128                switch (mpi_request->ExtPageType) {
 129                case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
 130                        desc = "sas_io_unit";
 131                        break;
 132                case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
 133                        desc = "sas_expander";
 134                        break;
 135                case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
 136                        desc = "sas_device";
 137                        break;
 138                case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
 139                        desc = "sas_phy";
 140                        break;
 141                case MPI2_CONFIG_EXTPAGETYPE_LOG:
 142                        desc = "log";
 143                        break;
 144                case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
 145                        desc = "enclosure";
 146                        break;
 147                case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
 148                        desc = "raid_config";
 149                        break;
 150                case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
 151                        desc = "driver_mapping";
 152                        break;
 153                }
 154                break;
 155        }
 156
 157        if (!desc)
 158                return;
 159
 160        pr_info(MPT3SAS_FMT
 161                "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n",
 162                ioc->name, calling_function_name, desc,
 163            mpi_request->Header.PageNumber, mpi_request->Action,
 164            le32_to_cpu(mpi_request->PageAddress), smid);
 165
 166        if (!mpi_reply)
 167                return;
 168
 169        if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
 170                pr_info(MPT3SAS_FMT
 171                    "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
 172                    ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
 173                    le32_to_cpu(mpi_reply->IOCLogInfo));
 174}
 175
 176/**
 177 * _config_alloc_config_dma_memory - obtain physical memory
 178 * @ioc: per adapter object
 179 * @mem: struct config_request
 180 *
 181 * A wrapper for obtaining dma-able memory for config page request.
 182 *
 183 * Returns 0 for success, non-zero for failure.
 184 */
 185static int
 186_config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
 187        struct config_request *mem)
 188{
 189        int r = 0;
 190
 191        if (mem->sz > ioc->config_page_sz) {
 192                mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
 193                    &mem->page_dma, GFP_KERNEL);
 194                if (!mem->page) {
 195                        pr_err(MPT3SAS_FMT
 196                                "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n",
 197                            ioc->name, __func__, mem->sz);
 198                        r = -ENOMEM;
 199                }
 200        } else { /* use tmp buffer if less than 512 bytes */
 201                mem->page = ioc->config_page;
 202                mem->page_dma = ioc->config_page_dma;
 203        }
 204        return r;
 205}
 206
 207/**
 208 * _config_free_config_dma_memory - wrapper to free the memory
 209 * @ioc: per adapter object
 210 * @mem: struct config_request
 211 *
 212 * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
 213 *
 214 * Returns 0 for success, non-zero for failure.
 215 */
 216static void
 217_config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
 218        struct config_request *mem)
 219{
 220        if (mem->sz > ioc->config_page_sz)
 221                dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
 222                    mem->page_dma);
 223}
 224
 225/**
 226 * mpt3sas_config_done - config page completion routine
 227 * @ioc: per adapter object
 228 * @smid: system request message index
 229 * @msix_index: MSIX table index supplied by the OS
 230 * @reply: reply message frame(lower 32bit addr)
 231 * Context: none.
 232 *
 233 * The callback handler when using _config_request.
 234 *
 235 * Return 1 meaning mf should be freed from _base_interrupt
 236 *        0 means the mf is freed from this function.
 237 */
 238u8
 239mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
 240        u32 reply)
 241{
 242        MPI2DefaultReply_t *mpi_reply;
 243
 244        if (ioc->config_cmds.status == MPT3_CMD_NOT_USED)
 245                return 1;
 246        if (ioc->config_cmds.smid != smid)
 247                return 1;
 248        ioc->config_cmds.status |= MPT3_CMD_COMPLETE;
 249        mpi_reply =  mpt3sas_base_get_reply_virt_addr(ioc, reply);
 250        if (mpi_reply) {
 251                ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID;
 252                memcpy(ioc->config_cmds.reply, mpi_reply,
 253                    mpi_reply->MsgLength*4);
 254        }
 255        ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
 256        _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
 257        ioc->config_cmds.smid = USHRT_MAX;
 258        complete(&ioc->config_cmds.done);
 259        return 1;
 260}
 261
 262/**
 263 * _config_request - main routine for sending config page requests
 264 * @ioc: per adapter object
 265 * @mpi_request: request message frame
 266 * @mpi_reply: reply mf payload returned from firmware
 267 * @timeout: timeout in seconds
 268 * @config_page: contents of the config page
 269 * @config_page_sz: size of config page
 270 * Context: sleep
 271 *
 272 * A generic API for config page requests to firmware.
 273 *
 274 * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling
 275 * this API.
 276 *
 277 * The callback index is set inside `ioc->config_cb_idx.
 278 *
 279 * Returns 0 for success, non-zero for failure.
 280 */
 281static int
 282_config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
 283        *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
 284        void *config_page, u16 config_page_sz)
 285{
 286        u16 smid;
 287        u32 ioc_state;
 288        unsigned long timeleft;
 289        Mpi2ConfigRequest_t *config_request;
 290        int r;
 291        u8 retry_count, issue_host_reset = 0;
 292        u16 wait_state_count;
 293        struct config_request mem;
 294        u32 ioc_status = UINT_MAX;
 295
 296        mutex_lock(&ioc->config_cmds.mutex);
 297        if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
 298                pr_err(MPT3SAS_FMT "%s: config_cmd in use\n",
 299                    ioc->name, __func__);
 300                mutex_unlock(&ioc->config_cmds.mutex);
 301                return -EAGAIN;
 302        }
 303
 304        retry_count = 0;
 305        memset(&mem, 0, sizeof(struct config_request));
 306
 307        mpi_request->VF_ID = 0; /* TODO */
 308        mpi_request->VP_ID = 0;
 309
 310        if (config_page) {
 311                mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
 312                mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
 313                mpi_request->Header.PageType = mpi_reply->Header.PageType;
 314                mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
 315                mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
 316                mpi_request->ExtPageType = mpi_reply->ExtPageType;
 317                if (mpi_request->Header.PageLength)
 318                        mem.sz = mpi_request->Header.PageLength * 4;
 319                else
 320                        mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
 321                r = _config_alloc_config_dma_memory(ioc, &mem);
 322                if (r != 0)
 323                        goto out;
 324                if (mpi_request->Action ==
 325                    MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
 326                    mpi_request->Action ==
 327                    MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
 328                        ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
 329                            MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
 330                            mem.page_dma);
 331                        memcpy(mem.page, config_page, min_t(u16, mem.sz,
 332                            config_page_sz));
 333                } else {
 334                        memset(config_page, 0, config_page_sz);
 335                        ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
 336                            MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
 337                        memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
 338                }
 339        }
 340
 341 retry_config:
 342        if (retry_count) {
 343                if (retry_count > 2) { /* attempt only 2 retries */
 344                        r = -EFAULT;
 345                        goto free_mem;
 346                }
 347                pr_info(MPT3SAS_FMT "%s: attempting retry (%d)\n",
 348                    ioc->name, __func__, retry_count);
 349        }
 350        wait_state_count = 0;
 351        ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
 352        while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
 353                if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) {
 354                        pr_err(MPT3SAS_FMT
 355                            "%s: failed due to ioc not operational\n",
 356                            ioc->name, __func__);
 357                        ioc->config_cmds.status = MPT3_CMD_NOT_USED;
 358                        r = -EFAULT;
 359                        goto free_mem;
 360                }
 361                ssleep(1);
 362                ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
 363                pr_info(MPT3SAS_FMT
 364                        "%s: waiting for operational state(count=%d)\n",
 365                        ioc->name, __func__, wait_state_count);
 366        }
 367        if (wait_state_count)
 368                pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
 369                    ioc->name, __func__);
 370
 371        smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
 372        if (!smid) {
 373                pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
 374                    ioc->name, __func__);
 375                ioc->config_cmds.status = MPT3_CMD_NOT_USED;
 376                r = -EAGAIN;
 377                goto free_mem;
 378        }
 379
 380        r = 0;
 381        memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
 382        ioc->config_cmds.status = MPT3_CMD_PENDING;
 383        config_request = mpt3sas_base_get_msg_frame(ioc, smid);
 384        ioc->config_cmds.smid = smid;
 385        memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
 386        _config_display_some_debug(ioc, smid, "config_request", NULL);
 387        init_completion(&ioc->config_cmds.done);
 388        mpt3sas_base_put_smid_default(ioc, smid);
 389        timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
 390            timeout*HZ);
 391        if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
 392                pr_err(MPT3SAS_FMT "%s: timeout\n",
 393                    ioc->name, __func__);
 394                _debug_dump_mf(mpi_request,
 395                    sizeof(Mpi2ConfigRequest_t)/4);
 396                retry_count++;
 397                if (ioc->config_cmds.smid == smid)
 398                        mpt3sas_base_free_smid(ioc, smid);
 399                if ((ioc->shost_recovery) || (ioc->config_cmds.status &
 400                    MPT3_CMD_RESET) || ioc->pci_error_recovery)
 401                        goto retry_config;
 402                issue_host_reset = 1;
 403                r = -EFAULT;
 404                goto free_mem;
 405        }
 406
 407        if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
 408                memcpy(mpi_reply, ioc->config_cmds.reply,
 409                    sizeof(Mpi2ConfigReply_t));
 410
 411                /* Reply Frame Sanity Checks to workaround FW issues */
 412                if ((mpi_request->Header.PageType & 0xF) !=
 413                    (mpi_reply->Header.PageType & 0xF)) {
 414                        _debug_dump_mf(mpi_request, ioc->request_sz/4);
 415                        _debug_dump_reply(mpi_reply, ioc->request_sz/4);
 416                        panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
 417                            " mpi_reply mismatch: Requested PageType(0x%02x)" \
 418                            " Reply PageType(0x%02x)\n", \
 419                            ioc->name, __func__,
 420                            (mpi_request->Header.PageType & 0xF),
 421                            (mpi_reply->Header.PageType & 0xF));
 422                }
 423
 424                if (((mpi_request->Header.PageType & 0xF) ==
 425                    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
 426                    mpi_request->ExtPageType != mpi_reply->ExtPageType) {
 427                        _debug_dump_mf(mpi_request, ioc->request_sz/4);
 428                        _debug_dump_reply(mpi_reply, ioc->request_sz/4);
 429                        panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
 430                            " mpi_reply mismatch: Requested ExtPageType(0x%02x)"
 431                            " Reply ExtPageType(0x%02x)\n",
 432                            ioc->name, __func__, 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                pr_info(MPT3SAS_FMT "%s: retry (%d) completed!!\n", \
 441                    ioc->name, __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                                _debug_dump_mf(mpi_request, ioc->request_sz/4);
 453                                _debug_dump_reply(mpi_reply, ioc->request_sz/4);
 454                                _debug_dump_config(p, min_t(u16, mem.sz,
 455                                    config_page_sz)/4);
 456                                panic(KERN_WARNING MPT3SAS_FMT
 457                                        "%s: Firmware BUG:" \
 458                                    " config page mismatch:"
 459                                    " Requested PageType(0x%02x)"
 460                                    " Reply PageType(0x%02x)\n",
 461                                    ioc->name, __func__,
 462                                    (mpi_request->Header.PageType & 0xF),
 463                                    (p[3] & 0xF));
 464                        }
 465
 466                        if (((mpi_request->Header.PageType & 0xF) ==
 467                            MPI2_CONFIG_PAGETYPE_EXTENDED) &&
 468                            (mpi_request->ExtPageType != p[6])) {
 469                                _debug_dump_mf(mpi_request, ioc->request_sz/4);
 470                                _debug_dump_reply(mpi_reply, ioc->request_sz/4);
 471                                _debug_dump_config(p, min_t(u16, mem.sz,
 472                                    config_page_sz)/4);
 473                                panic(KERN_WARNING MPT3SAS_FMT
 474                                        "%s: Firmware BUG:" \
 475                                    " config page mismatch:"
 476                                    " Requested ExtPageType(0x%02x)"
 477                                    " Reply ExtPageType(0x%02x)\n",
 478                                    ioc->name, __func__,
 479                                    mpi_request->ExtPageType, p[6]);
 480                        }
 481                }
 482                memcpy(config_page, mem.page, min_t(u16, mem.sz,
 483                    config_page_sz));
 484        }
 485
 486 free_mem:
 487        if (config_page)
 488                _config_free_config_dma_memory(ioc, &mem);
 489 out:
 490        ioc->config_cmds.status = MPT3_CMD_NOT_USED;
 491        mutex_unlock(&ioc->config_cmds.mutex);
 492
 493        if (issue_host_reset)
 494                mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
 495                    FORCE_BIG_HAMMER);
 496        return r;
 497}
 498
 499/**
 500 * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
 501 * @ioc: per adapter object
 502 * @mpi_reply: reply mf payload returned from firmware
 503 * @config_page: contents of the config page
 504 * Context: sleep.
 505 *
 506 * Returns 0 for success, non-zero for failure.
 507 */
 508int
 509mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
 510        Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
 511{
 512        Mpi2ConfigRequest_t mpi_request;
 513        int r;
 514
 515        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 516        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 517        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 518        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
 519        mpi_request.Header.PageNumber = 0;
 520        mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
 521        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 522        r = _config_request(ioc, &mpi_request, mpi_reply,
 523            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 524        if (r)
 525                goto out;
 526
 527        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 528        r = _config_request(ioc, &mpi_request, mpi_reply,
 529            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 530            sizeof(*config_page));
 531 out:
 532        return r;
 533}
 534
 535/**
 536 * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
 537 * @ioc: per adapter object
 538 * @mpi_reply: reply mf payload returned from firmware
 539 * @config_page: contents of the config page
 540 * @sz: size of buffer passed in config_page
 541 * Context: sleep.
 542 *
 543 * Returns 0 for success, non-zero for failure.
 544 */
 545int
 546mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
 547        Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
 548        u16 sz)
 549{
 550        Mpi2ConfigRequest_t mpi_request;
 551        int r;
 552
 553        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 554        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 555        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 556        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
 557        mpi_request.Header.PageNumber = 7;
 558        mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
 559        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 560        r = _config_request(ioc, &mpi_request, mpi_reply,
 561            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 562        if (r)
 563                goto out;
 564
 565        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 566        r = _config_request(ioc, &mpi_request, mpi_reply,
 567            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 568            sz);
 569 out:
 570        return r;
 571}
 572
 573/**
 574 * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
 575 * @ioc: per adapter object
 576 * @mpi_reply: reply mf payload returned from firmware
 577 * @config_page: contents of the config page
 578 * Context: sleep.
 579 *
 580 * Returns 0 for success, non-zero for failure.
 581 */
 582int
 583mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
 584        Mpi2ConfigReply_t *mpi_reply,
 585        struct Mpi2ManufacturingPage10_t *config_page)
 586{
 587        Mpi2ConfigRequest_t mpi_request;
 588        int r;
 589
 590        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 591        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 592        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 593        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
 594        mpi_request.Header.PageNumber = 10;
 595        mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
 596        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 597        r = _config_request(ioc, &mpi_request, mpi_reply,
 598            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 599        if (r)
 600                goto out;
 601
 602        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 603        r = _config_request(ioc, &mpi_request, mpi_reply,
 604            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 605            sizeof(*config_page));
 606 out:
 607        return r;
 608}
 609
 610/**
 611 * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
 612 * @ioc: per adapter object
 613 * @mpi_reply: reply mf payload returned from firmware
 614 * @config_page: contents of the config page
 615 * Context: sleep.
 616 *
 617 * Returns 0 for success, non-zero for failure.
 618 */
 619int
 620mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
 621        Mpi2ConfigReply_t *mpi_reply,
 622        struct Mpi2ManufacturingPage11_t *config_page)
 623{
 624        Mpi2ConfigRequest_t mpi_request;
 625        int r;
 626
 627        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 628        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 629        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 630        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
 631        mpi_request.Header.PageNumber = 11;
 632        mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
 633        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 634        r = _config_request(ioc, &mpi_request, mpi_reply,
 635            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 636        if (r)
 637                goto out;
 638
 639        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 640        r = _config_request(ioc, &mpi_request, mpi_reply,
 641            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 642            sizeof(*config_page));
 643 out:
 644        return r;
 645}
 646
 647/**
 648 * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
 649 * @ioc: per adapter object
 650 * @mpi_reply: reply mf payload returned from firmware
 651 * @config_page: contents of the config page
 652 * Context: sleep.
 653 *
 654 * Returns 0 for success, non-zero for failure.
 655 */
 656int
 657mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
 658        Mpi2ConfigReply_t *mpi_reply,
 659        struct Mpi2ManufacturingPage11_t *config_page)
 660{
 661        Mpi2ConfigRequest_t mpi_request;
 662        int r;
 663
 664        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 665        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 666        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 667        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
 668        mpi_request.Header.PageNumber = 11;
 669        mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
 670        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 671        r = _config_request(ioc, &mpi_request, mpi_reply,
 672            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 673        if (r)
 674                goto out;
 675
 676        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 677        r = _config_request(ioc, &mpi_request, mpi_reply,
 678            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 679            sizeof(*config_page));
 680        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
 681        r = _config_request(ioc, &mpi_request, mpi_reply,
 682            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 683            sizeof(*config_page));
 684 out:
 685        return r;
 686}
 687
 688/**
 689 * mpt3sas_config_get_bios_pg2 - obtain bios page 2
 690 * @ioc: per adapter object
 691 * @mpi_reply: reply mf payload returned from firmware
 692 * @config_page: contents of the config page
 693 * Context: sleep.
 694 *
 695 * Returns 0 for success, non-zero for failure.
 696 */
 697int
 698mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
 699        Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
 700{
 701        Mpi2ConfigRequest_t mpi_request;
 702        int r;
 703
 704        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 705        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 706        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 707        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
 708        mpi_request.Header.PageNumber = 2;
 709        mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
 710        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 711        r = _config_request(ioc, &mpi_request, mpi_reply,
 712            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 713        if (r)
 714                goto out;
 715
 716        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 717        r = _config_request(ioc, &mpi_request, mpi_reply,
 718            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 719            sizeof(*config_page));
 720 out:
 721        return r;
 722}
 723
 724/**
 725 * mpt3sas_config_get_bios_pg3 - obtain bios page 3
 726 * @ioc: per adapter object
 727 * @mpi_reply: reply mf payload returned from firmware
 728 * @config_page: contents of the config page
 729 * Context: sleep.
 730 *
 731 * Returns 0 for success, non-zero for failure.
 732 */
 733int
 734mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
 735        *mpi_reply, Mpi2BiosPage3_t *config_page)
 736{
 737        Mpi2ConfigRequest_t mpi_request;
 738        int r;
 739
 740        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 741        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 742        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 743        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
 744        mpi_request.Header.PageNumber = 3;
 745        mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
 746        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 747        r = _config_request(ioc, &mpi_request, mpi_reply,
 748            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 749        if (r)
 750                goto out;
 751
 752        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 753        r = _config_request(ioc, &mpi_request, mpi_reply,
 754            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 755            sizeof(*config_page));
 756 out:
 757        return r;
 758}
 759
 760/**
 761 * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
 762 * @ioc: per adapter object
 763 * @mpi_reply: reply mf payload returned from firmware
 764 * @config_page: contents of the config page
 765 * Context: sleep.
 766 *
 767 * Returns 0 for success, non-zero for failure.
 768 */
 769int
 770mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
 771        Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
 772{
 773        Mpi2ConfigRequest_t mpi_request;
 774        int r;
 775
 776        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 777        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 778        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 779        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
 780        mpi_request.Header.PageNumber = 0;
 781        mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
 782        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 783        r = _config_request(ioc, &mpi_request, mpi_reply,
 784            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 785        if (r)
 786                goto out;
 787
 788        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 789        r = _config_request(ioc, &mpi_request, mpi_reply,
 790            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 791            sizeof(*config_page));
 792 out:
 793        return r;
 794}
 795
 796/**
 797 * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
 798 * @ioc: per adapter object
 799 * @mpi_reply: reply mf payload returned from firmware
 800 * @config_page: contents of the config page
 801 * Context: sleep.
 802 *
 803 * Returns 0 for success, non-zero for failure.
 804 */
 805int
 806mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
 807        Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
 808{
 809        Mpi2ConfigRequest_t mpi_request;
 810        int r;
 811
 812        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 813        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 814        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 815        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
 816        mpi_request.Header.PageNumber = 1;
 817        mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
 818        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 819        r = _config_request(ioc, &mpi_request, mpi_reply,
 820            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 821        if (r)
 822                goto out;
 823
 824        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 825        r = _config_request(ioc, &mpi_request, mpi_reply,
 826            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 827            sizeof(*config_page));
 828 out:
 829        return r;
 830}
 831
 832/**
 833 * mpt3sas_config_set_iounit_pg1 - set iounit page 1
 834 * @ioc: per adapter object
 835 * @mpi_reply: reply mf payload returned from firmware
 836 * @config_page: contents of the config page
 837 * Context: sleep.
 838 *
 839 * Returns 0 for success, non-zero for failure.
 840 */
 841int
 842mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
 843        Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
 844{
 845        Mpi2ConfigRequest_t mpi_request;
 846        int r;
 847
 848        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 849        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 850        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 851        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
 852        mpi_request.Header.PageNumber = 1;
 853        mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
 854        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 855        r = _config_request(ioc, &mpi_request, mpi_reply,
 856            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 857        if (r)
 858                goto out;
 859
 860        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 861        r = _config_request(ioc, &mpi_request, mpi_reply,
 862            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 863            sizeof(*config_page));
 864 out:
 865        return r;
 866}
 867
 868/**
 869 * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
 870 * @ioc: per adapter object
 871 * @mpi_reply: reply mf payload returned from firmware
 872 * @config_page: contents of the config page
 873 * @sz: size of buffer passed in config_page
 874 * Context: sleep.
 875 *
 876 * Returns 0 for success, non-zero for failure.
 877 */
 878int
 879mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
 880        Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
 881{
 882        Mpi2ConfigRequest_t mpi_request;
 883        int r;
 884
 885        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 886        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 887        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 888        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
 889        mpi_request.Header.PageNumber = 3;
 890        mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
 891        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 892        r = _config_request(ioc, &mpi_request, mpi_reply,
 893            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 894        if (r)
 895                goto out;
 896
 897        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 898        r = _config_request(ioc, &mpi_request, mpi_reply,
 899            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
 900 out:
 901        return r;
 902}
 903
 904/**
 905 * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
 906 * @ioc: per adapter object
 907 * @mpi_reply: reply mf payload returned from firmware
 908 * @config_page: contents of the config page
 909 * Context: sleep.
 910 *
 911 * Returns 0 for success, non-zero for failure.
 912 */
 913int
 914mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc,
 915        Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
 916{
 917        Mpi2ConfigRequest_t mpi_request;
 918        int r;
 919
 920        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 921        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 922        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 923        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
 924        mpi_request.Header.PageNumber = 8;
 925        mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
 926        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 927        r = _config_request(ioc, &mpi_request, mpi_reply,
 928            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 929        if (r)
 930                goto out;
 931
 932        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 933        r = _config_request(ioc, &mpi_request, mpi_reply,
 934            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 935            sizeof(*config_page));
 936 out:
 937        return r;
 938}
 939
 940/**
 941 * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
 942 * @ioc: per adapter object
 943 * @mpi_reply: reply mf payload returned from firmware
 944 * @config_page: contents of the config page
 945 * Context: sleep.
 946 *
 947 * Returns 0 for success, non-zero for failure.
 948 */
 949int
 950mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
 951        Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
 952{
 953        Mpi2ConfigRequest_t mpi_request;
 954        int r;
 955
 956        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 957        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 958        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 959        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
 960        mpi_request.Header.PageNumber = 8;
 961        mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
 962        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 963        r = _config_request(ioc, &mpi_request, mpi_reply,
 964            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 965        if (r)
 966                goto out;
 967
 968        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 969        r = _config_request(ioc, &mpi_request, mpi_reply,
 970            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 971            sizeof(*config_page));
 972 out:
 973        return r;
 974}
 975
 976/**
 977 * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
 978 * @ioc: per adapter object
 979 * @mpi_reply: reply mf payload returned from firmware
 980 * @config_page: contents of the config page
 981 * @form: GET_NEXT_HANDLE or HANDLE
 982 * @handle: device handle
 983 * Context: sleep.
 984 *
 985 * Returns 0 for success, non-zero for failure.
 986 */
 987int
 988mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
 989        Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
 990        u32 form, u32 handle)
 991{
 992        Mpi2ConfigRequest_t mpi_request;
 993        int r;
 994
 995        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 996        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 997        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 998        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 999        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1000        mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
1001        mpi_request.Header.PageNumber = 0;
1002        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1003        r = _config_request(ioc, &mpi_request, mpi_reply,
1004            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1005        if (r)
1006                goto out;
1007
1008        mpi_request.PageAddress = cpu_to_le32(form | handle);
1009        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1010        r = _config_request(ioc, &mpi_request, mpi_reply,
1011            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1012            sizeof(*config_page));
1013 out:
1014        return r;
1015}
1016
1017/**
1018 * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
1019 * @ioc: per adapter object
1020 * @mpi_reply: reply mf payload returned from firmware
1021 * @config_page: contents of the config page
1022 * @form: GET_NEXT_HANDLE or HANDLE
1023 * @handle: device handle
1024 * Context: sleep.
1025 *
1026 * Returns 0 for success, non-zero for failure.
1027 */
1028int
1029mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1030        Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1031        u32 form, u32 handle)
1032{
1033        Mpi2ConfigRequest_t mpi_request;
1034        int r;
1035
1036        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1037        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1038        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1039        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1040        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1041        mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
1042        mpi_request.Header.PageNumber = 1;
1043        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1044        r = _config_request(ioc, &mpi_request, mpi_reply,
1045            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1046        if (r)
1047                goto out;
1048
1049        mpi_request.PageAddress = cpu_to_le32(form | handle);
1050        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1051        r = _config_request(ioc, &mpi_request, mpi_reply,
1052            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1053            sizeof(*config_page));
1054 out:
1055        return r;
1056}
1057
1058/**
1059 * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
1060 * @ioc: per adapter object
1061 * @num_phys: pointer returned with the number of phys
1062 * Context: sleep.
1063 *
1064 * Returns 0 for success, non-zero for failure.
1065 */
1066int
1067mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1068{
1069        Mpi2ConfigRequest_t mpi_request;
1070        int r;
1071        u16 ioc_status;
1072        Mpi2ConfigReply_t mpi_reply;
1073        Mpi2SasIOUnitPage0_t config_page;
1074
1075        *num_phys = 0;
1076        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1077        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1078        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1079        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1080        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1081        mpi_request.Header.PageNumber = 0;
1082        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1083        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1084        r = _config_request(ioc, &mpi_request, &mpi_reply,
1085            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1086        if (r)
1087                goto out;
1088
1089        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1090        r = _config_request(ioc, &mpi_request, &mpi_reply,
1091            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1092            sizeof(Mpi2SasIOUnitPage0_t));
1093        if (!r) {
1094                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1095                    MPI2_IOCSTATUS_MASK;
1096                if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1097                        *num_phys = config_page.NumPhys;
1098        }
1099 out:
1100        return r;
1101}
1102
1103/**
1104 * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1105 * @ioc: per adapter object
1106 * @mpi_reply: reply mf payload returned from firmware
1107 * @config_page: contents of the config page
1108 * @sz: size of buffer passed in config_page
1109 * Context: sleep.
1110 *
1111 * Calling function should call config_get_number_hba_phys prior to
1112 * this function, so enough memory is allocated for config_page.
1113 *
1114 * Returns 0 for success, non-zero for failure.
1115 */
1116int
1117mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1118        Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1119        u16 sz)
1120{
1121        Mpi2ConfigRequest_t mpi_request;
1122        int r;
1123
1124        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1125        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1126        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1127        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1128        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1129        mpi_request.Header.PageNumber = 0;
1130        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1131        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1132        r = _config_request(ioc, &mpi_request, mpi_reply,
1133            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1134        if (r)
1135                goto out;
1136
1137        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1138        r = _config_request(ioc, &mpi_request, mpi_reply,
1139            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1140 out:
1141        return r;
1142}
1143
1144/**
1145 * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1146 * @ioc: per adapter object
1147 * @mpi_reply: reply mf payload returned from firmware
1148 * @config_page: contents of the config page
1149 * @sz: size of buffer passed in config_page
1150 * Context: sleep.
1151 *
1152 * Calling function should call config_get_number_hba_phys prior to
1153 * this function, so enough memory is allocated for config_page.
1154 *
1155 * Returns 0 for success, non-zero for failure.
1156 */
1157int
1158mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1159        Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1160        u16 sz)
1161{
1162        Mpi2ConfigRequest_t mpi_request;
1163        int r;
1164
1165        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1166        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1167        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1168        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1169        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1170        mpi_request.Header.PageNumber = 1;
1171        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1172        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1173        r = _config_request(ioc, &mpi_request, mpi_reply,
1174            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1175        if (r)
1176                goto out;
1177
1178        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1179        r = _config_request(ioc, &mpi_request, mpi_reply,
1180            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1181 out:
1182        return r;
1183}
1184
1185/**
1186 * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1187 * @ioc: per adapter object
1188 * @mpi_reply: reply mf payload returned from firmware
1189 * @config_page: contents of the config page
1190 * @sz: size of buffer passed in config_page
1191 * Context: sleep.
1192 *
1193 * Calling function should call config_get_number_hba_phys prior to
1194 * this function, so enough memory is allocated for config_page.
1195 *
1196 * Returns 0 for success, non-zero for failure.
1197 */
1198int
1199mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1200        Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1201        u16 sz)
1202{
1203        Mpi2ConfigRequest_t mpi_request;
1204        int r;
1205
1206        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1207        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1208        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1209        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1210        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1211        mpi_request.Header.PageNumber = 1;
1212        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1213        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1214        r = _config_request(ioc, &mpi_request, mpi_reply,
1215            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1216        if (r)
1217                goto out;
1218
1219        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1220        _config_request(ioc, &mpi_request, mpi_reply,
1221            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1222        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1223        r = _config_request(ioc, &mpi_request, mpi_reply,
1224            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1225 out:
1226        return r;
1227}
1228
1229/**
1230 * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1231 * @ioc: per adapter object
1232 * @mpi_reply: reply mf payload returned from firmware
1233 * @config_page: contents of the config page
1234 * @form: GET_NEXT_HANDLE or HANDLE
1235 * @handle: expander handle
1236 * Context: sleep.
1237 *
1238 * Returns 0 for success, non-zero for failure.
1239 */
1240int
1241mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1242        *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1243{
1244        Mpi2ConfigRequest_t mpi_request;
1245        int r;
1246
1247        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1248        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1249        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1250        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1251        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1252        mpi_request.Header.PageNumber = 0;
1253        mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1254        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1255        r = _config_request(ioc, &mpi_request, mpi_reply,
1256            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1257        if (r)
1258                goto out;
1259
1260        mpi_request.PageAddress = cpu_to_le32(form | handle);
1261        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1262        r = _config_request(ioc, &mpi_request, mpi_reply,
1263            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1264            sizeof(*config_page));
1265 out:
1266        return r;
1267}
1268
1269/**
1270 * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1271 * @ioc: per adapter object
1272 * @mpi_reply: reply mf payload returned from firmware
1273 * @config_page: contents of the config page
1274 * @phy_number: phy number
1275 * @handle: expander handle
1276 * Context: sleep.
1277 *
1278 * Returns 0 for success, non-zero for failure.
1279 */
1280int
1281mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1282        *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1283        u16 handle)
1284{
1285        Mpi2ConfigRequest_t mpi_request;
1286        int r;
1287
1288        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1289        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1290        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1291        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1292        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1293        mpi_request.Header.PageNumber = 1;
1294        mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1295        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1296        r = _config_request(ioc, &mpi_request, mpi_reply,
1297            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1298        if (r)
1299                goto out;
1300
1301        mpi_request.PageAddress =
1302            cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1303            (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1304        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1305        r = _config_request(ioc, &mpi_request, mpi_reply,
1306            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1307            sizeof(*config_page));
1308 out:
1309        return r;
1310}
1311
1312/**
1313 * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1314 * @ioc: per adapter object
1315 * @mpi_reply: reply mf payload returned from firmware
1316 * @config_page: contents of the config page
1317 * @form: GET_NEXT_HANDLE or HANDLE
1318 * @handle: expander handle
1319 * Context: sleep.
1320 *
1321 * Returns 0 for success, non-zero for failure.
1322 */
1323int
1324mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1325        *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1326{
1327        Mpi2ConfigRequest_t mpi_request;
1328        int r;
1329
1330        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1331        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1332        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1333        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1334        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1335        mpi_request.Header.PageNumber = 0;
1336        mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1337        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1338        r = _config_request(ioc, &mpi_request, mpi_reply,
1339            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1340        if (r)
1341                goto out;
1342
1343        mpi_request.PageAddress = cpu_to_le32(form | handle);
1344        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1345        r = _config_request(ioc, &mpi_request, mpi_reply,
1346            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1347            sizeof(*config_page));
1348 out:
1349        return r;
1350}
1351
1352/**
1353 * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1354 * @ioc: per adapter object
1355 * @mpi_reply: reply mf payload returned from firmware
1356 * @config_page: contents of the config page
1357 * @phy_number: phy number
1358 * Context: sleep.
1359 *
1360 * Returns 0 for success, non-zero for failure.
1361 */
1362int
1363mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1364        *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1365{
1366        Mpi2ConfigRequest_t mpi_request;
1367        int r;
1368
1369        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1370        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1371        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1372        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1373        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1374        mpi_request.Header.PageNumber = 0;
1375        mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1376        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1377        r = _config_request(ioc, &mpi_request, mpi_reply,
1378            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1379        if (r)
1380                goto out;
1381
1382        mpi_request.PageAddress =
1383            cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1384        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1385        r = _config_request(ioc, &mpi_request, mpi_reply,
1386            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1387            sizeof(*config_page));
1388 out:
1389        return r;
1390}
1391
1392/**
1393 * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1394 * @ioc: per adapter object
1395 * @mpi_reply: reply mf payload returned from firmware
1396 * @config_page: contents of the config page
1397 * @phy_number: phy number
1398 * Context: sleep.
1399 *
1400 * Returns 0 for success, non-zero for failure.
1401 */
1402int
1403mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1404        *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1405{
1406        Mpi2ConfigRequest_t mpi_request;
1407        int r;
1408
1409        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1410        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1411        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1412        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1413        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1414        mpi_request.Header.PageNumber = 1;
1415        mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1416        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1417        r = _config_request(ioc, &mpi_request, mpi_reply,
1418            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1419        if (r)
1420                goto out;
1421
1422        mpi_request.PageAddress =
1423            cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1424        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1425        r = _config_request(ioc, &mpi_request, mpi_reply,
1426            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1427            sizeof(*config_page));
1428 out:
1429        return r;
1430}
1431
1432/**
1433 * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1434 * @ioc: per adapter object
1435 * @mpi_reply: reply mf payload returned from firmware
1436 * @config_page: contents of the config page
1437 * @form: GET_NEXT_HANDLE or HANDLE
1438 * @handle: volume handle
1439 * Context: sleep.
1440 *
1441 * Returns 0 for success, non-zero for failure.
1442 */
1443int
1444mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1445        Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1446        u32 handle)
1447{
1448        Mpi2ConfigRequest_t mpi_request;
1449        int r;
1450
1451        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1452        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1453        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1454        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1455        mpi_request.Header.PageNumber = 1;
1456        mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1457        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1458        r = _config_request(ioc, &mpi_request, mpi_reply,
1459            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1460        if (r)
1461                goto out;
1462
1463        mpi_request.PageAddress = cpu_to_le32(form | handle);
1464        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1465        r = _config_request(ioc, &mpi_request, mpi_reply,
1466            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1467            sizeof(*config_page));
1468 out:
1469        return r;
1470}
1471
1472/**
1473 * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1474 * @ioc: per adapter object
1475 * @handle: volume handle
1476 * @num_pds: returns pds count
1477 * Context: sleep.
1478 *
1479 * Returns 0 for success, non-zero for failure.
1480 */
1481int
1482mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1483        u8 *num_pds)
1484{
1485        Mpi2ConfigRequest_t mpi_request;
1486        Mpi2RaidVolPage0_t config_page;
1487        Mpi2ConfigReply_t mpi_reply;
1488        int r;
1489        u16 ioc_status;
1490
1491        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1492        *num_pds = 0;
1493        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1494        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1495        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1496        mpi_request.Header.PageNumber = 0;
1497        mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1498        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1499        r = _config_request(ioc, &mpi_request, &mpi_reply,
1500            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1501        if (r)
1502                goto out;
1503
1504        mpi_request.PageAddress =
1505            cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1506        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1507        r = _config_request(ioc, &mpi_request, &mpi_reply,
1508            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1509            sizeof(Mpi2RaidVolPage0_t));
1510        if (!r) {
1511                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1512                    MPI2_IOCSTATUS_MASK;
1513                if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1514                        *num_pds = config_page.NumPhysDisks;
1515        }
1516
1517 out:
1518        return r;
1519}
1520
1521/**
1522 * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1523 * @ioc: per adapter object
1524 * @mpi_reply: reply mf payload returned from firmware
1525 * @config_page: contents of the config page
1526 * @form: GET_NEXT_HANDLE or HANDLE
1527 * @handle: volume handle
1528 * @sz: size of buffer passed in config_page
1529 * Context: sleep.
1530 *
1531 * Returns 0 for success, non-zero for failure.
1532 */
1533int
1534mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1535        Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1536        u32 handle, u16 sz)
1537{
1538        Mpi2ConfigRequest_t mpi_request;
1539        int r;
1540
1541        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1542        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1543        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1544        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1545        mpi_request.Header.PageNumber = 0;
1546        mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1547        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1548        r = _config_request(ioc, &mpi_request, mpi_reply,
1549            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1550        if (r)
1551                goto out;
1552
1553        mpi_request.PageAddress = cpu_to_le32(form | handle);
1554        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1555        r = _config_request(ioc, &mpi_request, mpi_reply,
1556            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1557 out:
1558        return r;
1559}
1560
1561/**
1562 * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1563 * @ioc: per adapter object
1564 * @mpi_reply: reply mf payload returned from firmware
1565 * @config_page: contents of the config page
1566 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1567 * @form_specific: specific to the form
1568 * Context: sleep.
1569 *
1570 * Returns 0 for success, non-zero for failure.
1571 */
1572int
1573mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1574        *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1575        u32 form_specific)
1576{
1577        Mpi2ConfigRequest_t mpi_request;
1578        int r;
1579
1580        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1581        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1582        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1583        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1584        mpi_request.Header.PageNumber = 0;
1585        mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1586        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1587        r = _config_request(ioc, &mpi_request, mpi_reply,
1588            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1589        if (r)
1590                goto out;
1591
1592        mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1593        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1594        r = _config_request(ioc, &mpi_request, mpi_reply,
1595            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1596            sizeof(*config_page));
1597 out:
1598        return r;
1599}
1600
1601/**
1602 * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
1603 * raid components
1604 * @ioc: per adapter object
1605 * @pd_handle: phys disk handle
1606 * @volume_handle: volume handle
1607 * Context: sleep.
1608 *
1609 * Returns 0 for success, non-zero for failure.
1610 */
1611int
1612mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
1613        u16 *volume_handle)
1614{
1615        Mpi2RaidConfigurationPage0_t *config_page = NULL;
1616        Mpi2ConfigRequest_t mpi_request;
1617        Mpi2ConfigReply_t mpi_reply;
1618        int r, i, config_page_sz;
1619        u16 ioc_status;
1620        int config_num;
1621        u16 element_type;
1622        u16 phys_disk_dev_handle;
1623
1624        *volume_handle = 0;
1625        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1626        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1627        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1628        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1629        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1630        mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1631        mpi_request.Header.PageNumber = 0;
1632        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1633        r = _config_request(ioc, &mpi_request, &mpi_reply,
1634            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1635        if (r)
1636                goto out;
1637
1638        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1639        config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1640        config_page = kmalloc(config_page_sz, GFP_KERNEL);
1641        if (!config_page) {
1642                r = -1;
1643                goto out;
1644        }
1645
1646        config_num = 0xff;
1647        while (1) {
1648                mpi_request.PageAddress = cpu_to_le32(config_num +
1649                    MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1650                r = _config_request(ioc, &mpi_request, &mpi_reply,
1651                    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1652                    config_page_sz);
1653                if (r)
1654                        goto out;
1655                r = -1;
1656                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1657                    MPI2_IOCSTATUS_MASK;
1658                if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1659                        goto out;
1660                for (i = 0; i < config_page->NumElements; i++) {
1661                        element_type = le16_to_cpu(config_page->
1662                            ConfigElement[i].ElementFlags) &
1663                            MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1664                        if (element_type ==
1665                            MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1666                            element_type ==
1667                            MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1668                                phys_disk_dev_handle =
1669                                    le16_to_cpu(config_page->ConfigElement[i].
1670                                    PhysDiskDevHandle);
1671                                if (phys_disk_dev_handle == pd_handle) {
1672                                        *volume_handle =
1673                                            le16_to_cpu(config_page->
1674                                            ConfigElement[i].VolDevHandle);
1675                                        r = 0;
1676                                        goto out;
1677                                }
1678                        } else if (element_type ==
1679                            MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1680                                *volume_handle = 0;
1681                                r = 0;
1682                                goto out;
1683                        }
1684                }
1685                config_num = config_page->ConfigNum;
1686        }
1687 out:
1688        kfree(config_page);
1689        return r;
1690}
1691
1692/**
1693 * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
1694 * @ioc: per adapter object
1695 * @volume_handle: volume handle
1696 * @wwid: volume wwid
1697 * Context: sleep.
1698 *
1699 * Returns 0 for success, non-zero for failure.
1700 */
1701int
1702mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
1703        u64 *wwid)
1704{
1705        Mpi2ConfigReply_t mpi_reply;
1706        Mpi2RaidVolPage1_t raid_vol_pg1;
1707
1708        *wwid = 0;
1709        if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1710            &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1711            volume_handle))) {
1712                *wwid = le64_to_cpu(raid_vol_pg1.WWID);
1713                return 0;
1714        } else
1715                return -1;
1716}
1717