Linux Audio

Check our new training course

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