Linux Audio

Check our new training course

Loading...
   1/*
   2 * This module provides common API for accessing firmware configuration pages
   3 *
   4 * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
   5 * Copyright (C) 2007-2010  LSI Corporation
   6 *  (mailto:DL-MPTFusionLinux@lsi.com)
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License
  10 * as published by the Free Software Foundation; either version 2
  11 * of the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * NO WARRANTY
  19 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
  20 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
  21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
  22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
  23 * solely responsible for determining the appropriateness of using and
  24 * distributing the Program and assumes all risks associated with its
  25 * exercise of rights under this Agreement, including but not limited to
  26 * the risks and costs of program errors, damage to or loss of data,
  27 * programs or equipment, and unavailability or interruption of operations.
  28
  29 * DISCLAIMER OF LIABILITY
  30 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
  31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
  33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  35 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
  36 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
  37
  38 * You should have received a copy of the GNU General Public License
  39 * along with this program; if not, write to the Free Software
  40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  41 * USA.
  42 */
  43
  44#include <linux/module.h>
  45#include <linux/kernel.h>
  46#include <linux/init.h>
  47#include <linux/errno.h>
  48#include <linux/blkdev.h>
  49#include <linux/sched.h>
  50#include <linux/workqueue.h>
  51#include <linux/delay.h>
  52#include <linux/pci.h>
  53#include <linux/slab.h>
  54
  55#include "mpt2sas_base.h"
  56
  57/* local definitions */
  58
  59/* Timeout for config page request (in seconds) */
  60#define MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT 15
  61
  62/* Common sgl flags for READING a config page. */
  63#define MPT2_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 MPT2_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#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
  87/**
  88 * _config_display_some_debug - debug routine
  89 * @ioc: per adapter object
  90 * @smid: system request message index
  91 * @calling_function_name: string pass from calling function
  92 * @mpi_reply: reply message frame
  93 * Context: none.
  94 *
  95 * Function for displaying debug info helpful when debugging issues
  96 * in this module.
  97 */
  98static void
  99_config_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
 100    char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
 101{
 102	Mpi2ConfigRequest_t *mpi_request;
 103	char *desc = NULL;
 104
 105	if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
 106		return;
 107
 108	mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
 109	switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
 110	case MPI2_CONFIG_PAGETYPE_IO_UNIT:
 111		desc = "io_unit";
 112		break;
 113	case MPI2_CONFIG_PAGETYPE_IOC:
 114		desc = "ioc";
 115		break;
 116	case MPI2_CONFIG_PAGETYPE_BIOS:
 117		desc = "bios";
 118		break;
 119	case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
 120		desc = "raid_volume";
 121		break;
 122	case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
 123		desc = "manufaucturing";
 124		break;
 125	case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
 126		desc = "physdisk";
 127		break;
 128	case MPI2_CONFIG_PAGETYPE_EXTENDED:
 129		switch (mpi_request->ExtPageType) {
 130		case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
 131			desc = "sas_io_unit";
 132			break;
 133		case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
 134			desc = "sas_expander";
 135			break;
 136		case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
 137			desc = "sas_device";
 138			break;
 139		case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
 140			desc = "sas_phy";
 141			break;
 142		case MPI2_CONFIG_EXTPAGETYPE_LOG:
 143			desc = "log";
 144			break;
 145		case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
 146			desc = "enclosure";
 147			break;
 148		case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
 149			desc = "raid_config";
 150			break;
 151		case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
 152			desc = "driver_mapping";
 153			break;
 154		}
 155		break;
 156	}
 157
 158	if (!desc)
 159		return;
 160
 161	printk(MPT2SAS_INFO_FMT "%s: %s(%d), action(%d), form(0x%08x), "
 162	    "smid(%d)\n", ioc->name, calling_function_name, desc,
 163	    mpi_request->Header.PageNumber, mpi_request->Action,
 164	    le32_to_cpu(mpi_request->PageAddress), smid);
 165
 166	if (!mpi_reply)
 167		return;
 168
 169	if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
 170		printk(MPT2SAS_INFO_FMT
 171		    "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
 172		    ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
 173		    le32_to_cpu(mpi_reply->IOCLogInfo));
 174}
 175#endif
 176
 177/**
 178 * _config_alloc_config_dma_memory - obtain physical memory
 179 * @ioc: per adapter object
 180 * @mem: struct config_request
 181 *
 182 * A wrapper for obtaining dma-able memory for config page request.
 183 *
 184 * Returns 0 for success, non-zero for failure.
 185 */
 186static int
 187_config_alloc_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
 188    struct config_request *mem)
 189{
 190	int r = 0;
 191
 192	if (mem->sz > ioc->config_page_sz) {
 193		mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
 194		    &mem->page_dma, GFP_KERNEL);
 195		if (!mem->page) {
 196			printk(MPT2SAS_ERR_FMT "%s: dma_alloc_coherent"
 197			    " failed asking for (%d) bytes!!\n",
 198			    ioc->name, __func__, mem->sz);
 199			r = -ENOMEM;
 200		}
 201	} else { /* use tmp buffer if less than 512 bytes */
 202		mem->page = ioc->config_page;
 203		mem->page_dma = ioc->config_page_dma;
 204	}
 205	return r;
 206}
 207
 208/**
 209 * _config_free_config_dma_memory - wrapper to free the memory
 210 * @ioc: per adapter object
 211 * @mem: struct config_request
 212 *
 213 * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
 214 *
 215 * Returns 0 for success, non-zero for failure.
 216 */
 217static void
 218_config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
 219    struct config_request *mem)
 220{
 221	if (mem->sz > ioc->config_page_sz)
 222		dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
 223		    mem->page_dma);
 224}
 225
 226/**
 227 * mpt2sas_config_done - config page completion routine
 228 * @ioc: per adapter object
 229 * @smid: system request message index
 230 * @msix_index: MSIX table index supplied by the OS
 231 * @reply: reply message frame(lower 32bit addr)
 232 * Context: none.
 233 *
 234 * The callback handler when using _config_request.
 235 *
 236 * Return 1 meaning mf should be freed from _base_interrupt
 237 *        0 means the mf is freed from this function.
 238 */
 239u8
 240mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
 241    u32 reply)
 242{
 243	MPI2DefaultReply_t *mpi_reply;
 244
 245	if (ioc->config_cmds.status == MPT2_CMD_NOT_USED)
 246		return 1;
 247	if (ioc->config_cmds.smid != smid)
 248		return 1;
 249	ioc->config_cmds.status |= MPT2_CMD_COMPLETE;
 250	mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
 251	if (mpi_reply) {
 252		ioc->config_cmds.status |= MPT2_CMD_REPLY_VALID;
 253		memcpy(ioc->config_cmds.reply, mpi_reply,
 254		    mpi_reply->MsgLength*4);
 255	}
 256	ioc->config_cmds.status &= ~MPT2_CMD_PENDING;
 257#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 258	_config_display_some_debug(ioc, smid, "config_done", mpi_reply);
 259#endif
 260	ioc->config_cmds.smid = USHRT_MAX;
 261	complete(&ioc->config_cmds.done);
 262	return 1;
 263}
 264
 265/**
 266 * _config_request - main routine for sending config page requests
 267 * @ioc: per adapter object
 268 * @mpi_request: request message frame
 269 * @mpi_reply: reply mf payload returned from firmware
 270 * @timeout: timeout in seconds
 271 * @config_page: contents of the config page
 272 * @config_page_sz: size of config page
 273 * Context: sleep
 274 *
 275 * A generic API for config page requests to firmware.
 276 *
 277 * The ioc->config_cmds.status flag should be MPT2_CMD_NOT_USED before calling
 278 * this API.
 279 *
 280 * The callback index is set inside `ioc->config_cb_idx.
 281 *
 282 * Returns 0 for success, non-zero for failure.
 283 */
 284static int
 285_config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
 286    *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
 287    void *config_page, u16 config_page_sz)
 288{
 289	u16 smid;
 290	u32 ioc_state;
 291	unsigned long timeleft;
 292	Mpi2ConfigRequest_t *config_request;
 293	int r;
 294	u8 retry_count, issue_host_reset = 0;
 295	u16 wait_state_count;
 296	struct config_request mem;
 297
 298	mutex_lock(&ioc->config_cmds.mutex);
 299	if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) {
 300		printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n",
 301		    ioc->name, __func__);
 302		mutex_unlock(&ioc->config_cmds.mutex);
 303		return -EAGAIN;
 304	}
 305
 306	retry_count = 0;
 307	memset(&mem, 0, sizeof(struct config_request));
 308
 309	mpi_request->VF_ID = 0; /* TODO */
 310	mpi_request->VP_ID = 0;
 311
 312	if (config_page) {
 313		mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
 314		mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
 315		mpi_request->Header.PageType = mpi_reply->Header.PageType;
 316		mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
 317		mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
 318		mpi_request->ExtPageType = mpi_reply->ExtPageType;
 319		if (mpi_request->Header.PageLength)
 320			mem.sz = mpi_request->Header.PageLength * 4;
 321		else
 322			mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
 323		r = _config_alloc_config_dma_memory(ioc, &mem);
 324		if (r != 0)
 325			goto out;
 326		if (mpi_request->Action ==
 327		    MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
 328		    mpi_request->Action ==
 329		    MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
 330			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
 331			    MPT2_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
 332			    mem.page_dma);
 333			memcpy(mem.page, config_page, min_t(u16, mem.sz,
 334			    config_page_sz));
 335		} else {
 336			memset(config_page, 0, config_page_sz);
 337			ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
 338			    MPT2_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
 339		}
 340	}
 341
 342 retry_config:
 343	if (retry_count) {
 344		if (retry_count > 2) { /* attempt only 2 retries */
 345			r = -EFAULT;
 346			goto free_mem;
 347		}
 348		printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n",
 349		    ioc->name, __func__, retry_count);
 350	}
 351	wait_state_count = 0;
 352	ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
 353	while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
 354		if (wait_state_count++ == MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT) {
 355			printk(MPT2SAS_ERR_FMT
 356			    "%s: failed due to ioc not operational\n",
 357			    ioc->name, __func__);
 358			ioc->config_cmds.status = MPT2_CMD_NOT_USED;
 359			r = -EFAULT;
 360			goto free_mem;
 361		}
 362		ssleep(1);
 363		ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
 364		printk(MPT2SAS_INFO_FMT "%s: waiting for "
 365		    "operational state(count=%d)\n", ioc->name,
 366		    __func__, wait_state_count);
 367	}
 368	if (wait_state_count)
 369		printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
 370		    ioc->name, __func__);
 371
 372	smid = mpt2sas_base_get_smid(ioc, ioc->config_cb_idx);
 373	if (!smid) {
 374		printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
 375		    ioc->name, __func__);
 376		ioc->config_cmds.status = MPT2_CMD_NOT_USED;
 377		r = -EAGAIN;
 378		goto free_mem;
 379	}
 380
 381	r = 0;
 382	memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
 383	ioc->config_cmds.status = MPT2_CMD_PENDING;
 384	config_request = mpt2sas_base_get_msg_frame(ioc, smid);
 385	ioc->config_cmds.smid = smid;
 386	memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
 387#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 388	_config_display_some_debug(ioc, smid, "config_request", NULL);
 389#endif
 390	init_completion(&ioc->config_cmds.done);
 391	mpt2sas_base_put_smid_default(ioc, smid);
 392	timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
 393	    timeout*HZ);
 394	if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) {
 395		printk(MPT2SAS_ERR_FMT "%s: timeout\n",
 396		    ioc->name, __func__);
 397		_debug_dump_mf(mpi_request,
 398		    sizeof(Mpi2ConfigRequest_t)/4);
 399		retry_count++;
 400		if (ioc->config_cmds.smid == smid)
 401			mpt2sas_base_free_smid(ioc, smid);
 402		if ((ioc->shost_recovery) || (ioc->config_cmds.status &
 403		    MPT2_CMD_RESET) || ioc->pci_error_recovery)
 404			goto retry_config;
 405		issue_host_reset = 1;
 406		r = -EFAULT;
 407		goto free_mem;
 408	}
 409
 410	if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID)
 411		memcpy(mpi_reply, ioc->config_cmds.reply,
 412		    sizeof(Mpi2ConfigReply_t));
 413	if (retry_count)
 414		printk(MPT2SAS_INFO_FMT "%s: retry (%d) completed!!\n",
 415		    ioc->name, __func__, retry_count);
 416	if (config_page && mpi_request->Action ==
 417	    MPI2_CONFIG_ACTION_PAGE_READ_CURRENT)
 418		memcpy(config_page, mem.page, min_t(u16, mem.sz,
 419		    config_page_sz));
 420 free_mem:
 421	if (config_page)
 422		_config_free_config_dma_memory(ioc, &mem);
 423 out:
 424	ioc->config_cmds.status = MPT2_CMD_NOT_USED;
 425	mutex_unlock(&ioc->config_cmds.mutex);
 426
 427	if (issue_host_reset)
 428		mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
 429		    FORCE_BIG_HAMMER);
 430	return r;
 431}
 432
 433/**
 434 * mpt2sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
 435 * @ioc: per adapter object
 436 * @mpi_reply: reply mf payload returned from firmware
 437 * @config_page: contents of the config page
 438 * Context: sleep.
 439 *
 440 * Returns 0 for success, non-zero for failure.
 441 */
 442int
 443mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
 444    Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
 445{
 446	Mpi2ConfigRequest_t mpi_request;
 447	int r;
 448
 449	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 450	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 451	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 452	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
 453	mpi_request.Header.PageNumber = 0;
 454	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
 455	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 456	r = _config_request(ioc, &mpi_request, mpi_reply,
 457	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 458	if (r)
 459		goto out;
 460
 461	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 462	r = _config_request(ioc, &mpi_request, mpi_reply,
 463	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 464	    sizeof(*config_page));
 465 out:
 466	return r;
 467}
 468
 469/**
 470 * mpt2sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
 471 * @ioc: per adapter object
 472 * @mpi_reply: reply mf payload returned from firmware
 473 * @config_page: contents of the config page
 474 * Context: sleep.
 475 *
 476 * Returns 0 for success, non-zero for failure.
 477 */
 478int
 479mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc,
 480    Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page)
 481{
 482	Mpi2ConfigRequest_t mpi_request;
 483	int r;
 484
 485	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 486	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 487	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 488	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
 489	mpi_request.Header.PageNumber = 10;
 490	mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
 491	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 492	r = _config_request(ioc, &mpi_request, mpi_reply,
 493	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 494	if (r)
 495		goto out;
 496
 497	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 498	r = _config_request(ioc, &mpi_request, mpi_reply,
 499	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 500	    sizeof(*config_page));
 501 out:
 502	return r;
 503}
 504
 505/**
 506 * mpt2sas_config_get_bios_pg2 - obtain bios page 2
 507 * @ioc: per adapter object
 508 * @mpi_reply: reply mf payload returned from firmware
 509 * @config_page: contents of the config page
 510 * Context: sleep.
 511 *
 512 * Returns 0 for success, non-zero for failure.
 513 */
 514int
 515mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc,
 516    Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
 517{
 518	Mpi2ConfigRequest_t mpi_request;
 519	int r;
 520
 521	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 522	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 523	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 524	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
 525	mpi_request.Header.PageNumber = 2;
 526	mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
 527	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 528	r = _config_request(ioc, &mpi_request, mpi_reply,
 529	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 530	if (r)
 531		goto out;
 532
 533	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 534	r = _config_request(ioc, &mpi_request, mpi_reply,
 535	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 536	    sizeof(*config_page));
 537 out:
 538	return r;
 539}
 540
 541/**
 542 * mpt2sas_config_get_bios_pg3 - obtain bios page 3
 543 * @ioc: per adapter object
 544 * @mpi_reply: reply mf payload returned from firmware
 545 * @config_page: contents of the config page
 546 * Context: sleep.
 547 *
 548 * Returns 0 for success, non-zero for failure.
 549 */
 550int
 551mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
 552    *mpi_reply, Mpi2BiosPage3_t *config_page)
 553{
 554	Mpi2ConfigRequest_t mpi_request;
 555	int r;
 556
 557	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 558	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 559	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 560	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
 561	mpi_request.Header.PageNumber = 3;
 562	mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
 563	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 564	r = _config_request(ioc, &mpi_request, mpi_reply,
 565	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 566	if (r)
 567		goto out;
 568
 569	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 570	r = _config_request(ioc, &mpi_request, mpi_reply,
 571	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 572	    sizeof(*config_page));
 573 out:
 574	return r;
 575}
 576
 577/**
 578 * mpt2sas_config_get_iounit_pg0 - obtain iounit page 0
 579 * @ioc: per adapter object
 580 * @mpi_reply: reply mf payload returned from firmware
 581 * @config_page: contents of the config page
 582 * Context: sleep.
 583 *
 584 * Returns 0 for success, non-zero for failure.
 585 */
 586int
 587mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc,
 588    Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
 589{
 590	Mpi2ConfigRequest_t mpi_request;
 591	int r;
 592
 593	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 594	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 595	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 596	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
 597	mpi_request.Header.PageNumber = 0;
 598	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
 599	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 600	r = _config_request(ioc, &mpi_request, mpi_reply,
 601	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 602	if (r)
 603		goto out;
 604
 605	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 606	r = _config_request(ioc, &mpi_request, mpi_reply,
 607	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 608	    sizeof(*config_page));
 609 out:
 610	return r;
 611}
 612
 613/**
 614 * mpt2sas_config_get_iounit_pg1 - obtain iounit page 1
 615 * @ioc: per adapter object
 616 * @mpi_reply: reply mf payload returned from firmware
 617 * @config_page: contents of the config page
 618 * Context: sleep.
 619 *
 620 * Returns 0 for success, non-zero for failure.
 621 */
 622int
 623mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
 624    Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
 625{
 626	Mpi2ConfigRequest_t mpi_request;
 627	int r;
 628
 629	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 630	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 631	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 632	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
 633	mpi_request.Header.PageNumber = 1;
 634	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
 635	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 636	r = _config_request(ioc, &mpi_request, mpi_reply,
 637	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 638	if (r)
 639		goto out;
 640
 641	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 642	r = _config_request(ioc, &mpi_request, mpi_reply,
 643	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 644	    sizeof(*config_page));
 645 out:
 646	return r;
 647}
 648
 649/**
 650 * mpt2sas_config_set_iounit_pg1 - set iounit page 1
 651 * @ioc: per adapter object
 652 * @mpi_reply: reply mf payload returned from firmware
 653 * @config_page: contents of the config page
 654 * Context: sleep.
 655 *
 656 * Returns 0 for success, non-zero for failure.
 657 */
 658int
 659mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
 660    Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
 661{
 662	Mpi2ConfigRequest_t mpi_request;
 663	int r;
 664
 665	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 666	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 667	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 668	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
 669	mpi_request.Header.PageNumber = 1;
 670	mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
 671	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 672	r = _config_request(ioc, &mpi_request, mpi_reply,
 673	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 674	if (r)
 675		goto out;
 676
 677	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 678	r = _config_request(ioc, &mpi_request, mpi_reply,
 679	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 680	    sizeof(*config_page));
 681 out:
 682	return r;
 683}
 684
 685/**
 686 * mpt2sas_config_get_ioc_pg8 - obtain ioc page 8
 687 * @ioc: per adapter object
 688 * @mpi_reply: reply mf payload returned from firmware
 689 * @config_page: contents of the config page
 690 * Context: sleep.
 691 *
 692 * Returns 0 for success, non-zero for failure.
 693 */
 694int
 695mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc,
 696    Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
 697{
 698	Mpi2ConfigRequest_t mpi_request;
 699	int r;
 700
 701	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 702	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 703	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 704	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
 705	mpi_request.Header.PageNumber = 8;
 706	mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
 707	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 708	r = _config_request(ioc, &mpi_request, mpi_reply,
 709	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 710	if (r)
 711		goto out;
 712
 713	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 714	r = _config_request(ioc, &mpi_request, mpi_reply,
 715	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 716	    sizeof(*config_page));
 717 out:
 718	return r;
 719}
 720
 721/**
 722 * mpt2sas_config_get_sas_device_pg0 - obtain sas device page 0
 723 * @ioc: per adapter object
 724 * @mpi_reply: reply mf payload returned from firmware
 725 * @config_page: contents of the config page
 726 * @form: GET_NEXT_HANDLE or HANDLE
 727 * @handle: device handle
 728 * Context: sleep.
 729 *
 730 * Returns 0 for success, non-zero for failure.
 731 */
 732int
 733mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
 734    *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle)
 735{
 736	Mpi2ConfigRequest_t mpi_request;
 737	int r;
 738
 739	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 740	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 741	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 742	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 743	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
 744	mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
 745	mpi_request.Header.PageNumber = 0;
 746	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 747	r = _config_request(ioc, &mpi_request, mpi_reply,
 748	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 749	if (r)
 750		goto out;
 751
 752	mpi_request.PageAddress = cpu_to_le32(form | handle);
 753	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 754	r = _config_request(ioc, &mpi_request, mpi_reply,
 755	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 756	    sizeof(*config_page));
 757 out:
 758	return r;
 759}
 760
 761/**
 762 * mpt2sas_config_get_sas_device_pg1 - obtain sas device page 1
 763 * @ioc: per adapter object
 764 * @mpi_reply: reply mf payload returned from firmware
 765 * @config_page: contents of the config page
 766 * @form: GET_NEXT_HANDLE or HANDLE
 767 * @handle: device handle
 768 * Context: sleep.
 769 *
 770 * Returns 0 for success, non-zero for failure.
 771 */
 772int
 773mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
 774    *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle)
 775{
 776	Mpi2ConfigRequest_t mpi_request;
 777	int r;
 778
 779	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 780	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 781	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 782	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 783	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
 784	mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
 785	mpi_request.Header.PageNumber = 1;
 786	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 787	r = _config_request(ioc, &mpi_request, mpi_reply,
 788	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 789	if (r)
 790		goto out;
 791
 792	mpi_request.PageAddress = cpu_to_le32(form | handle);
 793	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 794	r = _config_request(ioc, &mpi_request, mpi_reply,
 795	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
 796	    sizeof(*config_page));
 797 out:
 798	return r;
 799}
 800
 801/**
 802 * mpt2sas_config_get_number_hba_phys - obtain number of phys on the host
 803 * @ioc: per adapter object
 804 * @num_phys: pointer returned with the number of phys
 805 * Context: sleep.
 806 *
 807 * Returns 0 for success, non-zero for failure.
 808 */
 809int
 810mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys)
 811{
 812	Mpi2ConfigRequest_t mpi_request;
 813	int r;
 814	u16 ioc_status;
 815	Mpi2ConfigReply_t mpi_reply;
 816	Mpi2SasIOUnitPage0_t config_page;
 817
 818	*num_phys = 0;
 819	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 820	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 821	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 822	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 823	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
 824	mpi_request.Header.PageNumber = 0;
 825	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
 826	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 827	r = _config_request(ioc, &mpi_request, &mpi_reply,
 828	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 829	if (r)
 830		goto out;
 831
 832	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 833	r = _config_request(ioc, &mpi_request, &mpi_reply,
 834	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
 835	    sizeof(Mpi2SasIOUnitPage0_t));
 836	if (!r) {
 837		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
 838		    MPI2_IOCSTATUS_MASK;
 839		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
 840			*num_phys = config_page.NumPhys;
 841	}
 842 out:
 843	return r;
 844}
 845
 846/**
 847 * mpt2sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
 848 * @ioc: per adapter object
 849 * @mpi_reply: reply mf payload returned from firmware
 850 * @config_page: contents of the config page
 851 * @sz: size of buffer passed in config_page
 852 * Context: sleep.
 853 *
 854 * Calling function should call config_get_number_hba_phys prior to
 855 * this function, so enough memory is allocated for config_page.
 856 *
 857 * Returns 0 for success, non-zero for failure.
 858 */
 859int
 860mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
 861    *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz)
 862{
 863	Mpi2ConfigRequest_t mpi_request;
 864	int r;
 865
 866	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 867	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 868	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 869	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 870	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
 871	mpi_request.Header.PageNumber = 0;
 872	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
 873	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 874	r = _config_request(ioc, &mpi_request, mpi_reply,
 875	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 876	if (r)
 877		goto out;
 878
 879	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 880	r = _config_request(ioc, &mpi_request, mpi_reply,
 881	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
 882 out:
 883	return r;
 884}
 885
 886/**
 887 * mpt2sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
 888 * @ioc: per adapter object
 889 * @mpi_reply: reply mf payload returned from firmware
 890 * @config_page: contents of the config page
 891 * @sz: size of buffer passed in config_page
 892 * Context: sleep.
 893 *
 894 * Calling function should call config_get_number_hba_phys prior to
 895 * this function, so enough memory is allocated for config_page.
 896 *
 897 * Returns 0 for success, non-zero for failure.
 898 */
 899int
 900mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
 901    *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz)
 902{
 903	Mpi2ConfigRequest_t mpi_request;
 904	int r;
 905
 906	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 907	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 908	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 909	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 910	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
 911	mpi_request.Header.PageNumber = 1;
 912	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
 913	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 914	r = _config_request(ioc, &mpi_request, mpi_reply,
 915	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 916	if (r)
 917		goto out;
 918
 919	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
 920	r = _config_request(ioc, &mpi_request, mpi_reply,
 921	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
 922 out:
 923	return r;
 924}
 925
 926/**
 927 * mpt2sas_config_set_sas_iounit_pg1 - send sas iounit page 1
 928 * @ioc: per adapter object
 929 * @mpi_reply: reply mf payload returned from firmware
 930 * @config_page: contents of the config page
 931 * @sz: size of buffer passed in config_page
 932 * Context: sleep.
 933 *
 934 * Calling function should call config_get_number_hba_phys prior to
 935 * this function, so enough memory is allocated for config_page.
 936 *
 937 * Returns 0 for success, non-zero for failure.
 938 */
 939int
 940mpt2sas_config_set_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
 941    *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz)
 942{
 943	Mpi2ConfigRequest_t mpi_request;
 944	int r;
 945
 946	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 947	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 948	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 949	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 950	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
 951	mpi_request.Header.PageNumber = 1;
 952	mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
 953	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 954	r = _config_request(ioc, &mpi_request, mpi_reply,
 955	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 956	if (r)
 957		goto out;
 958
 959	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 960	_config_request(ioc, &mpi_request, mpi_reply,
 961	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
 962	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
 963	r = _config_request(ioc, &mpi_request, mpi_reply,
 964	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
 965 out:
 966	return r;
 967}
 968
 969/**
 970 * mpt2sas_config_get_expander_pg0 - obtain expander page 0
 971 * @ioc: per adapter object
 972 * @mpi_reply: reply mf payload returned from firmware
 973 * @config_page: contents of the config page
 974 * @form: GET_NEXT_HANDLE or HANDLE
 975 * @handle: expander handle
 976 * Context: sleep.
 977 *
 978 * Returns 0 for success, non-zero for failure.
 979 */
 980int
 981mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
 982    *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
 983{
 984	Mpi2ConfigRequest_t mpi_request;
 985	int r;
 986
 987	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
 988	mpi_request.Function = MPI2_FUNCTION_CONFIG;
 989	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
 990	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
 991	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
 992	mpi_request.Header.PageNumber = 0;
 993	mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
 994	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
 995	r = _config_request(ioc, &mpi_request, mpi_reply,
 996	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
 997	if (r)
 998		goto out;
 999
1000	mpi_request.PageAddress = cpu_to_le32(form | handle);
1001	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1002	r = _config_request(ioc, &mpi_request, mpi_reply,
1003	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1004	    sizeof(*config_page));
1005 out:
1006	return r;
1007}
1008
1009/**
1010 * mpt2sas_config_get_expander_pg1 - obtain expander page 1
1011 * @ioc: per adapter object
1012 * @mpi_reply: reply mf payload returned from firmware
1013 * @config_page: contents of the config page
1014 * @phy_number: phy number
1015 * @handle: expander handle
1016 * Context: sleep.
1017 *
1018 * Returns 0 for success, non-zero for failure.
1019 */
1020int
1021mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1022    *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1023    u16 handle)
1024{
1025	Mpi2ConfigRequest_t mpi_request;
1026	int r;
1027
1028	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1029	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1030	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1031	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1032	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1033	mpi_request.Header.PageNumber = 1;
1034	mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1035	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1036	r = _config_request(ioc, &mpi_request, mpi_reply,
1037	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1038	if (r)
1039		goto out;
1040
1041	mpi_request.PageAddress =
1042	    cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1043	    (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1044	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1045	r = _config_request(ioc, &mpi_request, mpi_reply,
1046	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1047	    sizeof(*config_page));
1048 out:
1049	return r;
1050}
1051
1052/**
1053 * mpt2sas_config_get_enclosure_pg0 - obtain enclosure page 0
1054 * @ioc: per adapter object
1055 * @mpi_reply: reply mf payload returned from firmware
1056 * @config_page: contents of the config page
1057 * @form: GET_NEXT_HANDLE or HANDLE
1058 * @handle: expander handle
1059 * Context: sleep.
1060 *
1061 * Returns 0 for success, non-zero for failure.
1062 */
1063int
1064mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1065    *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1066{
1067	Mpi2ConfigRequest_t mpi_request;
1068	int r;
1069
1070	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1071	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1072	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1073	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1074	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1075	mpi_request.Header.PageNumber = 0;
1076	mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1077	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1078	r = _config_request(ioc, &mpi_request, mpi_reply,
1079	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1080	if (r)
1081		goto out;
1082
1083	mpi_request.PageAddress = cpu_to_le32(form | handle);
1084	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1085	r = _config_request(ioc, &mpi_request, mpi_reply,
1086	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1087	    sizeof(*config_page));
1088 out:
1089	return r;
1090}
1091
1092/**
1093 * mpt2sas_config_get_phy_pg0 - obtain phy page 0
1094 * @ioc: per adapter object
1095 * @mpi_reply: reply mf payload returned from firmware
1096 * @config_page: contents of the config page
1097 * @phy_number: phy number
1098 * Context: sleep.
1099 *
1100 * Returns 0 for success, non-zero for failure.
1101 */
1102int
1103mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1104    *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1105{
1106	Mpi2ConfigRequest_t mpi_request;
1107	int r;
1108
1109	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1110	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1111	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1112	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1113	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1114	mpi_request.Header.PageNumber = 0;
1115	mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1116	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1117	r = _config_request(ioc, &mpi_request, mpi_reply,
1118	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1119	if (r)
1120		goto out;
1121
1122	mpi_request.PageAddress =
1123	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1124	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1125	r = _config_request(ioc, &mpi_request, mpi_reply,
1126	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1127	    sizeof(*config_page));
1128 out:
1129	return r;
1130}
1131
1132/**
1133 * mpt2sas_config_get_phy_pg1 - obtain phy page 1
1134 * @ioc: per adapter object
1135 * @mpi_reply: reply mf payload returned from firmware
1136 * @config_page: contents of the config page
1137 * @phy_number: phy number
1138 * Context: sleep.
1139 *
1140 * Returns 0 for success, non-zero for failure.
1141 */
1142int
1143mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1144    *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1145{
1146	Mpi2ConfigRequest_t mpi_request;
1147	int r;
1148
1149	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1150	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1151	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1152	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1153	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1154	mpi_request.Header.PageNumber = 1;
1155	mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1156	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1157	r = _config_request(ioc, &mpi_request, mpi_reply,
1158	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1159	if (r)
1160		goto out;
1161
1162	mpi_request.PageAddress =
1163	    cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1164	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1165	r = _config_request(ioc, &mpi_request, mpi_reply,
1166	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1167	    sizeof(*config_page));
1168 out:
1169	return r;
1170}
1171
1172/**
1173 * mpt2sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1174 * @ioc: per adapter object
1175 * @mpi_reply: reply mf payload returned from firmware
1176 * @config_page: contents of the config page
1177 * @form: GET_NEXT_HANDLE or HANDLE
1178 * @handle: volume handle
1179 * Context: sleep.
1180 *
1181 * Returns 0 for success, non-zero for failure.
1182 */
1183int
1184mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc,
1185    Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1186    u32 handle)
1187{
1188	Mpi2ConfigRequest_t mpi_request;
1189	int r;
1190
1191	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1192	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1193	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1194	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1195	mpi_request.Header.PageNumber = 1;
1196	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1197	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1198	r = _config_request(ioc, &mpi_request, mpi_reply,
1199	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1200	if (r)
1201		goto out;
1202
1203	mpi_request.PageAddress = cpu_to_le32(form | handle);
1204	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1205	r = _config_request(ioc, &mpi_request, mpi_reply,
1206	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1207	    sizeof(*config_page));
1208 out:
1209	return r;
1210}
1211
1212/**
1213 * mpt2sas_config_get_number_pds - obtain number of phys disk assigned to volume
1214 * @ioc: per adapter object
1215 * @handle: volume handle
1216 * @num_pds: returns pds count
1217 * Context: sleep.
1218 *
1219 * Returns 0 for success, non-zero for failure.
1220 */
1221int
1222mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle,
1223    u8 *num_pds)
1224{
1225	Mpi2ConfigRequest_t mpi_request;
1226	Mpi2RaidVolPage0_t config_page;
1227	Mpi2ConfigReply_t mpi_reply;
1228	int r;
1229	u16 ioc_status;
1230
1231	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1232	*num_pds = 0;
1233	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1234	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1235	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1236	mpi_request.Header.PageNumber = 0;
1237	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1238	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1239	r = _config_request(ioc, &mpi_request, &mpi_reply,
1240	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1241	if (r)
1242		goto out;
1243
1244	mpi_request.PageAddress =
1245	    cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1246	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1247	r = _config_request(ioc, &mpi_request, &mpi_reply,
1248	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1249	    sizeof(Mpi2RaidVolPage0_t));
1250	if (!r) {
1251		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1252		    MPI2_IOCSTATUS_MASK;
1253		if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1254			*num_pds = config_page.NumPhysDisks;
1255	}
1256
1257 out:
1258	return r;
1259}
1260
1261/**
1262 * mpt2sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1263 * @ioc: per adapter object
1264 * @mpi_reply: reply mf payload returned from firmware
1265 * @config_page: contents of the config page
1266 * @form: GET_NEXT_HANDLE or HANDLE
1267 * @handle: volume handle
1268 * @sz: size of buffer passed in config_page
1269 * Context: sleep.
1270 *
1271 * Returns 0 for success, non-zero for failure.
1272 */
1273int
1274mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc,
1275    Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1276    u32 handle, u16 sz)
1277{
1278	Mpi2ConfigRequest_t mpi_request;
1279	int r;
1280
1281	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1282	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1283	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1284	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1285	mpi_request.Header.PageNumber = 0;
1286	mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1287	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1288	r = _config_request(ioc, &mpi_request, mpi_reply,
1289	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1290	if (r)
1291		goto out;
1292
1293	mpi_request.PageAddress = cpu_to_le32(form | handle);
1294	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1295	r = _config_request(ioc, &mpi_request, mpi_reply,
1296	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1297 out:
1298	return r;
1299}
1300
1301/**
1302 * mpt2sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1303 * @ioc: per adapter object
1304 * @mpi_reply: reply mf payload returned from firmware
1305 * @config_page: contents of the config page
1306 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1307 * @form_specific: specific to the form
1308 * Context: sleep.
1309 *
1310 * Returns 0 for success, non-zero for failure.
1311 */
1312int
1313mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1314    *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1315    u32 form_specific)
1316{
1317	Mpi2ConfigRequest_t mpi_request;
1318	int r;
1319
1320	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1321	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1322	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1323	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1324	mpi_request.Header.PageNumber = 0;
1325	mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1326	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1327	r = _config_request(ioc, &mpi_request, mpi_reply,
1328	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1329	if (r)
1330		goto out;
1331
1332	mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1333	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1334	r = _config_request(ioc, &mpi_request, mpi_reply,
1335	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1336	    sizeof(*config_page));
1337 out:
1338	return r;
1339}
1340
1341/**
1342 * mpt2sas_config_get_volume_handle - returns volume handle for give hidden raid components
1343 * @ioc: per adapter object
1344 * @pd_handle: phys disk handle
1345 * @volume_handle: volume handle
1346 * Context: sleep.
1347 *
1348 * Returns 0 for success, non-zero for failure.
1349 */
1350int
1351mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
1352    u16 *volume_handle)
1353{
1354	Mpi2RaidConfigurationPage0_t *config_page = NULL;
1355	Mpi2ConfigRequest_t mpi_request;
1356	Mpi2ConfigReply_t mpi_reply;
1357	int r, i, config_page_sz;
1358	u16 ioc_status;
1359	int config_num;
1360	u16 element_type;
1361	u16 phys_disk_dev_handle;
1362
1363	*volume_handle = 0;
1364	memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1365	mpi_request.Function = MPI2_FUNCTION_CONFIG;
1366	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1367	mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1368	mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1369	mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1370	mpi_request.Header.PageNumber = 0;
1371	mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1372	r = _config_request(ioc, &mpi_request, &mpi_reply,
1373	    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1374	if (r)
1375		goto out;
1376
1377	mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1378	config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1379	config_page = kmalloc(config_page_sz, GFP_KERNEL);
1380	if (!config_page) {
1381		r = -1;
1382		goto out;
1383	}
1384	config_num = 0xff;
1385	while (1) {
1386		mpi_request.PageAddress = cpu_to_le32(config_num +
1387		    MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1388		r = _config_request(ioc, &mpi_request, &mpi_reply,
1389		    MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1390		    config_page_sz);
1391		if (r)
1392			goto out;
1393		r = -1;
1394		ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1395		    MPI2_IOCSTATUS_MASK;
1396		if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1397			goto out;
1398		for (i = 0; i < config_page->NumElements; i++) {
1399			element_type = le16_to_cpu(config_page->
1400			    ConfigElement[i].ElementFlags) &
1401			    MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1402			if (element_type ==
1403			    MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1404			    element_type ==
1405			    MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1406				phys_disk_dev_handle =
1407				    le16_to_cpu(config_page->ConfigElement[i].
1408				    PhysDiskDevHandle);
1409				if (phys_disk_dev_handle == pd_handle) {
1410					*volume_handle =
1411					    le16_to_cpu(config_page->
1412					    ConfigElement[i].VolDevHandle);
1413					r = 0;
1414					goto out;
1415				}
1416			} else if (element_type ==
1417			    MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1418				*volume_handle = 0;
1419				r = 0;
1420				goto out;
1421			}
1422		}
1423		config_num = config_page->ConfigNum;
1424	}
1425 out:
1426	kfree(config_page);
1427	return r;
1428}
1429
1430/**
1431 * mpt2sas_config_get_volume_wwid - returns wwid given the volume handle
1432 * @ioc: per adapter object
1433 * @volume_handle: volume handle
1434 * @wwid: volume wwid
1435 * Context: sleep.
1436 *
1437 * Returns 0 for success, non-zero for failure.
1438 */
1439int
1440mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
1441    u64 *wwid)
1442{
1443	Mpi2ConfigReply_t mpi_reply;
1444	Mpi2RaidVolPage1_t raid_vol_pg1;
1445
1446	*wwid = 0;
1447	if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1448	    &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1449	    volume_handle))) {
1450		*wwid = le64_to_cpu(raid_vol_pg1.WWID);
1451		return 0;
1452	} else
1453		return -1;
1454}