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-2013  LSI Corporation
   6 *  (mailto:DL-MPTFusionLinux@lsi.com)
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License
  10 * as published by the Free Software Foundation; either version 2
  11 * of the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * NO WARRANTY
  19 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
  20 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
  21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
  22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
  23 * solely responsible for determining the appropriateness of using and
  24 * distributing the Program and assumes all risks associated with its
  25 * exercise of rights under this Agreement, including but not limited to
  26 * the risks and costs of program errors, damage to or loss of data,
  27 * programs or equipment, and unavailability or interruption of operations.
  28
  29 * DISCLAIMER OF LIABILITY
  30 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
  31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
  33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  35 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
  36 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
  37
  38 * You should have received a copy of the GNU General Public License
  39 * along with this program; if not, write to the Free Software
  40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  41 * USA.
  42 */
  43
  44#include <linux/module.h>
  45#include <linux/kernel.h>
  46#include <linux/init.h>
  47#include <linux/errno.h>
  48#include <linux/blkdev.h>
  49#include <linux/sched.h>
  50#include <linux/workqueue.h>
  51#include <linux/delay.h>
  52#include <linux/pci.h>
  53
  54#include "mpt3sas_base.h"
  55
  56/* local definitions */
  57
  58/* Timeout for config page request (in seconds) */
  59#define MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT 15
  60
  61/* Common sgl flags for READING a config page. */
  62#define MPT3_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
  63        MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
  64        | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT)
  65
  66/* Common sgl flags for WRITING a config page. */
  67#define MPT3_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
  68        MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
  69        | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \
  70        << MPI2_SGE_FLAGS_SHIFT)
  71
  72/**
  73 * struct config_request - obtain dma memory via routine
  74 * @sz: size
  75 * @page: virt pointer
  76 * @page_dma: phys pointer
  77 *
  78 */
  79struct config_request {
  80        u16                     sz;
  81        void                    *page;
  82        dma_addr_t              page_dma;
  83};
  84
  85#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
  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#endif
 176
 177/**
 178 * _config_alloc_config_dma_memory - obtain physical memory
 179 * @ioc: per adapter object
 180 * @mem: struct config_request
 181 *
 182 * A wrapper for obtaining dma-able memory for config page request.
 183 *
 184 * Returns 0 for success, non-zero for failure.
 185 */
 186static int
 187_config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
 188        struct config_request *mem)
 189{
 190        int r = 0;
 191
 192        if (mem->sz > ioc->config_page_sz) {
 193                mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
 194                    &mem->page_dma, GFP_KERNEL);
 195                if (!mem->page) {
 196                        pr_err(MPT3SAS_FMT
 197                                "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n",
 198                            ioc->name, __func__, mem->sz);
 199                        r = -ENOMEM;
 200                }
 201        } else { /* use tmp buffer if less than 512 bytes */
 202                mem->page = ioc->config_page;
 203                mem->page_dma = ioc->config_page_dma;
 204        }
 205        return r;
 206}
 207
 208/**
 209 * _config_free_config_dma_memory - wrapper to free the memory
 210 * @ioc: per adapter object
 211 * @mem: struct config_request
 212 *
 213 * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
 214 *
 215 * Returns 0 for success, non-zero for failure.
 216 */
 217static void
 218_config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
 219        struct config_request *mem)
 220{
 221        if (mem->sz > ioc->config_page_sz)
 222                dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
 223                    mem->page_dma);
 224}
 225
 226/**
 227 * mpt3sas_config_done - config page completion routine
 228 * @ioc: per adapter object
 229 * @smid: system request message index
 230 * @msix_index: MSIX table index supplied by the OS
 231 * @reply: reply message frame(lower 32bit addr)
 232 * Context: none.
 233 *
 234 * The callback handler when using _config_request.
 235 *
 236 * Return 1 meaning mf should be freed from _base_interrupt
 237 *        0 means the mf is freed from this function.
 238 */
 239u8
 240mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
 241        u32 reply)
 242{
 243        MPI2DefaultReply_t *mpi_reply;
 244
 245        if (ioc->config_cmds.status == MPT3_CMD_NOT_USED)
 246                return 1;
 247        if (ioc->config_cmds.smid != smid)
 248                return 1;
 249        ioc->config_cmds.status |= MPT3_CMD_COMPLETE;
 250        mpi_reply =  mpt3sas_base_get_reply_virt_addr(ioc, reply);
 251        if (mpi_reply) {
 252                ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID;
 253                memcpy(ioc->config_cmds.reply, mpi_reply,
 254                    mpi_reply->MsgLength*4);
 255        }
 256        ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
 257#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 258        _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
 259#endif
 260        ioc->config_cmds.smid = USHRT_MAX;
 261        complete(&ioc->config_cmds.done);
 262        return 1;
 263}
 264
 265/**
 266 * _config_request - main routine for sending config page requests
 267 * @ioc: per adapter object
 268 * @mpi_request: request message frame
 269 * @mpi_reply: reply mf payload returned from firmware
 270 * @timeout: timeout in seconds
 271 * @config_page: contents of the config page
 272 * @config_page_sz: size of config page
 273 * Context: sleep
 274 *
 275 * A generic API for config page requests to firmware.
 276 *
 277 * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling
 278 * this API.
 279 *
 280 * The callback index is set inside `ioc->config_cb_idx.
 281 *
 282 * Returns 0 for success, non-zero for failure.
 283 */
 284static int
 285_config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
 286        *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
 287        void *config_page, u16 config_page_sz)
 288{
 289        u16 smid;
 290        u32 ioc_state;
 291        unsigned long timeleft;
 292        Mpi2ConfigRequest_t *config_request;
 293        int r;
 294        u8 retry_count, issue_host_reset = 0;
 295        u16 wait_state_count;
 296        struct config_request mem;
 297        u32 ioc_status = UINT_MAX;
 298
 299        mutex_lock(&ioc->config_cmds.mutex);
 300        if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
 301                pr_err(MPT3SAS_FMT "%s: config_cmd in use\n",
 302                    ioc->name, __func__);
 303                mutex_unlock(&ioc->config_cmds.mutex);
 304                return -EAGAIN;
 305        }
 306
 307        retry_count = 0;
 308        memset(&mem, 0, sizeof(struct config_request));
 309
 310        mpi_request->VF_ID = 0; /* TODO */
 311        mpi_request->VP_ID = 0;
 312
 313        if (config_page) {
 314                mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
 315                mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
 316                mpi_request->Header.PageType = mpi_reply->Header.PageType;
 317                mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
 318                mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
 319                mpi_request->ExtPageType = mpi_reply->ExtPageType;
 320                if (mpi_request->Header.PageLength)
 321                        mem.sz = mpi_request->Header.PageLength * 4;
 322                else
 323                        mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
 324                r = _config_alloc_config_dma_memory(ioc, &mem);
 325                if (r != 0)
 326                        goto out;
 327                if (mpi_request->Action ==
 328                    MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
 329                    mpi_request->Action ==
 330                    MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
 331                        ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
 332                            MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
 333                            mem.page_dma);
 334                        memcpy(mem.page, config_page, min_t(u16, mem.sz,
 335                            config_page_sz));
 336                } else {
 337                        memset(config_page, 0, config_page_sz);
 338                        ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
 339                            MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
 340                        memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
 341                }
 342        }
 343
 344 retry_config:
 345        if (retry_count) {
 346                if (retry_count > 2) { /* attempt only 2 retries */
 347                        r = -EFAULT;
 348                        goto free_mem;
 349                }
 350                pr_info(MPT3SAS_FMT "%s: attempting retry (%d)\n",
 351                    ioc->name, __func__, retry_count);
 352        }
 353        wait_state_count = 0;
 354        ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
 355        while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
 356                if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) {
 357                        pr_err(MPT3SAS_FMT
 358                            "%s: failed due to ioc not operational\n",
 359                            ioc->name, __func__);
 360                        ioc->config_cmds.status = MPT3_CMD_NOT_USED;
 361                        r = -EFAULT;
 362                        goto free_mem;
 363                }
 364                ssleep(1);
 365                ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
 366                pr_info(MPT3SAS_FMT
 367                        "%s: waiting for operational state(count=%d)\n",
 368                        ioc->name, __func__, wait_state_count);
 369        }
 370        if (wait_state_count)
 371                pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
 372                    ioc->name, __func__);
 373
 374        smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
 375        if (!smid) {
 376                pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
 377                    ioc->name, __func__);
 378                ioc->config_cmds.status = MPT3_CMD_NOT_USED;
 379                r = -EAGAIN;
 380                goto free_mem;
 381        }
 382
 383        r = 0;
 384        memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
 385        ioc->config_cmds.status = MPT3_CMD_PENDING;
 386        config_request = mpt3sas_base_get_msg_frame(ioc, smid);
 387        ioc->config_cmds.smid = smid;
 388        memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
 389#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 390        _config_display_some_debug(ioc, smid, "config_request", NULL);
 391#endif
 392        init_completion(&ioc->config_cmds.done);
 393        mpt3sas_base_put_smid_default(ioc, smid);
 394        timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
 395            timeout*HZ);
 396        if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
 397                pr_err(MPT3SAS_FMT "%s: timeout\n",
 398                    ioc->name, __func__);
 399                _debug_dump_mf(mpi_request,
 400                    sizeof(Mpi2ConfigRequest_t)/4);
 401                retry_count++;
 402                if (ioc->config_cmds.smid == smid)
 403                        mpt3sas_base_free_smid(ioc, smid);
 404                if ((ioc->shost_recovery) || (ioc->config_cmds.status &
 405                    MPT3_CMD_RESET) || ioc->pci_error_recovery)
 406                        goto retry_config;
 407                issue_host_reset = 1;
 408                r = -EFAULT;
 409                goto free_mem;
 410        }
 411
 412        if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
 413                memcpy(mpi_reply, ioc->config_cmds.reply,
 414                    sizeof(Mpi2ConfigReply_t));
 415
 416                /* Reply Frame Sanity Checks to workaround FW issues */
 417                if ((mpi_request->Header.PageType & 0xF) !=
 418                    (mpi_reply->Header.PageType & 0xF)) {
 419                        _debug_dump_mf(mpi_request, ioc->request_sz/4);
 420                        _debug_dump_reply(mpi_reply, ioc->request_sz/4);
 421                        panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
 422                            " mpi_reply mismatch: Requested PageType(0x%02x)" \
 423                            " Reply PageType(0x%02x)\n", \
 424                            ioc->name, __func__,
 425                            (mpi_request->Header.PageType & 0xF),
 426                            (mpi_reply->Header.PageType & 0xF));
 427                }
 428
 429                if (((mpi_request->Header.PageType & 0xF) ==
 430                    MPI2_CONFIG_PAGETYPE_EXTENDED) &&
 431                    mpi_request->ExtPageType != mpi_reply->ExtPageType) {
 432                        _debug_dump_mf(mpi_request, ioc->request_sz/4);
 433                        _debug_dump_reply(mpi_reply, ioc->request_sz/4);
 434                        panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
 435                            " mpi_reply mismatch: Requested ExtPageType(0x%02x)"
 436                            " Reply ExtPageType(0x%02x)\n",
 437                            ioc->name, __func__, mpi_request->ExtPageType,
 438                            mpi_reply->ExtPageType);
 439                }
 440                ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
 441                    & MPI2_IOCSTATUS_MASK;
 442        }
 443
 444        if (retry_count)
 445                pr_info(MPT3SAS_FMT "%s: retry (%d) completed!!\n", \
 446                    ioc->name, __func__, retry_count);
 447
 448        if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
 449            config_page && mpi_request->Action ==
 450            MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
 451                u8 *p = (u8 *)mem.page;
 452
 453                /* Config Page Sanity Checks to workaround FW issues */
 454                if (p) {
 455                        if ((mpi_request->Header.PageType & 0xF) !=
 456                            (p[3] & 0xF)) {
 457                                _debug_dump_mf(mpi_request, ioc->request_sz/4);
 458                                _debug_dump_reply(mpi_reply, ioc->request_sz/4);
 459                                _debug_dump_config(p, min_t(u16, mem.sz,
 460                                    config_page_sz)/4);
 461                                panic(KERN_WARNING MPT3SAS_FMT
 462                                        "%s: Firmware BUG:" \
 463                                    " config page mismatch:"
 464                                    " Requested PageType(0x%02x)"
 465                                    " Reply PageType(0x%02x)\n",
 466                                    ioc->name, __func__,
 467                                    (mpi_request->Header.PageType & 0xF),
 468                                    (p[3] & 0xF));
 469                        }
 470
 471                        if (((mpi_request->Header.PageType & 0xF) ==
 472                            MPI2_CONFIG_PAGETYPE_EXTENDED) &&
 473                            (mpi_request->ExtPageType != p[6])) {
 474                                _debug_dump_mf(mpi_request, ioc->request_sz/4);
 475                                _debug_dump_reply(mpi_reply, ioc->request_sz/4);
 476                                _debug_dump_config(p, min_t(u16, mem.sz,
 477                                    config_page_sz)/4);
 478                                panic(KERN_WARNING MPT3SAS_FMT
 479                                        "%s: Firmware BUG:" \
 480                                    " config page mismatch:"
 481                                    " Requested ExtPageType(0x%02x)"
 482                                    " Reply ExtPageType(0x%02x)\n",
 483                                    ioc->name, __func__,
 484                                    mpi_request->ExtPageType, p[6]);
 485                        }
 486                }
 487                memcpy(config_page, mem.page, min_t(u16, mem.sz,
 488                    config_page_sz));
 489        }
 490
 491 free_mem:
 492        if (config_page)
 493                _config_free_config_dma_memory(ioc, &mem);
 494 out:
 495        ioc->config_cmds.status = MPT3_CMD_NOT_USED;
 496        mutex_unlock(&ioc->config_cmds.mutex);
 497
 498        if (issue_host_reset)
 499                mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
 500                    FORCE_BIG_HAMMER);
 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 * Returns 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 * Returns 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 * Returns 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 * Returns 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 * Returns 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        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
 686        r = _config_request(ioc, &mpi_request, mpi_reply,
 687            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 688            sizeof(*config_page));
 689 out:
 690        return r;
 691}
 692
 693/**
 694 * mpt3sas_config_get_bios_pg2 - obtain bios page 2
 695 * @ioc: per adapter object
 696 * @mpi_reply: reply mf payload returned from firmware
 697 * @config_page: contents of the config page
 698 * Context: sleep.
 699 *
 700 * Returns 0 for success, non-zero for failure.
 701 */
 702int
 703mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
 704        Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
 705{
 706        Mpi2ConfigRequest_t mpi_request;
 707        int r;
 708
 709        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 710        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 711        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 712        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
 713        mpi_request.Header.PageNumber = 2;
 714        mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
 715        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 716        r = _config_request(ioc, &mpi_request, mpi_reply,
 717            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 718        if (r)
 719                goto out;
 720
 721        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 722        r = _config_request(ioc, &mpi_request, mpi_reply,
 723            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 724            sizeof(*config_page));
 725 out:
 726        return r;
 727}
 728
 729/**
 730 * mpt3sas_config_get_bios_pg3 - obtain bios page 3
 731 * @ioc: per adapter object
 732 * @mpi_reply: reply mf payload returned from firmware
 733 * @config_page: contents of the config page
 734 * Context: sleep.
 735 *
 736 * Returns 0 for success, non-zero for failure.
 737 */
 738int
 739mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
 740        *mpi_reply, Mpi2BiosPage3_t *config_page)
 741{
 742        Mpi2ConfigRequest_t mpi_request;
 743        int r;
 744
 745        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 746        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 747        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 748        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
 749        mpi_request.Header.PageNumber = 3;
 750        mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
 751        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 752        r = _config_request(ioc, &mpi_request, mpi_reply,
 753            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 754        if (r)
 755                goto out;
 756
 757        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 758        r = _config_request(ioc, &mpi_request, mpi_reply,
 759            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 760            sizeof(*config_page));
 761 out:
 762        return r;
 763}
 764
 765/**
 766 * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
 767 * @ioc: per adapter object
 768 * @mpi_reply: reply mf payload returned from firmware
 769 * @config_page: contents of the config page
 770 * Context: sleep.
 771 *
 772 * Returns 0 for success, non-zero for failure.
 773 */
 774int
 775mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
 776        Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
 777{
 778        Mpi2ConfigRequest_t mpi_request;
 779        int r;
 780
 781        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 782        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 783        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 784        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
 785        mpi_request.Header.PageNumber = 0;
 786        mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
 787        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 788        r = _config_request(ioc, &mpi_request, mpi_reply,
 789            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 790        if (r)
 791                goto out;
 792
 793        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 794        r = _config_request(ioc, &mpi_request, mpi_reply,
 795            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 796            sizeof(*config_page));
 797 out:
 798        return r;
 799}
 800
 801/**
 802 * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
 803 * @ioc: per adapter object
 804 * @mpi_reply: reply mf payload returned from firmware
 805 * @config_page: contents of the config page
 806 * Context: sleep.
 807 *
 808 * Returns 0 for success, non-zero for failure.
 809 */
 810int
 811mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
 812        Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
 813{
 814        Mpi2ConfigRequest_t mpi_request;
 815        int r;
 816
 817        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 818        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 819        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 820        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
 821        mpi_request.Header.PageNumber = 1;
 822        mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
 823        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 824        r = _config_request(ioc, &mpi_request, mpi_reply,
 825            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 826        if (r)
 827                goto out;
 828
 829        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 830        r = _config_request(ioc, &mpi_request, mpi_reply,
 831            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 832            sizeof(*config_page));
 833 out:
 834        return r;
 835}
 836
 837/**
 838 * mpt3sas_config_set_iounit_pg1 - set iounit page 1
 839 * @ioc: per adapter object
 840 * @mpi_reply: reply mf payload returned from firmware
 841 * @config_page: contents of the config page
 842 * Context: sleep.
 843 *
 844 * Returns 0 for success, non-zero for failure.
 845 */
 846int
 847mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
 848        Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
 849{
 850        Mpi2ConfigRequest_t mpi_request;
 851        int r;
 852
 853        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 854        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 855        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 856        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
 857        mpi_request.Header.PageNumber = 1;
 858        mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
 859        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 860        r = _config_request(ioc, &mpi_request, mpi_reply,
 861            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 862        if (r)
 863                goto out;
 864
 865        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 866        r = _config_request(ioc, &mpi_request, mpi_reply,
 867            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 868            sizeof(*config_page));
 869 out:
 870        return r;
 871}
 872
 873/**
 874 * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
 875 * @ioc: per adapter object
 876 * @mpi_reply: reply mf payload returned from firmware
 877 * @config_page: contents of the config page
 878 * Context: sleep.
 879 *
 880 * Returns 0 for success, non-zero for failure.
 881 */
 882int
 883mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
 884        Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
 885{
 886        Mpi2ConfigRequest_t mpi_request;
 887        int r;
 888
 889        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 890        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 891        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 892        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
 893        mpi_request.Header.PageNumber = 8;
 894        mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
 895        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 896        r = _config_request(ioc, &mpi_request, mpi_reply,
 897            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 898        if (r)
 899                goto out;
 900
 901        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 902        r = _config_request(ioc, &mpi_request, mpi_reply,
 903            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 904            sizeof(*config_page));
 905 out:
 906        return r;
 907}
 908
 909/**
 910 * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
 911 * @ioc: per adapter object
 912 * @mpi_reply: reply mf payload returned from firmware
 913 * @config_page: contents of the config page
 914 * @form: GET_NEXT_HANDLE or HANDLE
 915 * @handle: device handle
 916 * Context: sleep.
 917 *
 918 * Returns 0 for success, non-zero for failure.
 919 */
 920int
 921mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
 922        Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
 923        u32 form, u32 handle)
 924{
 925        Mpi2ConfigRequest_t mpi_request;
 926        int r;
 927
 928        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 929        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 930        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 931        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 932        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
 933        mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
 934        mpi_request.Header.PageNumber = 0;
 935        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 936        r = _config_request(ioc, &mpi_request, mpi_reply,
 937            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 938        if (r)
 939                goto out;
 940
 941        mpi_request.PageAddress = cpu_to_le32(form | handle);
 942        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 943        r = _config_request(ioc, &mpi_request, mpi_reply,
 944            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 945            sizeof(*config_page));
 946 out:
 947        return r;
 948}
 949
 950/**
 951 * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
 952 * @ioc: per adapter object
 953 * @mpi_reply: reply mf payload returned from firmware
 954 * @config_page: contents of the config page
 955 * @form: GET_NEXT_HANDLE or HANDLE
 956 * @handle: device handle
 957 * Context: sleep.
 958 *
 959 * Returns 0 for success, non-zero for failure.
 960 */
 961int
 962mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
 963        Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
 964        u32 form, u32 handle)
 965{
 966        Mpi2ConfigRequest_t mpi_request;
 967        int r;
 968
 969        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 970        mpi_request.Function = MPI2_FUNCTION_CONFIG;
 971        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 972        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 973        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
 974        mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
 975        mpi_request.Header.PageNumber = 1;
 976        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
 977        r = _config_request(ioc, &mpi_request, mpi_reply,
 978            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 979        if (r)
 980                goto out;
 981
 982        mpi_request.PageAddress = cpu_to_le32(form | handle);
 983        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 984        r = _config_request(ioc, &mpi_request, mpi_reply,
 985            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 986            sizeof(*config_page));
 987 out:
 988        return r;
 989}
 990
 991/**
 992 * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
 993 * @ioc: per adapter object
 994 * @num_phys: pointer returned with the number of phys
 995 * Context: sleep.
 996 *
 997 * Returns 0 for success, non-zero for failure.
 998 */
 999int
1000mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1001{
1002        Mpi2ConfigRequest_t mpi_request;
1003        int r;
1004        u16 ioc_status;
1005        Mpi2ConfigReply_t mpi_reply;
1006        Mpi2SasIOUnitPage0_t config_page;
1007
1008        *num_phys = 0;
1009        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1010        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1011        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1012        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1013        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1014        mpi_request.Header.PageNumber = 0;
1015        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1016        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1017        r = _config_request(ioc, &mpi_request, &mpi_reply,
1018            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1019        if (r)
1020                goto out;
1021
1022        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1023        r = _config_request(ioc, &mpi_request, &mpi_reply,
1024            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1025            sizeof(Mpi2SasIOUnitPage0_t));
1026        if (!r) {
1027                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1028                    MPI2_IOCSTATUS_MASK;
1029                if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1030                        *num_phys = config_page.NumPhys;
1031        }
1032 out:
1033        return r;
1034}
1035
1036/**
1037 * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1038 * @ioc: per adapter object
1039 * @mpi_reply: reply mf payload returned from firmware
1040 * @config_page: contents of the config page
1041 * @sz: size of buffer passed in config_page
1042 * Context: sleep.
1043 *
1044 * Calling function should call config_get_number_hba_phys prior to
1045 * this function, so enough memory is allocated for config_page.
1046 *
1047 * Returns 0 for success, non-zero for failure.
1048 */
1049int
1050mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1051        Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1052        u16 sz)
1053{
1054        Mpi2ConfigRequest_t mpi_request;
1055        int r;
1056
1057        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1058        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1059        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1060        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1061        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1062        mpi_request.Header.PageNumber = 0;
1063        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1064        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1065        r = _config_request(ioc, &mpi_request, mpi_reply,
1066            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1067        if (r)
1068                goto out;
1069
1070        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1071        r = _config_request(ioc, &mpi_request, mpi_reply,
1072            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1073 out:
1074        return r;
1075}
1076
1077/**
1078 * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1079 * @ioc: per adapter object
1080 * @mpi_reply: reply mf payload returned from firmware
1081 * @config_page: contents of the config page
1082 * @sz: size of buffer passed in config_page
1083 * Context: sleep.
1084 *
1085 * Calling function should call config_get_number_hba_phys prior to
1086 * this function, so enough memory is allocated for config_page.
1087 *
1088 * Returns 0 for success, non-zero for failure.
1089 */
1090int
1091mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1092        Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1093        u16 sz)
1094{
1095        Mpi2ConfigRequest_t mpi_request;
1096        int r;
1097
1098        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1099        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1100        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1101        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1102        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1103        mpi_request.Header.PageNumber = 1;
1104        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1105        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1106        r = _config_request(ioc, &mpi_request, mpi_reply,
1107            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1108        if (r)
1109                goto out;
1110
1111        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1112        r = _config_request(ioc, &mpi_request, mpi_reply,
1113            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1114 out:
1115        return r;
1116}
1117
1118/**
1119 * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1120 * @ioc: per adapter object
1121 * @mpi_reply: reply mf payload returned from firmware
1122 * @config_page: contents of the config page
1123 * @sz: size of buffer passed in config_page
1124 * Context: sleep.
1125 *
1126 * Calling function should call config_get_number_hba_phys prior to
1127 * this function, so enough memory is allocated for config_page.
1128 *
1129 * Returns 0 for success, non-zero for failure.
1130 */
1131int
1132mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1133        Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1134        u16 sz)
1135{
1136        Mpi2ConfigRequest_t mpi_request;
1137        int r;
1138
1139        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1140        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1141        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1142        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1143        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1144        mpi_request.Header.PageNumber = 1;
1145        mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1146        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1147        r = _config_request(ioc, &mpi_request, mpi_reply,
1148            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1149        if (r)
1150                goto out;
1151
1152        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1153        _config_request(ioc, &mpi_request, mpi_reply,
1154            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1155        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1156        r = _config_request(ioc, &mpi_request, mpi_reply,
1157            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1158 out:
1159        return r;
1160}
1161
1162/**
1163 * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1164 * @ioc: per adapter object
1165 * @mpi_reply: reply mf payload returned from firmware
1166 * @config_page: contents of the config page
1167 * @form: GET_NEXT_HANDLE or HANDLE
1168 * @handle: expander handle
1169 * Context: sleep.
1170 *
1171 * Returns 0 for success, non-zero for failure.
1172 */
1173int
1174mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1175        *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1176{
1177        Mpi2ConfigRequest_t mpi_request;
1178        int r;
1179
1180        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1181        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1182        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1183        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1184        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1185        mpi_request.Header.PageNumber = 0;
1186        mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1187        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1188        r = _config_request(ioc, &mpi_request, mpi_reply,
1189            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1190        if (r)
1191                goto out;
1192
1193        mpi_request.PageAddress = cpu_to_le32(form | handle);
1194        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1195        r = _config_request(ioc, &mpi_request, mpi_reply,
1196            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1197            sizeof(*config_page));
1198 out:
1199        return r;
1200}
1201
1202/**
1203 * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1204 * @ioc: per adapter object
1205 * @mpi_reply: reply mf payload returned from firmware
1206 * @config_page: contents of the config page
1207 * @phy_number: phy number
1208 * @handle: expander handle
1209 * Context: sleep.
1210 *
1211 * Returns 0 for success, non-zero for failure.
1212 */
1213int
1214mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1215        *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1216        u16 handle)
1217{
1218        Mpi2ConfigRequest_t mpi_request;
1219        int r;
1220
1221        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1222        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1223        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1224        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1225        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1226        mpi_request.Header.PageNumber = 1;
1227        mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1228        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1229        r = _config_request(ioc, &mpi_request, mpi_reply,
1230            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1231        if (r)
1232                goto out;
1233
1234        mpi_request.PageAddress =
1235            cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1236            (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1237        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1238        r = _config_request(ioc, &mpi_request, mpi_reply,
1239            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1240            sizeof(*config_page));
1241 out:
1242        return r;
1243}
1244
1245/**
1246 * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1247 * @ioc: per adapter object
1248 * @mpi_reply: reply mf payload returned from firmware
1249 * @config_page: contents of the config page
1250 * @form: GET_NEXT_HANDLE or HANDLE
1251 * @handle: expander handle
1252 * Context: sleep.
1253 *
1254 * Returns 0 for success, non-zero for failure.
1255 */
1256int
1257mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1258        *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1259{
1260        Mpi2ConfigRequest_t mpi_request;
1261        int r;
1262
1263        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1264        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1265        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1266        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1267        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1268        mpi_request.Header.PageNumber = 0;
1269        mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1270        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1271        r = _config_request(ioc, &mpi_request, mpi_reply,
1272            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1273        if (r)
1274                goto out;
1275
1276        mpi_request.PageAddress = cpu_to_le32(form | handle);
1277        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1278        r = _config_request(ioc, &mpi_request, mpi_reply,
1279            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1280            sizeof(*config_page));
1281 out:
1282        return r;
1283}
1284
1285/**
1286 * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1287 * @ioc: per adapter object
1288 * @mpi_reply: reply mf payload returned from firmware
1289 * @config_page: contents of the config page
1290 * @phy_number: phy number
1291 * Context: sleep.
1292 *
1293 * Returns 0 for success, non-zero for failure.
1294 */
1295int
1296mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1297        *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1298{
1299        Mpi2ConfigRequest_t mpi_request;
1300        int r;
1301
1302        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1303        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1304        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1305        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1306        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1307        mpi_request.Header.PageNumber = 0;
1308        mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1309        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1310        r = _config_request(ioc, &mpi_request, mpi_reply,
1311            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1312        if (r)
1313                goto out;
1314
1315        mpi_request.PageAddress =
1316            cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1317        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1318        r = _config_request(ioc, &mpi_request, mpi_reply,
1319            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1320            sizeof(*config_page));
1321 out:
1322        return r;
1323}
1324
1325/**
1326 * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1327 * @ioc: per adapter object
1328 * @mpi_reply: reply mf payload returned from firmware
1329 * @config_page: contents of the config page
1330 * @phy_number: phy number
1331 * Context: sleep.
1332 *
1333 * Returns 0 for success, non-zero for failure.
1334 */
1335int
1336mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1337        *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1338{
1339        Mpi2ConfigRequest_t mpi_request;
1340        int r;
1341
1342        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1343        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1344        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1345        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1346        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1347        mpi_request.Header.PageNumber = 1;
1348        mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1349        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1350        r = _config_request(ioc, &mpi_request, mpi_reply,
1351            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1352        if (r)
1353                goto out;
1354
1355        mpi_request.PageAddress =
1356            cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1357        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1358        r = _config_request(ioc, &mpi_request, mpi_reply,
1359            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1360            sizeof(*config_page));
1361 out:
1362        return r;
1363}
1364
1365/**
1366 * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1367 * @ioc: per adapter object
1368 * @mpi_reply: reply mf payload returned from firmware
1369 * @config_page: contents of the config page
1370 * @form: GET_NEXT_HANDLE or HANDLE
1371 * @handle: volume handle
1372 * Context: sleep.
1373 *
1374 * Returns 0 for success, non-zero for failure.
1375 */
1376int
1377mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1378        Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1379        u32 handle)
1380{
1381        Mpi2ConfigRequest_t mpi_request;
1382        int r;
1383
1384        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1385        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1386        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1387        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1388        mpi_request.Header.PageNumber = 1;
1389        mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1390        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1391        r = _config_request(ioc, &mpi_request, mpi_reply,
1392            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1393        if (r)
1394                goto out;
1395
1396        mpi_request.PageAddress = cpu_to_le32(form | handle);
1397        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1398        r = _config_request(ioc, &mpi_request, mpi_reply,
1399            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1400            sizeof(*config_page));
1401 out:
1402        return r;
1403}
1404
1405/**
1406 * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1407 * @ioc: per adapter object
1408 * @handle: volume handle
1409 * @num_pds: returns pds count
1410 * Context: sleep.
1411 *
1412 * Returns 0 for success, non-zero for failure.
1413 */
1414int
1415mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1416        u8 *num_pds)
1417{
1418        Mpi2ConfigRequest_t mpi_request;
1419        Mpi2RaidVolPage0_t config_page;
1420        Mpi2ConfigReply_t mpi_reply;
1421        int r;
1422        u16 ioc_status;
1423
1424        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1425        *num_pds = 0;
1426        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1427        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1428        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1429        mpi_request.Header.PageNumber = 0;
1430        mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1431        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1432        r = _config_request(ioc, &mpi_request, &mpi_reply,
1433            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1434        if (r)
1435                goto out;
1436
1437        mpi_request.PageAddress =
1438            cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1439        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1440        r = _config_request(ioc, &mpi_request, &mpi_reply,
1441            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1442            sizeof(Mpi2RaidVolPage0_t));
1443        if (!r) {
1444                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1445                    MPI2_IOCSTATUS_MASK;
1446                if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1447                        *num_pds = config_page.NumPhysDisks;
1448        }
1449
1450 out:
1451        return r;
1452}
1453
1454/**
1455 * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1456 * @ioc: per adapter object
1457 * @mpi_reply: reply mf payload returned from firmware
1458 * @config_page: contents of the config page
1459 * @form: GET_NEXT_HANDLE or HANDLE
1460 * @handle: volume handle
1461 * @sz: size of buffer passed in config_page
1462 * Context: sleep.
1463 *
1464 * Returns 0 for success, non-zero for failure.
1465 */
1466int
1467mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1468        Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1469        u32 handle, u16 sz)
1470{
1471        Mpi2ConfigRequest_t mpi_request;
1472        int r;
1473
1474        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1475        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1476        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1477        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1478        mpi_request.Header.PageNumber = 0;
1479        mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1480        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1481        r = _config_request(ioc, &mpi_request, mpi_reply,
1482            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1483        if (r)
1484                goto out;
1485
1486        mpi_request.PageAddress = cpu_to_le32(form | handle);
1487        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1488        r = _config_request(ioc, &mpi_request, mpi_reply,
1489            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1490 out:
1491        return r;
1492}
1493
1494/**
1495 * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1496 * @ioc: per adapter object
1497 * @mpi_reply: reply mf payload returned from firmware
1498 * @config_page: contents of the config page
1499 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1500 * @form_specific: specific to the form
1501 * Context: sleep.
1502 *
1503 * Returns 0 for success, non-zero for failure.
1504 */
1505int
1506mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1507        *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1508        u32 form_specific)
1509{
1510        Mpi2ConfigRequest_t mpi_request;
1511        int r;
1512
1513        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1514        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1515        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1516        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1517        mpi_request.Header.PageNumber = 0;
1518        mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1519        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1520        r = _config_request(ioc, &mpi_request, mpi_reply,
1521            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1522        if (r)
1523                goto out;
1524
1525        mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1526        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1527        r = _config_request(ioc, &mpi_request, mpi_reply,
1528            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1529            sizeof(*config_page));
1530 out:
1531        return r;
1532}
1533
1534/**
1535 * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
1536 * raid components
1537 * @ioc: per adapter object
1538 * @pd_handle: phys disk handle
1539 * @volume_handle: volume handle
1540 * Context: sleep.
1541 *
1542 * Returns 0 for success, non-zero for failure.
1543 */
1544int
1545mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
1546        u16 *volume_handle)
1547{
1548        Mpi2RaidConfigurationPage0_t *config_page = NULL;
1549        Mpi2ConfigRequest_t mpi_request;
1550        Mpi2ConfigReply_t mpi_reply;
1551        int r, i, config_page_sz;
1552        u16 ioc_status;
1553        int config_num;
1554        u16 element_type;
1555        u16 phys_disk_dev_handle;
1556
1557        *volume_handle = 0;
1558        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1559        mpi_request.Function = MPI2_FUNCTION_CONFIG;
1560        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1561        mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1562        mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1563        mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1564        mpi_request.Header.PageNumber = 0;
1565        ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1566        r = _config_request(ioc, &mpi_request, &mpi_reply,
1567            MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1568        if (r)
1569                goto out;
1570
1571        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1572        config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1573        config_page = kmalloc(config_page_sz, GFP_KERNEL);
1574        if (!config_page) {
1575                r = -1;
1576                goto out;
1577        }
1578
1579        config_num = 0xff;
1580        while (1) {
1581                mpi_request.PageAddress = cpu_to_le32(config_num +
1582                    MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1583                r = _config_request(ioc, &mpi_request, &mpi_reply,
1584                    MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1585                    config_page_sz);
1586                if (r)
1587                        goto out;
1588                r = -1;
1589                ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1590                    MPI2_IOCSTATUS_MASK;
1591                if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1592                        goto out;
1593                for (i = 0; i < config_page->NumElements; i++) {
1594                        element_type = le16_to_cpu(config_page->
1595                            ConfigElement[i].ElementFlags) &
1596                            MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1597                        if (element_type ==
1598                            MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1599                            element_type ==
1600                            MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1601                                phys_disk_dev_handle =
1602                                    le16_to_cpu(config_page->ConfigElement[i].
1603                                    PhysDiskDevHandle);
1604                                if (phys_disk_dev_handle == pd_handle) {
1605                                        *volume_handle =
1606                                            le16_to_cpu(config_page->
1607                                            ConfigElement[i].VolDevHandle);
1608                                        r = 0;
1609                                        goto out;
1610                                }
1611                        } else if (element_type ==
1612                            MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1613                                *volume_handle = 0;
1614                                r = 0;
1615                                goto out;
1616                        }
1617                }
1618                config_num = config_page->ConfigNum;
1619        }
1620 out:
1621        kfree(config_page);
1622        return r;
1623}
1624
1625/**
1626 * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
1627 * @ioc: per adapter object
1628 * @volume_handle: volume handle
1629 * @wwid: volume wwid
1630 * Context: sleep.
1631 *
1632 * Returns 0 for success, non-zero for failure.
1633 */
1634int
1635mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
1636        u64 *wwid)
1637{
1638        Mpi2ConfigReply_t mpi_reply;
1639        Mpi2RaidVolPage1_t raid_vol_pg1;
1640
1641        *wwid = 0;
1642        if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1643            &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1644            volume_handle))) {
1645                *wwid = le64_to_cpu(raid_vol_pg1.WWID);
1646                return 0;
1647        } else
1648                return -1;
1649}
1650