cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mpt3sas_config.c (84385B)


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