File Index
Files and directories
Sign in
FILE

mpt3sas_config.c

File preview with syntax highlighting.

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