1265236Sken/*- 2283990Sslm * Copyright (c) 2011-2015 LSI Corp. 3283990Sslm * Copyright (c) 2013-2015 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: releng/10.2/sys/dev/mpr/mpr_sas_lsi.c 283990 2015-06-04 16:27:18Z slm $"); 32265236Sken 33283990Sslm/* Communications core for 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> 74265236Sken#include <dev/mpr/mpi/mpi2_cnfg.h> 75265236Sken#include <dev/mpr/mpi/mpi2_init.h> 76265236Sken#include <dev/mpr/mpi/mpi2_raid.h> 77265236Sken#include <dev/mpr/mpi/mpi2_tool.h> 78265236Sken#include <dev/mpr/mpr_ioctl.h> 79265236Sken#include <dev/mpr/mprvar.h> 80265236Sken#include <dev/mpr/mpr_table.h> 81265236Sken#include <dev/mpr/mpr_sas.h> 82265236Sken 83265236Sken/* For Hashed SAS Address creation for SATA Drives */ 84265236Sken#define MPT2SAS_SN_LEN 20 85265236Sken#define MPT2SAS_MN_LEN 40 86265236Sken 87265236Skenstruct mpr_fw_event_work { 88265236Sken u16 event; 89265236Sken void *event_data; 90265236Sken TAILQ_ENTRY(mpr_fw_event_work) ev_link; 91265236Sken}; 92265236Sken 93265236Skenunion _sata_sas_address { 94265236Sken u8 wwid[8]; 95265236Sken struct { 96265236Sken u32 high; 97265236Sken u32 low; 98265236Sken } word; 99265236Sken}; 100265236Sken 101265236Sken/* 102265236Sken * define the IDENTIFY DEVICE structure 103265236Sken */ 104265236Skenstruct _ata_identify_device_data { 105265236Sken u16 reserved1[10]; /* 0-9 */ 106265236Sken u16 serial_number[10]; /* 10-19 */ 107265236Sken u16 reserved2[7]; /* 20-26 */ 108265236Sken u16 model_number[20]; /* 27-46*/ 109283990Sslm u16 reserved3[170]; /* 47-216 */ 110283990Sslm u16 rotational_speed; /* 217 */ 111283990Sslm u16 reserved4[38]; /* 218-255 */ 112265236Sken}; 113265236Skenstatic u32 event_count; 114265236Skenstatic void mprsas_fw_work(struct mpr_softc *sc, 115265236Sken struct mpr_fw_event_work *fw_event); 116265236Skenstatic void mprsas_fw_event_free(struct mpr_softc *, 117265236Sken struct mpr_fw_event_work *); 118265236Skenstatic int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate); 119265236Skenstatic int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, 120265236Sken Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, 121265236Sken u32 devinfo); 122283990Sslmstatic void mprsas_ata_id_timeout(void *data); 123265236Skenint mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, 124283990Sslm u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); 125265236Skenstatic int mprsas_volume_add(struct mpr_softc *sc, 126265236Sken u16 handle); 127265236Skenstatic void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc); 128265236Skenstatic void mprsas_stop_unit_done(struct cam_periph *periph, 129265236Sken union ccb *done_ccb); 130265236Sken 131265236Skenvoid 132265236Skenmprsas_evt_handler(struct mpr_softc *sc, uintptr_t data, 133265236Sken MPI2_EVENT_NOTIFICATION_REPLY *event) 134265236Sken{ 135265236Sken struct mpr_fw_event_work *fw_event; 136265236Sken u16 sz; 137265236Sken 138265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 139265236Sken mpr_print_evt_sas(sc, event); 140265236Sken mprsas_record_event(sc, event); 141265236Sken 142265236Sken fw_event = malloc(sizeof(struct mpr_fw_event_work), M_MPR, 143265236Sken M_ZERO|M_NOWAIT); 144265236Sken if (!fw_event) { 145265236Sken printf("%s: allocate failed for fw_event\n", __func__); 146265236Sken return; 147265236Sken } 148265236Sken sz = le16toh(event->EventDataLength) * 4; 149265236Sken fw_event->event_data = malloc(sz, M_MPR, M_ZERO|M_NOWAIT); 150265236Sken if (!fw_event->event_data) { 151265236Sken printf("%s: allocate failed for event_data\n", __func__); 152265236Sken free(fw_event, M_MPR); 153265236Sken return; 154265236Sken } 155265236Sken 156265236Sken bcopy(event->EventData, fw_event->event_data, sz); 157265236Sken fw_event->event = event->Event; 158265236Sken if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || 159265236Sken event->Event == MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE || 160265236Sken event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) && 161265236Sken sc->track_mapping_events) 162265236Sken sc->pending_map_events++; 163265236Sken 164265236Sken /* 165265236Sken * When wait_for_port_enable flag is set, make sure that all the events 166265236Sken * are processed. Increment the startup_refcount and decrement it after 167265236Sken * events are processed. 168265236Sken */ 169265236Sken if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || 170265236Sken event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) && 171265236Sken sc->wait_for_port_enable) 172265236Sken mprsas_startup_increment(sc->sassc); 173265236Sken 174265236Sken TAILQ_INSERT_TAIL(&sc->sassc->ev_queue, fw_event, ev_link); 175265236Sken taskqueue_enqueue(sc->sassc->ev_tq, &sc->sassc->ev_task); 176265236Sken 177265236Sken} 178265236Sken 179265236Skenstatic void 180265236Skenmprsas_fw_event_free(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) 181265236Sken{ 182265236Sken 183265236Sken free(fw_event->event_data, M_MPR); 184265236Sken free(fw_event, M_MPR); 185265236Sken} 186265236Sken 187265236Sken/** 188265236Sken * _mpr_fw_work - delayed task for processing firmware events 189265236Sken * @sc: per adapter object 190265236Sken * @fw_event: The fw_event_work object 191265236Sken * Context: user. 192265236Sken * 193265236Sken * Return nothing. 194265236Sken */ 195265236Skenstatic void 196265236Skenmprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) 197265236Sken{ 198265236Sken struct mprsas_softc *sassc; 199265236Sken sassc = sc->sassc; 200265236Sken 201265236Sken mpr_dprint(sc, MPR_EVENT, "(%d)->(%s) Working on Event: [%x]\n", 202265236Sken event_count++, __func__, fw_event->event); 203265236Sken switch (fw_event->event) { 204265236Sken case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: 205265236Sken { 206265236Sken MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data; 207265236Sken MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy; 208265236Sken int i; 209265236Sken 210265236Sken data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *) 211265236Sken fw_event->event_data; 212265236Sken 213265236Sken mpr_mapping_topology_change_event(sc, fw_event->event_data); 214265236Sken 215265236Sken for (i = 0; i < data->NumEntries; i++) { 216265236Sken phy = &data->PHY[i]; 217265236Sken switch (phy->PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK) { 218265236Sken case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: 219265236Sken if (mprsas_add_device(sc, 220265236Sken le16toh(phy->AttachedDevHandle), 221265236Sken phy->LinkRate)) { 222265236Sken printf("%s: failed to add device with " 223265236Sken "handle 0x%x\n", __func__, 224265236Sken le16toh(phy->AttachedDevHandle)); 225265236Sken mprsas_prepare_remove(sassc, le16toh( 226265236Sken phy->AttachedDevHandle)); 227265236Sken } 228265236Sken break; 229265236Sken case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: 230265236Sken mprsas_prepare_remove(sassc, le16toh( 231265236Sken phy->AttachedDevHandle)); 232265236Sken break; 233265236Sken case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: 234265236Sken case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE: 235265236Sken case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING: 236265236Sken default: 237265236Sken break; 238265236Sken } 239265236Sken } 240265236Sken /* 241265236Sken * refcount was incremented for this event in 242265236Sken * mprsas_evt_handler. Decrement it here because the event has 243265236Sken * been processed. 244265236Sken */ 245265236Sken mprsas_startup_decrement(sassc); 246265236Sken break; 247265236Sken } 248265236Sken case MPI2_EVENT_SAS_DISCOVERY: 249265236Sken { 250265236Sken MPI2_EVENT_DATA_SAS_DISCOVERY *data; 251265236Sken 252265236Sken data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)fw_event->event_data; 253265236Sken 254265236Sken if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_STARTED) 255265236Sken mpr_dprint(sc, MPR_TRACE,"SAS discovery start " 256265236Sken "event\n"); 257265236Sken if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_COMPLETED) { 258265236Sken mpr_dprint(sc, MPR_TRACE,"SAS discovery stop event\n"); 259265236Sken sassc->flags &= ~MPRSAS_IN_DISCOVERY; 260265236Sken mprsas_discovery_end(sassc); 261265236Sken } 262265236Sken break; 263265236Sken } 264265236Sken case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: 265265236Sken { 266265236Sken Mpi2EventDataSasEnclDevStatusChange_t *data; 267265236Sken data = (Mpi2EventDataSasEnclDevStatusChange_t *) 268265236Sken fw_event->event_data; 269265236Sken mpr_mapping_enclosure_dev_status_change_event(sc, 270265236Sken fw_event->event_data); 271265236Sken break; 272265236Sken } 273265236Sken case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: 274265236Sken { 275265236Sken Mpi2EventIrConfigElement_t *element; 276265236Sken int i; 277265236Sken u8 foreign_config, reason; 278265236Sken u16 elementType; 279265236Sken Mpi2EventDataIrConfigChangeList_t *event_data; 280265236Sken struct mprsas_target *targ; 281265236Sken unsigned int id; 282265236Sken 283265236Sken event_data = fw_event->event_data; 284265236Sken foreign_config = (le32toh(event_data->Flags) & 285265236Sken MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; 286265236Sken 287265236Sken element = 288265236Sken (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; 289265236Sken id = mpr_mapping_get_raid_id_from_handle(sc, 290265236Sken element->VolDevHandle); 291265236Sken 292265236Sken mpr_mapping_ir_config_change_event(sc, event_data); 293265236Sken for (i = 0; i < event_data->NumElements; i++, element++) { 294265236Sken reason = element->ReasonCode; 295265236Sken elementType = le16toh(element->ElementFlags) & 296265236Sken MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK; 297265236Sken /* 298265236Sken * check for element type of Phys Disk or Hot Spare 299265236Sken */ 300265236Sken if ((elementType != 301265236Sken MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT) 302265236Sken && (elementType != 303265236Sken MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT)) 304265236Sken // do next element 305265236Sken goto skip_fp_send; 306265236Sken 307265236Sken /* 308265236Sken * check for reason of Hide, Unhide, PD Created, or PD 309265236Sken * Deleted 310265236Sken */ 311265236Sken if ((reason != MPI2_EVENT_IR_CHANGE_RC_HIDE) && 312265236Sken (reason != MPI2_EVENT_IR_CHANGE_RC_UNHIDE) && 313265236Sken (reason != MPI2_EVENT_IR_CHANGE_RC_PD_CREATED) && 314265236Sken (reason != MPI2_EVENT_IR_CHANGE_RC_PD_DELETED)) 315265236Sken goto skip_fp_send; 316265236Sken 317265236Sken // check for a reason of Hide or PD Created 318265236Sken if ((reason == MPI2_EVENT_IR_CHANGE_RC_HIDE) || 319265236Sken (reason == MPI2_EVENT_IR_CHANGE_RC_PD_CREATED)) 320265236Sken { 321265236Sken // build RAID Action message 322265236Sken Mpi2RaidActionRequest_t *action; 323265236Sken Mpi2RaidActionReply_t *reply; 324265236Sken struct mpr_command *cm; 325265236Sken int error = 0; 326265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 327265236Sken printf("%s: command alloc failed\n", 328265236Sken __func__); 329265236Sken return; 330265236Sken } 331265236Sken 332283990Sslm mpr_dprint(sc, MPR_EVENT, "Sending FP action " 333265236Sken "from " 334265236Sken "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST " 335265236Sken ":\n"); 336265236Sken action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req; 337265236Sken action->Function = MPI2_FUNCTION_RAID_ACTION; 338265236Sken action->Action = 339265236Sken MPI2_RAID_ACTION_PHYSDISK_HIDDEN; 340265236Sken action->PhysDiskNum = element->PhysDiskNum; 341265236Sken cm->cm_desc.Default.RequestFlags = 342265236Sken MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 343265236Sken error = mpr_request_polled(sc, cm); 344265236Sken reply = (Mpi2RaidActionReply_t *)cm->cm_reply; 345265236Sken if (error || (reply == NULL)) { 346265236Sken /* FIXME */ 347265236Sken /* 348265236Sken * If the poll returns error then we 349265236Sken * need to do diag reset 350265236Sken */ 351265236Sken printf("%s: poll for page completed " 352265236Sken "with error %d", __func__, error); 353265236Sken } 354265236Sken if (reply && (le16toh(reply->IOCStatus) & 355265236Sken MPI2_IOCSTATUS_MASK) != 356265236Sken MPI2_IOCSTATUS_SUCCESS) { 357283990Sslm mpr_dprint(sc, MPR_ERROR, "%s: error " 358283990Sslm "sending RaidActionPage; " 359283990Sslm "iocstatus = 0x%x\n", __func__, 360265236Sken le16toh(reply->IOCStatus)); 361265236Sken } 362265236Sken 363265236Sken if (cm) 364265236Sken mpr_free_command(sc, cm); 365265236Sken } 366265236Skenskip_fp_send: 367283990Sslm mpr_dprint(sc, MPR_EVENT, "Received " 368265236Sken "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST Reason " 369265236Sken "code %x:\n", element->ReasonCode); 370265236Sken switch (element->ReasonCode) { 371265236Sken case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: 372265236Sken case MPI2_EVENT_IR_CHANGE_RC_ADDED: 373265236Sken if (!foreign_config) { 374265236Sken if (mprsas_volume_add(sc, 375265236Sken le16toh(element->VolDevHandle))) { 376265236Sken printf("%s: failed to add RAID " 377265236Sken "volume with handle 0x%x\n", 378265236Sken __func__, le16toh(element-> 379265236Sken VolDevHandle)); 380265236Sken } 381265236Sken } 382265236Sken break; 383265236Sken case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: 384265236Sken case MPI2_EVENT_IR_CHANGE_RC_REMOVED: 385265236Sken /* 386265236Sken * Rescan after volume is deleted or removed. 387265236Sken */ 388265236Sken if (!foreign_config) { 389265236Sken if (id == MPR_MAP_BAD_ID) { 390265236Sken printf("%s: could not get ID " 391265236Sken "for volume with handle " 392265236Sken "0x%04x\n", __func__, 393265236Sken le16toh(element-> 394265236Sken VolDevHandle)); 395265236Sken break; 396265236Sken } 397265236Sken 398265236Sken targ = &sassc->targets[id]; 399265236Sken targ->handle = 0x0; 400265236Sken targ->encl_slot = 0x0; 401265236Sken targ->encl_handle = 0x0; 402265236Sken targ->encl_level_valid = 0x0; 403265236Sken targ->encl_level = 0x0; 404265236Sken targ->connector_name[0] = ' '; 405265236Sken targ->connector_name[1] = ' '; 406265236Sken targ->connector_name[2] = ' '; 407265236Sken targ->connector_name[3] = ' '; 408265236Sken targ->exp_dev_handle = 0x0; 409265236Sken targ->phy_num = 0x0; 410265236Sken targ->linkrate = 0x0; 411265236Sken mprsas_rescan_target(sc, targ); 412265236Sken printf("RAID target id 0x%x removed\n", 413265236Sken targ->tid); 414265236Sken } 415265236Sken break; 416265236Sken case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: 417265236Sken case MPI2_EVENT_IR_CHANGE_RC_HIDE: 418265236Sken /* 419265236Sken * Phys Disk of a volume has been created. Hide 420265236Sken * it from the OS. 421265236Sken */ 422265236Sken targ = mprsas_find_target_by_handle(sassc, 0, 423265236Sken element->PhysDiskDevHandle); 424265236Sken if (targ == NULL) 425265236Sken break; 426265236Sken targ->flags |= MPR_TARGET_FLAGS_RAID_COMPONENT; 427265236Sken mprsas_rescan_target(sc, targ); 428265236Sken break; 429265236Sken case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: 430265236Sken /* 431265236Sken * Phys Disk of a volume has been deleted. 432265236Sken * Expose it to the OS. 433265236Sken */ 434265236Sken if (mprsas_add_device(sc, 435265236Sken le16toh(element->PhysDiskDevHandle), 0)) { 436265236Sken printf("%s: failed to add device with " 437265236Sken "handle 0x%x\n", __func__, 438265236Sken le16toh(element-> 439265236Sken PhysDiskDevHandle)); 440265236Sken mprsas_prepare_remove(sassc, 441265236Sken le16toh(element-> 442265236Sken PhysDiskDevHandle)); 443265236Sken } 444265236Sken break; 445265236Sken } 446265236Sken } 447265236Sken /* 448265236Sken * refcount was incremented for this event in 449265236Sken * mprsas_evt_handler. Decrement it here because the event has 450265236Sken * been processed. 451265236Sken */ 452265236Sken mprsas_startup_decrement(sassc); 453265236Sken break; 454265236Sken } 455265236Sken case MPI2_EVENT_IR_VOLUME: 456265236Sken { 457265236Sken Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; 458265236Sken 459265236Sken /* 460265236Sken * Informational only. 461265236Sken */ 462265236Sken mpr_dprint(sc, MPR_EVENT, "Received IR Volume event:\n"); 463265236Sken switch (event_data->ReasonCode) { 464265236Sken case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED: 465265236Sken mpr_dprint(sc, MPR_EVENT, " Volume Settings " 466265236Sken "changed from 0x%x to 0x%x for Volome with " 467265236Sken "handle 0x%x", le32toh(event_data->PreviousValue), 468265236Sken le32toh(event_data->NewValue), 469265236Sken le16toh(event_data->VolDevHandle)); 470265236Sken break; 471265236Sken case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED: 472265236Sken mpr_dprint(sc, MPR_EVENT, " Volume Status " 473265236Sken "changed from 0x%x to 0x%x for Volome with " 474265236Sken "handle 0x%x", le32toh(event_data->PreviousValue), 475265236Sken le32toh(event_data->NewValue), 476265236Sken le16toh(event_data->VolDevHandle)); 477265236Sken break; 478265236Sken case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED: 479265236Sken mpr_dprint(sc, MPR_EVENT, " Volume State " 480265236Sken "changed from 0x%x to 0x%x for Volome with " 481265236Sken "handle 0x%x", le32toh(event_data->PreviousValue), 482265236Sken le32toh(event_data->NewValue), 483265236Sken le16toh(event_data->VolDevHandle)); 484265236Sken u32 state; 485265236Sken struct mprsas_target *targ; 486265236Sken state = le32toh(event_data->NewValue); 487265236Sken switch (state) { 488265236Sken case MPI2_RAID_VOL_STATE_MISSING: 489265236Sken case MPI2_RAID_VOL_STATE_FAILED: 490265236Sken mprsas_prepare_volume_remove(sassc, 491265236Sken event_data->VolDevHandle); 492265236Sken break; 493265236Sken 494265236Sken case MPI2_RAID_VOL_STATE_ONLINE: 495265236Sken case MPI2_RAID_VOL_STATE_DEGRADED: 496265236Sken case MPI2_RAID_VOL_STATE_OPTIMAL: 497265236Sken targ = 498265236Sken mprsas_find_target_by_handle(sassc, 499265236Sken 0, event_data->VolDevHandle); 500265236Sken if (targ) { 501265236Sken printf("%s %d: Volume handle " 502265236Sken "0x%x is already added \n", 503265236Sken __func__, __LINE__, 504265236Sken event_data->VolDevHandle); 505265236Sken break; 506265236Sken } 507265236Sken if (mprsas_volume_add(sc, 508265236Sken le16toh(event_data-> 509265236Sken VolDevHandle))) { 510265236Sken printf("%s: failed to add RAID " 511265236Sken "volume with handle 0x%x\n", 512265236Sken __func__, le16toh( 513265236Sken event_data->VolDevHandle)); 514265236Sken } 515265236Sken break; 516265236Sken default: 517265236Sken break; 518265236Sken } 519265236Sken break; 520265236Sken default: 521265236Sken break; 522265236Sken } 523265236Sken break; 524265236Sken } 525265236Sken case MPI2_EVENT_IR_PHYSICAL_DISK: 526265236Sken { 527265236Sken Mpi2EventDataIrPhysicalDisk_t *event_data = 528265236Sken fw_event->event_data; 529265236Sken struct mprsas_target *targ; 530265236Sken 531265236Sken /* 532265236Sken * Informational only. 533265236Sken */ 534265236Sken mpr_dprint(sc, MPR_EVENT, "Received IR Phys Disk event:\n"); 535265236Sken switch (event_data->ReasonCode) { 536265236Sken case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED: 537265236Sken mpr_dprint(sc, MPR_EVENT, " Phys Disk Settings " 538265236Sken "changed from 0x%x to 0x%x for Phys Disk Number " 539265236Sken "%d and handle 0x%x at Enclosure handle 0x%x, Slot " 540265236Sken "%d", le32toh(event_data->PreviousValue), 541265236Sken le32toh(event_data->NewValue), 542265236Sken event_data->PhysDiskNum, 543265236Sken le16toh(event_data->PhysDiskDevHandle), 544265236Sken le16toh(event_data->EnclosureHandle), 545265236Sken le16toh(event_data->Slot)); 546265236Sken break; 547265236Sken case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED: 548265236Sken mpr_dprint(sc, MPR_EVENT, " Phys Disk Status changed " 549265236Sken "from 0x%x to 0x%x for Phys Disk Number %d and " 550265236Sken "handle 0x%x at Enclosure handle 0x%x, Slot %d", 551265236Sken le32toh(event_data->PreviousValue), 552265236Sken le32toh(event_data->NewValue), 553265236Sken event_data->PhysDiskNum, 554265236Sken le16toh(event_data->PhysDiskDevHandle), 555265236Sken le16toh(event_data->EnclosureHandle), 556265236Sken le16toh(event_data->Slot)); 557265236Sken break; 558265236Sken case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED: 559265236Sken mpr_dprint(sc, MPR_EVENT, " Phys Disk State changed " 560265236Sken "from 0x%x to 0x%x for Phys Disk Number %d and " 561265236Sken "handle 0x%x at Enclosure handle 0x%x, Slot %d", 562265236Sken le32toh(event_data->PreviousValue), 563265236Sken le32toh(event_data->NewValue), 564265236Sken event_data->PhysDiskNum, 565265236Sken le16toh(event_data->PhysDiskDevHandle), 566265236Sken le16toh(event_data->EnclosureHandle), 567265236Sken le16toh(event_data->Slot)); 568265236Sken switch (event_data->NewValue) { 569265236Sken case MPI2_RAID_PD_STATE_ONLINE: 570265236Sken case MPI2_RAID_PD_STATE_DEGRADED: 571265236Sken case MPI2_RAID_PD_STATE_REBUILDING: 572265236Sken case MPI2_RAID_PD_STATE_OPTIMAL: 573265236Sken case MPI2_RAID_PD_STATE_HOT_SPARE: 574265236Sken targ = mprsas_find_target_by_handle( 575265236Sken sassc, 0, 576265236Sken event_data->PhysDiskDevHandle); 577265236Sken if (targ) { 578265236Sken targ->flags |= 579265236Sken MPR_TARGET_FLAGS_RAID_COMPONENT; 580265236Sken printf("%s %d: Found Target " 581265236Sken "for handle 0x%x.\n", 582265236Sken __func__, __LINE__ , 583265236Sken event_data-> 584265236Sken PhysDiskDevHandle); 585265236Sken } 586265236Sken break; 587265236Sken case MPI2_RAID_PD_STATE_OFFLINE: 588265236Sken case MPI2_RAID_PD_STATE_NOT_CONFIGURED: 589265236Sken case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: 590265236Sken default: 591265236Sken targ = mprsas_find_target_by_handle( 592265236Sken sassc, 0, 593265236Sken event_data->PhysDiskDevHandle); 594265236Sken if (targ) { 595265236Sken targ->flags |= 596265236Sken ~MPR_TARGET_FLAGS_RAID_COMPONENT; 597265236Sken printf("%s %d: Found Target " 598265236Sken "for handle 0x%x. \n", 599265236Sken __func__, __LINE__ , 600265236Sken event_data-> 601265236Sken PhysDiskDevHandle); 602265236Sken } 603265236Sken break; 604265236Sken } 605265236Sken default: 606265236Sken break; 607265236Sken } 608265236Sken break; 609265236Sken } 610265236Sken case MPI2_EVENT_IR_OPERATION_STATUS: 611265236Sken { 612265236Sken Mpi2EventDataIrOperationStatus_t *event_data = 613265236Sken fw_event->event_data; 614265236Sken 615265236Sken /* 616265236Sken * Informational only. 617265236Sken */ 618265236Sken mpr_dprint(sc, MPR_EVENT, "Received IR Op Status event:\n"); 619265236Sken mpr_dprint(sc, MPR_EVENT, " RAID Operation of %d is %d " 620265236Sken "percent complete for Volume with handle 0x%x", 621265236Sken event_data->RAIDOperation, event_data->PercentComplete, 622265236Sken le16toh(event_data->VolDevHandle)); 623265236Sken break; 624265236Sken } 625265236Sken case MPI2_EVENT_TEMP_THRESHOLD: 626265236Sken { 627265236Sken pMpi2EventDataTemperature_t temp_event; 628265236Sken 629265236Sken temp_event = (pMpi2EventDataTemperature_t)fw_event->event_data; 630265236Sken 631265236Sken /* 632265236Sken * The Temp Sensor Count must be greater than the event's Sensor 633265236Sken * Num to be valid. If valid, print the temp thresholds that 634265236Sken * have been exceeded. 635265236Sken */ 636265236Sken if (sc->iounit_pg8.NumSensors > temp_event->SensorNum) { 637265236Sken mpr_dprint(sc, MPR_FAULT, "Temperature Threshold flags " 638265236Sken "%s %s %s %s exceeded for Sensor: %d !!!\n", 639265236Sken ((temp_event->Status & 0x01) == 1) ? "0 " : " ", 640265236Sken ((temp_event->Status & 0x02) == 2) ? "1 " : " ", 641265236Sken ((temp_event->Status & 0x04) == 4) ? "2 " : " ", 642265236Sken ((temp_event->Status & 0x08) == 8) ? "3 " : " ", 643265236Sken temp_event->SensorNum); 644265236Sken mpr_dprint(sc, MPR_FAULT, "Current Temp in Celsius: " 645265236Sken "%d\n", temp_event->CurrentTemperature); 646265236Sken } 647265236Sken break; 648265236Sken } 649265236Sken case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: 650265236Sken case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: 651265236Sken default: 652265236Sken mpr_dprint(sc, MPR_TRACE,"Unhandled event 0x%0X\n", 653265236Sken fw_event->event); 654265236Sken break; 655265236Sken 656265236Sken } 657265236Sken mpr_dprint(sc, MPR_EVENT, "(%d)->(%s) Event Free: [%x]\n", event_count, 658265236Sken __func__, fw_event->event); 659265236Sken mprsas_fw_event_free(sc, fw_event); 660265236Sken} 661265236Sken 662265236Skenvoid 663265236Skenmprsas_firmware_event_work(void *arg, int pending) 664265236Sken{ 665265236Sken struct mpr_fw_event_work *fw_event; 666265236Sken struct mpr_softc *sc; 667265236Sken 668265236Sken sc = (struct mpr_softc *)arg; 669265236Sken mpr_lock(sc); 670265236Sken while ((fw_event = TAILQ_FIRST(&sc->sassc->ev_queue)) != NULL) { 671265236Sken TAILQ_REMOVE(&sc->sassc->ev_queue, fw_event, ev_link); 672265236Sken mprsas_fw_work(sc, fw_event); 673265236Sken } 674265236Sken mpr_unlock(sc); 675265236Sken} 676265236Sken 677265236Skenstatic int 678265236Skenmprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ 679265236Sken char devstring[80]; 680265236Sken struct mprsas_softc *sassc; 681265236Sken struct mprsas_target *targ; 682265236Sken Mpi2ConfigReply_t mpi_reply; 683265236Sken Mpi2SasDevicePage0_t config_page; 684283990Sslm uint64_t sas_address, parent_sas_address = 0; 685265236Sken u32 device_info, parent_devinfo = 0; 686265236Sken unsigned int id; 687283990Sslm int ret = 1, error = 0, i; 688265236Sken struct mprsas_lun *lun; 689283990Sslm u8 is_SATA_SSD = 0; 690283990Sslm struct mpr_command *cm; 691265236Sken 692265236Sken sassc = sc->sassc; 693265236Sken mprsas_startup_increment(sassc); 694265236Sken if ((mpr_config_get_sas_device_pg0(sc, &mpi_reply, &config_page, 695265236Sken MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { 696265236Sken printf("%s: error reading SAS device page0\n", __func__); 697265236Sken error = ENXIO; 698265236Sken goto out; 699265236Sken } 700265236Sken 701265236Sken device_info = le32toh(config_page.DeviceInfo); 702265236Sken 703265236Sken if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) 704265236Sken && (le16toh(config_page.ParentDevHandle) != 0)) { 705265236Sken Mpi2ConfigReply_t tmp_mpi_reply; 706265236Sken Mpi2SasDevicePage0_t parent_config_page; 707265236Sken 708265236Sken if ((mpr_config_get_sas_device_pg0(sc, &tmp_mpi_reply, 709265236Sken &parent_config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, 710265236Sken le16toh(config_page.ParentDevHandle)))) { 711265236Sken printf("%s: error reading SAS device %#x page0\n", 712265236Sken __func__, le16toh(config_page.ParentDevHandle)); 713265236Sken } else { 714265236Sken parent_sas_address = parent_config_page.SASAddress.High; 715265236Sken parent_sas_address = (parent_sas_address << 32) | 716265236Sken parent_config_page.SASAddress.Low; 717265236Sken parent_devinfo = le32toh(parent_config_page.DeviceInfo); 718265236Sken } 719265236Sken } 720265236Sken /* TODO Check proper endianess */ 721265236Sken sas_address = config_page.SASAddress.High; 722283990Sslm sas_address = (sas_address << 32) | config_page.SASAddress.Low; 723283990Sslm mpr_dprint(sc, MPR_INFO, "SAS Address from SAS device page0 = %jx\n", 724283990Sslm sas_address); 725265236Sken 726283990Sslm /* 727283990Sslm * Always get SATA Identify information because this is used to 728283990Sslm * determine if Start/Stop Unit should be sent to the drive when the 729283990Sslm * system is shutdown. 730283990Sslm */ 731283990Sslm if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { 732283990Sslm ret = mprsas_get_sas_address_for_sata_disk(sc, &sas_address, 733283990Sslm handle, device_info, &is_SATA_SSD); 734283990Sslm if (ret) { 735283990Sslm mpr_dprint(sc, MPR_ERROR, "%s: failed to get disk type " 736283990Sslm "(SSD or HDD) for SATA device with handle 0x%04x\n", 737283990Sslm __func__, handle); 738283990Sslm } else { 739283990Sslm mpr_dprint(sc, MPR_INFO, "SAS Address from SATA " 740283990Sslm "device = %jx\n", sas_address); 741283990Sslm } 742283990Sslm } 743265236Sken 744283990Sslm id = mpr_mapping_get_sas_id(sc, sas_address, handle); 745265236Sken if (id == MPR_MAP_BAD_ID) { 746265236Sken printf("failure at %s:%d/%s()! Could not get ID for device " 747265236Sken "with handle 0x%04x\n", __FILE__, __LINE__, __func__, 748265236Sken handle); 749265236Sken error = ENXIO; 750265236Sken goto out; 751265236Sken } 752265236Sken 753265236Sken if (mprsas_check_id(sassc, id) != 0) { 754265236Sken device_printf(sc->mpr_dev, "Excluding target id %d\n", id); 755265236Sken error = ENXIO; 756265236Sken goto out; 757265236Sken } 758283990Sslm 759265236Sken mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n", 760265236Sken sas_address); 761265236Sken targ = &sassc->targets[id]; 762265236Sken targ->devinfo = device_info; 763265236Sken targ->devname = le32toh(config_page.DeviceName.High); 764265236Sken targ->devname = (targ->devname << 32) | 765265236Sken le32toh(config_page.DeviceName.Low); 766265236Sken targ->encl_handle = le16toh(config_page.EnclosureHandle); 767265236Sken targ->encl_slot = le16toh(config_page.Slot); 768265236Sken targ->encl_level = config_page.EnclosureLevel; 769265236Sken targ->connector_name[0] = config_page.ConnectorName[0]; 770265236Sken targ->connector_name[1] = config_page.ConnectorName[1]; 771265236Sken targ->connector_name[2] = config_page.ConnectorName[2]; 772265236Sken targ->connector_name[3] = config_page.ConnectorName[3]; 773265236Sken targ->handle = handle; 774265236Sken targ->parent_handle = le16toh(config_page.ParentDevHandle); 775265236Sken targ->sasaddr = mpr_to_u64(&config_page.SASAddress); 776265236Sken targ->parent_sasaddr = le64toh(parent_sas_address); 777265236Sken targ->parent_devinfo = parent_devinfo; 778265236Sken targ->tid = id; 779265236Sken targ->linkrate = (linkrate>>4); 780265236Sken targ->flags = 0; 781283990Sslm if (is_SATA_SSD) { 782283990Sslm targ->flags = MPR_TARGET_IS_SATA_SSD; 783283990Sslm } 784265236Sken if (le16toh(config_page.Flags) & 785265236Sken MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) { 786265236Sken targ->scsi_req_desc_type = 787265236Sken MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO; 788265236Sken } 789265236Sken if (le16toh(config_page.Flags) & 790265236Sken MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { 791265236Sken targ->encl_level_valid = TRUE; 792265236Sken } 793265236Sken TAILQ_INIT(&targ->commands); 794265236Sken TAILQ_INIT(&targ->timedout_commands); 795265236Sken while (!SLIST_EMPTY(&targ->luns)) { 796265236Sken lun = SLIST_FIRST(&targ->luns); 797265236Sken SLIST_REMOVE_HEAD(&targ->luns, lun_link); 798265236Sken free(lun, M_MPR); 799265236Sken } 800265236Sken SLIST_INIT(&targ->luns); 801265236Sken 802265236Sken mpr_describe_devinfo(targ->devinfo, devstring, 80); 803283990Sslm mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found device <%s> <%s> " 804265236Sken "handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring, 805265236Sken mpr_describe_table(mpr_linkrate_names, targ->linkrate), 806265236Sken targ->handle, targ->encl_handle, targ->encl_slot); 807265236Sken if (targ->encl_level_valid) { 808283990Sslm mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d " 809265236Sken "and connector name (%4s)\n", targ->encl_level, 810265236Sken targ->connector_name); 811265236Sken } 812266548Sken#if ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000039)) || \ 813266548Sken (__FreeBSD_version < 902502) 814265236Sken if ((sassc->flags & MPRSAS_IN_STARTUP) == 0) 815265236Sken#endif 816265236Sken mprsas_rescan_target(sc, targ); 817265236Sken mpr_dprint(sc, MPR_MAPPING, "Target id 0x%x added\n", targ->tid); 818283990Sslm 819283990Sslm /* 820283990Sslm * Check all commands to see if the SATA_ID_TIMEOUT flag has been set. 821283990Sslm * If so, send a Target Reset TM to the target that was just created. 822283990Sslm * An Abort Task TM should be used instead of a Target Reset, but that 823283990Sslm * would be much more difficult because targets have not been fully 824283990Sslm * discovered yet, and LUN's haven't been setup. So, just reset the 825283990Sslm * target instead of the LUN. 826283990Sslm */ 827283990Sslm for (i = 1; i < sc->num_reqs; i++) { 828283990Sslm cm = &sc->commands[i]; 829283990Sslm if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { 830283990Sslm targ->timeouts++; 831283990Sslm cm->cm_state = MPR_CM_STATE_TIMEDOUT; 832283990Sslm 833283990Sslm if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) { 834283990Sslm mpr_dprint(sc, MPR_INFO, "%s: sending Target " 835283990Sslm "Reset for stuck SATA identify command " 836283990Sslm "(cm = %p)\n", __func__, cm); 837283990Sslm targ->tm->cm_targ = targ; 838283990Sslm mprsas_send_reset(sc, targ->tm, 839283990Sslm MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); 840283990Sslm } else { 841283990Sslm mpr_dprint(sc, MPR_ERROR, "Failed to allocate " 842283990Sslm "tm for Target Reset after SATA ID " 843283990Sslm "command timed out (cm %p)\n", cm); 844283990Sslm } 845283990Sslm /* 846283990Sslm * No need to check for more since the target is 847283990Sslm * already being reset. 848283990Sslm */ 849283990Sslm break; 850283990Sslm } 851283990Sslm } 852265236Skenout: 853283990Sslm /* 854283990Sslm * Free the commands that may not have been freed from the SATA ID call 855283990Sslm */ 856283990Sslm for (i = 1; i < sc->num_reqs; i++) { 857283990Sslm cm = &sc->commands[i]; 858283990Sslm if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { 859283990Sslm mpr_free_command(sc, cm); 860283990Sslm } 861283990Sslm } 862265236Sken mprsas_startup_decrement(sassc); 863265236Sken return (error); 864265236Sken} 865265236Sken 866265236Skenint 867265236Skenmprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, 868283990Sslm u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD) 869265236Sken{ 870265236Sken Mpi2SataPassthroughReply_t mpi_reply; 871265236Sken int i, rc, try_count; 872265236Sken u32 *bufferptr; 873265236Sken union _sata_sas_address hash_address; 874265236Sken struct _ata_identify_device_data ata_identify; 875265236Sken u8 buffer[MPT2SAS_MN_LEN + MPT2SAS_SN_LEN]; 876265236Sken u32 ioc_status; 877265236Sken u8 sas_status; 878265236Sken 879265236Sken memset(&ata_identify, 0, sizeof(ata_identify)); 880265236Sken try_count = 0; 881265236Sken do { 882265236Sken rc = mprsas_get_sata_identify(sc, handle, &mpi_reply, 883265236Sken (char *)&ata_identify, sizeof(ata_identify), device_info); 884265236Sken try_count++; 885265236Sken ioc_status = le16toh(mpi_reply.IOCStatus) 886265236Sken & MPI2_IOCSTATUS_MASK; 887265236Sken sas_status = mpi_reply.SASStatus; 888283990Sslm if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { 889283990Sslm if (sc->spinup_wait_time > 0) { 890283990Sslm mpr_dprint(sc, MPR_INFO, "Sleeping %d seconds " 891283990Sslm "after SATA ID error to wait for spinup\n", 892283990Sslm sc->spinup_wait_time); 893283990Sslm msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, 894283990Sslm "mprid", sc->spinup_wait_time * hz); 895283990Sslm } 896283990Sslm } 897283990Sslm } while (((rc && (rc != EWOULDBLOCK)) || ioc_status || sas_status) && 898265236Sken (try_count < 5)); 899265236Sken 900265236Sken if (rc == 0 && !ioc_status && !sas_status) { 901265236Sken mpr_dprint(sc, MPR_MAPPING, "%s: got SATA identify " 902265236Sken "successfully for handle = 0x%x with try_count = %d\n", 903265236Sken __func__, handle, try_count); 904265236Sken } else { 905265236Sken mpr_dprint(sc, MPR_MAPPING, "%s: handle = 0x%x failed\n", 906265236Sken __func__, handle); 907265236Sken return -1; 908265236Sken } 909265236Sken /* Copy & byteswap the 40 byte model number to a buffer */ 910265236Sken for (i = 0; i < MPT2SAS_MN_LEN; i += 2) { 911265236Sken buffer[i] = ((u8 *)ata_identify.model_number)[i + 1]; 912265236Sken buffer[i + 1] = ((u8 *)ata_identify.model_number)[i]; 913265236Sken } 914265236Sken /* Copy & byteswap the 20 byte serial number to a buffer */ 915265236Sken for (i = 0; i < MPT2SAS_SN_LEN; i += 2) { 916265236Sken buffer[MPT2SAS_MN_LEN + i] = 917265236Sken ((u8 *)ata_identify.serial_number)[i + 1]; 918265236Sken buffer[MPT2SAS_MN_LEN + i + 1] = 919265236Sken ((u8 *)ata_identify.serial_number)[i]; 920265236Sken } 921265236Sken bufferptr = (u32 *)buffer; 922265236Sken /* There are 60 bytes to hash down to 8. 60 isn't divisible by 8, 923265236Sken * so loop through the first 56 bytes (7*8), 924265236Sken * and then add in the last dword. 925265236Sken */ 926265236Sken hash_address.word.low = 0; 927265236Sken hash_address.word.high = 0; 928265236Sken for (i = 0; (i < ((MPT2SAS_MN_LEN+MPT2SAS_SN_LEN)/8)); i++) { 929265236Sken hash_address.word.low += *bufferptr; 930265236Sken bufferptr++; 931265236Sken hash_address.word.high += *bufferptr; 932265236Sken bufferptr++; 933265236Sken } 934265236Sken /* Add the last dword */ 935265236Sken hash_address.word.low += *bufferptr; 936265236Sken /* Make sure the hash doesn't start with 5, because it could clash 937265236Sken * with a SAS address. Change 5 to a D. 938265236Sken */ 939265236Sken if ((hash_address.word.high & 0x000000F0) == (0x00000050)) 940265236Sken hash_address.word.high |= 0x00000080; 941265236Sken *sas_address = (u64)hash_address.wwid[0] << 56 | 942265236Sken (u64)hash_address.wwid[1] << 48 | (u64)hash_address.wwid[2] << 40 | 943265236Sken (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 | 944265236Sken (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] << 8 | 945265236Sken (u64)hash_address.wwid[7]; 946283990Sslm if (ata_identify.rotational_speed == 1) { 947283990Sslm *is_SATA_SSD = 1; 948283990Sslm } 949283990Sslm 950265236Sken return 0; 951265236Sken} 952265236Sken 953265236Skenstatic int 954265236Skenmprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, 955265236Sken Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo) 956265236Sken{ 957265236Sken Mpi2SataPassthroughRequest_t *mpi_request; 958265236Sken Mpi2SataPassthroughReply_t *reply; 959265236Sken struct mpr_command *cm; 960265236Sken char *buffer; 961265236Sken int error = 0; 962265236Sken 963265236Sken buffer = malloc( sz, M_MPR, M_NOWAIT | M_ZERO); 964265236Sken if (!buffer) 965265236Sken return ENOMEM; 966265236Sken 967265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 968265236Sken free(buffer, M_MPR); 969265236Sken return (EBUSY); 970265236Sken } 971265236Sken mpi_request = (MPI2_SATA_PASSTHROUGH_REQUEST *)cm->cm_req; 972265236Sken bzero(mpi_request,sizeof(MPI2_SATA_PASSTHROUGH_REQUEST)); 973265236Sken mpi_request->Function = MPI2_FUNCTION_SATA_PASSTHROUGH; 974265236Sken mpi_request->VF_ID = 0; 975265236Sken mpi_request->DevHandle = htole16(handle); 976265236Sken mpi_request->PassthroughFlags = (MPI2_SATA_PT_REQ_PT_FLAGS_PIO | 977265236Sken MPI2_SATA_PT_REQ_PT_FLAGS_READ); 978265236Sken mpi_request->DataLength = htole32(sz); 979265236Sken mpi_request->CommandFIS[0] = 0x27; 980265236Sken mpi_request->CommandFIS[1] = 0x80; 981265236Sken mpi_request->CommandFIS[2] = (devinfo & 982265236Sken MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? 0xA1 : 0xEC; 983265236Sken cm->cm_sge = &mpi_request->SGL; 984265236Sken cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); 985265236Sken cm->cm_flags = MPR_CM_FLAGS_DATAIN; 986265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 987265236Sken cm->cm_data = buffer; 988265236Sken cm->cm_length = htole32(sz); 989283990Sslm 990283990Sslm /* 991283990Sslm * Start a timeout counter specifically for the SATA ID command. This 992283990Sslm * is used to fix a problem where the FW does not send a reply sometimes 993283990Sslm * when a bad disk is in the topology. So, this is used to timeout the 994283990Sslm * command so that processing can continue normally. 995283990Sslm */ 996283990Sslm mpr_dprint(sc, MPR_XINFO, "%s start timeout counter for SATA ID " 997283990Sslm "command\n", __func__); 998283990Sslm callout_reset(&cm->cm_callout, MPR_ATA_ID_TIMEOUT * hz, 999283990Sslm mprsas_ata_id_timeout, cm); 1000265236Sken error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); 1001283990Sslm mpr_dprint(sc, MPR_XINFO, "%s stop timeout counter for SATA ID " 1002283990Sslm "command\n", __func__); 1003283990Sslm callout_stop(&cm->cm_callout); 1004283990Sslm 1005265236Sken reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; 1006265236Sken if (error || (reply == NULL)) { 1007265236Sken /* FIXME */ 1008265236Sken /* 1009265236Sken * If the request returns an error then we need to do a diag 1010265236Sken * reset 1011283990Sslm */ 1012265236Sken printf("%s: request for page completed with error %d", 1013265236Sken __func__, error); 1014265236Sken error = ENXIO; 1015265236Sken goto out; 1016265236Sken } 1017265236Sken bcopy(buffer, id_buffer, sz); 1018265236Sken bcopy(reply, mpi_reply, sizeof(Mpi2SataPassthroughReply_t)); 1019265236Sken if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != 1020265236Sken MPI2_IOCSTATUS_SUCCESS) { 1021265236Sken printf("%s: error reading SATA PASSTHRU; iocstatus = 0x%x\n", 1022265236Sken __func__, reply->IOCStatus); 1023265236Sken error = ENXIO; 1024265236Sken goto out; 1025265236Sken } 1026265236Skenout: 1027283990Sslm /* 1028283990Sslm * If the SATA_ID_TIMEOUT flag has been set for this command, don't free 1029283990Sslm * it. The command will be freed after sending a target reset TM. If 1030283990Sslm * the command did timeout, use EWOULDBLOCK. 1031283990Sslm */ 1032283990Sslm if ((cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0) 1033283990Sslm mpr_free_command(sc, cm); 1034283990Sslm else if (error == 0) 1035283990Sslm error = EWOULDBLOCK; 1036283990Sslm free(buffer, M_MPR); 1037265236Sken return (error); 1038265236Sken} 1039265236Sken 1040283990Sslmstatic void 1041283990Sslmmprsas_ata_id_timeout(void *data) 1042283990Sslm{ 1043283990Sslm struct mpr_softc *sc; 1044283990Sslm struct mpr_command *cm; 1045283990Sslm 1046283990Sslm cm = (struct mpr_command *)data; 1047283990Sslm sc = cm->cm_sc; 1048283990Sslm mtx_assert(&sc->mpr_mtx, MA_OWNED); 1049283990Sslm 1050283990Sslm mpr_dprint(sc, MPR_INFO, "%s checking ATA ID command %p sc %p\n", 1051283990Sslm __func__, cm, sc); 1052283990Sslm if ((callout_pending(&cm->cm_callout)) || 1053283990Sslm (!callout_active(&cm->cm_callout))) { 1054283990Sslm mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed " 1055283990Sslm "out\n", __func__); 1056283990Sslm return; 1057283990Sslm } 1058283990Sslm callout_deactivate(&cm->cm_callout); 1059283990Sslm 1060283990Sslm /* 1061283990Sslm * Run the interrupt handler to make sure it's not pending. This 1062283990Sslm * isn't perfect because the command could have already completed 1063283990Sslm * and been re-used, though this is unlikely. 1064283990Sslm */ 1065283990Sslm mpr_intr_locked(sc); 1066283990Sslm if (cm->cm_state == MPR_CM_STATE_FREE) { 1067283990Sslm mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed " 1068283990Sslm "out\n", __func__); 1069283990Sslm return; 1070283990Sslm } 1071283990Sslm 1072283990Sslm mpr_dprint(sc, MPR_INFO, "ATA ID command timeout cm %p\n", cm); 1073283990Sslm 1074283990Sslm /* 1075283990Sslm * Send wakeup() to the sleeping thread that issued this ATA ID 1076283990Sslm * command. wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), 1077283990Sslm * and this will keep reinit() from being called. This way, an Abort 1078283990Sslm * Task TM can be issued so that the timed out command can be cleared. 1079283990Sslm * The Abort Task cannot be sent from here because the driver has not 1080283990Sslm * completed setting up targets. Instead, the command is flagged so 1081283990Sslm * that special handling will be used to send the abort. 1082283990Sslm */ 1083283990Sslm cm->cm_flags |= MPR_CM_FLAGS_SATA_ID_TIMEOUT; 1084283990Sslm wakeup(cm); 1085283990Sslm} 1086283990Sslm 1087265236Skenstatic int 1088265236Skenmprsas_volume_add(struct mpr_softc *sc, u16 handle) 1089265236Sken{ 1090265236Sken struct mprsas_softc *sassc; 1091265236Sken struct mprsas_target *targ; 1092265236Sken u64 wwid; 1093265236Sken unsigned int id; 1094265236Sken int error = 0; 1095265236Sken struct mprsas_lun *lun; 1096265236Sken 1097265236Sken sassc = sc->sassc; 1098265236Sken mprsas_startup_increment(sassc); 1099265236Sken /* wwid is endian safe */ 1100265236Sken mpr_config_get_volume_wwid(sc, handle, &wwid); 1101265236Sken if (!wwid) { 1102265236Sken printf("%s: invalid WWID; cannot add volume to mapping table\n", 1103265236Sken __func__); 1104265236Sken error = ENXIO; 1105265236Sken goto out; 1106265236Sken } 1107265236Sken 1108265236Sken id = mpr_mapping_get_raid_id(sc, wwid, handle); 1109265236Sken if (id == MPR_MAP_BAD_ID) { 1110265236Sken printf("%s: could not get ID for volume with handle 0x%04x and " 1111265236Sken "WWID 0x%016llx\n", __func__, handle, 1112265236Sken (unsigned long long)wwid); 1113265236Sken error = ENXIO; 1114265236Sken goto out; 1115265236Sken } 1116265236Sken 1117265236Sken targ = &sassc->targets[id]; 1118265236Sken targ->tid = id; 1119265236Sken targ->handle = handle; 1120265236Sken targ->devname = wwid; 1121265236Sken TAILQ_INIT(&targ->commands); 1122265236Sken TAILQ_INIT(&targ->timedout_commands); 1123265236Sken while (!SLIST_EMPTY(&targ->luns)) { 1124265236Sken lun = SLIST_FIRST(&targ->luns); 1125265236Sken SLIST_REMOVE_HEAD(&targ->luns, lun_link); 1126265236Sken free(lun, M_MPR); 1127265236Sken } 1128265236Sken SLIST_INIT(&targ->luns); 1129266548Sken#if ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000039)) || \ 1130266548Sken (__FreeBSD_version < 902502) 1131265236Sken if ((sassc->flags & MPRSAS_IN_STARTUP) == 0) 1132265236Sken#endif 1133265236Sken mprsas_rescan_target(sc, targ); 1134265236Sken mpr_dprint(sc, MPR_MAPPING, "RAID target id %d added (WWID = 0x%jx)\n", 1135265236Sken targ->tid, wwid); 1136265236Skenout: 1137265236Sken mprsas_startup_decrement(sassc); 1138265236Sken return (error); 1139265236Sken} 1140265236Sken 1141265236Sken/** 1142265236Sken * mprsas_SSU_to_SATA_devices 1143265236Sken * @sc: per adapter object 1144265236Sken * 1145265236Sken * Looks through the target list and issues a StartStopUnit SCSI command to each 1146265236Sken * SATA direct-access device. This helps to ensure that data corruption is 1147265236Sken * avoided when the system is being shut down. This must be called after the IR 1148265236Sken * System Shutdown RAID Action is sent if in IR mode. 1149265236Sken * 1150265236Sken * Return nothing. 1151265236Sken */ 1152265236Skenstatic void 1153265236Skenmprsas_SSU_to_SATA_devices(struct mpr_softc *sc) 1154265236Sken{ 1155265236Sken struct mprsas_softc *sassc = sc->sassc; 1156265236Sken union ccb *ccb; 1157265236Sken path_id_t pathid = cam_sim_path(sassc->sim); 1158265236Sken target_id_t targetid; 1159265236Sken struct mprsas_target *target; 1160265236Sken char path_str[64]; 1161265236Sken struct timeval cur_time, start_time; 1162265236Sken 1163266548Sken mpr_lock(sc); 1164266548Sken 1165265236Sken /* 1166283990Sslm * For each target, issue a StartStopUnit command to stop the device. 1167265236Sken */ 1168265236Sken sc->SSU_started = TRUE; 1169265236Sken sc->SSU_refcount = 0; 1170265236Sken for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) { 1171265236Sken target = &sassc->targets[targetid]; 1172265236Sken if (target->handle == 0x0) { 1173265236Sken continue; 1174265236Sken } 1175265236Sken 1176283990Sslm ccb = xpt_alloc_ccb_nowait(); 1177283990Sslm if (ccb == NULL) { 1178283990Sslm mpr_dprint(sc, MPR_FAULT, "Unable to alloc CCB to stop " 1179283990Sslm "unit.\n"); 1180283990Sslm return; 1181283990Sslm } 1182283990Sslm 1183283990Sslm /* 1184283990Sslm * The stop_at_shutdown flag will be set if this device is 1185283990Sslm * a SATA direct-access end device. 1186283990Sslm */ 1187283990Sslm if (target->stop_at_shutdown) { 1188283990Sslm if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, 1189283990Sslm pathid, targetid, CAM_LUN_WILDCARD) != 1190283990Sslm CAM_REQ_CMP) { 1191283990Sslm mpr_dprint(sc, MPR_ERROR, "Unable to create " 1192283990Sslm "path to stop unit.\n"); 1193283990Sslm xpt_free_ccb(ccb); 1194265236Sken return; 1195265236Sken } 1196283990Sslm xpt_path_string(ccb->ccb_h.path, path_str, 1197283990Sslm sizeof(path_str)); 1198265236Sken 1199283990Sslm mpr_dprint(sc, MPR_INFO, "Sending StopUnit: path %s " 1200283990Sslm "handle %d\n", path_str, target->handle); 1201283990Sslm 1202265236Sken /* 1203283990Sslm * Issue a START STOP UNIT command for the target. 1204283990Sslm * Increment the SSU counter to be used to count the 1205283990Sslm * number of required replies. 1206265236Sken */ 1207283990Sslm mpr_dprint(sc, MPR_INFO, "Incrementing SSU count\n"); 1208283990Sslm sc->SSU_refcount++; 1209283990Sslm ccb->ccb_h.target_id = 1210283990Sslm xpt_path_target_id(ccb->ccb_h.path); 1211283990Sslm ccb->ccb_h.ppriv_ptr1 = sassc; 1212283990Sslm scsi_start_stop(&ccb->csio, 1213283990Sslm /*retries*/0, 1214283990Sslm mprsas_stop_unit_done, 1215283990Sslm MSG_SIMPLE_Q_TAG, 1216283990Sslm /*start*/FALSE, 1217283990Sslm /*load/eject*/0, 1218283990Sslm /*immediate*/FALSE, 1219283990Sslm MPR_SENSE_LEN, 1220283990Sslm /*timeout*/10000); 1221283990Sslm xpt_action(ccb); 1222265236Sken } 1223265236Sken } 1224265236Sken 1225266548Sken mpr_unlock(sc); 1226266548Sken 1227265236Sken /* 1228265236Sken * Wait until all of the SSU commands have completed or time has 1229283990Sslm * expired (60 seconds). Pause for 100ms each time through. If any 1230265236Sken * command times out, the target will be reset in the SCSI command 1231265236Sken * timeout routine. 1232265236Sken */ 1233265236Sken getmicrotime(&start_time); 1234265236Sken while (sc->SSU_refcount) { 1235265236Sken pause("mprwait", hz/10); 1236265236Sken 1237265236Sken getmicrotime(&cur_time); 1238265236Sken if ((cur_time.tv_sec - start_time.tv_sec) > 60) { 1239283990Sslm mpr_dprint(sc, MPR_ERROR, "Time has expired waiting " 1240265236Sken "for SSU commands to complete.\n"); 1241265236Sken break; 1242265236Sken } 1243265236Sken } 1244265236Sken} 1245265236Sken 1246265236Skenstatic void 1247265236Skenmprsas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb) 1248265236Sken{ 1249265236Sken struct mprsas_softc *sassc; 1250265236Sken char path_str[64]; 1251265236Sken 1252265236Sken sassc = (struct mprsas_softc *)done_ccb->ccb_h.ppriv_ptr1; 1253265236Sken 1254265236Sken xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str)); 1255265236Sken mpr_dprint(sassc->sc, MPR_INFO, "Completing stop unit for %s\n", 1256265236Sken path_str); 1257265236Sken 1258265236Sken if (done_ccb == NULL) 1259265236Sken return; 1260265236Sken 1261265236Sken /* 1262265236Sken * Nothing more to do except free the CCB and path. If the command 1263265236Sken * timed out, an abort reset, then target reset will be issued during 1264265236Sken * the SCSI Command process. 1265265236Sken */ 1266265236Sken xpt_free_path(done_ccb->ccb_h.path); 1267265236Sken xpt_free_ccb(done_ccb); 1268265236Sken} 1269265236Sken 1270265236Sken/** 1271265236Sken * mprsas_ir_shutdown - IR shutdown notification 1272265236Sken * @sc: per adapter object 1273265236Sken * 1274265236Sken * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that 1275265236Sken * the host system is shutting down. 1276265236Sken * 1277265236Sken * Return nothing. 1278265236Sken */ 1279265236Skenvoid 1280265236Skenmprsas_ir_shutdown(struct mpr_softc *sc) 1281265236Sken{ 1282265236Sken u16 volume_mapping_flags; 1283265236Sken u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); 1284265236Sken struct dev_mapping_table *mt_entry; 1285265236Sken u32 start_idx, end_idx; 1286265236Sken unsigned int id, found_volume = 0; 1287265236Sken struct mpr_command *cm; 1288265236Sken Mpi2RaidActionRequest_t *action; 1289283990Sslm target_id_t targetid; 1290283990Sslm struct mprsas_target *target; 1291265236Sken 1292265236Sken mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); 1293265236Sken 1294265236Sken /* is IR firmware build loaded? */ 1295265236Sken if (!sc->ir_firmware) 1296265236Sken goto out; 1297265236Sken 1298265236Sken /* are there any volumes? Look at IR target IDs. */ 1299265236Sken // TODO-later, this should be looked up in the RAID config structure 1300265236Sken // when it is implemented. 1301265236Sken volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & 1302265236Sken MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; 1303265236Sken if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) { 1304265236Sken start_idx = 0; 1305265236Sken if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) 1306265236Sken start_idx = 1; 1307265236Sken } else 1308265236Sken start_idx = sc->max_devices - sc->max_volumes; 1309265236Sken end_idx = start_idx + sc->max_volumes - 1; 1310265236Sken 1311265236Sken for (id = start_idx; id < end_idx; id++) { 1312265236Sken mt_entry = &sc->mapping_table[id]; 1313265236Sken if ((mt_entry->physical_id != 0) && 1314265236Sken (mt_entry->missing_count == 0)) { 1315265236Sken found_volume = 1; 1316265236Sken break; 1317265236Sken } 1318265236Sken } 1319265236Sken 1320265236Sken if (!found_volume) 1321265236Sken goto out; 1322265236Sken 1323265236Sken if ((cm = mpr_alloc_command(sc)) == NULL) { 1324265236Sken printf("%s: command alloc failed\n", __func__); 1325265236Sken goto out; 1326265236Sken } 1327265236Sken 1328265236Sken action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req; 1329265236Sken action->Function = MPI2_FUNCTION_RAID_ACTION; 1330265236Sken action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; 1331265236Sken cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; 1332265236Sken mpr_lock(sc); 1333265236Sken mpr_wait_command(sc, cm, 5, CAN_SLEEP); 1334265236Sken mpr_unlock(sc); 1335265236Sken 1336265236Sken /* 1337265236Sken * Don't check for reply, just leave. 1338265236Sken */ 1339265236Sken if (cm) 1340265236Sken mpr_free_command(sc, cm); 1341265236Sken 1342265236Skenout: 1343283990Sslm /* 1344283990Sslm * All of the targets must have the correct value set for 1345283990Sslm * 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable. 1346283990Sslm * 1347283990Sslm * The possible values for the 'enable_ssu' variable are: 1348283990Sslm * 0: disable to SSD and HDD 1349283990Sslm * 1: disable only to HDD (default) 1350283990Sslm * 2: disable only to SSD 1351283990Sslm * 3: enable to SSD and HDD 1352283990Sslm * anything else will default to 1. 1353283990Sslm */ 1354283990Sslm for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) { 1355283990Sslm target = &sc->sassc->targets[targetid]; 1356283990Sslm if (target->handle == 0x0) { 1357283990Sslm continue; 1358283990Sslm } 1359283990Sslm 1360283990Sslm if (target->supports_SSU) { 1361283990Sslm switch (sc->enable_ssu) { 1362283990Sslm case MPR_SSU_DISABLE_SSD_DISABLE_HDD: 1363283990Sslm target->stop_at_shutdown = FALSE; 1364283990Sslm break; 1365283990Sslm case MPR_SSU_DISABLE_SSD_ENABLE_HDD: 1366283990Sslm target->stop_at_shutdown = TRUE; 1367283990Sslm if (target->flags & MPR_TARGET_IS_SATA_SSD) { 1368283990Sslm target->stop_at_shutdown = FALSE; 1369283990Sslm } 1370283990Sslm break; 1371283990Sslm case MPR_SSU_ENABLE_SSD_ENABLE_HDD: 1372283990Sslm target->stop_at_shutdown = TRUE; 1373283990Sslm break; 1374283990Sslm case MPR_SSU_ENABLE_SSD_DISABLE_HDD: 1375283990Sslm default: 1376283990Sslm target->stop_at_shutdown = TRUE; 1377283990Sslm if ((target->flags & 1378283990Sslm MPR_TARGET_IS_SATA_SSD) == 0) { 1379283990Sslm target->stop_at_shutdown = FALSE; 1380283990Sslm } 1381283990Sslm break; 1382283990Sslm } 1383283990Sslm } 1384283990Sslm } 1385265236Sken mprsas_SSU_to_SATA_devices(sc); 1386265236Sken} 1387