1265236Sken/*- 2283990Sslm * Copyright (c) 2011-2015 LSI Corp. 3299962Sslm * Copyright (c) 2013-2016 Avago Technologies 4265236Sken * All rights reserved. 5265236Sken * 6265236Sken * Redistribution and use in source and binary forms, with or without 7265236Sken * modification, are permitted provided that the following conditions 8265236Sken * are met: 9265236Sken * 1. Redistributions of source code must retain the above copyright 10265236Sken * notice, this list of conditions and the following disclaimer. 11265236Sken * 2. Redistributions in binary form must reproduce the above copyright 12265236Sken * notice, this list of conditions and the following disclaimer in the 13265236Sken * documentation and/or other materials provided with the distribution. 14265236Sken * 15265236Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16265236Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17265236Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18265236Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19265236Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20265236Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21265236Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22265236Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23265236Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24265236Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25265236Sken * SUCH DAMAGE. 26265236Sken * 27283990Sslm * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD 28265236Sken */ 29265236Sken 30265236Sken#include <sys/cdefs.h> 31265236Sken__FBSDID("$FreeBSD: stable/10/sys/dev/mpr/mpr_sas_lsi.c 322661 2017-08-18 15:38:08Z ken $"); 32265236Sken 33299962Sslm/* Communications core for Avago Technologies (LSI) MPT3 */ 34265236Sken 35265236Sken/* TODO Move headers to mprvar */ 36265236Sken#include <sys/types.h> 37265236Sken#include <sys/param.h> 38265236Sken#include <sys/systm.h> 39265236Sken#include <sys/kernel.h> 40265236Sken#include <sys/selinfo.h> 41265236Sken#include <sys/module.h> 42265236Sken#include <sys/bus.h> 43265236Sken#include <sys/conf.h> 44265236Sken#include <sys/bio.h> 45265236Sken#include <sys/malloc.h> 46265236Sken#include <sys/uio.h> 47265236Sken#include <sys/sysctl.h> 48265236Sken#include <sys/endian.h> 49265236Sken#include <sys/queue.h> 50265236Sken#include <sys/kthread.h> 51265236Sken#include <sys/taskqueue.h> 52265236Sken#include <sys/sbuf.h> 53265236Sken 54265236Sken#include <machine/bus.h> 55265236Sken#include <machine/resource.h> 56265236Sken#include <sys/rman.h> 57265236Sken 58265236Sken#include <machine/stdarg.h> 59265236Sken 60265236Sken#include <cam/cam.h> 61265236Sken#include <cam/cam_ccb.h> 62265236Sken#include <cam/cam_debug.h> 63265236Sken#include <cam/cam_sim.h> 64265236Sken#include <cam/cam_xpt_sim.h> 65265236Sken#include <cam/cam_xpt_periph.h> 66265236Sken#include <cam/cam_periph.h> 67265236Sken#include <cam/scsi/scsi_all.h> 68265236Sken#include <cam/scsi/scsi_message.h> 69265236Sken 70265236Sken#include <dev/mpr/mpi/mpi2_type.h> 71265236Sken#include <dev/mpr/mpi/mpi2.h> 72265236Sken#include <dev/mpr/mpi/mpi2_ioc.h> 73265236Sken#include <dev/mpr/mpi/mpi2_sas.h> 74319436Sslm#include <dev/mpr/mpi/mpi2_pci.h> 75265236Sken#include <dev/mpr/mpi/mpi2_cnfg.h> 76265236Sken#include <dev/mpr/mpi/mpi2_init.h> 77265236Sken#include <dev/mpr/mpi/mpi2_raid.h> 78265236Sken#include <dev/mpr/mpi/mpi2_tool.h> 79265236Sken#include <dev/mpr/mpr_ioctl.h> 80265236Sken#include <dev/mpr/mprvar.h> 81265236Sken#include <dev/mpr/mpr_table.h> 82265236Sken#include <dev/mpr/mpr_sas.h> 83265236Sken 84265236Sken/* For Hashed SAS Address creation for SATA Drives */ 85265236Sken#define MPT2SAS_SN_LEN 20 86265236Sken#define MPT2SAS_MN_LEN 40 87265236Sken 88265236Skenstruct mpr_fw_event_work { 89265236Sken u16 event; 90265236Sken void *event_data; 91265236Sken TAILQ_ENTRY(mpr_fw_event_work) ev_link; 92265236Sken}; 93265236Sken 94265236Skenunion _sata_sas_address { 95265236Sken u8 wwid[8]; 96265236Sken struct { 97265236Sken u32 high; 98265236Sken u32 low; 99265236Sken } word; 100265236Sken}; 101265236Sken 102265236Sken/* 103265236Sken * define the IDENTIFY DEVICE structure 104265236Sken */ 105265236Skenstruct _ata_identify_device_data { 106265236Sken u16 reserved1[10]; /* 0-9 */ 107265236Sken u16 serial_number[10]; /* 10-19 */ 108265236Sken u16 reserved2[7]; /* 20-26 */ 109265236Sken u16 model_number[20]; /* 27-46*/ 110283990Sslm u16 reserved3[170]; /* 47-216 */ 111283990Sslm u16 rotational_speed; /* 217 */ 112283990Sslm u16 reserved4[38]; /* 218-255 */ 113265236Sken}; 114265236Skenstatic u32 event_count; 115265236Skenstatic void mprsas_fw_work(struct mpr_softc *sc, 116265236Sken struct mpr_fw_event_work *fw_event); 117265236Skenstatic void mprsas_fw_event_free(struct mpr_softc *, 118265236Sken struct mpr_fw_event_work *); 119265236Skenstatic int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate); 120319436Sslmstatic int mprsas_add_pcie_device(struct mpr_softc *sc, u16 handle, 121319436Sslm u8 linkrate); 122265236Skenstatic int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, 123265236Sken Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, 124265236Sken u32 devinfo); 125283990Sslmstatic void mprsas_ata_id_timeout(void *data); 126265236Skenint mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, 127283990Sslm u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); 128265236Skenstatic int mprsas_volume_add(struct mpr_softc *sc, 129265236Sken u16 handle); 130265236Skenstatic void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc); 131265236Skenstatic void mprsas_stop_unit_done(struct cam_periph *periph, 132265236Sken union ccb *done_ccb); 133265236Sken 134265236Skenvoid 135265236Skenmprsas_evt_handler(struct mpr_softc *sc, uintptr_t data, 136265236Sken MPI2_EVENT_NOTIFICATION_REPLY *event) 137265236Sken{ 138265236Sken struct mpr_fw_event_work *fw_event; 139265236Sken u16 sz; 140265236Sken 141265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 142322661Sken MPR_DPRINT_EVENT(sc, sas, event); 143265236Sken mprsas_record_event(sc, event); 144265236Sken 145265236Sken fw_event = malloc(sizeof(struct mpr_fw_event_work), M_MPR, 146265236Sken M_ZERO|M_NOWAIT); 147265236Sken if (!fw_event) { 148265236Sken printf("%s: allocate failed for fw_event\n", __func__); 149265236Sken return; 150265236Sken } 151265236Sken sz = le16toh(event->EventDataLength) * 4; 152265236Sken fw_event->event_data = malloc(sz, M_MPR, M_ZERO|M_NOWAIT); 153265236Sken if (!fw_event->event_data) { 154265236Sken printf("%s: allocate failed for event_data\n", __func__); 155265236Sken free(fw_event, M_MPR); 156265236Sken return; 157265236Sken } 158265236Sken 159265236Sken bcopy(event->EventData, fw_event->event_data, sz); 160265236Sken fw_event->event = event->Event; 161265236Sken if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || 162319436Sslm event->Event == MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST || 163265236Sken event->Event == MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE || 164265236Sken event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) && 165265236Sken sc->track_mapping_events) 166265236Sken sc->pending_map_events++; 167265236Sken 168265236Sken /* 169265236Sken * When wait_for_port_enable flag is set, make sure that all the events 170265236Sken * are processed. Increment the startup_refcount and decrement it after 171265236Sken * events are processed. 172265236Sken */ 173265236Sken if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || 174319436Sslm event->Event == MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST || 175265236Sken event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) && 176265236Sken sc->wait_for_port_enable) 177265236Sken mprsas_startup_increment(sc->sassc); 178265236Sken 179265236Sken TAILQ_INSERT_TAIL(&sc->sassc->ev_queue, fw_event, ev_link); 180265236Sken taskqueue_enqueue(sc->sassc->ev_tq, &sc->sassc->ev_task); 181265236Sken} 182265236Sken 183265236Skenstatic void 184265236Skenmprsas_fw_event_free(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) 185265236Sken{ 186265236Sken 187265236Sken free(fw_event->event_data, M_MPR); 188265236Sken free(fw_event, M_MPR); 189265236Sken} 190265236Sken 191265236Sken/** 192265236Sken * _mpr_fw_work - delayed task for processing firmware events 193265236Sken * @sc: per adapter object 194265236Sken * @fw_event: The fw_event_work object 195265236Sken * Context: user. 196265236Sken * 197265236Sken * Return nothing. 198265236Sken */ 199265236Skenstatic void 200265236Skenmprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) 201265236Sken{ 202265236Sken struct mprsas_softc *sassc; 203265236Sken sassc = sc->sassc; 204265236Sken 205265236Sken mpr_dprint(sc, MPR_EVENT, "(%d)->(%s) Working on Event: [%x]\n", 206265236Sken event_count++, __func__, fw_event->event); 207265236Sken switch (fw_event->event) { 208265236Sken case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: 209265236Sken { 210265236Sken MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data; 211265236Sken MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy; 212319436Sslm uint8_t i; 213265236Sken 214265236Sken data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *) 215265236Sken fw_event->event_data; 216265236Sken 217265236Sken mpr_mapping_topology_change_event(sc, fw_event->event_data); 218265236Sken 219265236Sken for (i = 0; i < data->NumEntries; i++) { 220265236Sken phy = &data->PHY[i]; 221265236Sken switch (phy->PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK) { 222265236Sken case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: 223265236Sken if (mprsas_add_device(sc, 224265236Sken le16toh(phy->AttachedDevHandle), 225265236Sken phy->LinkRate)) { 226319445Sslm mpr_dprint(sc, MPR_ERROR, "%s: " 227319445Sslm "failed to add device with handle " 228319445Sslm "0x%x\n", __func__, 229265236Sken le16toh(phy->AttachedDevHandle)); 230265236Sken mprsas_prepare_remove(sassc, le16toh( 231265236Sken phy->AttachedDevHandle)); 232265236Sken } 233265236Sken break; 234265236Sken case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: 235265236Sken mprsas_prepare_remove(sassc, le16toh( 236265236Sken phy->AttachedDevHandle)); 237265236Sken break; 238265236Sken case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: 239265236Sken case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE: 240265236Sken case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING: 241265236Sken default: 242265236Sken break; 243265236Sken } 244265236Sken } 245265236Sken /* 246265236Sken * refcount was incremented for this event in 247265236Sken * mprsas_evt_handler. Decrement it here because the event has 248265236Sken * been processed. 249265236Sken */ 250265236Sken mprsas_startup_decrement(sassc); 251265236Sken break; 252265236Sken } 253265236Sken case MPI2_EVENT_SAS_DISCOVERY: 254265236Sken { 255265236Sken MPI2_EVENT_DATA_SAS_DISCOVERY *data; 256265236Sken 257265236Sken data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)fw_event->event_data; 258265236Sken 259265236Sken if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_STARTED) 260299962Sslm mpr_dprint(sc, MPR_TRACE,"SAS discovery start event\n"); 261265236Sken if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_COMPLETED) { 262265236Sken mpr_dprint(sc, MPR_TRACE,"SAS discovery stop event\n"); 263265236Sken sassc->flags &= ~MPRSAS_IN_DISCOVERY; 264265236Sken mprsas_discovery_end(sassc); 265265236Sken } 266265236Sken break; 267265236Sken } 268265236Sken case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: 269265236Sken { 270265236Sken Mpi2EventDataSasEnclDevStatusChange_t *data; 271265236Sken data = (Mpi2EventDataSasEnclDevStatusChange_t *) 272265236Sken fw_event->event_data; 273265236Sken mpr_mapping_enclosure_dev_status_change_event(sc, 274265236Sken fw_event->event_data); 275265236Sken break; 276265236Sken } 277265236Sken case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: 278265236Sken { 279265236Sken Mpi2EventIrConfigElement_t *element; 280265236Sken int i; 281265236Sken u8 foreign_config, reason; 282265236Sken u16 elementType; 283265236Sken Mpi2EventDataIrConfigChangeList_t *event_data; 284265236Sken struct mprsas_target *targ; 285265236Sken unsigned int id; 286265236Sken 287265236Sken event_data = fw_event->event_data; 288265236Sken foreign_config = (le32toh(event_data->Flags) & 289265236Sken MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; 290265236Sken 291265236Sken element = 292265236Sken (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; 293319445Sslm id = mpr_mapping_get_raid_tid_from_handle(sc, 294265236Sken element->VolDevHandle); 295265236Sken 296265236Sken mpr_mapping_ir_config_change_event(sc, event_data); 297265236Sken for (i = 0; i < event_data->NumElements; i++, element++) { 298265236Sken reason = element->ReasonCode; 299265236Sken elementType = le16toh(element->ElementFlags) & 300265236Sken MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK; 301265236Sken /* 302265236Sken * check for element type of Phys Disk or Hot Spare 303265236Sken */ 304265236Sken if ((elementType != 305265236Sken MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT) 306265236Sken && (elementType != 307265236Sken MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT)) 308265236Sken // do next element 309265236Sken goto skip_fp_send; 310265236Sken 311265236Sken /* 312265236Sken * check for reason of Hide, Unhide, PD Created, or PD 313265236Sken * Deleted 314265236Sken */ 315265236Sken if ((reason != MPI2_EVENT_IR_CHANGE_RC_HIDE) && 316265236Sken (reason != MPI2_EVENT_IR_CHANGE_RC_UNHIDE) && 317265236Sken (reason != MPI2_EVENT_IR_CHANGE_RC_PD_CREATED) && 318265236Sken (reason != MPI2_EVENT_IR_CHANGE_RC_PD_DELETED)) 319265236Sken goto skip_fp_send; 320265236Sken 321265236Sken // check for a reason of Hide or PD Created 322265236Sken if ((reason == MPI2_EVENT_IR_CHANGE_RC_HIDE) || 323265236Sken (reason == MPI2_EVENT_IR_CHANGE_RC_PD_CREATED)) 324265236Sken { 325265236Sken // build RAID Action message 326265236Sken Mpi2RaidActionRequest_t *action; 327322661Sken Mpi2RaidActionReply_t *reply = NULL; 328265236Sken struct mpr_command *cm; 329265236Sken int error = 0; 330265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 331265236Sken printf("%s: command alloc failed\n", 332265236Sken __func__); 333265236Sken return; 334265236Sken } 335265236Sken 336283990Sslm mpr_dprint(sc, MPR_EVENT, "Sending FP action " 337265236Sken "from " 338265236Sken "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST " 339265236Sken ":\n"); 340265236Sken action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req; 341265236Sken action->Function = MPI2_FUNCTION_RAID_ACTION; 342265236Sken action->Action = 343265236Sken MPI2_RAID_ACTION_PHYSDISK_HIDDEN; 344265236Sken action->PhysDiskNum = element->PhysDiskNum; 345265236Sken cm->cm_desc.Default.RequestFlags = 346265236Sken MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 347322661Sken error = mpr_request_polled(sc, &cm); 348322661Sken if (cm != NULL) 349322661Sken reply = (Mpi2RaidActionReply_t *) 350322661Sken cm->cm_reply; 351265236Sken if (error || (reply == NULL)) { 352265236Sken /* FIXME */ 353265236Sken /* 354265236Sken * If the poll returns error then we 355265236Sken * need to do diag reset 356265236Sken */ 357265236Sken printf("%s: poll for page completed " 358265236Sken "with error %d", __func__, error); 359265236Sken } 360265236Sken if (reply && (le16toh(reply->IOCStatus) & 361265236Sken MPI2_IOCSTATUS_MASK) != 362265236Sken MPI2_IOCSTATUS_SUCCESS) { 363283990Sslm mpr_dprint(sc, MPR_ERROR, "%s: error " 364283990Sslm "sending RaidActionPage; " 365283990Sslm "iocstatus = 0x%x\n", __func__, 366265236Sken le16toh(reply->IOCStatus)); 367265236Sken } 368265236Sken 369265236Sken if (cm) 370265236Sken mpr_free_command(sc, cm); 371265236Sken } 372265236Skenskip_fp_send: 373283990Sslm mpr_dprint(sc, MPR_EVENT, "Received " 374265236Sken "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST Reason " 375265236Sken "code %x:\n", element->ReasonCode); 376265236Sken switch (element->ReasonCode) { 377265236Sken case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: 378265236Sken case MPI2_EVENT_IR_CHANGE_RC_ADDED: 379265236Sken if (!foreign_config) { 380265236Sken if (mprsas_volume_add(sc, 381265236Sken le16toh(element->VolDevHandle))) { 382265236Sken printf("%s: failed to add RAID " 383265236Sken "volume with handle 0x%x\n", 384265236Sken __func__, le16toh(element-> 385265236Sken VolDevHandle)); 386265236Sken } 387265236Sken } 388265236Sken break; 389265236Sken case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: 390265236Sken case MPI2_EVENT_IR_CHANGE_RC_REMOVED: 391265236Sken /* 392265236Sken * Rescan after volume is deleted or removed. 393265236Sken */ 394265236Sken if (!foreign_config) { 395265236Sken if (id == MPR_MAP_BAD_ID) { 396265236Sken printf("%s: could not get ID " 397265236Sken "for volume with handle " 398265236Sken "0x%04x\n", __func__, 399265236Sken le16toh(element-> 400265236Sken VolDevHandle)); 401265236Sken break; 402265236Sken } 403265236Sken 404265236Sken targ = &sassc->targets[id]; 405265236Sken targ->handle = 0x0; 406265236Sken targ->encl_slot = 0x0; 407265236Sken targ->encl_handle = 0x0; 408265236Sken targ->encl_level_valid = 0x0; 409265236Sken targ->encl_level = 0x0; 410265236Sken targ->connector_name[0] = ' '; 411265236Sken targ->connector_name[1] = ' '; 412265236Sken targ->connector_name[2] = ' '; 413265236Sken targ->connector_name[3] = ' '; 414265236Sken targ->exp_dev_handle = 0x0; 415265236Sken targ->phy_num = 0x0; 416265236Sken targ->linkrate = 0x0; 417265236Sken mprsas_rescan_target(sc, targ); 418265236Sken printf("RAID target id 0x%x removed\n", 419265236Sken targ->tid); 420265236Sken } 421265236Sken break; 422265236Sken case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: 423265236Sken case MPI2_EVENT_IR_CHANGE_RC_HIDE: 424265236Sken /* 425265236Sken * Phys Disk of a volume has been created. Hide 426265236Sken * it from the OS. 427265236Sken */ 428265236Sken targ = mprsas_find_target_by_handle(sassc, 0, 429265236Sken element->PhysDiskDevHandle); 430265236Sken if (targ == NULL) 431265236Sken break; 432265236Sken targ->flags |= MPR_TARGET_FLAGS_RAID_COMPONENT; 433265236Sken mprsas_rescan_target(sc, targ); 434265236Sken break; 435265236Sken case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: 436265236Sken /* 437265236Sken * Phys Disk of a volume has been deleted. 438265236Sken * Expose it to the OS. 439265236Sken */ 440265236Sken if (mprsas_add_device(sc, 441265236Sken le16toh(element->PhysDiskDevHandle), 0)) { 442265236Sken printf("%s: failed to add device with " 443265236Sken "handle 0x%x\n", __func__, 444265236Sken le16toh(element-> 445265236Sken PhysDiskDevHandle)); 446265236Sken mprsas_prepare_remove(sassc, 447265236Sken le16toh(element-> 448265236Sken PhysDiskDevHandle)); 449265236Sken } 450265236Sken break; 451265236Sken } 452265236Sken } 453265236Sken /* 454265236Sken * refcount was incremented for this event in 455265236Sken * mprsas_evt_handler. Decrement it here because the event has 456265236Sken * been processed. 457265236Sken */ 458265236Sken mprsas_startup_decrement(sassc); 459265236Sken break; 460265236Sken } 461265236Sken case MPI2_EVENT_IR_VOLUME: 462265236Sken { 463265236Sken Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; 464265236Sken 465265236Sken /* 466265236Sken * Informational only. 467265236Sken */ 468265236Sken mpr_dprint(sc, MPR_EVENT, "Received IR Volume event:\n"); 469265236Sken switch (event_data->ReasonCode) { 470265236Sken case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED: 471265236Sken mpr_dprint(sc, MPR_EVENT, " Volume Settings " 472265236Sken "changed from 0x%x to 0x%x for Volome with " 473265236Sken "handle 0x%x", le32toh(event_data->PreviousValue), 474265236Sken le32toh(event_data->NewValue), 475265236Sken le16toh(event_data->VolDevHandle)); 476265236Sken break; 477265236Sken case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED: 478265236Sken mpr_dprint(sc, MPR_EVENT, " Volume Status " 479265236Sken "changed from 0x%x to 0x%x for Volome with " 480265236Sken "handle 0x%x", le32toh(event_data->PreviousValue), 481265236Sken le32toh(event_data->NewValue), 482265236Sken le16toh(event_data->VolDevHandle)); 483265236Sken break; 484265236Sken case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED: 485265236Sken mpr_dprint(sc, MPR_EVENT, " Volume State " 486265236Sken "changed from 0x%x to 0x%x for Volome with " 487265236Sken "handle 0x%x", le32toh(event_data->PreviousValue), 488265236Sken le32toh(event_data->NewValue), 489265236Sken le16toh(event_data->VolDevHandle)); 490265236Sken u32 state; 491265236Sken struct mprsas_target *targ; 492265236Sken state = le32toh(event_data->NewValue); 493265236Sken switch (state) { 494265236Sken case MPI2_RAID_VOL_STATE_MISSING: 495265236Sken case MPI2_RAID_VOL_STATE_FAILED: 496265236Sken mprsas_prepare_volume_remove(sassc, 497265236Sken event_data->VolDevHandle); 498265236Sken break; 499265236Sken 500265236Sken case MPI2_RAID_VOL_STATE_ONLINE: 501265236Sken case MPI2_RAID_VOL_STATE_DEGRADED: 502265236Sken case MPI2_RAID_VOL_STATE_OPTIMAL: 503265236Sken targ = 504265236Sken mprsas_find_target_by_handle(sassc, 505265236Sken 0, event_data->VolDevHandle); 506265236Sken if (targ) { 507265236Sken printf("%s %d: Volume handle " 508265236Sken "0x%x is already added \n", 509265236Sken __func__, __LINE__, 510265236Sken event_data->VolDevHandle); 511265236Sken break; 512265236Sken } 513265236Sken if (mprsas_volume_add(sc, 514265236Sken le16toh(event_data-> 515265236Sken VolDevHandle))) { 516265236Sken printf("%s: failed to add RAID " 517265236Sken "volume with handle 0x%x\n", 518265236Sken __func__, le16toh( 519265236Sken event_data->VolDevHandle)); 520265236Sken } 521265236Sken break; 522265236Sken default: 523265236Sken break; 524265236Sken } 525265236Sken break; 526265236Sken default: 527265236Sken break; 528265236Sken } 529265236Sken break; 530265236Sken } 531265236Sken case MPI2_EVENT_IR_PHYSICAL_DISK: 532265236Sken { 533265236Sken Mpi2EventDataIrPhysicalDisk_t *event_data = 534265236Sken fw_event->event_data; 535265236Sken struct mprsas_target *targ; 536265236Sken 537265236Sken /* 538265236Sken * Informational only. 539265236Sken */ 540265236Sken mpr_dprint(sc, MPR_EVENT, "Received IR Phys Disk event:\n"); 541265236Sken switch (event_data->ReasonCode) { 542265236Sken case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED: 543265236Sken mpr_dprint(sc, MPR_EVENT, " Phys Disk Settings " 544265236Sken "changed from 0x%x to 0x%x for Phys Disk Number " 545265236Sken "%d and handle 0x%x at Enclosure handle 0x%x, Slot " 546265236Sken "%d", le32toh(event_data->PreviousValue), 547265236Sken le32toh(event_data->NewValue), 548265236Sken event_data->PhysDiskNum, 549265236Sken le16toh(event_data->PhysDiskDevHandle), 550265236Sken le16toh(event_data->EnclosureHandle), 551265236Sken le16toh(event_data->Slot)); 552265236Sken break; 553265236Sken case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED: 554265236Sken mpr_dprint(sc, MPR_EVENT, " Phys Disk Status changed " 555265236Sken "from 0x%x to 0x%x for Phys Disk Number %d and " 556265236Sken "handle 0x%x at Enclosure handle 0x%x, Slot %d", 557265236Sken le32toh(event_data->PreviousValue), 558265236Sken le32toh(event_data->NewValue), 559265236Sken event_data->PhysDiskNum, 560265236Sken le16toh(event_data->PhysDiskDevHandle), 561265236Sken le16toh(event_data->EnclosureHandle), 562265236Sken le16toh(event_data->Slot)); 563265236Sken break; 564265236Sken case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED: 565265236Sken mpr_dprint(sc, MPR_EVENT, " Phys Disk State changed " 566265236Sken "from 0x%x to 0x%x for Phys Disk Number %d and " 567265236Sken "handle 0x%x at Enclosure handle 0x%x, Slot %d", 568265236Sken le32toh(event_data->PreviousValue), 569265236Sken le32toh(event_data->NewValue), 570265236Sken event_data->PhysDiskNum, 571265236Sken le16toh(event_data->PhysDiskDevHandle), 572265236Sken le16toh(event_data->EnclosureHandle), 573265236Sken le16toh(event_data->Slot)); 574265236Sken switch (event_data->NewValue) { 575265236Sken case MPI2_RAID_PD_STATE_ONLINE: 576265236Sken case MPI2_RAID_PD_STATE_DEGRADED: 577265236Sken case MPI2_RAID_PD_STATE_REBUILDING: 578265236Sken case MPI2_RAID_PD_STATE_OPTIMAL: 579265236Sken case MPI2_RAID_PD_STATE_HOT_SPARE: 580265236Sken targ = mprsas_find_target_by_handle( 581265236Sken sassc, 0, 582265236Sken event_data->PhysDiskDevHandle); 583265236Sken if (targ) { 584265236Sken targ->flags |= 585265236Sken MPR_TARGET_FLAGS_RAID_COMPONENT; 586265236Sken printf("%s %d: Found Target " 587265236Sken "for handle 0x%x.\n", 588265236Sken __func__, __LINE__ , 589265236Sken event_data-> 590265236Sken PhysDiskDevHandle); 591265236Sken } 592265236Sken break; 593265236Sken case MPI2_RAID_PD_STATE_OFFLINE: 594265236Sken case MPI2_RAID_PD_STATE_NOT_CONFIGURED: 595265236Sken case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: 596265236Sken default: 597265236Sken targ = mprsas_find_target_by_handle( 598265236Sken sassc, 0, 599265236Sken event_data->PhysDiskDevHandle); 600265236Sken if (targ) { 601265236Sken targ->flags |= 602265236Sken ~MPR_TARGET_FLAGS_RAID_COMPONENT; 603265236Sken printf("%s %d: Found Target " 604265236Sken "for handle 0x%x. \n", 605265236Sken __func__, __LINE__ , 606265236Sken event_data-> 607265236Sken PhysDiskDevHandle); 608265236Sken } 609265236Sken break; 610265236Sken } 611265236Sken default: 612265236Sken break; 613265236Sken } 614265236Sken break; 615265236Sken } 616265236Sken case MPI2_EVENT_IR_OPERATION_STATUS: 617265236Sken { 618265236Sken Mpi2EventDataIrOperationStatus_t *event_data = 619265236Sken fw_event->event_data; 620265236Sken 621265236Sken /* 622265236Sken * Informational only. 623265236Sken */ 624265236Sken mpr_dprint(sc, MPR_EVENT, "Received IR Op Status event:\n"); 625265236Sken mpr_dprint(sc, MPR_EVENT, " RAID Operation of %d is %d " 626265236Sken "percent complete for Volume with handle 0x%x", 627265236Sken event_data->RAIDOperation, event_data->PercentComplete, 628265236Sken le16toh(event_data->VolDevHandle)); 629265236Sken break; 630265236Sken } 631265236Sken case MPI2_EVENT_TEMP_THRESHOLD: 632265236Sken { 633265236Sken pMpi2EventDataTemperature_t temp_event; 634265236Sken 635265236Sken temp_event = (pMpi2EventDataTemperature_t)fw_event->event_data; 636265236Sken 637265236Sken /* 638265236Sken * The Temp Sensor Count must be greater than the event's Sensor 639265236Sken * Num to be valid. If valid, print the temp thresholds that 640265236Sken * have been exceeded. 641265236Sken */ 642265236Sken if (sc->iounit_pg8.NumSensors > temp_event->SensorNum) { 643265236Sken mpr_dprint(sc, MPR_FAULT, "Temperature Threshold flags " 644265236Sken "%s %s %s %s exceeded for Sensor: %d !!!\n", 645265236Sken ((temp_event->Status & 0x01) == 1) ? "0 " : " ", 646265236Sken ((temp_event->Status & 0x02) == 2) ? "1 " : " ", 647265236Sken ((temp_event->Status & 0x04) == 4) ? "2 " : " ", 648265236Sken ((temp_event->Status & 0x08) == 8) ? "3 " : " ", 649265236Sken temp_event->SensorNum); 650265236Sken mpr_dprint(sc, MPR_FAULT, "Current Temp in Celsius: " 651265236Sken "%d\n", temp_event->CurrentTemperature); 652265236Sken } 653265236Sken break; 654265236Sken } 655299962Sslm case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION: 656299962Sslm { 657299962Sslm pMpi26EventDataActiveCableExcept_t ace_event_data; 658299962Sslm ace_event_data = 659299962Sslm (pMpi26EventDataActiveCableExcept_t)fw_event->event_data; 660299962Sslm 661315189Smav switch(ace_event_data->ReasonCode) { 662315189Smav case MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER: 663315189Smav { 664315189Smav mpr_printf(sc, "Currently a cable with " 665299962Sslm "ReceptacleID %d cannot be powered and device " 666299962Sslm "connected to this active cable will not be seen. " 667299962Sslm "This active cable requires %d mW of power.\n", 668299962Sslm ace_event_data->ReceptacleID, 669299962Sslm ace_event_data->ActiveCablePowerRequirement); 670315189Smav break; 671299962Sslm } 672315189Smav case MPI26_EVENT_ACTIVE_CABLE_DEGRADED: 673315189Smav { 674315189Smav mpr_printf(sc, "Currently a cable with " 675315189Smav "ReceptacleID %d is not running at optimal speed " 676315189Smav "(12 Gb/s rate)\n", ace_event_data->ReceptacleID); 677315189Smav break; 678315189Smav } 679315189Smav default: 680315189Smav break; 681315189Smav } 682299962Sslm break; 683299962Sslm } 684319436Sslm case MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: 685319436Sslm { 686319436Sslm MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST *data; 687319436Sslm MPI26_EVENT_PCIE_TOPO_PORT_ENTRY *port_entry; 688319436Sslm uint8_t i, link_rate; 689319436Sslm uint16_t handle; 690319436Sslm 691319436Sslm data = (MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST *) 692319436Sslm fw_event->event_data; 693319436Sslm 694319436Sslm mpr_mapping_pcie_topology_change_event(sc, 695319436Sslm fw_event->event_data); 696319436Sslm 697319436Sslm for (i = 0; i < data->NumEntries; i++) { 698319436Sslm port_entry = &data->PortEntry[i]; 699319436Sslm handle = le16toh(port_entry->AttachedDevHandle); 700319436Sslm link_rate = port_entry->CurrentPortInfo & 701319436Sslm MPI26_EVENT_PCIE_TOPO_PI_RATE_MASK; 702319436Sslm switch (port_entry->PortStatus) { 703319436Sslm case MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED: 704319436Sslm if (link_rate < 705319436Sslm MPI26_EVENT_PCIE_TOPO_PI_RATE_2_5) { 706319436Sslm mpr_dprint(sc, MPR_ERROR, "%s: Cannot " 707319436Sslm "add PCIe device with handle 0x%x " 708319436Sslm "with unknown link rate.\n", 709319436Sslm __func__, handle); 710319436Sslm break; 711319436Sslm } 712319436Sslm if (mprsas_add_pcie_device(sc, handle, 713319436Sslm link_rate)) { 714319436Sslm mpr_dprint(sc, MPR_ERROR, "%s: failed " 715319436Sslm "to add PCIe device with handle " 716319436Sslm "0x%x\n", __func__, handle); 717319436Sslm mprsas_prepare_remove(sassc, handle); 718319436Sslm } 719319436Sslm break; 720319436Sslm case MPI26_EVENT_PCIE_TOPO_PS_NOT_RESPONDING: 721319436Sslm mprsas_prepare_remove(sassc, handle); 722319436Sslm break; 723319436Sslm case MPI26_EVENT_PCIE_TOPO_PS_PORT_CHANGED: 724319436Sslm case MPI26_EVENT_PCIE_TOPO_PS_NO_CHANGE: 725319436Sslm case MPI26_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING: 726319436Sslm default: 727319436Sslm break; 728319436Sslm } 729319436Sslm } 730319436Sslm /* 731319436Sslm * refcount was incremented for this event in 732319436Sslm * mprsas_evt_handler. Decrement it here because the event has 733319436Sslm * been processed. 734319436Sslm */ 735319436Sslm mprsas_startup_decrement(sassc); 736319436Sslm break; 737319436Sslm } 738265236Sken case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: 739265236Sken case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: 740265236Sken default: 741265236Sken mpr_dprint(sc, MPR_TRACE,"Unhandled event 0x%0X\n", 742265236Sken fw_event->event); 743265236Sken break; 744265236Sken 745265236Sken } 746265236Sken mpr_dprint(sc, MPR_EVENT, "(%d)->(%s) Event Free: [%x]\n", event_count, 747265236Sken __func__, fw_event->event); 748265236Sken mprsas_fw_event_free(sc, fw_event); 749265236Sken} 750265236Sken 751265236Skenvoid 752265236Skenmprsas_firmware_event_work(void *arg, int pending) 753265236Sken{ 754265236Sken struct mpr_fw_event_work *fw_event; 755265236Sken struct mpr_softc *sc; 756265236Sken 757265236Sken sc = (struct mpr_softc *)arg; 758265236Sken mpr_lock(sc); 759265236Sken while ((fw_event = TAILQ_FIRST(&sc->sassc->ev_queue)) != NULL) { 760265236Sken TAILQ_REMOVE(&sc->sassc->ev_queue, fw_event, ev_link); 761265236Sken mprsas_fw_work(sc, fw_event); 762265236Sken } 763265236Sken mpr_unlock(sc); 764265236Sken} 765265236Sken 766265236Skenstatic int 767319436Sslmmprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate) 768319436Sslm{ 769265236Sken char devstring[80]; 770265236Sken struct mprsas_softc *sassc; 771265236Sken struct mprsas_target *targ; 772265236Sken Mpi2ConfigReply_t mpi_reply; 773265236Sken Mpi2SasDevicePage0_t config_page; 774283990Sslm uint64_t sas_address, parent_sas_address = 0; 775265236Sken u32 device_info, parent_devinfo = 0; 776265236Sken unsigned int id; 777283990Sslm int ret = 1, error = 0, i; 778265236Sken struct mprsas_lun *lun; 779283990Sslm u8 is_SATA_SSD = 0; 780283990Sslm struct mpr_command *cm; 781265236Sken 782265236Sken sassc = sc->sassc; 783265236Sken mprsas_startup_increment(sassc); 784265236Sken if ((mpr_config_get_sas_device_pg0(sc, &mpi_reply, &config_page, 785265236Sken MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { 786265236Sken printf("%s: error reading SAS device page0\n", __func__); 787265236Sken error = ENXIO; 788265236Sken goto out; 789265236Sken } 790265236Sken 791265236Sken device_info = le32toh(config_page.DeviceInfo); 792265236Sken 793265236Sken if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) 794265236Sken && (le16toh(config_page.ParentDevHandle) != 0)) { 795265236Sken Mpi2ConfigReply_t tmp_mpi_reply; 796265236Sken Mpi2SasDevicePage0_t parent_config_page; 797265236Sken 798265236Sken if ((mpr_config_get_sas_device_pg0(sc, &tmp_mpi_reply, 799265236Sken &parent_config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, 800265236Sken le16toh(config_page.ParentDevHandle)))) { 801265236Sken printf("%s: error reading SAS device %#x page0\n", 802265236Sken __func__, le16toh(config_page.ParentDevHandle)); 803265236Sken } else { 804265236Sken parent_sas_address = parent_config_page.SASAddress.High; 805265236Sken parent_sas_address = (parent_sas_address << 32) | 806265236Sken parent_config_page.SASAddress.Low; 807265236Sken parent_devinfo = le32toh(parent_config_page.DeviceInfo); 808265236Sken } 809265236Sken } 810265236Sken /* TODO Check proper endianess */ 811265236Sken sas_address = config_page.SASAddress.High; 812283990Sslm sas_address = (sas_address << 32) | config_page.SASAddress.Low; 813283990Sslm mpr_dprint(sc, MPR_INFO, "SAS Address from SAS device page0 = %jx\n", 814283990Sslm sas_address); 815265236Sken 816283990Sslm /* 817283990Sslm * Always get SATA Identify information because this is used to 818283990Sslm * determine if Start/Stop Unit should be sent to the drive when the 819283990Sslm * system is shutdown. 820283990Sslm */ 821283990Sslm if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { 822283990Sslm ret = mprsas_get_sas_address_for_sata_disk(sc, &sas_address, 823283990Sslm handle, device_info, &is_SATA_SSD); 824283990Sslm if (ret) { 825283990Sslm mpr_dprint(sc, MPR_ERROR, "%s: failed to get disk type " 826283990Sslm "(SSD or HDD) for SATA device with handle 0x%04x\n", 827283990Sslm __func__, handle); 828283990Sslm } else { 829283990Sslm mpr_dprint(sc, MPR_INFO, "SAS Address from SATA " 830283990Sslm "device = %jx\n", sas_address); 831283990Sslm } 832283990Sslm } 833265236Sken 834319436Sslm /* 835319436Sslm * use_phynum: 836319436Sslm * 1 - use the PhyNum field as a fallback to the mapping logic 837319436Sslm * 0 - never use the PhyNum field 838319436Sslm * -1 - only use the PhyNum field 839319445Sslm * 840319445Sslm * Note that using the Phy number to map a device can cause device adds 841319445Sslm * to fail if multiple enclosures/expanders are in the topology. For 842319445Sslm * example, if two devices are in the same slot number in two different 843319445Sslm * enclosures within the topology, only one of those devices will be 844319445Sslm * added. PhyNum mapping should not be used if multiple enclosures are 845319445Sslm * in the topology. 846319436Sslm */ 847319436Sslm id = MPR_MAP_BAD_ID; 848319436Sslm if (sc->use_phynum != -1) 849319445Sslm id = mpr_mapping_get_tid(sc, sas_address, handle); 850265236Sken if (id == MPR_MAP_BAD_ID) { 851319436Sslm if ((sc->use_phynum == 0) || 852319436Sslm ((id = config_page.PhyNum) > sassc->maxtargets)) { 853319436Sslm mpr_dprint(sc, MPR_INFO, "failure at %s:%d/%s()! " 854319436Sslm "Could not get ID for device with handle 0x%04x\n", 855319436Sslm __FILE__, __LINE__, __func__, handle); 856319436Sslm error = ENXIO; 857319436Sslm goto out; 858319436Sslm } 859265236Sken } 860319445Sslm mpr_dprint(sc, MPR_MAPPING, "%s: Target ID for added device is %d.\n", 861319445Sslm __func__, id); 862265236Sken 863319445Sslm /* 864319445Sslm * Only do the ID check and reuse check if the target is not from a 865319445Sslm * RAID Component. For Physical Disks of a Volume, the ID will be reused 866319445Sslm * when a volume is deleted because the mapping entry for the PD will 867319445Sslm * still be in the mapping table. The ID check should not be done here 868319445Sslm * either since this PD is already being used. 869319445Sslm */ 870319445Sslm targ = &sassc->targets[id]; 871319445Sslm if (!(targ->flags & MPR_TARGET_FLAGS_RAID_COMPONENT)) { 872319445Sslm if (mprsas_check_id(sassc, id) != 0) { 873319445Sslm device_printf(sc->mpr_dev, "Excluding target id %d\n", 874319445Sslm id); 875319445Sslm error = ENXIO; 876319445Sslm goto out; 877319445Sslm } 878283990Sslm 879319445Sslm if (targ->handle != 0x0) { 880319445Sslm mpr_dprint(sc, MPR_MAPPING, "Attempting to reuse " 881319445Sslm "target id %d handle 0x%04x\n", id, targ->handle); 882319445Sslm error = ENXIO; 883319445Sslm goto out; 884319445Sslm } 885319436Sslm } 886319436Sslm 887265236Sken mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n", 888265236Sken sas_address); 889265236Sken targ->devinfo = device_info; 890265236Sken targ->devname = le32toh(config_page.DeviceName.High); 891265236Sken targ->devname = (targ->devname << 32) | 892265236Sken le32toh(config_page.DeviceName.Low); 893265236Sken targ->encl_handle = le16toh(config_page.EnclosureHandle); 894265236Sken targ->encl_slot = le16toh(config_page.Slot); 895265236Sken targ->encl_level = config_page.EnclosureLevel; 896265236Sken targ->connector_name[0] = config_page.ConnectorName[0]; 897265236Sken targ->connector_name[1] = config_page.ConnectorName[1]; 898265236Sken targ->connector_name[2] = config_page.ConnectorName[2]; 899265236Sken targ->connector_name[3] = config_page.ConnectorName[3]; 900265236Sken targ->handle = handle; 901265236Sken targ->parent_handle = le16toh(config_page.ParentDevHandle); 902265236Sken targ->sasaddr = mpr_to_u64(&config_page.SASAddress); 903265236Sken targ->parent_sasaddr = le64toh(parent_sas_address); 904265236Sken targ->parent_devinfo = parent_devinfo; 905265236Sken targ->tid = id; 906265236Sken targ->linkrate = (linkrate>>4); 907265236Sken targ->flags = 0; 908283990Sslm if (is_SATA_SSD) { 909283990Sslm targ->flags = MPR_TARGET_IS_SATA_SSD; 910283990Sslm } 911319436Sslm if ((le16toh(config_page.Flags) & 912319436Sslm MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) && 913319436Sslm (le16toh(config_page.Flags) & 914319436Sslm MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE)) { 915265236Sken targ->scsi_req_desc_type = 916265236Sken MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO; 917265236Sken } 918265236Sken if (le16toh(config_page.Flags) & 919265236Sken MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { 920265236Sken targ->encl_level_valid = TRUE; 921265236Sken } 922265236Sken TAILQ_INIT(&targ->commands); 923265236Sken TAILQ_INIT(&targ->timedout_commands); 924265236Sken while (!SLIST_EMPTY(&targ->luns)) { 925265236Sken lun = SLIST_FIRST(&targ->luns); 926265236Sken SLIST_REMOVE_HEAD(&targ->luns, lun_link); 927265236Sken free(lun, M_MPR); 928265236Sken } 929265236Sken SLIST_INIT(&targ->luns); 930265236Sken 931265236Sken mpr_describe_devinfo(targ->devinfo, devstring, 80); 932283990Sslm mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found device <%s> <%s> " 933265236Sken "handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring, 934265236Sken mpr_describe_table(mpr_linkrate_names, targ->linkrate), 935265236Sken targ->handle, targ->encl_handle, targ->encl_slot); 936265236Sken if (targ->encl_level_valid) { 937283990Sslm mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d " 938265236Sken "and connector name (%4s)\n", targ->encl_level, 939265236Sken targ->connector_name); 940265236Sken } 941266548Sken#if ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000039)) || \ 942266548Sken (__FreeBSD_version < 902502) 943265236Sken if ((sassc->flags & MPRSAS_IN_STARTUP) == 0) 944265236Sken#endif 945265236Sken mprsas_rescan_target(sc, targ); 946265236Sken mpr_dprint(sc, MPR_MAPPING, "Target id 0x%x added\n", targ->tid); 947283990Sslm 948283990Sslm /* 949283990Sslm * Check all commands to see if the SATA_ID_TIMEOUT flag has been set. 950283990Sslm * If so, send a Target Reset TM to the target that was just created. 951283990Sslm * An Abort Task TM should be used instead of a Target Reset, but that 952283990Sslm * would be much more difficult because targets have not been fully 953283990Sslm * discovered yet, and LUN's haven't been setup. So, just reset the 954283990Sslm * target instead of the LUN. 955283990Sslm */ 956283990Sslm for (i = 1; i < sc->num_reqs; i++) { 957283990Sslm cm = &sc->commands[i]; 958283990Sslm if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { 959283990Sslm targ->timeouts++; 960283990Sslm cm->cm_state = MPR_CM_STATE_TIMEDOUT; 961283990Sslm 962283990Sslm if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) { 963283990Sslm mpr_dprint(sc, MPR_INFO, "%s: sending Target " 964283990Sslm "Reset for stuck SATA identify command " 965283990Sslm "(cm = %p)\n", __func__, cm); 966283990Sslm targ->tm->cm_targ = targ; 967283990Sslm mprsas_send_reset(sc, targ->tm, 968283990Sslm MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); 969283990Sslm } else { 970283990Sslm mpr_dprint(sc, MPR_ERROR, "Failed to allocate " 971299962Sslm "tm for Target Reset after SATA ID command " 972299962Sslm "timed out (cm %p)\n", cm); 973283990Sslm } 974283990Sslm /* 975283990Sslm * No need to check for more since the target is 976283990Sslm * already being reset. 977283990Sslm */ 978283990Sslm break; 979283990Sslm } 980283990Sslm } 981265236Skenout: 982283990Sslm /* 983283990Sslm * Free the commands that may not have been freed from the SATA ID call 984283990Sslm */ 985283990Sslm for (i = 1; i < sc->num_reqs; i++) { 986283990Sslm cm = &sc->commands[i]; 987283990Sslm if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { 988283990Sslm mpr_free_command(sc, cm); 989283990Sslm } 990283990Sslm } 991265236Sken mprsas_startup_decrement(sassc); 992265236Sken return (error); 993265236Sken} 994319436Sslm 995265236Skenint 996265236Skenmprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, 997283990Sslm u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD) 998265236Sken{ 999265236Sken Mpi2SataPassthroughReply_t mpi_reply; 1000265236Sken int i, rc, try_count; 1001265236Sken u32 *bufferptr; 1002265236Sken union _sata_sas_address hash_address; 1003265236Sken struct _ata_identify_device_data ata_identify; 1004265236Sken u8 buffer[MPT2SAS_MN_LEN + MPT2SAS_SN_LEN]; 1005265236Sken u32 ioc_status; 1006265236Sken u8 sas_status; 1007265236Sken 1008265236Sken memset(&ata_identify, 0, sizeof(ata_identify)); 1009314440Sasomers memset(&mpi_reply, 0, sizeof(mpi_reply)); 1010265236Sken try_count = 0; 1011265236Sken do { 1012265236Sken rc = mprsas_get_sata_identify(sc, handle, &mpi_reply, 1013265236Sken (char *)&ata_identify, sizeof(ata_identify), device_info); 1014265236Sken try_count++; 1015265236Sken ioc_status = le16toh(mpi_reply.IOCStatus) 1016265236Sken & MPI2_IOCSTATUS_MASK; 1017265236Sken sas_status = mpi_reply.SASStatus; 1018293701Sasomers switch (ioc_status) { 1019293701Sasomers case MPI2_IOCSTATUS_SUCCESS: 1020293701Sasomers break; 1021293701Sasomers case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: 1022293701Sasomers /* No sense sleeping. this error won't get better */ 1023293701Sasomers break; 1024293701Sasomers default: 1025283990Sslm if (sc->spinup_wait_time > 0) { 1026283990Sslm mpr_dprint(sc, MPR_INFO, "Sleeping %d seconds " 1027283990Sslm "after SATA ID error to wait for spinup\n", 1028283990Sslm sc->spinup_wait_time); 1029283990Sslm msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, 1030283990Sslm "mprid", sc->spinup_wait_time * hz); 1031283990Sslm } 1032283990Sslm } 1033293701Sasomers } while (((rc && (rc != EWOULDBLOCK)) || 1034299962Sslm (ioc_status && (ioc_status != MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR)) 1035299962Sslm || sas_status) && (try_count < 5)); 1036265236Sken 1037265236Sken if (rc == 0 && !ioc_status && !sas_status) { 1038265236Sken mpr_dprint(sc, MPR_MAPPING, "%s: got SATA identify " 1039265236Sken "successfully for handle = 0x%x with try_count = %d\n", 1040265236Sken __func__, handle, try_count); 1041265236Sken } else { 1042265236Sken mpr_dprint(sc, MPR_MAPPING, "%s: handle = 0x%x failed\n", 1043265236Sken __func__, handle); 1044265236Sken return -1; 1045265236Sken } 1046265236Sken /* Copy & byteswap the 40 byte model number to a buffer */ 1047265236Sken for (i = 0; i < MPT2SAS_MN_LEN; i += 2) { 1048265236Sken buffer[i] = ((u8 *)ata_identify.model_number)[i + 1]; 1049265236Sken buffer[i + 1] = ((u8 *)ata_identify.model_number)[i]; 1050265236Sken } 1051265236Sken /* Copy & byteswap the 20 byte serial number to a buffer */ 1052265236Sken for (i = 0; i < MPT2SAS_SN_LEN; i += 2) { 1053265236Sken buffer[MPT2SAS_MN_LEN + i] = 1054265236Sken ((u8 *)ata_identify.serial_number)[i + 1]; 1055265236Sken buffer[MPT2SAS_MN_LEN + i + 1] = 1056265236Sken ((u8 *)ata_identify.serial_number)[i]; 1057265236Sken } 1058265236Sken bufferptr = (u32 *)buffer; 1059265236Sken /* There are 60 bytes to hash down to 8. 60 isn't divisible by 8, 1060265236Sken * so loop through the first 56 bytes (7*8), 1061265236Sken * and then add in the last dword. 1062265236Sken */ 1063265236Sken hash_address.word.low = 0; 1064265236Sken hash_address.word.high = 0; 1065265236Sken for (i = 0; (i < ((MPT2SAS_MN_LEN+MPT2SAS_SN_LEN)/8)); i++) { 1066265236Sken hash_address.word.low += *bufferptr; 1067265236Sken bufferptr++; 1068265236Sken hash_address.word.high += *bufferptr; 1069265236Sken bufferptr++; 1070265236Sken } 1071265236Sken /* Add the last dword */ 1072265236Sken hash_address.word.low += *bufferptr; 1073265236Sken /* Make sure the hash doesn't start with 5, because it could clash 1074265236Sken * with a SAS address. Change 5 to a D. 1075265236Sken */ 1076265236Sken if ((hash_address.word.high & 0x000000F0) == (0x00000050)) 1077265236Sken hash_address.word.high |= 0x00000080; 1078265236Sken *sas_address = (u64)hash_address.wwid[0] << 56 | 1079265236Sken (u64)hash_address.wwid[1] << 48 | (u64)hash_address.wwid[2] << 40 | 1080265236Sken (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 | 1081265236Sken (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] << 8 | 1082265236Sken (u64)hash_address.wwid[7]; 1083283990Sslm if (ata_identify.rotational_speed == 1) { 1084283990Sslm *is_SATA_SSD = 1; 1085283990Sslm } 1086283990Sslm 1087265236Sken return 0; 1088265236Sken} 1089265236Sken 1090265236Skenstatic int 1091265236Skenmprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, 1092265236Sken Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo) 1093265236Sken{ 1094265236Sken Mpi2SataPassthroughRequest_t *mpi_request; 1095265236Sken Mpi2SataPassthroughReply_t *reply; 1096265236Sken struct mpr_command *cm; 1097265236Sken char *buffer; 1098265236Sken int error = 0; 1099265236Sken 1100265236Sken buffer = malloc( sz, M_MPR, M_NOWAIT | M_ZERO); 1101265236Sken if (!buffer) 1102265236Sken return ENOMEM; 1103265236Sken 1104265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 1105265236Sken free(buffer, M_MPR); 1106265236Sken return (EBUSY); 1107265236Sken } 1108265236Sken mpi_request = (MPI2_SATA_PASSTHROUGH_REQUEST *)cm->cm_req; 1109265236Sken bzero(mpi_request,sizeof(MPI2_SATA_PASSTHROUGH_REQUEST)); 1110265236Sken mpi_request->Function = MPI2_FUNCTION_SATA_PASSTHROUGH; 1111265236Sken mpi_request->VF_ID = 0; 1112265236Sken mpi_request->DevHandle = htole16(handle); 1113265236Sken mpi_request->PassthroughFlags = (MPI2_SATA_PT_REQ_PT_FLAGS_PIO | 1114265236Sken MPI2_SATA_PT_REQ_PT_FLAGS_READ); 1115265236Sken mpi_request->DataLength = htole32(sz); 1116265236Sken mpi_request->CommandFIS[0] = 0x27; 1117265236Sken mpi_request->CommandFIS[1] = 0x80; 1118265236Sken mpi_request->CommandFIS[2] = (devinfo & 1119265236Sken MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? 0xA1 : 0xEC; 1120265236Sken cm->cm_sge = &mpi_request->SGL; 1121265236Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 1122265236Sken cm->cm_flags = MPR_CM_FLAGS_DATAIN; 1123265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1124265236Sken cm->cm_data = buffer; 1125265236Sken cm->cm_length = htole32(sz); 1126283990Sslm 1127283990Sslm /* 1128283990Sslm * Start a timeout counter specifically for the SATA ID command. This 1129283990Sslm * is used to fix a problem where the FW does not send a reply sometimes 1130283990Sslm * when a bad disk is in the topology. So, this is used to timeout the 1131283990Sslm * command so that processing can continue normally. 1132283990Sslm */ 1133283990Sslm mpr_dprint(sc, MPR_XINFO, "%s start timeout counter for SATA ID " 1134283990Sslm "command\n", __func__); 1135283990Sslm callout_reset(&cm->cm_callout, MPR_ATA_ID_TIMEOUT * hz, 1136283990Sslm mprsas_ata_id_timeout, cm); 1137322661Sken error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP); 1138283990Sslm mpr_dprint(sc, MPR_XINFO, "%s stop timeout counter for SATA ID " 1139283990Sslm "command\n", __func__); 1140322661Sken /* XXX KDM need to fix the case where this command is destroyed */ 1141283990Sslm callout_stop(&cm->cm_callout); 1142283990Sslm 1143322661Sken if (cm != NULL) 1144322661Sken reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; 1145265236Sken if (error || (reply == NULL)) { 1146265236Sken /* FIXME */ 1147265236Sken /* 1148265236Sken * If the request returns an error then we need to do a diag 1149265236Sken * reset 1150283990Sslm */ 1151265236Sken printf("%s: request for page completed with error %d", 1152265236Sken __func__, error); 1153265236Sken error = ENXIO; 1154265236Sken goto out; 1155265236Sken } 1156265236Sken bcopy(buffer, id_buffer, sz); 1157265236Sken bcopy(reply, mpi_reply, sizeof(Mpi2SataPassthroughReply_t)); 1158265236Sken if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != 1159265236Sken MPI2_IOCSTATUS_SUCCESS) { 1160265236Sken printf("%s: error reading SATA PASSTHRU; iocstatus = 0x%x\n", 1161265236Sken __func__, reply->IOCStatus); 1162265236Sken error = ENXIO; 1163265236Sken goto out; 1164265236Sken } 1165265236Skenout: 1166283990Sslm /* 1167283990Sslm * If the SATA_ID_TIMEOUT flag has been set for this command, don't free 1168283990Sslm * it. The command will be freed after sending a target reset TM. If 1169283990Sslm * the command did timeout, use EWOULDBLOCK. 1170283990Sslm */ 1171283990Sslm if ((cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0) 1172283990Sslm mpr_free_command(sc, cm); 1173283990Sslm else if (error == 0) 1174283990Sslm error = EWOULDBLOCK; 1175313103Sasomers cm->cm_data = NULL; 1176283990Sslm free(buffer, M_MPR); 1177265236Sken return (error); 1178265236Sken} 1179265236Sken 1180283990Sslmstatic void 1181283990Sslmmprsas_ata_id_timeout(void *data) 1182283990Sslm{ 1183283990Sslm struct mpr_softc *sc; 1184283990Sslm struct mpr_command *cm; 1185283990Sslm 1186283990Sslm cm = (struct mpr_command *)data; 1187283990Sslm sc = cm->cm_sc; 1188283990Sslm mtx_assert(&sc->mpr_mtx, MA_OWNED); 1189283990Sslm 1190283990Sslm mpr_dprint(sc, MPR_INFO, "%s checking ATA ID command %p sc %p\n", 1191283990Sslm __func__, cm, sc); 1192283990Sslm if ((callout_pending(&cm->cm_callout)) || 1193283990Sslm (!callout_active(&cm->cm_callout))) { 1194299962Sslm mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed out\n", 1195299962Sslm __func__); 1196283990Sslm return; 1197283990Sslm } 1198283990Sslm callout_deactivate(&cm->cm_callout); 1199283990Sslm 1200283990Sslm /* 1201283990Sslm * Run the interrupt handler to make sure it's not pending. This 1202283990Sslm * isn't perfect because the command could have already completed 1203283990Sslm * and been re-used, though this is unlikely. 1204283990Sslm */ 1205283990Sslm mpr_intr_locked(sc); 1206283990Sslm if (cm->cm_state == MPR_CM_STATE_FREE) { 1207299962Sslm mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed out\n", 1208299962Sslm __func__); 1209283990Sslm return; 1210283990Sslm } 1211283990Sslm 1212283990Sslm mpr_dprint(sc, MPR_INFO, "ATA ID command timeout cm %p\n", cm); 1213283990Sslm 1214283990Sslm /* 1215299962Sslm * Send wakeup() to the sleeping thread that issued this ATA ID command. 1216299962Sslm * wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), and this 1217299962Sslm * will keep reinit() from being called. This way, an Abort Task TM can 1218299962Sslm * be issued so that the timed out command can be cleared. The Abort 1219299962Sslm * Task cannot be sent from here because the driver has not completed 1220299962Sslm * setting up targets. Instead, the command is flagged so that special 1221299962Sslm * handling will be used to send the abort. 1222283990Sslm */ 1223283990Sslm cm->cm_flags |= MPR_CM_FLAGS_SATA_ID_TIMEOUT; 1224283990Sslm wakeup(cm); 1225283990Sslm} 1226283990Sslm 1227265236Skenstatic int 1228319436Sslmmprsas_add_pcie_device(struct mpr_softc *sc, u16 handle, u8 linkrate) 1229319436Sslm{ 1230319436Sslm char devstring[80]; 1231319436Sslm struct mprsas_softc *sassc; 1232319436Sslm struct mprsas_target *targ; 1233319436Sslm Mpi2ConfigReply_t mpi_reply; 1234319436Sslm Mpi26PCIeDevicePage0_t config_page; 1235319436Sslm Mpi26PCIeDevicePage2_t config_page2; 1236319436Sslm uint64_t pcie_wwid, parent_wwid = 0; 1237319436Sslm u32 device_info, parent_devinfo = 0; 1238319436Sslm unsigned int id; 1239319436Sslm int error = 0; 1240319436Sslm struct mprsas_lun *lun; 1241319436Sslm 1242319436Sslm sassc = sc->sassc; 1243319436Sslm mprsas_startup_increment(sassc); 1244319436Sslm if ((mpr_config_get_pcie_device_pg0(sc, &mpi_reply, &config_page, 1245319436Sslm MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE, handle))) { 1246319436Sslm printf("%s: error reading PCIe device page0\n", __func__); 1247319436Sslm error = ENXIO; 1248319436Sslm goto out; 1249319436Sslm } 1250319436Sslm 1251319436Sslm device_info = le32toh(config_page.DeviceInfo); 1252319436Sslm 1253319436Sslm if (((device_info & MPI26_PCIE_DEVINFO_PCI_SWITCH) == 0) 1254319436Sslm && (le16toh(config_page.ParentDevHandle) != 0)) { 1255319436Sslm Mpi2ConfigReply_t tmp_mpi_reply; 1256319436Sslm Mpi26PCIeDevicePage0_t parent_config_page; 1257319436Sslm 1258319436Sslm if ((mpr_config_get_pcie_device_pg0(sc, &tmp_mpi_reply, 1259319436Sslm &parent_config_page, MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE, 1260319436Sslm le16toh(config_page.ParentDevHandle)))) { 1261319436Sslm printf("%s: error reading PCIe device %#x page0\n", 1262319436Sslm __func__, le16toh(config_page.ParentDevHandle)); 1263319436Sslm } else { 1264319436Sslm parent_wwid = parent_config_page.WWID.High; 1265319436Sslm parent_wwid = (parent_wwid << 32) | 1266319436Sslm parent_config_page.WWID.Low; 1267319436Sslm parent_devinfo = le32toh(parent_config_page.DeviceInfo); 1268319436Sslm } 1269319436Sslm } 1270319436Sslm /* TODO Check proper endianness */ 1271319436Sslm pcie_wwid = config_page.WWID.High; 1272319436Sslm pcie_wwid = (pcie_wwid << 32) | config_page.WWID.Low; 1273319436Sslm mpr_dprint(sc, MPR_INFO, "PCIe WWID from PCIe device page0 = %jx\n", 1274319436Sslm pcie_wwid); 1275319436Sslm 1276319436Sslm if ((mpr_config_get_pcie_device_pg2(sc, &mpi_reply, &config_page2, 1277319436Sslm MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE, handle))) { 1278319436Sslm printf("%s: error reading PCIe device page2\n", __func__); 1279319436Sslm error = ENXIO; 1280319436Sslm goto out; 1281319436Sslm } 1282319436Sslm 1283319445Sslm id = mpr_mapping_get_tid(sc, pcie_wwid, handle); 1284319436Sslm if (id == MPR_MAP_BAD_ID) { 1285319445Sslm mpr_dprint(sc, MPR_ERROR | MPR_INFO, "failure at %s:%d/%s()! " 1286319445Sslm "Could not get ID for device with handle 0x%04x\n", 1287319445Sslm __FILE__, __LINE__, __func__, handle); 1288319436Sslm error = ENXIO; 1289319436Sslm goto out; 1290319436Sslm } 1291319445Sslm mpr_dprint(sc, MPR_MAPPING, "%s: Target ID for added device is %d.\n", 1292319445Sslm __func__, id); 1293319436Sslm 1294319436Sslm if (mprsas_check_id(sassc, id) != 0) { 1295319436Sslm device_printf(sc->mpr_dev, "Excluding target id %d\n", id); 1296319436Sslm error = ENXIO; 1297319436Sslm goto out; 1298319436Sslm } 1299319436Sslm 1300319436Sslm mpr_dprint(sc, MPR_MAPPING, "WWID from PCIe device page0 = %jx\n", 1301319436Sslm pcie_wwid); 1302319436Sslm targ = &sassc->targets[id]; 1303319436Sslm targ->devinfo = device_info; 1304319436Sslm targ->encl_handle = le16toh(config_page.EnclosureHandle); 1305319436Sslm targ->encl_slot = le16toh(config_page.Slot); 1306319436Sslm targ->encl_level = config_page.EnclosureLevel; 1307319436Sslm targ->connector_name[0] = ((char *)&config_page.ConnectorName)[0]; 1308319436Sslm targ->connector_name[1] = ((char *)&config_page.ConnectorName)[1]; 1309319436Sslm targ->connector_name[2] = ((char *)&config_page.ConnectorName)[2]; 1310319436Sslm targ->connector_name[3] = ((char *)&config_page.ConnectorName)[3]; 1311319436Sslm targ->is_nvme = device_info & MPI26_PCIE_DEVINFO_NVME; 1312319436Sslm targ->MDTS = config_page2.MaximumDataTransferSize; 1313319436Sslm /* 1314319436Sslm * Assume always TRUE for encl_level_valid because there is no valid 1315319436Sslm * flag for PCIe. 1316319436Sslm */ 1317319436Sslm targ->encl_level_valid = TRUE; 1318319436Sslm targ->handle = handle; 1319319436Sslm targ->parent_handle = le16toh(config_page.ParentDevHandle); 1320319436Sslm targ->sasaddr = mpr_to_u64(&config_page.WWID); 1321319436Sslm targ->parent_sasaddr = le64toh(parent_wwid); 1322319436Sslm targ->parent_devinfo = parent_devinfo; 1323319436Sslm targ->tid = id; 1324319436Sslm targ->linkrate = linkrate; 1325319436Sslm targ->flags = 0; 1326319436Sslm if ((le16toh(config_page.Flags) & 1327319436Sslm MPI26_PCIEDEV0_FLAGS_ENABLED_FAST_PATH) && 1328319436Sslm (le16toh(config_page.Flags) & 1329319436Sslm MPI26_PCIEDEV0_FLAGS_FAST_PATH_CAPABLE)) { 1330319436Sslm targ->scsi_req_desc_type = 1331319436Sslm MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO; 1332319436Sslm } 1333319436Sslm TAILQ_INIT(&targ->commands); 1334319436Sslm TAILQ_INIT(&targ->timedout_commands); 1335319436Sslm while (!SLIST_EMPTY(&targ->luns)) { 1336319436Sslm lun = SLIST_FIRST(&targ->luns); 1337319436Sslm SLIST_REMOVE_HEAD(&targ->luns, lun_link); 1338319436Sslm free(lun, M_MPR); 1339319436Sslm } 1340319436Sslm SLIST_INIT(&targ->luns); 1341319436Sslm 1342319436Sslm mpr_describe_devinfo(targ->devinfo, devstring, 80); 1343319436Sslm mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found PCIe device <%s> <%s> " 1344319436Sslm "handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring, 1345319436Sslm mpr_describe_table(mpr_pcie_linkrate_names, targ->linkrate), 1346319436Sslm targ->handle, targ->encl_handle, targ->encl_slot); 1347319436Sslm if (targ->encl_level_valid) { 1348319436Sslm mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d " 1349319436Sslm "and connector name (%4s)\n", targ->encl_level, 1350319436Sslm targ->connector_name); 1351319436Sslm } 1352319436Sslm#if ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000039)) || \ 1353319436Sslm (__FreeBSD_version < 902502) 1354319436Sslm if ((sassc->flags & MPRSAS_IN_STARTUP) == 0) 1355319436Sslm#endif 1356319436Sslm mprsas_rescan_target(sc, targ); 1357319436Sslm mpr_dprint(sc, MPR_MAPPING, "Target id 0x%x added\n", targ->tid); 1358319436Sslm 1359319436Sslmout: 1360319436Sslm mprsas_startup_decrement(sassc); 1361319436Sslm return (error); 1362319436Sslm} 1363319436Sslm 1364319436Sslmstatic int 1365265236Skenmprsas_volume_add(struct mpr_softc *sc, u16 handle) 1366265236Sken{ 1367265236Sken struct mprsas_softc *sassc; 1368265236Sken struct mprsas_target *targ; 1369265236Sken u64 wwid; 1370265236Sken unsigned int id; 1371265236Sken int error = 0; 1372265236Sken struct mprsas_lun *lun; 1373265236Sken 1374265236Sken sassc = sc->sassc; 1375265236Sken mprsas_startup_increment(sassc); 1376265236Sken /* wwid is endian safe */ 1377265236Sken mpr_config_get_volume_wwid(sc, handle, &wwid); 1378265236Sken if (!wwid) { 1379265236Sken printf("%s: invalid WWID; cannot add volume to mapping table\n", 1380265236Sken __func__); 1381265236Sken error = ENXIO; 1382265236Sken goto out; 1383265236Sken } 1384265236Sken 1385319445Sslm id = mpr_mapping_get_raid_tid(sc, wwid, handle); 1386265236Sken if (id == MPR_MAP_BAD_ID) { 1387265236Sken printf("%s: could not get ID for volume with handle 0x%04x and " 1388265236Sken "WWID 0x%016llx\n", __func__, handle, 1389265236Sken (unsigned long long)wwid); 1390265236Sken error = ENXIO; 1391265236Sken goto out; 1392265236Sken } 1393265236Sken 1394265236Sken targ = &sassc->targets[id]; 1395265236Sken targ->tid = id; 1396265236Sken targ->handle = handle; 1397265236Sken targ->devname = wwid; 1398265236Sken TAILQ_INIT(&targ->commands); 1399265236Sken TAILQ_INIT(&targ->timedout_commands); 1400265236Sken while (!SLIST_EMPTY(&targ->luns)) { 1401265236Sken lun = SLIST_FIRST(&targ->luns); 1402265236Sken SLIST_REMOVE_HEAD(&targ->luns, lun_link); 1403265236Sken free(lun, M_MPR); 1404265236Sken } 1405265236Sken SLIST_INIT(&targ->luns); 1406266548Sken#if ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000039)) || \ 1407266548Sken (__FreeBSD_version < 902502) 1408265236Sken if ((sassc->flags & MPRSAS_IN_STARTUP) == 0) 1409265236Sken#endif 1410265236Sken mprsas_rescan_target(sc, targ); 1411265236Sken mpr_dprint(sc, MPR_MAPPING, "RAID target id %d added (WWID = 0x%jx)\n", 1412265236Sken targ->tid, wwid); 1413265236Skenout: 1414265236Sken mprsas_startup_decrement(sassc); 1415265236Sken return (error); 1416265236Sken} 1417265236Sken 1418265236Sken/** 1419265236Sken * mprsas_SSU_to_SATA_devices 1420265236Sken * @sc: per adapter object 1421265236Sken * 1422265236Sken * Looks through the target list and issues a StartStopUnit SCSI command to each 1423265236Sken * SATA direct-access device. This helps to ensure that data corruption is 1424265236Sken * avoided when the system is being shut down. This must be called after the IR 1425265236Sken * System Shutdown RAID Action is sent if in IR mode. 1426265236Sken * 1427265236Sken * Return nothing. 1428265236Sken */ 1429265236Skenstatic void 1430265236Skenmprsas_SSU_to_SATA_devices(struct mpr_softc *sc) 1431265236Sken{ 1432265236Sken struct mprsas_softc *sassc = sc->sassc; 1433265236Sken union ccb *ccb; 1434265236Sken path_id_t pathid = cam_sim_path(sassc->sim); 1435265236Sken target_id_t targetid; 1436265236Sken struct mprsas_target *target; 1437265236Sken char path_str[64]; 1438265236Sken struct timeval cur_time, start_time; 1439265236Sken 1440266548Sken mpr_lock(sc); 1441266548Sken 1442265236Sken /* 1443283990Sslm * For each target, issue a StartStopUnit command to stop the device. 1444265236Sken */ 1445265236Sken sc->SSU_started = TRUE; 1446265236Sken sc->SSU_refcount = 0; 1447319445Sslm for (targetid = 0; targetid < sc->max_devices; targetid++) { 1448265236Sken target = &sassc->targets[targetid]; 1449265236Sken if (target->handle == 0x0) { 1450265236Sken continue; 1451265236Sken } 1452265236Sken 1453283990Sslm /* 1454283990Sslm * The stop_at_shutdown flag will be set if this device is 1455283990Sslm * a SATA direct-access end device. 1456283990Sslm */ 1457283990Sslm if (target->stop_at_shutdown) { 1458313103Sasomers ccb = xpt_alloc_ccb_nowait(); 1459313103Sasomers if (ccb == NULL) { 1460319436Sslm mpr_dprint(sc, MPR_FAULT, "Unable to alloc CCB " 1461319436Sslm "to stop unit.\n"); 1462313103Sasomers return; 1463313103Sasomers } 1464313103Sasomers 1465283990Sslm if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, 1466283990Sslm pathid, targetid, CAM_LUN_WILDCARD) != 1467283990Sslm CAM_REQ_CMP) { 1468283990Sslm mpr_dprint(sc, MPR_ERROR, "Unable to create " 1469283990Sslm "path to stop unit.\n"); 1470283990Sslm xpt_free_ccb(ccb); 1471265236Sken return; 1472265236Sken } 1473283990Sslm xpt_path_string(ccb->ccb_h.path, path_str, 1474283990Sslm sizeof(path_str)); 1475265236Sken 1476283990Sslm mpr_dprint(sc, MPR_INFO, "Sending StopUnit: path %s " 1477283990Sslm "handle %d\n", path_str, target->handle); 1478283990Sslm 1479265236Sken /* 1480283990Sslm * Issue a START STOP UNIT command for the target. 1481283990Sslm * Increment the SSU counter to be used to count the 1482283990Sslm * number of required replies. 1483265236Sken */ 1484283990Sslm mpr_dprint(sc, MPR_INFO, "Incrementing SSU count\n"); 1485283990Sslm sc->SSU_refcount++; 1486283990Sslm ccb->ccb_h.target_id = 1487283990Sslm xpt_path_target_id(ccb->ccb_h.path); 1488283990Sslm ccb->ccb_h.ppriv_ptr1 = sassc; 1489283990Sslm scsi_start_stop(&ccb->csio, 1490283990Sslm /*retries*/0, 1491283990Sslm mprsas_stop_unit_done, 1492283990Sslm MSG_SIMPLE_Q_TAG, 1493283990Sslm /*start*/FALSE, 1494283990Sslm /*load/eject*/0, 1495283990Sslm /*immediate*/FALSE, 1496283990Sslm MPR_SENSE_LEN, 1497283990Sslm /*timeout*/10000); 1498283990Sslm xpt_action(ccb); 1499265236Sken } 1500265236Sken } 1501265236Sken 1502266548Sken mpr_unlock(sc); 1503266548Sken 1504265236Sken /* 1505265236Sken * Wait until all of the SSU commands have completed or time has 1506283990Sslm * expired (60 seconds). Pause for 100ms each time through. If any 1507265236Sken * command times out, the target will be reset in the SCSI command 1508265236Sken * timeout routine. 1509265236Sken */ 1510265236Sken getmicrotime(&start_time); 1511265236Sken while (sc->SSU_refcount) { 1512265236Sken pause("mprwait", hz/10); 1513265236Sken 1514265236Sken getmicrotime(&cur_time); 1515265236Sken if ((cur_time.tv_sec - start_time.tv_sec) > 60) { 1516283990Sslm mpr_dprint(sc, MPR_ERROR, "Time has expired waiting " 1517265236Sken "for SSU commands to complete.\n"); 1518265236Sken break; 1519265236Sken } 1520265236Sken } 1521265236Sken} 1522265236Sken 1523265236Skenstatic void 1524265236Skenmprsas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb) 1525265236Sken{ 1526265236Sken struct mprsas_softc *sassc; 1527265236Sken char path_str[64]; 1528265236Sken 1529299962Sslm if (done_ccb == NULL) 1530299962Sslm return; 1531299962Sslm 1532265236Sken sassc = (struct mprsas_softc *)done_ccb->ccb_h.ppriv_ptr1; 1533265236Sken 1534265236Sken xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str)); 1535265236Sken mpr_dprint(sassc->sc, MPR_INFO, "Completing stop unit for %s\n", 1536265236Sken path_str); 1537265236Sken 1538265236Sken /* 1539265236Sken * Nothing more to do except free the CCB and path. If the command 1540265236Sken * timed out, an abort reset, then target reset will be issued during 1541265236Sken * the SCSI Command process. 1542265236Sken */ 1543265236Sken xpt_free_path(done_ccb->ccb_h.path); 1544265236Sken xpt_free_ccb(done_ccb); 1545265236Sken} 1546265236Sken 1547265236Sken/** 1548265236Sken * mprsas_ir_shutdown - IR shutdown notification 1549265236Sken * @sc: per adapter object 1550265236Sken * 1551265236Sken * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that 1552265236Sken * the host system is shutting down. 1553265236Sken * 1554265236Sken * Return nothing. 1555265236Sken */ 1556265236Skenvoid 1557265236Skenmprsas_ir_shutdown(struct mpr_softc *sc) 1558265236Sken{ 1559265236Sken u16 volume_mapping_flags; 1560265236Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1561265236Sken struct dev_mapping_table *mt_entry; 1562265236Sken u32 start_idx, end_idx; 1563265236Sken unsigned int id, found_volume = 0; 1564265236Sken struct mpr_command *cm; 1565265236Sken Mpi2RaidActionRequest_t *action; 1566283990Sslm target_id_t targetid; 1567283990Sslm struct mprsas_target *target; 1568265236Sken 1569265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1570265236Sken 1571265236Sken /* is IR firmware build loaded? */ 1572265236Sken if (!sc->ir_firmware) 1573265236Sken goto out; 1574265236Sken 1575265236Sken /* are there any volumes? Look at IR target IDs. */ 1576265236Sken // TODO-later, this should be looked up in the RAID config structure 1577265236Sken // when it is implemented. 1578265236Sken volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 1579265236Sken MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 1580265236Sken if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) { 1581265236Sken start_idx = 0; 1582265236Sken if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 1583265236Sken start_idx = 1; 1584265236Sken } else 1585265236Sken start_idx = sc->max_devices - sc->max_volumes; 1586265236Sken end_idx = start_idx + sc->max_volumes - 1; 1587265236Sken 1588265236Sken for (id = start_idx; id < end_idx; id++) { 1589265236Sken mt_entry = &sc->mapping_table[id]; 1590265236Sken if ((mt_entry->physical_id != 0) && 1591265236Sken (mt_entry->missing_count == 0)) { 1592265236Sken found_volume = 1; 1593265236Sken break; 1594265236Sken } 1595265236Sken } 1596265236Sken 1597265236Sken if (!found_volume) 1598265236Sken goto out; 1599265236Sken 1600265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 1601265236Sken printf("%s: command alloc failed\n", __func__); 1602265236Sken goto out; 1603265236Sken } 1604265236Sken 1605265236Sken action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req; 1606265236Sken action->Function = MPI2_FUNCTION_RAID_ACTION; 1607265236Sken action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; 1608265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1609265236Sken mpr_lock(sc); 1610322661Sken mpr_wait_command(sc, &cm, 5, CAN_SLEEP); 1611265236Sken mpr_unlock(sc); 1612265236Sken 1613265236Sken /* 1614265236Sken * Don't check for reply, just leave. 1615265236Sken */ 1616265236Sken if (cm) 1617265236Sken mpr_free_command(sc, cm); 1618265236Sken 1619265236Skenout: 1620283990Sslm /* 1621283990Sslm * All of the targets must have the correct value set for 1622283990Sslm * 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable. 1623283990Sslm * 1624283990Sslm * The possible values for the 'enable_ssu' variable are: 1625283990Sslm * 0: disable to SSD and HDD 1626283990Sslm * 1: disable only to HDD (default) 1627283990Sslm * 2: disable only to SSD 1628283990Sslm * 3: enable to SSD and HDD 1629283990Sslm * anything else will default to 1. 1630283990Sslm */ 1631319445Sslm for (targetid = 0; targetid < sc->max_devices; targetid++) { 1632283990Sslm target = &sc->sassc->targets[targetid]; 1633283990Sslm if (target->handle == 0x0) { 1634283990Sslm continue; 1635283990Sslm } 1636283990Sslm 1637283990Sslm if (target->supports_SSU) { 1638283990Sslm switch (sc->enable_ssu) { 1639283990Sslm case MPR_SSU_DISABLE_SSD_DISABLE_HDD: 1640283990Sslm target->stop_at_shutdown = FALSE; 1641283990Sslm break; 1642283990Sslm case MPR_SSU_DISABLE_SSD_ENABLE_HDD: 1643283990Sslm target->stop_at_shutdown = TRUE; 1644283990Sslm if (target->flags & MPR_TARGET_IS_SATA_SSD) { 1645283990Sslm target->stop_at_shutdown = FALSE; 1646283990Sslm } 1647283990Sslm break; 1648283990Sslm case MPR_SSU_ENABLE_SSD_ENABLE_HDD: 1649283990Sslm target->stop_at_shutdown = TRUE; 1650283990Sslm break; 1651283990Sslm case MPR_SSU_ENABLE_SSD_DISABLE_HDD: 1652283990Sslm default: 1653283990Sslm target->stop_at_shutdown = TRUE; 1654283990Sslm if ((target->flags & 1655283990Sslm MPR_TARGET_IS_SATA_SSD) == 0) { 1656283990Sslm target->stop_at_shutdown = FALSE; 1657283990Sslm } 1658283990Sslm break; 1659283990Sslm } 1660283990Sslm } 1661283990Sslm } 1662265236Sken mprsas_SSU_to_SATA_devices(sc); 1663265236Sken} 1664