1230592Sken/*- 2281564Sslm * Copyright (c) 2011-2015 LSI Corp. 3281564Sslm * Copyright (c) 2013-2015 Avago Technologies 4230592Sken * All rights reserved. 5230592Sken * 6230592Sken * Redistribution and use in source and binary forms, with or without 7230592Sken * modification, are permitted provided that the following conditions 8230592Sken * are met: 9230592Sken * 1. Redistributions of source code must retain the above copyright 10230592Sken * notice, this list of conditions and the following disclaimer. 11230592Sken * 2. Redistributions in binary form must reproduce the above copyright 12230592Sken * notice, this list of conditions and the following disclaimer in the 13230592Sken * documentation and/or other materials provided with the distribution. 14230592Sken * 15230592Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16230592Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17230592Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18230592Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19230592Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20230592Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21230592Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22230592Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23230592Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24230592Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25230592Sken * SUCH DAMAGE. 26230592Sken * 27281564Sslm * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD 28230592Sken */ 29230592Sken 30230592Sken#include <sys/cdefs.h> 31230592Sken__FBSDID("$FreeBSD: releng/10.2/sys/dev/mps/mps_config.c 281564 2015-04-15 21:47:15Z slm $"); 32230592Sken 33230592Sken/* TODO Move headers to mpsvar */ 34230592Sken#include <sys/types.h> 35230592Sken#include <sys/param.h> 36230592Sken#include <sys/lock.h> 37230592Sken#include <sys/mutex.h> 38230592Sken#include <sys/systm.h> 39230592Sken#include <sys/kernel.h> 40230592Sken#include <sys/malloc.h> 41230592Sken#include <sys/kthread.h> 42230592Sken#include <sys/taskqueue.h> 43230592Sken#include <sys/bus.h> 44230592Sken#include <sys/endian.h> 45230592Sken#include <sys/sysctl.h> 46230592Sken#include <sys/eventhandler.h> 47230592Sken#include <sys/uio.h> 48230592Sken#include <machine/bus.h> 49230592Sken#include <machine/resource.h> 50230592Sken#include <dev/mps/mpi/mpi2_type.h> 51230592Sken#include <dev/mps/mpi/mpi2.h> 52230592Sken#include <dev/mps/mpi/mpi2_ioc.h> 53230592Sken#include <dev/mps/mpi/mpi2_sas.h> 54230592Sken#include <dev/mps/mpi/mpi2_cnfg.h> 55230592Sken#include <dev/mps/mpi/mpi2_init.h> 56230592Sken#include <dev/mps/mpi/mpi2_tool.h> 57230592Sken#include <dev/mps/mps_ioctl.h> 58230592Sken#include <dev/mps/mpsvar.h> 59230592Sken 60230592Sken/** 61230592Sken * mps_config_get_ioc_pg8 - obtain ioc page 8 62230592Sken * @sc: per adapter object 63230592Sken * @mpi_reply: reply mf payload returned from firmware 64230592Sken * @config_page: contents of the config page 65230592Sken * Context: sleep. 66230592Sken * 67230592Sken * Returns 0 for success, non-zero for failure. 68230592Sken */ 69230592Skenint 70230592Skenmps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 71230592Sken Mpi2IOCPage8_t *config_page) 72230592Sken{ 73230592Sken MPI2_CONFIG_REQUEST *request; 74230592Sken MPI2_CONFIG_REPLY *reply; 75230592Sken struct mps_command *cm; 76230592Sken MPI2_CONFIG_PAGE_IOC_8 *page = NULL; 77230592Sken int error = 0; 78230592Sken u16 ioc_status; 79230592Sken 80230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 81230592Sken 82230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 83230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 84230592Sken __LINE__); 85230592Sken error = EBUSY; 86230592Sken goto out; 87230592Sken } 88230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 89230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 90230592Sken request->Function = MPI2_FUNCTION_CONFIG; 91230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 92230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 93230592Sken request->Header.PageNumber = 8; 94230592Sken request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 95230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 96230592Sken cm->cm_data = NULL; 97253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 98230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 99230592Sken if (error || (reply == NULL)) { 100230592Sken /* FIXME */ 101253550Sken /* 102253550Sken * If the request returns an error then we need to do a diag 103253550Sken * reset 104253550Sken */ 105253550Sken printf("%s: request for header completed with error %d", 106230592Sken __func__, error); 107230592Sken error = ENXIO; 108230592Sken goto out; 109230592Sken } 110230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 111230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 112230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 113230592Sken /* FIXME */ 114253550Sken /* 115253550Sken * If the request returns an error then we need to do a diag 116253550Sken * reset 117253550Sken */ 118230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 119230592Sken __func__, ioc_status); 120230592Sken error = ENXIO; 121230592Sken goto out; 122230592Sken } 123230592Sken /* We have to do free and alloc for the reply-free and reply-post 124230592Sken * counters to match - Need to review the reply FIFO handling. 125230592Sken */ 126230592Sken mps_free_command(sc, cm); 127230592Sken 128230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 129230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 130230592Sken __LINE__); 131230592Sken error = EBUSY; 132230592Sken goto out; 133230592Sken } 134230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 135230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 136230592Sken request->Function = MPI2_FUNCTION_CONFIG; 137230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 138230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 139230592Sken request->Header.PageNumber = 8; 140230592Sken request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 141230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 142230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 143230592Sken cm->cm_sge = &request->PageBufferSGE; 144230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 145230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 146230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 147230592Sken page = malloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT); 148230592Sken if (!page) { 149230592Sken printf("%s: page alloc failed\n", __func__); 150230592Sken error = ENOMEM; 151230592Sken goto out; 152230592Sken } 153230592Sken cm->cm_data = page; 154253550Sken 155253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 156230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 157230592Sken if (error || (reply == NULL)) { 158230592Sken /* FIXME */ 159253550Sken /* 160253550Sken * If the request returns an error then we need to do a diag 161253550Sken * reset 162253550Sken */ 163253550Sken printf("%s: request for page completed with error %d", 164230592Sken __func__, error); 165230592Sken error = ENXIO; 166230592Sken goto out; 167230592Sken } 168230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 169230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 170230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 171230592Sken /* FIXME */ 172253550Sken /* 173253550Sken * If the request returns an error then we need to do a diag 174253550Sken * reset 175253550Sken */ 176230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 177230592Sken __func__, ioc_status); 178230592Sken error = ENXIO; 179230592Sken goto out; 180230592Sken } 181230592Sken bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t)))); 182230592Sken 183230592Skenout: 184230592Sken free(page, M_MPT2); 185230592Sken if (cm) 186230592Sken mps_free_command(sc, cm); 187230592Sken return (error); 188230592Sken} 189230592Sken 190230592Sken/** 191230592Sken * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags 192230592Sken * accordingly. Currently, this page does not need to return to caller. 193230592Sken * @sc: per adapter object 194230592Sken * @mpi_reply: reply mf payload returned from firmware 195230592Sken * Context: sleep. 196230592Sken * 197230592Sken * Returns 0 for success, non-zero for failure. 198230592Sken */ 199230592Skenint 200230592Skenmps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply) 201230592Sken{ 202230592Sken MPI2_CONFIG_REQUEST *request; 203230592Sken MPI2_CONFIG_REPLY *reply; 204230592Sken struct mps_command *cm; 205230592Sken pMpi2ManufacturingPagePS_t page = NULL; 206230592Sken uint32_t *pPS_info; 207230592Sken uint8_t OEM_Value = 0; 208230592Sken int error = 0; 209230592Sken u16 ioc_status; 210230592Sken 211230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 212230592Sken 213230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 214230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 215230592Sken __LINE__); 216230592Sken error = EBUSY; 217230592Sken goto out; 218230592Sken } 219230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 220230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 221230592Sken request->Function = MPI2_FUNCTION_CONFIG; 222230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 223230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 224230592Sken request->Header.PageNumber = 10; 225230592Sken request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION; 226230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 227230592Sken cm->cm_data = NULL; 228253550Sken 229253550Sken /* 230253550Sken * This page must be polled because the IOC isn't ready yet when this 231253550Sken * page is needed. 232253550Sken */ 233230592Sken error = mps_request_polled(sc, cm); 234230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 235230592Sken if (error || (reply == NULL)) { 236230592Sken /* FIXME */ 237230592Sken /* If the poll returns error then we need to do diag reset */ 238230592Sken printf("%s: poll for header completed with error %d", 239230592Sken __func__, error); 240230592Sken error = ENXIO; 241230592Sken goto out; 242230592Sken } 243230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 244230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 245230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 246230592Sken /* FIXME */ 247230592Sken /* If the poll returns error then we need to do diag reset */ 248230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 249230592Sken __func__, ioc_status); 250230592Sken error = ENXIO; 251230592Sken goto out; 252230592Sken } 253230592Sken /* We have to do free and alloc for the reply-free and reply-post 254230592Sken * counters to match - Need to review the reply FIFO handling. 255230592Sken */ 256230592Sken mps_free_command(sc, cm); 257230592Sken 258230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 259230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 260230592Sken __LINE__); 261230592Sken error = EBUSY; 262230592Sken goto out; 263230592Sken } 264230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 265230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 266230592Sken request->Function = MPI2_FUNCTION_CONFIG; 267230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 268230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 269230592Sken request->Header.PageNumber = 10; 270230592Sken request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION; 271230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 272230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 273230592Sken cm->cm_sge = &request->PageBufferSGE; 274230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 275230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 276230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 277230592Sken page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT); 278230592Sken if (!page) { 279230592Sken printf("%s: page alloc failed\n", __func__); 280230592Sken error = ENOMEM; 281230592Sken goto out; 282230592Sken } 283230592Sken cm->cm_data = page; 284253550Sken 285253550Sken /* 286253550Sken * This page must be polled because the IOC isn't ready yet when this 287253550Sken * page is needed. 288253550Sken */ 289230592Sken error = mps_request_polled(sc, cm); 290230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 291230592Sken if (error || (reply == NULL)) { 292230592Sken /* FIXME */ 293230592Sken /* If the poll returns error then we need to do diag reset */ 294230592Sken printf("%s: poll for page completed with error %d", 295230592Sken __func__, error); 296230592Sken error = ENXIO; 297230592Sken goto out; 298230592Sken } 299230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 300230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 301230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 302230592Sken /* FIXME */ 303230592Sken /* If the poll returns error then we need to do diag reset */ 304230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 305230592Sken __func__, ioc_status); 306230592Sken error = ENXIO; 307230592Sken goto out; 308230592Sken } 309230592Sken 310230592Sken /* 311230592Sken * If OEM ID is unknown, fail the request. 312230592Sken */ 313230592Sken sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS; 314230592Sken OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF); 315230592Sken if (OEM_Value != MPS_WD_LSI_OEM) { 316230592Sken mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive " 317230592Sken "(0x%x)\n", OEM_Value); 318230592Sken error = ENXIO; 319230592Sken goto out; 320230592Sken } 321230592Sken 322230592Sken /* 323230592Sken * Set the phys disks hide/expose value. 324230592Sken */ 325230592Sken pPS_info = &page->ProductSpecificInfo; 326230592Sken sc->WD_hide_expose = (uint8_t)(pPS_info[5]); 327230592Sken sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK; 328230592Sken if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) && 329230592Sken (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) && 330230592Sken (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) { 331230592Sken mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive " 332230592Sken "hide/expose: 0x%x\n", sc->WD_hide_expose); 333230592Sken error = ENXIO; 334230592Sken goto out; 335230592Sken } 336230592Sken 337230592Skenout: 338230592Sken free(page, M_MPT2); 339230592Sken if (cm) 340230592Sken mps_free_command(sc, cm); 341230592Sken return (error); 342230592Sken} 343230592Sken 344230592Sken/** 345230592Sken * mps_base_static_config_pages - static start of day config pages. 346230592Sken * @sc: per adapter object 347230592Sken * 348230592Sken * Return nothing. 349230592Sken */ 350230592Skenvoid 351230592Skenmps_base_static_config_pages(struct mps_softc *sc) 352230592Sken{ 353230592Sken Mpi2ConfigReply_t mpi_reply; 354230592Sken int retry; 355230592Sken 356230592Sken retry = 0; 357230592Sken while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) { 358230592Sken retry++; 359230592Sken if (retry > 5) { 360230592Sken /* We need to Handle this situation */ 361230592Sken /*FIXME*/ 362230592Sken break; 363230592Sken } 364230592Sken } 365230592Sken} 366230592Sken 367230592Sken/** 368230592Sken * mps_wd_config_pages - get info required to support WarpDrive. This needs to 369230592Sken * be called after discovery is complete to guarentee that IR info is there. 370230592Sken * @sc: per adapter object 371230592Sken * 372230592Sken * Return nothing. 373230592Sken */ 374230592Skenvoid 375230592Skenmps_wd_config_pages(struct mps_softc *sc) 376230592Sken{ 377230592Sken Mpi2ConfigReply_t mpi_reply; 378230592Sken pMpi2RaidVolPage0_t raid_vol_pg0 = NULL; 379230592Sken Mpi2RaidPhysDiskPage0_t phys_disk_pg0; 380230592Sken pMpi2RaidVol0PhysDisk_t pRVPD; 381230592Sken uint32_t stripe_size, phys_disk_page_address; 382230592Sken uint16_t block_size; 383230592Sken uint8_t index, stripe_exp = 0, block_exp = 0; 384230592Sken 385230592Sken /* 386230592Sken * Get the WD settings from manufacturing page 10 if using a WD HBA. 387230592Sken * This will be used to determine if phys disks should always be 388230592Sken * hidden, hidden only if part of a WD volume, or never hidden. Also, 389230592Sken * get the WD RAID Volume info and fail if volume does not exist or if 390230592Sken * volume does not meet the requirements for a WD volume. No retry 391230592Sken * here. Just default to HIDE ALWAYS if man Page10 fails, or clear WD 392230592Sken * Valid flag if Volume info fails. 393230592Sken */ 394230592Sken sc->WD_valid_config = FALSE; 395230592Sken if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) { 396230592Sken if (mps_config_get_man_pg10(sc, &mpi_reply)) { 397230592Sken mps_dprint(sc, MPS_FAULT, 398230592Sken "mps_config_get_man_pg10 failed! Using 0 (Hide " 399230592Sken "Always) for WarpDrive hide/expose value.\n"); 400230592Sken sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS; 401230592Sken } 402230592Sken 403230592Sken /* 404230592Sken * Get first RAID Volume Page0 using GET_NEXT_HANDLE. 405230592Sken */ 406230592Sken raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) + 407230592Sken (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL), 408230592Sken M_MPT2, M_ZERO | M_NOWAIT); 409230592Sken if (!raid_vol_pg0) { 410230592Sken printf("%s: page alloc failed\n", __func__); 411230592Sken goto out; 412230592Sken } 413230592Sken 414230592Sken if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0, 415230592Sken 0x0000FFFF)) { 416230592Sken mps_dprint(sc, MPS_INFO, 417230592Sken "mps_config_get_raid_volume_pg0 failed! Assuming " 418230592Sken "WarpDrive IT mode.\n"); 419230592Sken goto out; 420230592Sken } 421230592Sken 422230592Sken /* 423230592Sken * Check for valid WD configuration: 424230592Sken * volume type is RAID0 425230592Sken * number of phys disks in the volume is no more than 8 426230592Sken */ 427230592Sken if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) || 428230592Sken (raid_vol_pg0->NumPhysDisks > 8)) { 429230592Sken mps_dprint(sc, MPS_FAULT, 430230592Sken "Invalid WarpDrive configuration. Direct Drive I/O " 431230592Sken "will not be used.\n"); 432230592Sken goto out; 433230592Sken } 434230592Sken 435230592Sken /* 436230592Sken * Save the WD RAID data to be used during WD I/O. 437230592Sken */ 438230592Sken sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High << 439230592Sken 32 | (uint64_t)raid_vol_pg0->MaxLBA.Low); 440230592Sken sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks; 441230592Sken sc->DD_dev_handle = raid_vol_pg0->DevHandle; 442230592Sken sc->DD_stripe_size = raid_vol_pg0->StripeSize; 443230592Sken sc->DD_block_size = raid_vol_pg0->BlockSize; 444230592Sken 445230592Sken /* 446230592Sken * Find power of 2 of stripe size and set this as the exponent. 447230592Sken * Fail if stripe size is 0. 448230592Sken */ 449230592Sken stripe_size = raid_vol_pg0->StripeSize; 450230592Sken for (index = 0; index < 32; index++) { 451230592Sken if (stripe_size & 1) 452230592Sken break; 453230592Sken stripe_exp++; 454230592Sken stripe_size >>= 1; 455230592Sken } 456230592Sken if (index == 32) { 457230592Sken mps_dprint(sc, MPS_FAULT, 458230592Sken "RAID Volume's stripe size is 0. Direct Drive I/O " 459230592Sken "will not be used.\n"); 460230592Sken goto out; 461230592Sken } 462230592Sken sc->DD_stripe_exponent = stripe_exp; 463230592Sken 464230592Sken /* 465230592Sken * Find power of 2 of block size and set this as the exponent. 466230592Sken * Fail if block size is 0. 467230592Sken */ 468230592Sken block_size = raid_vol_pg0->BlockSize; 469230592Sken for (index = 0; index < 16; index++) { 470230592Sken if (block_size & 1) 471230592Sken break; 472230592Sken block_exp++; 473230592Sken block_size >>= 1; 474230592Sken } 475230592Sken if (index == 16) { 476230592Sken mps_dprint(sc, MPS_FAULT, 477230592Sken "RAID Volume's block size is 0. Direct Drive I/O " 478230592Sken "will not be used.\n"); 479230592Sken goto out; 480230592Sken } 481230592Sken sc->DD_block_exponent = block_exp; 482230592Sken 483230592Sken /* 484230592Sken * Loop through all of the volume's Phys Disks to map the phys 485230592Sken * disk number into the columm map. This is used during Direct 486230592Sken * Drive I/O to send the request to the correct SSD. 487230592Sken */ 488230592Sken pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk; 489230592Sken for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) { 490230592Sken sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num = 491230592Sken pRVPD->PhysDiskNum; 492230592Sken pRVPD++; 493230592Sken } 494230592Sken 495230592Sken /* 496230592Sken * Get second RAID Volume Page0 using previous handle. This 497230592Sken * page should not exist. If it does, must not proceed with WD 498230592Sken * handling. 499230592Sken */ 500230592Sken if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, 501230592Sken raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) { 502230592Sken if (mpi_reply.IOCStatus != 503230592Sken MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) { 504230592Sken mps_dprint(sc, MPS_FAULT, 505230592Sken "Multiple RAID Volume Page0! Direct Drive " 506230592Sken "I/O will not be used.\n"); 507230592Sken goto out; 508230592Sken } 509230592Sken } else { 510230592Sken mps_dprint(sc, MPS_FAULT, 511230592Sken "Multiple volumes! Direct Drive I/O will not be " 512230592Sken "used.\n"); 513230592Sken goto out; 514230592Sken } 515230592Sken 516230592Sken /* 517230592Sken * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume. 518230592Sken */ 519230592Sken for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) { 520230592Sken phys_disk_page_address = 521230592Sken MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM + 522230592Sken sc->DD_column_map[index].phys_disk_num; 523230592Sken if (mps_config_get_raid_pd_pg0(sc, &mpi_reply, 524230592Sken &phys_disk_pg0, phys_disk_page_address)) { 525230592Sken mps_dprint(sc, MPS_FAULT, 526230592Sken "mps_config_get_raid_pd_pg0 failed! Direct " 527230592Sken "Drive I/O will not be used.\n"); 528230592Sken goto out; 529230592Sken } 530230592Sken if (phys_disk_pg0.DevHandle == 0xFFFF) { 531230592Sken mps_dprint(sc, MPS_FAULT, 532230592Sken "Invalid Phys Disk DevHandle! Direct Drive " 533230592Sken "I/O will not be used.\n"); 534230592Sken goto out; 535230592Sken } 536230592Sken sc->DD_column_map[index].dev_handle = 537230592Sken phys_disk_pg0.DevHandle; 538230592Sken } 539230592Sken sc->WD_valid_config = TRUE; 540230592Skenout: 541230592Sken if (raid_vol_pg0) 542230592Sken free(raid_vol_pg0, M_MPT2); 543230592Sken } 544230592Sken} 545230592Sken 546230592Sken/** 547230592Sken * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0 548230592Sken * @sc: per adapter object 549230592Sken * @mpi_reply: reply mf payload returned from firmware 550230592Sken * @config_page: contents of the config page 551230592Sken * @sz: size of buffer passed in config_page 552230592Sken * Context: sleep. 553230592Sken * 554230592Sken * Returns 0 for success, non-zero for failure. 555230592Sken */ 556230592Skenint 557230592Skenmps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 558230592Sken Mpi2DriverMappingPage0_t *config_page, u16 sz) 559230592Sken{ 560230592Sken MPI2_CONFIG_REQUEST *request; 561230592Sken MPI2_CONFIG_REPLY *reply; 562230592Sken struct mps_command *cm; 563230592Sken Mpi2DriverMappingPage0_t *page = NULL; 564230592Sken int error = 0; 565230592Sken u16 ioc_status; 566230592Sken 567230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 568230592Sken 569230592Sken memset(config_page, 0, sz); 570230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 571230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 572230592Sken __LINE__); 573230592Sken error = EBUSY; 574230592Sken goto out; 575230592Sken } 576230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 577230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 578230592Sken request->Function = MPI2_FUNCTION_CONFIG; 579230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 580230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 581230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 582230592Sken request->Header.PageNumber = 0; 583230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 584230592Sken request->PageAddress = sc->max_dpm_entries << 585230592Sken MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 586230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 587230592Sken cm->cm_data = NULL; 588253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 589230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 590230592Sken if (error || (reply == NULL)) { 591230592Sken /* FIXME */ 592253550Sken /* 593253550Sken * If the request returns an error then we need to do a diag 594253550Sken * reset 595253550Sken */ 596253550Sken printf("%s: request for header completed with error %d", 597230592Sken __func__, error); 598230592Sken error = ENXIO; 599230592Sken goto out; 600230592Sken } 601230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 602230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 603230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 604230592Sken /* FIXME */ 605253550Sken /* 606253550Sken * If the request returns an error then we need to do a diag 607253550Sken * reset 608253550Sken */ 609230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 610230592Sken __func__, ioc_status); 611230592Sken error = ENXIO; 612230592Sken goto out; 613230592Sken } 614230592Sken /* We have to do free and alloc for the reply-free and reply-post 615230592Sken * counters to match - Need to review the reply FIFO handling. 616230592Sken */ 617230592Sken mps_free_command(sc, cm); 618230592Sken 619230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 620230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 621230592Sken __LINE__); 622230592Sken error = EBUSY; 623230592Sken goto out; 624230592Sken } 625230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 626230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 627230592Sken request->Function = MPI2_FUNCTION_CONFIG; 628230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM; 629230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 630230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 631230592Sken request->Header.PageNumber = 0; 632230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 633230592Sken request->PageAddress = sc->max_dpm_entries << 634230592Sken MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 635230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 636230592Sken cm->cm_length = le16toh(request->ExtPageLength) * 4; 637230592Sken cm->cm_sge = &request->PageBufferSGE; 638230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 639230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 640230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 641230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT); 642230592Sken if (!page) { 643230592Sken printf("%s: page alloc failed\n", __func__); 644230592Sken error = ENOMEM; 645230592Sken goto out; 646230592Sken } 647230592Sken cm->cm_data = page; 648253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 649230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 650230592Sken if (error || (reply == NULL)) { 651230592Sken /* FIXME */ 652253550Sken /* 653253550Sken * If the request returns an error then we need to do a diag 654253550Sken * reset 655253550Sken */ 656253550Sken printf("%s: request for page completed with error %d", 657230592Sken __func__, error); 658230592Sken error = ENXIO; 659230592Sken goto out; 660230592Sken } 661230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 662230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 663230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 664230592Sken /* FIXME */ 665253550Sken /* 666253550Sken * If the request returns an error then we need to do a diag 667253550Sken * reset 668253550Sken */ 669230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 670230592Sken __func__, ioc_status); 671230592Sken error = ENXIO; 672230592Sken goto out; 673230592Sken } 674230592Sken bcopy(page, config_page, MIN(cm->cm_length, sz)); 675230592Skenout: 676230592Sken free(page, M_MPT2); 677230592Sken if (cm) 678230592Sken mps_free_command(sc, cm); 679230592Sken return (error); 680230592Sken} 681230592Sken 682230592Sken/** 683230592Sken * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0 684230592Sken * @sc: per adapter object 685230592Sken * @mpi_reply: reply mf payload returned from firmware 686230592Sken * @config_page: contents of the config page 687230592Sken * @entry_idx: entry index in DPM Page0 to be modified 688230592Sken * Context: sleep. 689230592Sken * 690230592Sken * Returns 0 for success, non-zero for failure. 691230592Sken */ 692230592Sken 693230592Skenint mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 694230592Sken Mpi2DriverMappingPage0_t *config_page, u16 entry_idx) 695230592Sken{ 696230592Sken MPI2_CONFIG_REQUEST *request; 697230592Sken MPI2_CONFIG_REPLY *reply; 698230592Sken struct mps_command *cm; 699230592Sken MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; 700230592Sken int error = 0; 701230592Sken u16 ioc_status; 702230592Sken 703230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 704230592Sken 705230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 706230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 707230592Sken __LINE__); 708230592Sken error = EBUSY; 709230592Sken goto out; 710230592Sken } 711230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 712230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 713230592Sken request->Function = MPI2_FUNCTION_CONFIG; 714230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 715230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 716230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 717230592Sken request->Header.PageNumber = 0; 718230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 719237683Sken /* We can remove below two lines ????*/ 720230592Sken request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 721230592Sken request->PageAddress |= htole16(entry_idx); 722230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 723230592Sken cm->cm_data = NULL; 724253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 725230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 726230592Sken if (error || (reply == NULL)) { 727230592Sken /* FIXME */ 728253550Sken /* 729253550Sken * If the request returns an error then we need to do a diag 730253550Sken * reset 731253550Sken */ 732253550Sken printf("%s: request for header completed with error %d", 733230592Sken __func__, error); 734230592Sken error = ENXIO; 735230592Sken goto out; 736230592Sken } 737230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 738230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 739230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 740230592Sken /* FIXME */ 741253550Sken /* 742253550Sken * If the request returns an error then we need to do a diag 743253550Sken * reset 744253550Sken */ 745230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 746230592Sken __func__, ioc_status); 747230592Sken error = ENXIO; 748230592Sken goto out; 749230592Sken } 750230592Sken /* We have to do free and alloc for the reply-free and reply-post 751230592Sken * counters to match - Need to review the reply FIFO handling. 752230592Sken */ 753230592Sken mps_free_command(sc, cm); 754230592Sken 755230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 756230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 757230592Sken __LINE__); 758230592Sken error = EBUSY; 759230592Sken goto out; 760230592Sken } 761230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 762230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 763230592Sken request->Function = MPI2_FUNCTION_CONFIG; 764230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 765230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 766230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 767230592Sken request->Header.PageNumber = 0; 768230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 769230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 770230592Sken request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 771230592Sken request->PageAddress |= htole16(entry_idx); 772230592Sken cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 773230592Sken cm->cm_sge = &request->PageBufferSGE; 774230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 775230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT; 776230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 777230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 778230592Sken if (!page) { 779230592Sken printf("%s: page alloc failed\n", __func__); 780230592Sken error = ENOMEM; 781230592Sken goto out; 782230592Sken } 783230592Sken bcopy(config_page, page, MIN(cm->cm_length, 784230592Sken (sizeof(Mpi2DriverMappingPage0_t)))); 785230592Sken cm->cm_data = page; 786253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 787230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 788230592Sken if (error || (reply == NULL)) { 789230592Sken /* FIXME */ 790253550Sken /* 791253550Sken * If the request returns an error then we need to do a diag 792253550Sken * reset 793253550Sken */ 794253550Sken printf("%s: request to write page completed with error %d", 795230592Sken __func__, error); 796230592Sken error = ENXIO; 797230592Sken goto out; 798230592Sken } 799230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 800230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 801230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 802230592Sken /* FIXME */ 803253550Sken /* 804253550Sken * If the request returns an error then we need to do a diag 805253550Sken * reset 806253550Sken */ 807230592Sken printf("%s: page written with error; iocstatus = 0x%x\n", 808230592Sken __func__, ioc_status); 809230592Sken error = ENXIO; 810230592Sken goto out; 811230592Sken } 812230592Skenout: 813230592Sken free(page, M_MPT2); 814230592Sken if (cm) 815230592Sken mps_free_command(sc, cm); 816230592Sken return (error); 817230592Sken} 818230592Sken 819230592Sken/** 820230592Sken * mps_config_get_sas_device_pg0 - obtain sas device page 0 821230592Sken * @sc: per adapter object 822230592Sken * @mpi_reply: reply mf payload returned from firmware 823230592Sken * @config_page: contents of the config page 824230592Sken * @form: GET_NEXT_HANDLE or HANDLE 825230592Sken * @handle: device handle 826230592Sken * Context: sleep. 827230592Sken * 828230592Sken * Returns 0 for success, non-zero for failure. 829230592Sken */ 830230592Skenint 831230592Skenmps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 832230592Sken *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle) 833230592Sken{ 834230592Sken MPI2_CONFIG_REQUEST *request; 835230592Sken MPI2_CONFIG_REPLY *reply; 836230592Sken struct mps_command *cm; 837230592Sken Mpi2SasDevicePage0_t *page = NULL; 838230592Sken int error = 0; 839230592Sken u16 ioc_status; 840230592Sken 841230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 842230592Sken 843230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 844230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 845230592Sken __LINE__); 846230592Sken error = EBUSY; 847230592Sken goto out; 848230592Sken } 849230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 850230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 851230592Sken request->Function = MPI2_FUNCTION_CONFIG; 852230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 853230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 854230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 855230592Sken request->Header.PageNumber = 0; 856230592Sken request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 857230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 858230592Sken cm->cm_data = NULL; 859253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 860230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 861230592Sken if (error || (reply == NULL)) { 862230592Sken /* FIXME */ 863253550Sken /* 864253550Sken * If the request returns an error then we need to do a diag 865253550Sken * reset 866253550Sken */ 867253550Sken printf("%s: request for header completed with error %d", 868230592Sken __func__, error); 869230592Sken error = ENXIO; 870230592Sken goto out; 871230592Sken } 872230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 873230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 874230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 875230592Sken /* FIXME */ 876253550Sken /* 877253550Sken * If the request returns an error then we need to do a diag 878253550Sken * reset 879253550Sken */ 880230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 881230592Sken __func__, ioc_status); 882230592Sken error = ENXIO; 883230592Sken goto out; 884230592Sken } 885230592Sken /* We have to do free and alloc for the reply-free and reply-post 886230592Sken * counters to match - Need to review the reply FIFO handling. 887230592Sken */ 888230592Sken mps_free_command(sc, cm); 889230592Sken 890230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 891230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 892230592Sken __LINE__); 893230592Sken error = EBUSY; 894230592Sken goto out; 895230592Sken } 896230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 897230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 898230592Sken request->Function = MPI2_FUNCTION_CONFIG; 899230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 900230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 901230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 902230592Sken request->Header.PageNumber = 0; 903230592Sken request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 904230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 905230592Sken request->PageAddress = htole32(form | handle); 906230592Sken cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 907230592Sken cm->cm_sge = &request->PageBufferSGE; 908230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 909230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 910230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 911230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 912230592Sken if (!page) { 913230592Sken printf("%s: page alloc failed\n", __func__); 914230592Sken error = ENOMEM; 915230592Sken goto out; 916230592Sken } 917230592Sken cm->cm_data = page; 918230592Sken 919253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 920230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 921230592Sken if (error || (reply == NULL)) { 922230592Sken /* FIXME */ 923253550Sken /* 924253550Sken * If the request returns an error then we need to do a diag 925253550Sken * reset 926253550Sken */ 927253550Sken printf("%s: request for page completed with error %d", 928230592Sken __func__, error); 929230592Sken error = ENXIO; 930230592Sken goto out; 931230592Sken } 932230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 933230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 934230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 935230592Sken /* FIXME */ 936253550Sken /* 937253550Sken * If the request returns an error then we need to do a diag 938253550Sken * reset 939253550Sken */ 940230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 941230592Sken __func__, ioc_status); 942230592Sken error = ENXIO; 943230592Sken goto out; 944230592Sken } 945230592Sken bcopy(page, config_page, MIN(cm->cm_length, 946230592Sken sizeof(Mpi2SasDevicePage0_t))); 947230592Skenout: 948230592Sken free(page, M_MPT2); 949230592Sken if (cm) 950230592Sken mps_free_command(sc, cm); 951230592Sken return (error); 952230592Sken} 953230592Sken 954230592Sken/** 955230592Sken * mps_config_get_bios_pg3 - obtain BIOS page 3 956230592Sken * @sc: per adapter object 957230592Sken * @mpi_reply: reply mf payload returned from firmware 958230592Sken * @config_page: contents of the config page 959230592Sken * Context: sleep. 960230592Sken * 961230592Sken * Returns 0 for success, non-zero for failure. 962230592Sken */ 963230592Skenint 964230592Skenmps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 965230592Sken Mpi2BiosPage3_t *config_page) 966230592Sken{ 967230592Sken MPI2_CONFIG_REQUEST *request; 968230592Sken MPI2_CONFIG_REPLY *reply; 969230592Sken struct mps_command *cm; 970230592Sken Mpi2BiosPage3_t *page = NULL; 971230592Sken int error = 0; 972230592Sken u16 ioc_status; 973230592Sken 974230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 975230592Sken 976230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 977230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 978230592Sken __LINE__); 979230592Sken error = EBUSY; 980230592Sken goto out; 981230592Sken } 982230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 983230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 984230592Sken request->Function = MPI2_FUNCTION_CONFIG; 985230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 986230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 987230592Sken request->Header.PageNumber = 3; 988230592Sken request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 989230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 990230592Sken cm->cm_data = NULL; 991253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 992230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 993230592Sken if (error || (reply == NULL)) { 994230592Sken /* FIXME */ 995253550Sken /* 996253550Sken * If the request returns an error then we need to do a diag 997253550Sken * reset 998253550Sken */ 999253550Sken printf("%s: request for header completed with error %d", 1000230592Sken __func__, error); 1001230592Sken error = ENXIO; 1002230592Sken goto out; 1003230592Sken } 1004230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1005230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1006230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1007230592Sken /* FIXME */ 1008253550Sken /* 1009253550Sken * If the request returns an error then we need to do a diag 1010253550Sken * reset 1011253550Sken */ 1012230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1013230592Sken __func__, ioc_status); 1014230592Sken error = ENXIO; 1015230592Sken goto out; 1016230592Sken } 1017230592Sken /* We have to do free and alloc for the reply-free and reply-post 1018230592Sken * counters to match - Need to review the reply FIFO handling. 1019230592Sken */ 1020230592Sken mps_free_command(sc, cm); 1021230592Sken 1022230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1023230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1024230592Sken __LINE__); 1025230592Sken error = EBUSY; 1026230592Sken goto out; 1027230592Sken } 1028230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1029230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1030230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1031230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1032230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 1033230592Sken request->Header.PageNumber = 3; 1034230592Sken request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 1035230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1036230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1037230592Sken cm->cm_sge = &request->PageBufferSGE; 1038230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1039230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1040230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1041230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1042230592Sken if (!page) { 1043230592Sken printf("%s: page alloc failed\n", __func__); 1044230592Sken error = ENOMEM; 1045230592Sken goto out; 1046230592Sken } 1047230592Sken cm->cm_data = page; 1048230592Sken 1049253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1050230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1051230592Sken if (error || (reply == NULL)) { 1052230592Sken /* FIXME */ 1053253550Sken /* 1054253550Sken * If the request returns an error then we need to do a diag 1055253550Sken * reset 1056253550Sken */ 1057253550Sken printf("%s: request for page completed with error %d", 1058230592Sken __func__, error); 1059230592Sken error = ENXIO; 1060230592Sken goto out; 1061230592Sken } 1062230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1063230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1064230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1065230592Sken /* FIXME */ 1066253550Sken /* 1067253550Sken * If the request returns an error then we need to do a diag 1068253550Sken * reset 1069253550Sken */ 1070230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1071230592Sken __func__, ioc_status); 1072230592Sken error = ENXIO; 1073230592Sken goto out; 1074230592Sken } 1075230592Sken bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t))); 1076230592Skenout: 1077230592Sken free(page, M_MPT2); 1078230592Sken if (cm) 1079230592Sken mps_free_command(sc, cm); 1080230592Sken return (error); 1081230592Sken} 1082230592Sken 1083230592Sken/** 1084230592Sken * mps_config_get_raid_volume_pg0 - obtain raid volume page 0 1085230592Sken * @sc: per adapter object 1086230592Sken * @mpi_reply: reply mf payload returned from firmware 1087230592Sken * @config_page: contents of the config page 1088230592Sken * @page_address: form and handle value used to get page 1089230592Sken * Context: sleep. 1090230592Sken * 1091230592Sken * Returns 0 for success, non-zero for failure. 1092230592Sken */ 1093230592Skenint 1094230592Skenmps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 1095230592Sken *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) 1096230592Sken{ 1097230592Sken MPI2_CONFIG_REQUEST *request; 1098230592Sken MPI2_CONFIG_REPLY *reply; 1099230592Sken struct mps_command *cm; 1100230592Sken Mpi2RaidVolPage0_t *page = NULL; 1101230592Sken int error = 0; 1102230592Sken u16 ioc_status; 1103230592Sken 1104230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1105230592Sken 1106230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1107230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1108230592Sken __LINE__); 1109230592Sken error = EBUSY; 1110230592Sken goto out; 1111230592Sken } 1112230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1113230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1114230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1115230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1116230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1117230592Sken request->Header.PageNumber = 0; 1118230592Sken request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1119230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1120230592Sken cm->cm_data = NULL; 1121253550Sken 1122253550Sken /* 1123253550Sken * This page must be polled because the IOC isn't ready yet when this 1124253550Sken * page is needed. 1125253550Sken */ 1126230592Sken error = mps_request_polled(sc, cm); 1127230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1128230592Sken if (error || (reply == NULL)) { 1129230592Sken /* FIXME */ 1130230592Sken /* If the poll returns error then we need to do diag reset */ 1131230592Sken printf("%s: poll for header completed with error %d", 1132230592Sken __func__, error); 1133230592Sken error = ENXIO; 1134230592Sken goto out; 1135230592Sken } 1136230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1137230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1138230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1139230592Sken /* FIXME */ 1140230592Sken /* If the poll returns error then we need to do diag reset */ 1141230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1142230592Sken __func__, ioc_status); 1143230592Sken error = ENXIO; 1144230592Sken goto out; 1145230592Sken } 1146230592Sken /* We have to do free and alloc for the reply-free and reply-post 1147230592Sken * counters to match - Need to review the reply FIFO handling. 1148230592Sken */ 1149230592Sken mps_free_command(sc, cm); 1150230592Sken 1151230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1152230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1153230592Sken __LINE__); 1154230592Sken error = EBUSY; 1155230592Sken goto out; 1156230592Sken } 1157230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1158230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1159230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1160230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1161230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1162230592Sken request->Header.PageNumber = 0; 1163230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1164230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1165230592Sken request->PageAddress = page_address; 1166230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1167230592Sken cm->cm_sge = &request->PageBufferSGE; 1168230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1169230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1170230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1171230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1172230592Sken if (!page) { 1173230592Sken printf("%s: page alloc failed\n", __func__); 1174230592Sken error = ENOMEM; 1175230592Sken goto out; 1176230592Sken } 1177230592Sken cm->cm_data = page; 1178230592Sken 1179253550Sken /* 1180253550Sken * This page must be polled because the IOC isn't ready yet when this 1181253550Sken * page is needed. 1182253550Sken */ 1183230592Sken error = mps_request_polled(sc, cm); 1184230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1185230592Sken if (error || (reply == NULL)) { 1186230592Sken /* FIXME */ 1187230592Sken /* If the poll returns error then we need to do diag reset */ 1188230592Sken printf("%s: poll for page completed with error %d", 1189230592Sken __func__, error); 1190230592Sken error = ENXIO; 1191230592Sken goto out; 1192230592Sken } 1193230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1194230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1195230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1196230592Sken /* FIXME */ 1197230592Sken /* If the poll returns error then we need to do diag reset */ 1198230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1199230592Sken __func__, ioc_status); 1200230592Sken error = ENXIO; 1201230592Sken goto out; 1202230592Sken } 1203230592Sken bcopy(page, config_page, cm->cm_length); 1204230592Skenout: 1205230592Sken free(page, M_MPT2); 1206230592Sken if (cm) 1207230592Sken mps_free_command(sc, cm); 1208230592Sken return (error); 1209230592Sken} 1210230592Sken 1211230592Sken/** 1212230592Sken * mps_config_get_raid_volume_pg1 - obtain raid volume page 1 1213230592Sken * @sc: per adapter object 1214230592Sken * @mpi_reply: reply mf payload returned from firmware 1215230592Sken * @config_page: contents of the config page 1216230592Sken * @form: GET_NEXT_HANDLE or HANDLE 1217230592Sken * @handle: volume handle 1218230592Sken * Context: sleep. 1219230592Sken * 1220230592Sken * Returns 0 for success, non-zero for failure. 1221230592Sken */ 1222230592Skenint 1223230592Skenmps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t 1224230592Sken *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle) 1225230592Sken{ 1226230592Sken MPI2_CONFIG_REQUEST *request; 1227230592Sken MPI2_CONFIG_REPLY *reply; 1228230592Sken struct mps_command *cm; 1229230592Sken Mpi2RaidVolPage1_t *page = NULL; 1230230592Sken int error = 0; 1231230592Sken u16 ioc_status; 1232230592Sken 1233230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1234230592Sken 1235230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1236230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1237230592Sken __LINE__); 1238230592Sken error = EBUSY; 1239230592Sken goto out; 1240230592Sken } 1241230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1242230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1243230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1244230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1245230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1246230592Sken request->Header.PageNumber = 1; 1247230592Sken request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; 1248230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1249230592Sken cm->cm_data = NULL; 1250253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1251230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1252230592Sken if (error || (reply == NULL)) { 1253230592Sken /* FIXME */ 1254253550Sken /* 1255253550Sken * If the request returns an error then we need to do a diag 1256253550Sken * reset 1257253550Sken */ 1258253550Sken printf("%s: request for header completed with error %d", 1259230592Sken __func__, error); 1260230592Sken error = ENXIO; 1261230592Sken goto out; 1262230592Sken } 1263230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1264230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1265230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1266230592Sken /* FIXME */ 1267253550Sken /* 1268253550Sken * If the request returns an error then we need to do a diag 1269253550Sken * reset 1270253550Sken */ 1271230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1272230592Sken __func__, ioc_status); 1273230592Sken error = ENXIO; 1274230592Sken goto out; 1275230592Sken } 1276230592Sken /* We have to do free and alloc for the reply-free and reply-post 1277230592Sken * counters to match - Need to review the reply FIFO handling. 1278230592Sken */ 1279230592Sken mps_free_command(sc, cm); 1280230592Sken 1281230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1282230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1283230592Sken __LINE__); 1284230592Sken error = EBUSY; 1285230592Sken goto out; 1286230592Sken } 1287230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1288230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1289230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1290230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1291230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1292230592Sken request->Header.PageNumber = 1; 1293230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1294230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1295230592Sken request->PageAddress = htole32(form | handle); 1296230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1297230592Sken cm->cm_sge = &request->PageBufferSGE; 1298230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1299230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1300230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1301230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1302230592Sken if (!page) { 1303230592Sken printf("%s: page alloc failed\n", __func__); 1304230592Sken error = ENOMEM; 1305230592Sken goto out; 1306230592Sken } 1307230592Sken cm->cm_data = page; 1308230592Sken 1309253550Sken error = mps_wait_command(sc, cm, 60, CAN_SLEEP); 1310230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1311230592Sken if (error || (reply == NULL)) { 1312230592Sken /* FIXME */ 1313253550Sken /* 1314253550Sken * If the request returns an error then we need to do a diag 1315253550Sken * reset 1316253550Sken */ 1317253550Sken printf("%s: request for page completed with error %d", 1318230592Sken __func__, error); 1319230592Sken error = ENXIO; 1320230592Sken goto out; 1321230592Sken } 1322230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1323230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1324230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1325230592Sken /* FIXME */ 1326253550Sken /* 1327253550Sken * If the request returns an error then we need to do a diag 1328253550Sken * reset 1329253550Sken */ 1330230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1331230592Sken __func__, ioc_status); 1332230592Sken error = ENXIO; 1333230592Sken goto out; 1334230592Sken } 1335230592Sken bcopy(page, config_page, MIN(cm->cm_length, 1336230592Sken sizeof(Mpi2RaidVolPage1_t))); 1337230592Skenout: 1338230592Sken free(page, M_MPT2); 1339230592Sken if (cm) 1340230592Sken mps_free_command(sc, cm); 1341230592Sken return (error); 1342230592Sken} 1343230592Sken 1344230592Sken/** 1345230592Sken * mps_config_get_volume_wwid - returns wwid given the volume handle 1346230592Sken * @sc: per adapter object 1347230592Sken * @volume_handle: volume handle 1348230592Sken * @wwid: volume wwid 1349230592Sken * Context: sleep. 1350230592Sken * 1351230592Sken * Returns 0 for success, non-zero for failure. 1352230592Sken */ 1353230592Skenint 1354230592Skenmps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid) 1355230592Sken{ 1356230592Sken Mpi2ConfigReply_t mpi_reply; 1357230592Sken Mpi2RaidVolPage1_t raid_vol_pg1; 1358230592Sken 1359230592Sken *wwid = 0; 1360230592Sken if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1, 1361230592Sken MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) { 1362230592Sken *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 | 1363230592Sken raid_vol_pg1.WWID.Low); 1364230592Sken return 0; 1365230592Sken } else 1366230592Sken return -1; 1367230592Sken} 1368230592Sken 1369230592Sken/** 1370230592Sken * mps_config_get_pd_pg0 - obtain raid phys disk page 0 1371230592Sken * @sc: per adapter object 1372230592Sken * @mpi_reply: reply mf payload returned from firmware 1373230592Sken * @config_page: contents of the config page 1374230592Sken * @page_address: form and handle value used to get page 1375230592Sken * Context: sleep. 1376230592Sken * 1377230592Sken * Returns 0 for success, non-zero for failure. 1378230592Sken */ 1379230592Skenint 1380230592Skenmps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1381230592Sken Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) 1382230592Sken{ 1383230592Sken MPI2_CONFIG_REQUEST *request; 1384230592Sken MPI2_CONFIG_REPLY *reply; 1385230592Sken struct mps_command *cm; 1386230592Sken Mpi2RaidPhysDiskPage0_t *page = NULL; 1387230592Sken int error = 0; 1388230592Sken u16 ioc_status; 1389230592Sken 1390230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1391230592Sken 1392230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1393230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1394230592Sken __LINE__); 1395230592Sken error = EBUSY; 1396230592Sken goto out; 1397230592Sken } 1398230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1399230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1400230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1401230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1402230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1403230592Sken request->Header.PageNumber = 0; 1404230592Sken request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; 1405230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1406230592Sken cm->cm_data = NULL; 1407253550Sken 1408253550Sken /* 1409253550Sken * This page must be polled because the IOC isn't ready yet when this 1410253550Sken * page is needed. 1411253550Sken */ 1412230592Sken error = mps_request_polled(sc, cm); 1413230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1414230592Sken if (error || (reply == NULL)) { 1415230592Sken /* FIXME */ 1416230592Sken /* If the poll returns error then we need to do diag reset */ 1417230592Sken printf("%s: poll for header completed with error %d", 1418230592Sken __func__, error); 1419230592Sken error = ENXIO; 1420230592Sken goto out; 1421230592Sken } 1422230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1423230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1424230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1425230592Sken /* FIXME */ 1426230592Sken /* If the poll returns error then we need to do diag reset */ 1427230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1428230592Sken __func__, ioc_status); 1429230592Sken error = ENXIO; 1430230592Sken goto out; 1431230592Sken } 1432230592Sken /* We have to do free and alloc for the reply-free and reply-post 1433230592Sken * counters to match - Need to review the reply FIFO handling. 1434230592Sken */ 1435230592Sken mps_free_command(sc, cm); 1436230592Sken 1437230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1438230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1439230592Sken __LINE__); 1440230592Sken error = EBUSY; 1441230592Sken goto out; 1442230592Sken } 1443230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1444230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1445230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1446230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1447230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1448230592Sken request->Header.PageNumber = 0; 1449230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1450230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1451230592Sken request->PageAddress = page_address; 1452230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1453230592Sken cm->cm_sge = &request->PageBufferSGE; 1454230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1455230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1456230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1457230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1458230592Sken if (!page) { 1459230592Sken printf("%s: page alloc failed\n", __func__); 1460230592Sken error = ENOMEM; 1461230592Sken goto out; 1462230592Sken } 1463230592Sken cm->cm_data = page; 1464230592Sken 1465253550Sken /* 1466253550Sken * This page must be polled because the IOC isn't ready yet when this 1467253550Sken * page is needed. 1468253550Sken */ 1469230592Sken error = mps_request_polled(sc, cm); 1470230592Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1471230592Sken if (error || (reply == NULL)) { 1472230592Sken /* FIXME */ 1473230592Sken /* If the poll returns error then we need to do diag reset */ 1474230592Sken printf("%s: poll for page completed with error %d", 1475230592Sken __func__, error); 1476230592Sken error = ENXIO; 1477230592Sken goto out; 1478230592Sken } 1479230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1480230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1481230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1482230592Sken /* FIXME */ 1483230592Sken /* If the poll returns error then we need to do diag reset */ 1484230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1485230592Sken __func__, ioc_status); 1486230592Sken error = ENXIO; 1487230592Sken goto out; 1488230592Sken } 1489230592Sken bcopy(page, config_page, MIN(cm->cm_length, 1490230592Sken sizeof(Mpi2RaidPhysDiskPage0_t))); 1491230592Skenout: 1492230592Sken free(page, M_MPT2); 1493230592Sken if (cm) 1494230592Sken mps_free_command(sc, cm); 1495230592Sken return (error); 1496230592Sken} 1497