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: stable/10/sys/dev/mps/mps_config.c 322661 2017-08-18 15:38:08Z ken $"); 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; 74322661Sken MPI2_CONFIG_REPLY *reply = NULL; 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; 97322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 98322661Sken if (cm != NULL) 99322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 100230592Sken if (error || (reply == NULL)) { 101230592Sken /* FIXME */ 102253550Sken /* 103253550Sken * If the request returns an error then we need to do a diag 104253550Sken * reset 105253550Sken */ 106253550Sken printf("%s: request for header completed with error %d", 107230592Sken __func__, error); 108230592Sken error = ENXIO; 109230592Sken goto out; 110230592Sken } 111230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 112230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 113230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 114230592Sken /* FIXME */ 115253550Sken /* 116253550Sken * If the request returns an error then we need to do a diag 117253550Sken * reset 118253550Sken */ 119230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 120230592Sken __func__, ioc_status); 121230592Sken error = ENXIO; 122230592Sken goto out; 123230592Sken } 124230592Sken /* We have to do free and alloc for the reply-free and reply-post 125230592Sken * counters to match - Need to review the reply FIFO handling. 126230592Sken */ 127230592Sken mps_free_command(sc, cm); 128230592Sken 129230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 130230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 131230592Sken __LINE__); 132230592Sken error = EBUSY; 133230592Sken goto out; 134230592Sken } 135230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 136230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 137230592Sken request->Function = MPI2_FUNCTION_CONFIG; 138230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 139230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; 140230592Sken request->Header.PageNumber = 8; 141230592Sken request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; 142230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 143230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 144230592Sken cm->cm_sge = &request->PageBufferSGE; 145230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 146230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 147230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 148230592Sken page = malloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT); 149230592Sken if (!page) { 150230592Sken printf("%s: page alloc failed\n", __func__); 151230592Sken error = ENOMEM; 152230592Sken goto out; 153230592Sken } 154230592Sken cm->cm_data = page; 155253550Sken 156322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 157322661Sken if (cm != NULL) 158322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 159230592Sken if (error || (reply == NULL)) { 160230592Sken /* FIXME */ 161253550Sken /* 162253550Sken * If the request returns an error then we need to do a diag 163253550Sken * reset 164253550Sken */ 165253550Sken printf("%s: request for page completed with error %d", 166230592Sken __func__, error); 167230592Sken error = ENXIO; 168230592Sken goto out; 169230592Sken } 170230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 171230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 172230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 173230592Sken /* FIXME */ 174253550Sken /* 175253550Sken * If the request returns an error then we need to do a diag 176253550Sken * reset 177253550Sken */ 178230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 179230592Sken __func__, ioc_status); 180230592Sken error = ENXIO; 181230592Sken goto out; 182230592Sken } 183230592Sken bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t)))); 184230592Sken 185230592Skenout: 186230592Sken free(page, M_MPT2); 187230592Sken if (cm) 188230592Sken mps_free_command(sc, cm); 189230592Sken return (error); 190230592Sken} 191230592Sken 192230592Sken/** 193230592Sken * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags 194230592Sken * accordingly. Currently, this page does not need to return to caller. 195230592Sken * @sc: per adapter object 196230592Sken * @mpi_reply: reply mf payload returned from firmware 197230592Sken * Context: sleep. 198230592Sken * 199230592Sken * Returns 0 for success, non-zero for failure. 200230592Sken */ 201230592Skenint 202230592Skenmps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply) 203230592Sken{ 204230592Sken MPI2_CONFIG_REQUEST *request; 205322661Sken MPI2_CONFIG_REPLY *reply = NULL; 206230592Sken struct mps_command *cm; 207230592Sken pMpi2ManufacturingPagePS_t page = NULL; 208230592Sken uint32_t *pPS_info; 209230592Sken uint8_t OEM_Value = 0; 210230592Sken int error = 0; 211230592Sken u16 ioc_status; 212230592Sken 213230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 214230592Sken 215230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 216230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 217230592Sken __LINE__); 218230592Sken error = EBUSY; 219230592Sken goto out; 220230592Sken } 221230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 222230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 223230592Sken request->Function = MPI2_FUNCTION_CONFIG; 224230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 225230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 226230592Sken request->Header.PageNumber = 10; 227230592Sken request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION; 228230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 229230592Sken cm->cm_data = NULL; 230253550Sken 231253550Sken /* 232253550Sken * This page must be polled because the IOC isn't ready yet when this 233253550Sken * page is needed. 234253550Sken */ 235322661Sken error = mps_wait_command(sc, &cm, 60, 0); 236322661Sken if (cm != NULL) 237322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 238230592Sken if (error || (reply == NULL)) { 239230592Sken /* FIXME */ 240230592Sken /* If the poll returns error then we need to do diag reset */ 241230592Sken printf("%s: poll for header completed with error %d", 242230592Sken __func__, error); 243230592Sken error = ENXIO; 244230592Sken goto out; 245230592Sken } 246230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 247230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 248230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 249230592Sken /* FIXME */ 250230592Sken /* If the poll returns error then we need to do diag reset */ 251230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 252230592Sken __func__, ioc_status); 253230592Sken error = ENXIO; 254230592Sken goto out; 255230592Sken } 256230592Sken /* We have to do free and alloc for the reply-free and reply-post 257230592Sken * counters to match - Need to review the reply FIFO handling. 258230592Sken */ 259230592Sken mps_free_command(sc, cm); 260230592Sken 261230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 262230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 263230592Sken __LINE__); 264230592Sken error = EBUSY; 265230592Sken goto out; 266230592Sken } 267230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 268230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 269230592Sken request->Function = MPI2_FUNCTION_CONFIG; 270230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 271230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; 272230592Sken request->Header.PageNumber = 10; 273230592Sken request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION; 274230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 275230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 276230592Sken cm->cm_sge = &request->PageBufferSGE; 277230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 278230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 279230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 280230592Sken page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT); 281230592Sken if (!page) { 282230592Sken printf("%s: page alloc failed\n", __func__); 283230592Sken error = ENOMEM; 284230592Sken goto out; 285230592Sken } 286230592Sken cm->cm_data = page; 287253550Sken 288253550Sken /* 289253550Sken * This page must be polled because the IOC isn't ready yet when this 290253550Sken * page is needed. 291253550Sken */ 292322661Sken error = mps_wait_command(sc, &cm, 60, 0); 293322661Sken if (cm != NULL) 294322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 295230592Sken if (error || (reply == NULL)) { 296230592Sken /* FIXME */ 297230592Sken /* If the poll returns error then we need to do diag reset */ 298230592Sken printf("%s: poll for page completed with error %d", 299230592Sken __func__, error); 300230592Sken error = ENXIO; 301230592Sken goto out; 302230592Sken } 303230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 304230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 305230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 306230592Sken /* FIXME */ 307230592Sken /* If the poll returns error then we need to do diag reset */ 308230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 309230592Sken __func__, ioc_status); 310230592Sken error = ENXIO; 311230592Sken goto out; 312230592Sken } 313230592Sken 314230592Sken /* 315230592Sken * If OEM ID is unknown, fail the request. 316230592Sken */ 317230592Sken sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS; 318230592Sken OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF); 319230592Sken if (OEM_Value != MPS_WD_LSI_OEM) { 320230592Sken mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive " 321230592Sken "(0x%x)\n", OEM_Value); 322230592Sken error = ENXIO; 323230592Sken goto out; 324230592Sken } 325230592Sken 326230592Sken /* 327230592Sken * Set the phys disks hide/expose value. 328230592Sken */ 329230592Sken pPS_info = &page->ProductSpecificInfo; 330230592Sken sc->WD_hide_expose = (uint8_t)(pPS_info[5]); 331230592Sken sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK; 332230592Sken if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) && 333230592Sken (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) && 334230592Sken (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) { 335230592Sken mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive " 336230592Sken "hide/expose: 0x%x\n", sc->WD_hide_expose); 337230592Sken error = ENXIO; 338230592Sken goto out; 339230592Sken } 340230592Sken 341230592Skenout: 342230592Sken free(page, M_MPT2); 343230592Sken if (cm) 344230592Sken mps_free_command(sc, cm); 345230592Sken return (error); 346230592Sken} 347230592Sken 348230592Sken/** 349230592Sken * mps_base_static_config_pages - static start of day config pages. 350230592Sken * @sc: per adapter object 351230592Sken * 352230592Sken * Return nothing. 353230592Sken */ 354230592Skenvoid 355230592Skenmps_base_static_config_pages(struct mps_softc *sc) 356230592Sken{ 357230592Sken Mpi2ConfigReply_t mpi_reply; 358230592Sken int retry; 359230592Sken 360230592Sken retry = 0; 361230592Sken while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) { 362230592Sken retry++; 363230592Sken if (retry > 5) { 364230592Sken /* We need to Handle this situation */ 365230592Sken /*FIXME*/ 366230592Sken break; 367230592Sken } 368230592Sken } 369230592Sken} 370230592Sken 371230592Sken/** 372230592Sken * mps_wd_config_pages - get info required to support WarpDrive. This needs to 373230592Sken * be called after discovery is complete to guarentee that IR info is there. 374230592Sken * @sc: per adapter object 375230592Sken * 376230592Sken * Return nothing. 377230592Sken */ 378230592Skenvoid 379230592Skenmps_wd_config_pages(struct mps_softc *sc) 380230592Sken{ 381230592Sken Mpi2ConfigReply_t mpi_reply; 382230592Sken pMpi2RaidVolPage0_t raid_vol_pg0 = NULL; 383230592Sken Mpi2RaidPhysDiskPage0_t phys_disk_pg0; 384230592Sken pMpi2RaidVol0PhysDisk_t pRVPD; 385230592Sken uint32_t stripe_size, phys_disk_page_address; 386230592Sken uint16_t block_size; 387230592Sken uint8_t index, stripe_exp = 0, block_exp = 0; 388230592Sken 389230592Sken /* 390230592Sken * Get the WD settings from manufacturing page 10 if using a WD HBA. 391230592Sken * This will be used to determine if phys disks should always be 392230592Sken * hidden, hidden only if part of a WD volume, or never hidden. Also, 393230592Sken * get the WD RAID Volume info and fail if volume does not exist or if 394230592Sken * volume does not meet the requirements for a WD volume. No retry 395230592Sken * here. Just default to HIDE ALWAYS if man Page10 fails, or clear WD 396230592Sken * Valid flag if Volume info fails. 397230592Sken */ 398230592Sken sc->WD_valid_config = FALSE; 399230592Sken if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) { 400230592Sken if (mps_config_get_man_pg10(sc, &mpi_reply)) { 401230592Sken mps_dprint(sc, MPS_FAULT, 402230592Sken "mps_config_get_man_pg10 failed! Using 0 (Hide " 403230592Sken "Always) for WarpDrive hide/expose value.\n"); 404230592Sken sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS; 405230592Sken } 406230592Sken 407230592Sken /* 408230592Sken * Get first RAID Volume Page0 using GET_NEXT_HANDLE. 409230592Sken */ 410230592Sken raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) + 411230592Sken (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL), 412230592Sken M_MPT2, M_ZERO | M_NOWAIT); 413230592Sken if (!raid_vol_pg0) { 414230592Sken printf("%s: page alloc failed\n", __func__); 415230592Sken goto out; 416230592Sken } 417230592Sken 418230592Sken if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0, 419230592Sken 0x0000FFFF)) { 420230592Sken mps_dprint(sc, MPS_INFO, 421230592Sken "mps_config_get_raid_volume_pg0 failed! Assuming " 422230592Sken "WarpDrive IT mode.\n"); 423230592Sken goto out; 424230592Sken } 425230592Sken 426230592Sken /* 427230592Sken * Check for valid WD configuration: 428230592Sken * volume type is RAID0 429230592Sken * number of phys disks in the volume is no more than 8 430230592Sken */ 431230592Sken if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) || 432230592Sken (raid_vol_pg0->NumPhysDisks > 8)) { 433230592Sken mps_dprint(sc, MPS_FAULT, 434230592Sken "Invalid WarpDrive configuration. Direct Drive I/O " 435230592Sken "will not be used.\n"); 436230592Sken goto out; 437230592Sken } 438230592Sken 439230592Sken /* 440230592Sken * Save the WD RAID data to be used during WD I/O. 441230592Sken */ 442230592Sken sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High << 443230592Sken 32 | (uint64_t)raid_vol_pg0->MaxLBA.Low); 444230592Sken sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks; 445230592Sken sc->DD_dev_handle = raid_vol_pg0->DevHandle; 446230592Sken sc->DD_stripe_size = raid_vol_pg0->StripeSize; 447230592Sken sc->DD_block_size = raid_vol_pg0->BlockSize; 448230592Sken 449230592Sken /* 450230592Sken * Find power of 2 of stripe size and set this as the exponent. 451230592Sken * Fail if stripe size is 0. 452230592Sken */ 453230592Sken stripe_size = raid_vol_pg0->StripeSize; 454230592Sken for (index = 0; index < 32; index++) { 455230592Sken if (stripe_size & 1) 456230592Sken break; 457230592Sken stripe_exp++; 458230592Sken stripe_size >>= 1; 459230592Sken } 460230592Sken if (index == 32) { 461230592Sken mps_dprint(sc, MPS_FAULT, 462230592Sken "RAID Volume's stripe size is 0. Direct Drive I/O " 463230592Sken "will not be used.\n"); 464230592Sken goto out; 465230592Sken } 466230592Sken sc->DD_stripe_exponent = stripe_exp; 467230592Sken 468230592Sken /* 469230592Sken * Find power of 2 of block size and set this as the exponent. 470230592Sken * Fail if block size is 0. 471230592Sken */ 472230592Sken block_size = raid_vol_pg0->BlockSize; 473230592Sken for (index = 0; index < 16; index++) { 474230592Sken if (block_size & 1) 475230592Sken break; 476230592Sken block_exp++; 477230592Sken block_size >>= 1; 478230592Sken } 479230592Sken if (index == 16) { 480230592Sken mps_dprint(sc, MPS_FAULT, 481230592Sken "RAID Volume's block size is 0. Direct Drive I/O " 482230592Sken "will not be used.\n"); 483230592Sken goto out; 484230592Sken } 485230592Sken sc->DD_block_exponent = block_exp; 486230592Sken 487230592Sken /* 488230592Sken * Loop through all of the volume's Phys Disks to map the phys 489230592Sken * disk number into the columm map. This is used during Direct 490230592Sken * Drive I/O to send the request to the correct SSD. 491230592Sken */ 492230592Sken pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk; 493230592Sken for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) { 494230592Sken sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num = 495230592Sken pRVPD->PhysDiskNum; 496230592Sken pRVPD++; 497230592Sken } 498230592Sken 499230592Sken /* 500230592Sken * Get second RAID Volume Page0 using previous handle. This 501230592Sken * page should not exist. If it does, must not proceed with WD 502230592Sken * handling. 503230592Sken */ 504230592Sken if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, 505230592Sken raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) { 506302225Sslm if ((le16toh(mpi_reply.IOCStatus) & 507302225Sslm MPI2_IOCSTATUS_MASK) != 508230592Sken MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) { 509230592Sken mps_dprint(sc, MPS_FAULT, 510230592Sken "Multiple RAID Volume Page0! Direct Drive " 511230592Sken "I/O will not be used.\n"); 512230592Sken goto out; 513230592Sken } 514230592Sken } else { 515230592Sken mps_dprint(sc, MPS_FAULT, 516230592Sken "Multiple volumes! Direct Drive I/O will not be " 517230592Sken "used.\n"); 518230592Sken goto out; 519230592Sken } 520230592Sken 521230592Sken /* 522230592Sken * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume. 523230592Sken */ 524230592Sken for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) { 525230592Sken phys_disk_page_address = 526230592Sken MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM + 527230592Sken sc->DD_column_map[index].phys_disk_num; 528230592Sken if (mps_config_get_raid_pd_pg0(sc, &mpi_reply, 529230592Sken &phys_disk_pg0, phys_disk_page_address)) { 530230592Sken mps_dprint(sc, MPS_FAULT, 531230592Sken "mps_config_get_raid_pd_pg0 failed! Direct " 532230592Sken "Drive I/O will not be used.\n"); 533230592Sken goto out; 534230592Sken } 535230592Sken if (phys_disk_pg0.DevHandle == 0xFFFF) { 536230592Sken mps_dprint(sc, MPS_FAULT, 537230592Sken "Invalid Phys Disk DevHandle! Direct Drive " 538230592Sken "I/O will not be used.\n"); 539230592Sken goto out; 540230592Sken } 541230592Sken sc->DD_column_map[index].dev_handle = 542230592Sken phys_disk_pg0.DevHandle; 543230592Sken } 544230592Sken sc->WD_valid_config = TRUE; 545230592Skenout: 546230592Sken if (raid_vol_pg0) 547230592Sken free(raid_vol_pg0, M_MPT2); 548230592Sken } 549230592Sken} 550230592Sken 551230592Sken/** 552230592Sken * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0 553230592Sken * @sc: per adapter object 554230592Sken * @mpi_reply: reply mf payload returned from firmware 555230592Sken * @config_page: contents of the config page 556230592Sken * @sz: size of buffer passed in config_page 557230592Sken * Context: sleep. 558230592Sken * 559230592Sken * Returns 0 for success, non-zero for failure. 560230592Sken */ 561230592Skenint 562230592Skenmps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 563230592Sken Mpi2DriverMappingPage0_t *config_page, u16 sz) 564230592Sken{ 565230592Sken MPI2_CONFIG_REQUEST *request; 566322661Sken MPI2_CONFIG_REPLY *reply = NULL; 567230592Sken struct mps_command *cm; 568230592Sken Mpi2DriverMappingPage0_t *page = NULL; 569230592Sken int error = 0; 570230592Sken u16 ioc_status; 571230592Sken 572230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 573230592Sken 574230592Sken memset(config_page, 0, sz); 575230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 576230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 577230592Sken __LINE__); 578230592Sken error = EBUSY; 579230592Sken goto out; 580230592Sken } 581230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 582230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 583230592Sken request->Function = MPI2_FUNCTION_CONFIG; 584230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 585230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 586230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 587230592Sken request->Header.PageNumber = 0; 588230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 589230592Sken request->PageAddress = sc->max_dpm_entries << 590230592Sken MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 591230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 592230592Sken cm->cm_data = NULL; 593322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 594322661Sken if (cm != NULL) 595322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 596230592Sken if (error || (reply == NULL)) { 597230592Sken /* FIXME */ 598253550Sken /* 599253550Sken * If the request returns an error then we need to do a diag 600253550Sken * reset 601253550Sken */ 602253550Sken printf("%s: request for header completed with error %d", 603230592Sken __func__, error); 604230592Sken error = ENXIO; 605230592Sken goto out; 606230592Sken } 607230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 608230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 609230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 610230592Sken /* FIXME */ 611253550Sken /* 612253550Sken * If the request returns an error then we need to do a diag 613253550Sken * reset 614253550Sken */ 615230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 616230592Sken __func__, ioc_status); 617230592Sken error = ENXIO; 618230592Sken goto out; 619230592Sken } 620230592Sken /* We have to do free and alloc for the reply-free and reply-post 621230592Sken * counters to match - Need to review the reply FIFO handling. 622230592Sken */ 623230592Sken mps_free_command(sc, cm); 624230592Sken 625230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 626230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 627230592Sken __LINE__); 628230592Sken error = EBUSY; 629230592Sken goto out; 630230592Sken } 631230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 632230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 633230592Sken request->Function = MPI2_FUNCTION_CONFIG; 634230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM; 635230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 636230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 637230592Sken request->Header.PageNumber = 0; 638230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 639230592Sken request->PageAddress = sc->max_dpm_entries << 640230592Sken MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 641230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 642230592Sken cm->cm_length = le16toh(request->ExtPageLength) * 4; 643230592Sken cm->cm_sge = &request->PageBufferSGE; 644230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 645230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 646230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 647230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT); 648230592Sken if (!page) { 649230592Sken printf("%s: page alloc failed\n", __func__); 650230592Sken error = ENOMEM; 651230592Sken goto out; 652230592Sken } 653230592Sken cm->cm_data = page; 654322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 655322661Sken if (cm != NULL) 656322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 657230592Sken if (error || (reply == NULL)) { 658230592Sken /* FIXME */ 659253550Sken /* 660253550Sken * If the request returns an error then we need to do a diag 661253550Sken * reset 662253550Sken */ 663253550Sken printf("%s: request for page completed with error %d", 664230592Sken __func__, error); 665230592Sken error = ENXIO; 666230592Sken goto out; 667230592Sken } 668230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 669230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 670230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 671230592Sken /* FIXME */ 672253550Sken /* 673253550Sken * If the request returns an error then we need to do a diag 674253550Sken * reset 675253550Sken */ 676230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 677230592Sken __func__, ioc_status); 678230592Sken error = ENXIO; 679230592Sken goto out; 680230592Sken } 681230592Sken bcopy(page, config_page, MIN(cm->cm_length, sz)); 682230592Skenout: 683230592Sken free(page, M_MPT2); 684230592Sken if (cm) 685230592Sken mps_free_command(sc, cm); 686230592Sken return (error); 687230592Sken} 688230592Sken 689230592Sken/** 690230592Sken * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0 691230592Sken * @sc: per adapter object 692230592Sken * @mpi_reply: reply mf payload returned from firmware 693230592Sken * @config_page: contents of the config page 694230592Sken * @entry_idx: entry index in DPM Page0 to be modified 695230592Sken * Context: sleep. 696230592Sken * 697230592Sken * Returns 0 for success, non-zero for failure. 698230592Sken */ 699230592Sken 700230592Skenint mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 701230592Sken Mpi2DriverMappingPage0_t *config_page, u16 entry_idx) 702230592Sken{ 703230592Sken MPI2_CONFIG_REQUEST *request; 704322661Sken MPI2_CONFIG_REPLY *reply = NULL; 705230592Sken struct mps_command *cm; 706230592Sken MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL; 707230592Sken int error = 0; 708230592Sken u16 ioc_status; 709230592Sken 710230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 711230592Sken 712230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 713230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 714230592Sken __LINE__); 715230592Sken error = EBUSY; 716230592Sken goto out; 717230592Sken } 718230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 719230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 720230592Sken request->Function = MPI2_FUNCTION_CONFIG; 721230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 722230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 723230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 724230592Sken request->Header.PageNumber = 0; 725230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 726237683Sken /* We can remove below two lines ????*/ 727230592Sken request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 728230592Sken request->PageAddress |= htole16(entry_idx); 729230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 730230592Sken cm->cm_data = NULL; 731322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 732322661Sken if (cm != NULL) 733322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 734230592Sken if (error || (reply == NULL)) { 735230592Sken /* FIXME */ 736253550Sken /* 737253550Sken * If the request returns an error then we need to do a diag 738253550Sken * reset 739253550Sken */ 740253550Sken printf("%s: request for header completed with error %d", 741230592Sken __func__, error); 742230592Sken error = ENXIO; 743230592Sken goto out; 744230592Sken } 745230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 746230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 747230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 748230592Sken /* FIXME */ 749253550Sken /* 750253550Sken * If the request returns an error then we need to do a diag 751253550Sken * reset 752253550Sken */ 753230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 754230592Sken __func__, ioc_status); 755230592Sken error = ENXIO; 756230592Sken goto out; 757230592Sken } 758230592Sken /* We have to do free and alloc for the reply-free and reply-post 759230592Sken * counters to match - Need to review the reply FIFO handling. 760230592Sken */ 761230592Sken mps_free_command(sc, cm); 762230592Sken 763230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 764230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 765230592Sken __LINE__); 766230592Sken error = EBUSY; 767230592Sken goto out; 768230592Sken } 769230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 770230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 771230592Sken request->Function = MPI2_FUNCTION_CONFIG; 772230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; 773230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 774230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING; 775230592Sken request->Header.PageNumber = 0; 776230592Sken request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION; 777230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 778230592Sken request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT; 779230592Sken request->PageAddress |= htole16(entry_idx); 780230592Sken cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 781230592Sken cm->cm_sge = &request->PageBufferSGE; 782230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 783230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT; 784230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 785230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 786230592Sken if (!page) { 787230592Sken printf("%s: page alloc failed\n", __func__); 788230592Sken error = ENOMEM; 789230592Sken goto out; 790230592Sken } 791230592Sken bcopy(config_page, page, MIN(cm->cm_length, 792230592Sken (sizeof(Mpi2DriverMappingPage0_t)))); 793230592Sken cm->cm_data = page; 794322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 795322661Sken if (cm != NULL) 796322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 797230592Sken if (error || (reply == NULL)) { 798230592Sken /* FIXME */ 799253550Sken /* 800253550Sken * If the request returns an error then we need to do a diag 801253550Sken * reset 802253550Sken */ 803253550Sken printf("%s: request to write page completed with error %d", 804230592Sken __func__, error); 805230592Sken error = ENXIO; 806230592Sken goto out; 807230592Sken } 808230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 809230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 810230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 811230592Sken /* FIXME */ 812253550Sken /* 813253550Sken * If the request returns an error then we need to do a diag 814253550Sken * reset 815253550Sken */ 816230592Sken printf("%s: page written with error; iocstatus = 0x%x\n", 817230592Sken __func__, ioc_status); 818230592Sken error = ENXIO; 819230592Sken goto out; 820230592Sken } 821230592Skenout: 822230592Sken free(page, M_MPT2); 823230592Sken if (cm) 824230592Sken mps_free_command(sc, cm); 825230592Sken return (error); 826230592Sken} 827230592Sken 828230592Sken/** 829230592Sken * mps_config_get_sas_device_pg0 - obtain sas device page 0 830230592Sken * @sc: per adapter object 831230592Sken * @mpi_reply: reply mf payload returned from firmware 832230592Sken * @config_page: contents of the config page 833230592Sken * @form: GET_NEXT_HANDLE or HANDLE 834230592Sken * @handle: device handle 835230592Sken * Context: sleep. 836230592Sken * 837230592Sken * Returns 0 for success, non-zero for failure. 838230592Sken */ 839230592Skenint 840230592Skenmps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 841230592Sken *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle) 842230592Sken{ 843230592Sken MPI2_CONFIG_REQUEST *request; 844322661Sken MPI2_CONFIG_REPLY *reply = NULL; 845230592Sken struct mps_command *cm; 846230592Sken Mpi2SasDevicePage0_t *page = NULL; 847230592Sken int error = 0; 848230592Sken u16 ioc_status; 849230592Sken 850230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 851230592Sken 852230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 853230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 854230592Sken __LINE__); 855230592Sken error = EBUSY; 856230592Sken goto out; 857230592Sken } 858230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 859230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 860230592Sken request->Function = MPI2_FUNCTION_CONFIG; 861230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 862230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 863230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 864230592Sken request->Header.PageNumber = 0; 865230592Sken request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 866230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 867230592Sken cm->cm_data = NULL; 868322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 869322661Sken if (cm != NULL) 870322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 871230592Sken if (error || (reply == NULL)) { 872230592Sken /* FIXME */ 873253550Sken /* 874253550Sken * If the request returns an error then we need to do a diag 875253550Sken * reset 876253550Sken */ 877253550Sken printf("%s: request for header completed with error %d", 878230592Sken __func__, error); 879230592Sken error = ENXIO; 880230592Sken goto out; 881230592Sken } 882230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 883230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 884230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 885230592Sken /* FIXME */ 886253550Sken /* 887253550Sken * If the request returns an error then we need to do a diag 888253550Sken * reset 889253550Sken */ 890230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 891230592Sken __func__, ioc_status); 892230592Sken error = ENXIO; 893230592Sken goto out; 894230592Sken } 895230592Sken /* We have to do free and alloc for the reply-free and reply-post 896230592Sken * counters to match - Need to review the reply FIFO handling. 897230592Sken */ 898230592Sken mps_free_command(sc, cm); 899230592Sken 900230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 901230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 902230592Sken __LINE__); 903230592Sken error = EBUSY; 904230592Sken goto out; 905230592Sken } 906230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 907230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 908230592Sken request->Function = MPI2_FUNCTION_CONFIG; 909230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 910230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; 911230592Sken request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; 912230592Sken request->Header.PageNumber = 0; 913230592Sken request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; 914230592Sken request->ExtPageLength = mpi_reply->ExtPageLength; 915230592Sken request->PageAddress = htole32(form | handle); 916230592Sken cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4; 917230592Sken cm->cm_sge = &request->PageBufferSGE; 918230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 919230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 920230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 921230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 922230592Sken if (!page) { 923230592Sken printf("%s: page alloc failed\n", __func__); 924230592Sken error = ENOMEM; 925230592Sken goto out; 926230592Sken } 927230592Sken cm->cm_data = page; 928230592Sken 929322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 930322661Sken if (cm != NULL) 931322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 932230592Sken if (error || (reply == NULL)) { 933230592Sken /* FIXME */ 934253550Sken /* 935253550Sken * If the request returns an error then we need to do a diag 936253550Sken * reset 937253550Sken */ 938253550Sken printf("%s: request for page completed with error %d", 939230592Sken __func__, error); 940230592Sken error = ENXIO; 941230592Sken goto out; 942230592Sken } 943230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 944230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 945230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 946230592Sken /* FIXME */ 947253550Sken /* 948253550Sken * If the request returns an error then we need to do a diag 949253550Sken * reset 950253550Sken */ 951230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 952230592Sken __func__, ioc_status); 953230592Sken error = ENXIO; 954230592Sken goto out; 955230592Sken } 956230592Sken bcopy(page, config_page, MIN(cm->cm_length, 957230592Sken sizeof(Mpi2SasDevicePage0_t))); 958230592Skenout: 959230592Sken free(page, M_MPT2); 960230592Sken if (cm) 961230592Sken mps_free_command(sc, cm); 962230592Sken return (error); 963230592Sken} 964230592Sken 965230592Sken/** 966230592Sken * mps_config_get_bios_pg3 - obtain BIOS page 3 967230592Sken * @sc: per adapter object 968230592Sken * @mpi_reply: reply mf payload returned from firmware 969230592Sken * @config_page: contents of the config page 970230592Sken * Context: sleep. 971230592Sken * 972230592Sken * Returns 0 for success, non-zero for failure. 973230592Sken */ 974230592Skenint 975230592Skenmps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 976230592Sken Mpi2BiosPage3_t *config_page) 977230592Sken{ 978230592Sken MPI2_CONFIG_REQUEST *request; 979322661Sken MPI2_CONFIG_REPLY *reply = NULL; 980230592Sken struct mps_command *cm; 981230592Sken Mpi2BiosPage3_t *page = NULL; 982230592Sken int error = 0; 983230592Sken u16 ioc_status; 984230592Sken 985230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 986230592Sken 987230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 988230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 989230592Sken __LINE__); 990230592Sken error = EBUSY; 991230592Sken goto out; 992230592Sken } 993230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 994230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 995230592Sken request->Function = MPI2_FUNCTION_CONFIG; 996230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 997230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 998230592Sken request->Header.PageNumber = 3; 999230592Sken request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 1000230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1001230592Sken cm->cm_data = NULL; 1002322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 1003322661Sken if (cm != NULL) 1004322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1005230592Sken if (error || (reply == NULL)) { 1006230592Sken /* FIXME */ 1007253550Sken /* 1008253550Sken * If the request returns an error then we need to do a diag 1009253550Sken * reset 1010253550Sken */ 1011253550Sken printf("%s: request for header completed with error %d", 1012230592Sken __func__, error); 1013230592Sken error = ENXIO; 1014230592Sken goto out; 1015230592Sken } 1016230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1017230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1018230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1019230592Sken /* FIXME */ 1020253550Sken /* 1021253550Sken * If the request returns an error then we need to do a diag 1022253550Sken * reset 1023253550Sken */ 1024230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1025230592Sken __func__, ioc_status); 1026230592Sken error = ENXIO; 1027230592Sken goto out; 1028230592Sken } 1029230592Sken /* We have to do free and alloc for the reply-free and reply-post 1030230592Sken * counters to match - Need to review the reply FIFO handling. 1031230592Sken */ 1032230592Sken mps_free_command(sc, cm); 1033230592Sken 1034230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1035230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1036230592Sken __LINE__); 1037230592Sken error = EBUSY; 1038230592Sken goto out; 1039230592Sken } 1040230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1041230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1042230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1043230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1044230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; 1045230592Sken request->Header.PageNumber = 3; 1046230592Sken request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; 1047230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1048230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1049230592Sken cm->cm_sge = &request->PageBufferSGE; 1050230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1051230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1052230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1053230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1054230592Sken if (!page) { 1055230592Sken printf("%s: page alloc failed\n", __func__); 1056230592Sken error = ENOMEM; 1057230592Sken goto out; 1058230592Sken } 1059230592Sken cm->cm_data = page; 1060230592Sken 1061322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 1062322661Sken if (cm != NULL) 1063322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1064230592Sken if (error || (reply == NULL)) { 1065230592Sken /* FIXME */ 1066253550Sken /* 1067253550Sken * If the request returns an error then we need to do a diag 1068253550Sken * reset 1069253550Sken */ 1070253550Sken printf("%s: request for page completed with error %d", 1071230592Sken __func__, error); 1072230592Sken error = ENXIO; 1073230592Sken goto out; 1074230592Sken } 1075230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1076230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1077230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1078230592Sken /* FIXME */ 1079253550Sken /* 1080253550Sken * If the request returns an error then we need to do a diag 1081253550Sken * reset 1082253550Sken */ 1083230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1084230592Sken __func__, ioc_status); 1085230592Sken error = ENXIO; 1086230592Sken goto out; 1087230592Sken } 1088230592Sken bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t))); 1089230592Skenout: 1090230592Sken free(page, M_MPT2); 1091230592Sken if (cm) 1092230592Sken mps_free_command(sc, cm); 1093230592Sken return (error); 1094230592Sken} 1095230592Sken 1096230592Sken/** 1097230592Sken * mps_config_get_raid_volume_pg0 - obtain raid volume page 0 1098230592Sken * @sc: per adapter object 1099230592Sken * @mpi_reply: reply mf payload returned from firmware 1100230592Sken * @config_page: contents of the config page 1101230592Sken * @page_address: form and handle value used to get page 1102230592Sken * Context: sleep. 1103230592Sken * 1104230592Sken * Returns 0 for success, non-zero for failure. 1105230592Sken */ 1106230592Skenint 1107230592Skenmps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t 1108230592Sken *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address) 1109230592Sken{ 1110230592Sken MPI2_CONFIG_REQUEST *request; 1111322661Sken MPI2_CONFIG_REPLY *reply = NULL; 1112230592Sken struct mps_command *cm; 1113230592Sken Mpi2RaidVolPage0_t *page = NULL; 1114230592Sken int error = 0; 1115230592Sken u16 ioc_status; 1116230592Sken 1117230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1118230592Sken 1119230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1120230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1121230592Sken __LINE__); 1122230592Sken error = EBUSY; 1123230592Sken goto out; 1124230592Sken } 1125230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1126230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1127230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1128230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1129230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1130230592Sken request->Header.PageNumber = 0; 1131230592Sken request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; 1132230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1133230592Sken cm->cm_data = NULL; 1134253550Sken 1135253550Sken /* 1136253550Sken * This page must be polled because the IOC isn't ready yet when this 1137253550Sken * page is needed. 1138253550Sken */ 1139322661Sken error = mps_wait_command(sc, &cm, 60, 0); 1140322661Sken if (cm != NULL) 1141322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1142230592Sken if (error || (reply == NULL)) { 1143230592Sken /* FIXME */ 1144230592Sken /* If the poll returns error then we need to do diag reset */ 1145230592Sken printf("%s: poll for header completed with error %d", 1146230592Sken __func__, error); 1147230592Sken error = ENXIO; 1148230592Sken goto out; 1149230592Sken } 1150230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1151230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1152230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1153230592Sken /* FIXME */ 1154230592Sken /* If the poll returns error then we need to do diag reset */ 1155230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1156230592Sken __func__, ioc_status); 1157230592Sken error = ENXIO; 1158230592Sken goto out; 1159230592Sken } 1160230592Sken /* We have to do free and alloc for the reply-free and reply-post 1161230592Sken * counters to match - Need to review the reply FIFO handling. 1162230592Sken */ 1163230592Sken mps_free_command(sc, cm); 1164230592Sken 1165230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1166230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1167230592Sken __LINE__); 1168230592Sken error = EBUSY; 1169230592Sken goto out; 1170230592Sken } 1171230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1172230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1173230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1174230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1175230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1176230592Sken request->Header.PageNumber = 0; 1177230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1178230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1179230592Sken request->PageAddress = page_address; 1180230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1181230592Sken cm->cm_sge = &request->PageBufferSGE; 1182230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1183230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1184230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1185230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1186230592Sken if (!page) { 1187230592Sken printf("%s: page alloc failed\n", __func__); 1188230592Sken error = ENOMEM; 1189230592Sken goto out; 1190230592Sken } 1191230592Sken cm->cm_data = page; 1192230592Sken 1193253550Sken /* 1194253550Sken * This page must be polled because the IOC isn't ready yet when this 1195253550Sken * page is needed. 1196253550Sken */ 1197322661Sken error = mps_wait_command(sc, &cm, 60, 0); 1198322661Sken if (cm != NULL) 1199322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1200230592Sken if (error || (reply == NULL)) { 1201230592Sken /* FIXME */ 1202230592Sken /* If the poll returns error then we need to do diag reset */ 1203230592Sken printf("%s: poll for page completed with error %d", 1204230592Sken __func__, error); 1205230592Sken error = ENXIO; 1206230592Sken goto out; 1207230592Sken } 1208230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1209230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1210230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1211230592Sken /* FIXME */ 1212230592Sken /* If the poll returns error then we need to do diag reset */ 1213230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1214230592Sken __func__, ioc_status); 1215230592Sken error = ENXIO; 1216230592Sken goto out; 1217230592Sken } 1218230592Sken bcopy(page, config_page, cm->cm_length); 1219230592Skenout: 1220230592Sken free(page, M_MPT2); 1221230592Sken if (cm) 1222230592Sken mps_free_command(sc, cm); 1223230592Sken return (error); 1224230592Sken} 1225230592Sken 1226230592Sken/** 1227230592Sken * mps_config_get_raid_volume_pg1 - obtain raid volume page 1 1228230592Sken * @sc: per adapter object 1229230592Sken * @mpi_reply: reply mf payload returned from firmware 1230230592Sken * @config_page: contents of the config page 1231230592Sken * @form: GET_NEXT_HANDLE or HANDLE 1232230592Sken * @handle: volume handle 1233230592Sken * Context: sleep. 1234230592Sken * 1235230592Sken * Returns 0 for success, non-zero for failure. 1236230592Sken */ 1237230592Skenint 1238230592Skenmps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t 1239230592Sken *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle) 1240230592Sken{ 1241230592Sken MPI2_CONFIG_REQUEST *request; 1242322661Sken MPI2_CONFIG_REPLY *reply = NULL; 1243230592Sken struct mps_command *cm; 1244230592Sken Mpi2RaidVolPage1_t *page = NULL; 1245230592Sken int error = 0; 1246230592Sken u16 ioc_status; 1247230592Sken 1248230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1249230592Sken 1250230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1251230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1252230592Sken __LINE__); 1253230592Sken error = EBUSY; 1254230592Sken goto out; 1255230592Sken } 1256230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1257230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1258230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1259230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1260230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1261230592Sken request->Header.PageNumber = 1; 1262230592Sken request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; 1263230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1264230592Sken cm->cm_data = NULL; 1265322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 1266322661Sken if (cm != NULL) 1267322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1268230592Sken if (error || (reply == NULL)) { 1269230592Sken /* FIXME */ 1270253550Sken /* 1271253550Sken * If the request returns an error then we need to do a diag 1272253550Sken * reset 1273253550Sken */ 1274253550Sken printf("%s: request for header completed with error %d", 1275230592Sken __func__, error); 1276230592Sken error = ENXIO; 1277230592Sken goto out; 1278230592Sken } 1279230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1280230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1281230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1282230592Sken /* FIXME */ 1283253550Sken /* 1284253550Sken * If the request returns an error then we need to do a diag 1285253550Sken * reset 1286253550Sken */ 1287230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1288230592Sken __func__, ioc_status); 1289230592Sken error = ENXIO; 1290230592Sken goto out; 1291230592Sken } 1292230592Sken /* We have to do free and alloc for the reply-free and reply-post 1293230592Sken * counters to match - Need to review the reply FIFO handling. 1294230592Sken */ 1295230592Sken mps_free_command(sc, cm); 1296230592Sken 1297230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1298230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1299230592Sken __LINE__); 1300230592Sken error = EBUSY; 1301230592Sken goto out; 1302230592Sken } 1303230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1304230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1305230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1306230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1307230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; 1308230592Sken request->Header.PageNumber = 1; 1309230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1310230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1311230592Sken request->PageAddress = htole32(form | handle); 1312230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1313230592Sken cm->cm_sge = &request->PageBufferSGE; 1314230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1315230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1316230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1317230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1318230592Sken if (!page) { 1319230592Sken printf("%s: page alloc failed\n", __func__); 1320230592Sken error = ENOMEM; 1321230592Sken goto out; 1322230592Sken } 1323230592Sken cm->cm_data = page; 1324230592Sken 1325322661Sken error = mps_wait_command(sc, &cm, 60, CAN_SLEEP); 1326322661Sken if (cm != NULL) 1327322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1328230592Sken if (error || (reply == NULL)) { 1329230592Sken /* FIXME */ 1330253550Sken /* 1331253550Sken * If the request returns an error then we need to do a diag 1332253550Sken * reset 1333253550Sken */ 1334253550Sken printf("%s: request for page completed with error %d", 1335230592Sken __func__, error); 1336230592Sken error = ENXIO; 1337230592Sken goto out; 1338230592Sken } 1339230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1340230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1341230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1342230592Sken /* FIXME */ 1343253550Sken /* 1344253550Sken * If the request returns an error then we need to do a diag 1345253550Sken * reset 1346253550Sken */ 1347230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1348230592Sken __func__, ioc_status); 1349230592Sken error = ENXIO; 1350230592Sken goto out; 1351230592Sken } 1352230592Sken bcopy(page, config_page, MIN(cm->cm_length, 1353230592Sken sizeof(Mpi2RaidVolPage1_t))); 1354230592Skenout: 1355230592Sken free(page, M_MPT2); 1356230592Sken if (cm) 1357230592Sken mps_free_command(sc, cm); 1358230592Sken return (error); 1359230592Sken} 1360230592Sken 1361230592Sken/** 1362230592Sken * mps_config_get_volume_wwid - returns wwid given the volume handle 1363230592Sken * @sc: per adapter object 1364230592Sken * @volume_handle: volume handle 1365230592Sken * @wwid: volume wwid 1366230592Sken * Context: sleep. 1367230592Sken * 1368230592Sken * Returns 0 for success, non-zero for failure. 1369230592Sken */ 1370230592Skenint 1371230592Skenmps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid) 1372230592Sken{ 1373230592Sken Mpi2ConfigReply_t mpi_reply; 1374230592Sken Mpi2RaidVolPage1_t raid_vol_pg1; 1375230592Sken 1376230592Sken *wwid = 0; 1377230592Sken if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1, 1378230592Sken MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) { 1379230592Sken *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 | 1380230592Sken raid_vol_pg1.WWID.Low); 1381230592Sken return 0; 1382230592Sken } else 1383230592Sken return -1; 1384230592Sken} 1385230592Sken 1386230592Sken/** 1387230592Sken * mps_config_get_pd_pg0 - obtain raid phys disk page 0 1388230592Sken * @sc: per adapter object 1389230592Sken * @mpi_reply: reply mf payload returned from firmware 1390230592Sken * @config_page: contents of the config page 1391230592Sken * @page_address: form and handle value used to get page 1392230592Sken * Context: sleep. 1393230592Sken * 1394230592Sken * Returns 0 for success, non-zero for failure. 1395230592Sken */ 1396230592Skenint 1397230592Skenmps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply, 1398230592Sken Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address) 1399230592Sken{ 1400230592Sken MPI2_CONFIG_REQUEST *request; 1401322661Sken MPI2_CONFIG_REPLY *reply = NULL; 1402230592Sken struct mps_command *cm; 1403230592Sken Mpi2RaidPhysDiskPage0_t *page = NULL; 1404230592Sken int error = 0; 1405230592Sken u16 ioc_status; 1406230592Sken 1407230592Sken mps_dprint(sc, MPS_TRACE, "%s\n", __func__); 1408230592Sken 1409230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1410230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1411230592Sken __LINE__); 1412230592Sken error = EBUSY; 1413230592Sken goto out; 1414230592Sken } 1415230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1416230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1417230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1418230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER; 1419230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1420230592Sken request->Header.PageNumber = 0; 1421230592Sken request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; 1422230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1423230592Sken cm->cm_data = NULL; 1424253550Sken 1425253550Sken /* 1426253550Sken * This page must be polled because the IOC isn't ready yet when this 1427253550Sken * page is needed. 1428253550Sken */ 1429322661Sken error = mps_wait_command(sc, &cm, 60, 0); 1430322661Sken if (cm != NULL) 1431322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1432230592Sken if (error || (reply == NULL)) { 1433230592Sken /* FIXME */ 1434230592Sken /* If the poll returns error then we need to do diag reset */ 1435230592Sken printf("%s: poll for header completed with error %d", 1436230592Sken __func__, error); 1437230592Sken error = ENXIO; 1438230592Sken goto out; 1439230592Sken } 1440230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1441230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1442230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1443230592Sken /* FIXME */ 1444230592Sken /* If the poll returns error then we need to do diag reset */ 1445230592Sken printf("%s: header read with error; iocstatus = 0x%x\n", 1446230592Sken __func__, ioc_status); 1447230592Sken error = ENXIO; 1448230592Sken goto out; 1449230592Sken } 1450230592Sken /* We have to do free and alloc for the reply-free and reply-post 1451230592Sken * counters to match - Need to review the reply FIFO handling. 1452230592Sken */ 1453230592Sken mps_free_command(sc, cm); 1454230592Sken 1455230592Sken if ((cm = mps_alloc_command(sc)) == NULL) { 1456230592Sken printf("%s: command alloc failed @ line %d\n", __func__, 1457230592Sken __LINE__); 1458230592Sken error = EBUSY; 1459230592Sken goto out; 1460230592Sken } 1461230592Sken request = (MPI2_CONFIG_REQUEST *)cm->cm_req; 1462230592Sken bzero(request, sizeof(MPI2_CONFIG_REQUEST)); 1463230592Sken request->Function = MPI2_FUNCTION_CONFIG; 1464230592Sken request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; 1465230592Sken request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; 1466230592Sken request->Header.PageNumber = 0; 1467230592Sken request->Header.PageLength = mpi_reply->Header.PageLength; 1468230592Sken request->Header.PageVersion = mpi_reply->Header.PageVersion; 1469230592Sken request->PageAddress = page_address; 1470230592Sken cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4; 1471230592Sken cm->cm_sge = &request->PageBufferSGE; 1472230592Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1473230592Sken cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN; 1474230592Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1475230592Sken page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT); 1476230592Sken if (!page) { 1477230592Sken printf("%s: page alloc failed\n", __func__); 1478230592Sken error = ENOMEM; 1479230592Sken goto out; 1480230592Sken } 1481230592Sken cm->cm_data = page; 1482230592Sken 1483253550Sken /* 1484253550Sken * This page must be polled because the IOC isn't ready yet when this 1485253550Sken * page is needed. 1486253550Sken */ 1487322661Sken error = mps_wait_command(sc, &cm, 60, 0); 1488322661Sken if (cm != NULL) 1489322661Sken reply = (MPI2_CONFIG_REPLY *)cm->cm_reply; 1490230592Sken if (error || (reply == NULL)) { 1491230592Sken /* FIXME */ 1492230592Sken /* If the poll returns error then we need to do diag reset */ 1493230592Sken printf("%s: poll for page completed with error %d", 1494230592Sken __func__, error); 1495230592Sken error = ENXIO; 1496230592Sken goto out; 1497230592Sken } 1498230592Sken ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK; 1499230592Sken bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY)); 1500230592Sken if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 1501230592Sken /* FIXME */ 1502230592Sken /* If the poll returns error then we need to do diag reset */ 1503230592Sken printf("%s: page read with error; iocstatus = 0x%x\n", 1504230592Sken __func__, ioc_status); 1505230592Sken error = ENXIO; 1506230592Sken goto out; 1507230592Sken } 1508230592Sken bcopy(page, config_page, MIN(cm->cm_length, 1509230592Sken sizeof(Mpi2RaidPhysDiskPage0_t))); 1510230592Skenout: 1511230592Sken free(page, M_MPT2); 1512230592Sken if (cm) 1513230592Sken mps_free_command(sc, cm); 1514230592Sken return (error); 1515230592Sken} 1516