diff options
Diffstat (limited to 'sys/dev/mps')
-rw-r--r-- | sys/dev/mps/mpi/mpi2.h | 8 | ||||
-rw-r--r-- | sys/dev/mps/mpi/mpi2_cnfg.h | 8 | ||||
-rw-r--r-- | sys/dev/mps/mpi/mpi2_hbd.h | 8 | ||||
-rw-r--r-- | sys/dev/mps/mpi/mpi2_history.txt | 8 | ||||
-rw-r--r-- | sys/dev/mps/mpi/mpi2_init.h | 8 | ||||
-rw-r--r-- | sys/dev/mps/mpi/mpi2_ioc.h | 8 | ||||
-rw-r--r-- | sys/dev/mps/mpi/mpi2_ra.h | 8 | ||||
-rw-r--r-- | sys/dev/mps/mpi/mpi2_raid.h | 8 | ||||
-rw-r--r-- | sys/dev/mps/mpi/mpi2_sas.h | 8 | ||||
-rw-r--r-- | sys/dev/mps/mpi/mpi2_targ.h | 8 | ||||
-rw-r--r-- | sys/dev/mps/mpi/mpi2_tool.h | 8 | ||||
-rw-r--r-- | sys/dev/mps/mpi/mpi2_type.h | 8 | ||||
-rw-r--r-- | sys/dev/mps/mps.c | 28 | ||||
-rw-r--r-- | sys/dev/mps/mps_config.c | 5 | ||||
-rw-r--r-- | sys/dev/mps/mps_ioctl.h | 7 | ||||
-rw-r--r-- | sys/dev/mps/mps_mapping.c | 71 | ||||
-rw-r--r-- | sys/dev/mps/mps_mapping.h | 10 | ||||
-rw-r--r-- | sys/dev/mps/mps_pci.c | 36 | ||||
-rw-r--r-- | sys/dev/mps/mps_sas.c | 181 | ||||
-rw-r--r-- | sys/dev/mps/mps_sas.h | 15 | ||||
-rw-r--r-- | sys/dev/mps/mps_sas_lsi.c | 355 | ||||
-rw-r--r-- | sys/dev/mps/mps_user.c | 27 | ||||
-rw-r--r-- | sys/dev/mps/mpsvar.h | 20 |
23 files changed, 577 insertions, 274 deletions
diff --git a/sys/dev/mps/mpi/mpi2.h b/sys/dev/mps/mpi/mpi2.h index 45fb7d9..1d38721 100644 --- a/sys/dev/mps/mpi/mpi2.h +++ b/sys/dev/mps/mpi/mpi2.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2006-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2006-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2.h diff --git a/sys/dev/mps/mpi/mpi2_cnfg.h b/sys/dev/mps/mpi/mpi2_cnfg.h index 4db5f09..871d2b8 100644 --- a/sys/dev/mps/mpi/mpi2_cnfg.h +++ b/sys/dev/mps/mpi/mpi2_cnfg.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2006-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2006-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_cnfg.h diff --git a/sys/dev/mps/mpi/mpi2_hbd.h b/sys/dev/mps/mpi/mpi2_hbd.h index d8645e6..1b42ff3 100644 --- a/sys/dev/mps/mpi/mpi2_hbd.h +++ b/sys/dev/mps/mpi/mpi2_hbd.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2009-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2009-2012 LSI Corporation. + * Copyright (c) 2009-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_hbd.h diff --git a/sys/dev/mps/mpi/mpi2_history.txt b/sys/dev/mps/mpi/mpi2_history.txt index e6bb5b0..d0c2c1d 100644 --- a/sys/dev/mps/mpi/mpi2_history.txt +++ b/sys/dev/mps/mpi/mpi2_history.txt @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2000-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -32,7 +33,8 @@ Fusion-MPT MPI 2.0 Header File Change History ============================== - Copyright (c) 2000-2012 LSI Corporation. + Copyright (c) 2000-2015 LSI Corporation. + Copyright (c) 2013-2015 Avago Technologies --------------------------------------- Header Set Release Version: 02.00.18 diff --git a/sys/dev/mps/mpi/mpi2_init.h b/sys/dev/mps/mpi/mpi2_init.h index 0f0a192..189e457 100644 --- a/sys/dev/mps/mpi/mpi2_init.h +++ b/sys/dev/mps/mpi/mpi2_init.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2006-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2006-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_init.h diff --git a/sys/dev/mps/mpi/mpi2_ioc.h b/sys/dev/mps/mpi/mpi2_ioc.h index fd4df2b2..0cef643 100644 --- a/sys/dev/mps/mpi/mpi2_ioc.h +++ b/sys/dev/mps/mpi/mpi2_ioc.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2006-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2006-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_ioc.h diff --git a/sys/dev/mps/mpi/mpi2_ra.h b/sys/dev/mps/mpi/mpi2_ra.h index 2847fa9d..4ba141b 100644 --- a/sys/dev/mps/mpi/mpi2_ra.h +++ b/sys/dev/mps/mpi/mpi2_ra.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2009-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2012 LSI Corporation. + * Copyright (c) 2009-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_ra.h diff --git a/sys/dev/mps/mpi/mpi2_raid.h b/sys/dev/mps/mpi/mpi2_raid.h index 2d497ee..4154077 100644 --- a/sys/dev/mps/mpi/mpi2_raid.h +++ b/sys/dev/mps/mpi/mpi2_raid.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2007-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2007-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_raid.h diff --git a/sys/dev/mps/mpi/mpi2_sas.h b/sys/dev/mps/mpi/mpi2_sas.h index 54a995b..2514370 100644 --- a/sys/dev/mps/mpi/mpi2_sas.h +++ b/sys/dev/mps/mpi/mpi2_sas.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2007-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2007-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_sas.h diff --git a/sys/dev/mps/mpi/mpi2_targ.h b/sys/dev/mps/mpi/mpi2_targ.h index 179ca53..7e30381 100644 --- a/sys/dev/mps/mpi/mpi2_targ.h +++ b/sys/dev/mps/mpi/mpi2_targ.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2006-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2006-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_targ.h diff --git a/sys/dev/mps/mpi/mpi2_tool.h b/sys/dev/mps/mpi/mpi2_tool.h index 73ece21..b9f0f53 100644 --- a/sys/dev/mps/mpi/mpi2_tool.h +++ b/sys/dev/mps/mpi/mpi2_tool.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2007-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2007-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_tool.h diff --git a/sys/dev/mps/mpi/mpi2_type.h b/sys/dev/mps/mpi/mpi2_type.h index 0ea541a..6b93716 100644 --- a/sys/dev/mps/mpi/mpi2_type.h +++ b/sys/dev/mps/mpi/mpi2_type.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2006-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2006-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_type.h diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c index 0957602..d4fbda1 100644 --- a/sys/dev/mps/mps.c +++ b/sys/dev/mps/mps.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2012 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -32,7 +33,7 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for Avago Technologies (LSI) MPT2 */ /* TODO Move headers to mpsvar */ #include <sys/types.h> @@ -1349,6 +1350,8 @@ mps_get_tunables(struct mps_softc *sc) sc->disable_msix = 0; sc->disable_msi = 0; sc->max_chains = MPS_CHAIN_FRAMES; + sc->enable_ssu = MPS_SSU_ENABLE_SSD_DISABLE_HDD; + sc->spinup_wait_time = DEFAULT_SPINUP_WAIT; /* * Grab the global variables. @@ -1357,6 +1360,8 @@ mps_get_tunables(struct mps_softc *sc) TUNABLE_INT_FETCH("hw.mps.disable_msix", &sc->disable_msix); TUNABLE_INT_FETCH("hw.mps.disable_msi", &sc->disable_msi); TUNABLE_INT_FETCH("hw.mps.max_chains", &sc->max_chains); + TUNABLE_INT_FETCH("hw.mps.enable_ssu", &sc->enable_ssu); + TUNABLE_INT_FETCH("hw.mps.spinup_wait_time", &sc->spinup_wait_time); /* Grab the unit-instance variables */ snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.debug_level", @@ -1379,6 +1384,14 @@ mps_get_tunables(struct mps_softc *sc) snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.exclude_ids", device_get_unit(sc->mps_dev)); TUNABLE_STR_FETCH(tmpstr, sc->exclude_ids, sizeof(sc->exclude_ids)); + + snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.enable_ssu", + device_get_unit(sc->mps_dev)); + TUNABLE_INT_FETCH(tmpstr, &sc->enable_ssu); + + snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.spinup_wait_time", + device_get_unit(sc->mps_dev)); + TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time); } static void @@ -1451,11 +1464,20 @@ mps_setup_sysctl(struct mps_softc *sc) OID_AUTO, "max_chains", CTLFLAG_RD, &sc->max_chains, 0,"maximum chain frames that will be allocated"); + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "enable_ssu", CTLFLAG_RW, &sc->enable_ssu, 0, + "enable SSU to SATA SSD/HDD at shutdown"); + #if __FreeBSD_version >= 900030 SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "chain_alloc_fail", CTLFLAG_RD, &sc->chain_alloc_fail, "chain allocation failures"); #endif //FreeBSD_version >= 900030 + + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "spinup_wait_time", CTLFLAG_RD, + &sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for " + "spinup after SATA ID error"); } int diff --git a/sys/dev/mps/mps_config.c b/sys/dev/mps/mps_config.c index d6e2a8c..e3bebaa 100644 --- a/sys/dev/mps/mps_config.c +++ b/sys/dev/mps/mps_config.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ #include <sys/cdefs.h> diff --git a/sys/dev/mps/mps_ioctl.h b/sys/dev/mps/mps_ioctl.h index a52f80e..cb0d9c5 100644 --- a/sys/dev/mps/mps_ioctl.h +++ b/sys/dev/mps/mps_ioctl.h @@ -27,12 +27,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD userland interface + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface * * $FreeBSD$ */ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,7 +57,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ diff --git a/sys/dev/mps/mps_mapping.c b/sys/dev/mps/mps_mapping.c index 80022ea..d0819ef 100644 --- a/sys/dev/mps/mps_mapping.c +++ b/sys/dev/mps/mps_mapping.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ #include <sys/cdefs.h> @@ -889,14 +890,14 @@ _mapping_get_dev_info(struct mps_softc *sc, u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; - u8 entry, enc_idx, phy_idx; + u8 entry, enc_idx, phy_idx, sata_end_device; u32 map_idx, index, device_info; struct _map_phy_change *phy_change, *tmp_phy_change; uint64_t sas_address; struct enc_mapping_table *et_entry; struct dev_mapping_table *mt_entry; u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED; - int rc; + int rc = 1; for (entry = 0; entry < topo_change->num_entries; entry++) { phy_change = &topo_change->phy_details[entry]; @@ -910,42 +911,36 @@ _mapping_get_dev_info(struct mps_softc *sc, continue; } + /* + * Always get SATA Identify information because this is used + * to determine if Start/Stop Unit should be sent to the drive + * when the system is shutdown. + */ device_info = le32toh(sas_device_pg0.DeviceInfo); - if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == - MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { - if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && - (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { - rc = mpssas_get_sas_address_for_sata_disk(sc, - &sas_address, phy_change->dev_handle, - device_info); - if (rc) { - printf("%s: failed to compute the " - "hashed SAS Address for SATA " - "device with handle 0x%04x\n", - __func__, phy_change->dev_handle); - sas_address = - sas_device_pg0.SASAddress.High; - sas_address = (sas_address << 32) | - sas_device_pg0.SASAddress.Low; - } - mps_dprint(sc, MPS_MAPPING, - "SAS Address for SATA device = %jx\n", - sas_address); + sas_address = sas_device_pg0.SASAddress.High; + sas_address = (sas_address << 32) | + sas_device_pg0.SASAddress.Low; + sata_end_device = 0; + if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) && + (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) { + sata_end_device = 1; + rc = mpssas_get_sas_address_for_sata_disk(sc, + &sas_address, phy_change->dev_handle, device_info, + &phy_change->is_SATA_SSD); + if (rc) { + mps_dprint(sc, MPS_ERROR, "%s: failed to get " + "disk type (SSD or HDD) and SAS Address " + "for SATA device with handle 0x%04x\n", + __func__, phy_change->dev_handle); } else { - sas_address = - sas_device_pg0.SASAddress.High; - sas_address = (sas_address << 32) | - sas_device_pg0.SASAddress.Low; + mps_dprint(sc, MPS_INFO, "SAS Address for SATA " + "device = %jx\n", sas_address); } - } else { - sas_address = sas_device_pg0.SASAddress.High; - sas_address = (sas_address << 32) | - sas_device_pg0.SASAddress.Low; } + phy_change->physical_id = sas_address; phy_change->slot = le16toh(sas_device_pg0.Slot); - phy_change->device_info = - le32toh(sas_device_pg0.DeviceInfo); + phy_change->device_info = le32toh(sas_device_pg0.DeviceInfo); if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) { @@ -953,10 +948,10 @@ _mapping_get_dev_info(struct mps_softc *sc, topo_change->enc_handle); if (enc_idx == MPS_ENCTABLE_BAD_IDX) { phy_change->is_processed = 1; - printf("%s: failed to add the device with " - "handle 0x%04x because the enclosure is " - "not in the mapping table\n", __func__, - phy_change->dev_handle); + mps_dprint(sc, MPS_MAPPING, "%s: failed to add " + "the device with handle 0x%04x because the " + "enclosure is not in the mapping table\n", + __func__, phy_change->dev_handle); continue; } if (!((phy_change->device_info & diff --git a/sys/dev/mps/mps_mapping.h b/sys/dev/mps/mps_mapping.h index e188d8f..c370d50 100644 --- a/sys/dev/mps/mps_mapping.h +++ b/sys/dev/mps/mps_mapping.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -38,6 +39,7 @@ * @dev_handle: device handle for the device pointed by this entry * @slot: slot ID * @is_processed: Flag to indicate whether this entry is processed or not + * @is_SATA_SSD: 1 if this is a SATA device AND an SSD, 0 otherwise */ struct _map_phy_change { uint64_t physical_id; @@ -46,6 +48,8 @@ struct _map_phy_change { uint16_t slot; uint8_t reason; uint8_t is_processed; + uint8_t is_SATA_SSD; + uint8_t reserved; }; /** @@ -66,6 +70,6 @@ struct _map_topology_change { extern int mpssas_get_sas_address_for_sata_disk(struct mps_softc *ioc, - u64 *sas_address, u16 handle, u32 device_info); + u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); #endif diff --git a/sys/dev/mps/mps_pci.c b/sys/dev/mps/mps_pci.c index 5417ae6..cee4376 100644 --- a/sys/dev/mps/mps_pci.c +++ b/sys/dev/mps/mps_pci.c @@ -27,7 +27,7 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -/* PCI/PCI-X/PCIe bus interface for the LSI MPT2 controllers */ +/* PCI/PCI-X/PCIe bus interface for the Avago Tech (LSI) MPT2 controllers */ /* TODO Move headers to mpsvar */ #include <sys/types.h> @@ -98,33 +98,33 @@ struct mps_ident { const char *desc; } mps_identifiers[] = { { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004, - 0xffff, 0xffff, 0, "LSI SAS2004" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2004" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008, - 0xffff, 0xffff, 0, "LSI SAS2008" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2008" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1, - 0xffff, 0xffff, 0, "LSI SAS2108" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2108" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2, - 0xffff, 0xffff, 0, "LSI SAS2108" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2108" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3, - 0xffff, 0xffff, 0, "LSI SAS2108" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2108" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1, - 0xffff, 0xffff, 0, "LSI SAS2116" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2116" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2, - 0xffff, 0xffff, 0, "LSI SAS2116" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2116" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1, - 0xffff, 0xffff, 0, "LSI SAS2208" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2, - 0xffff, 0xffff, 0, "LSI SAS2208" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3, - 0xffff, 0xffff, 0, "LSI SAS2208" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4, - 0xffff, 0xffff, 0, "LSI SAS2208" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5, - 0xffff, 0xffff, 0, "LSI SAS2208" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6, - 0xffff, 0xffff, 0, "LSI SAS2208" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1, - 0xffff, 0xffff, 0, "LSI SAS2308" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2308" }, // Add Customer specific vender/subdevice id before generic // (0xffff) vender/subdevice id. { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2, @@ -136,11 +136,11 @@ struct mps_ident { { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2, 0x8086, 0x3519, 0, "Intel(R) Integrated RAID Module RMS25KB040" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2, - 0xffff, 0xffff, 0, "LSI SAS2308" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2308" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3, - 0xffff, 0xffff, 0, "LSI SAS2308" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2308" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200, - 0xffff, 0xffff, MPS_FLAGS_WD_AVAILABLE, "LSI SSS6200" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SSS6200" }, { 0, 0, 0, 0, 0, NULL } }; diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c index cd651ca..4fbdbb2 100644 --- a/sys/dev/mps/mps_sas.c +++ b/sys/dev/mps/mps_sas.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -32,7 +33,7 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for Avago Technologies (LSI) MPT2 */ /* TODO Move headers to mpsvar */ #include <sys/types.h> @@ -119,6 +120,8 @@ static void mpssas_remove_device(struct mps_softc *, struct mps_command *); static void mpssas_remove_complete(struct mps_softc *, struct mps_command *); static void mpssas_action(struct cam_sim *sim, union ccb *ccb); static void mpssas_poll(struct cam_sim *sim); +static int mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, + struct mps_command *cm); static void mpssas_scsiio_timeout(void *data); static void mpssas_abort_complete(struct mps_softc *sc, struct mps_command *cm); static void mpssas_direct_drive_io(struct mpssas_softc *sassc, @@ -133,8 +136,6 @@ static void mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, static void mpssas_action_smpio(struct mpssas_softc *sassc, union ccb *ccb); #endif //FreeBSD_version >= 900026 static void mpssas_resetdev_complete(struct mps_softc *, struct mps_command *); -static int mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm); -static int mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type); static void mpssas_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg); #if (__FreeBSD_version < 901503) || \ @@ -224,7 +225,7 @@ mpssas_startup_decrement(struct mpssas_softc *sassc) } } -/* LSI's firmware requires us to stop sending commands when we're doing task +/* The firmware requires us to stop sending commands when we're doing task * management, so refcount the TMs and keep the simq frozen when any are in * use. */ @@ -233,37 +234,31 @@ mpssas_alloc_tm(struct mps_softc *sc) { struct mps_command *tm; - MPS_FUNCTRACE(sc); tm = mps_alloc_high_priority_command(sc); - if (tm != NULL) { - if (sc->sassc->tm_count++ == 0) { - mps_dprint(sc, MPS_RECOVERY, - "%s freezing simq\n", __func__); - xpt_freeze_simq(sc->sassc->sim, 1); - } - mps_dprint(sc, MPS_RECOVERY, "%s tm_count %u\n", __func__, - sc->sassc->tm_count); - } return tm; } void mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm) { - mps_dprint(sc, MPS_TRACE, "%s", __func__); if (tm == NULL) return; - /* if there are no TMs in use, we can release the simq. We use our - * own refcount so that it's easier for a diag reset to cleanup and - * release the simq. + /* + * For TM's the devq is frozen for the device. Unfreeze it here and + * free the resources used for freezing the devq. Must clear the + * INRESET flag as well or scsi I/O will not work. */ - if (--sc->sassc->tm_count == 0) { - mps_dprint(sc, MPS_RECOVERY, "%s releasing simq\n", __func__); - xpt_release_simq(sc->sassc->sim, 1); + if (tm->cm_targ != NULL) { + tm->cm_targ->flags &= ~MPSSAS_TARGET_INRESET; + } + if (tm->cm_ccb) { + mps_dprint(sc, MPS_INFO, "Unfreezing devq for target ID %d\n", + tm->cm_targ->tid); + xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE); + xpt_free_path(tm->cm_ccb->ccb_h.path); + xpt_free_ccb(tm->cm_ccb); } - mps_dprint(sc, MPS_RECOVERY, "%s tm_count %u\n", __func__, - sc->sassc->tm_count); mps_free_high_priority_command(sc, tm); } @@ -371,7 +366,8 @@ mpssas_remove_volume(struct mps_softc *sc, struct mps_command *tm) if (reply == NULL) { /* XXX retry the remove after the diag reset completes? */ mps_dprint(sc, MPS_FAULT, - "%s NULL reply reseting device 0x%04x\n", __func__, handle); + "%s NULL reply resetting device 0x%04x\n", __func__, + handle); mpssas_free_tm(sc, tm); return; } @@ -475,6 +471,11 @@ mpssas_prepare_volume_remove(struct mpssas_softc *sassc, uint16_t handle) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mpssas_remove_volume; cm->cm_complete_data = (void *)(uintptr_t)handle; + + mps_dprint(sc, MPS_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); + mpssas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + mps_map_command(sc, cm); } @@ -533,6 +534,11 @@ mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle) cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mpssas_remove_device; cm->cm_complete_data = (void *)(uintptr_t)handle; + + mps_dprint(sc, MPS_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); + mpssas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + mps_map_command(sc, cm); } @@ -758,9 +764,7 @@ mps_attach_sas(struct mps_softc *sc) TASK_INIT(&sassc->ev_task, 0, mpssas_firmware_event_work, sc); sassc->ev_tq = taskqueue_create("mps_taskq", M_NOWAIT | M_ZERO, taskqueue_thread_enqueue, &sassc->ev_tq); - - /* Run the task queue with lowest priority */ - taskqueue_start_threads(&sassc->ev_tq, 1, 255, "%s taskq", + taskqueue_start_threads(&sassc->ev_tq, 1, PRIBIO, "%s taskq", device_get_nameunit(sc->mps_dev)); mps_lock(sc); @@ -787,9 +791,6 @@ mps_attach_sas(struct mps_softc *sc) mpssas_startup_increment(sassc); callout_init(&sassc->discovery_callout, 1 /*mpsafe*/); - sassc->discovery_timeouts = 0; - - sassc->tm_count = 0; /* * Register for async events so we can determine the EEDP @@ -940,7 +941,7 @@ mpssas_action(struct cam_sim *sim, union ccb *ccb) cpi->max_lun = 255; cpi->initiator_id = sassc->maxtargets - 1; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN); + strncpy(cpi->hba_vid, "Avago Tech (LSI)", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); cpi->bus_id = cam_sim_bus(sim); @@ -1042,8 +1043,8 @@ mpssas_announce_reset(struct mps_softc *sc, uint32_t ac_code, path_id_t path_id = cam_sim_path(sc->sassc->sim); struct cam_path *path; - mps_dprint(sc, MPS_XINFO, "%s code %x target %d lun %d\n", __func__, - ac_code, target_id, lun_id); + mps_dprint(sc, MPS_XINFO, "%s code %x target %d lun %jx\n", __func__, + ac_code, target_id, (uintmax_t)lun_id); if (xpt_create_path(&path, NULL, path_id, target_id, lun_id) != CAM_REQ_CMP) { @@ -1136,8 +1137,8 @@ mpssas_handle_reinit(struct mps_softc *sc) mpssas_complete_all_commands(sc); mps_dprint(sc, MPS_INIT, - "%s startup %u tm %u after command completion\n", - __func__, sc->sassc->startup_refcount, sc->sassc->tm_count); + "%s startup %u after command completion\n", __func__, + sc->sassc->startup_refcount); /* zero all the target handles, since they may change after the * reset, and we have to rediscover all the targets and use the new @@ -1200,7 +1201,6 @@ mpssas_logical_unit_reset_complete(struct mps_softc *sc, struct mps_command *tm) "NULL reset reply for tm %p\n", tm); if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ - targ->flags &= ~MPSSAS_TARGET_INRESET; targ->tm = NULL; mpssas_free_tm(sc, tm); } @@ -1289,7 +1289,6 @@ mpssas_target_reset_complete(struct mps_softc *sc, struct mps_command *tm) "NULL reset reply for tm %p\n", tm); if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ - targ->flags &= ~MPSSAS_TARGET_INRESET; targ->tm = NULL; mpssas_free_tm(sc, tm); } @@ -1305,8 +1304,6 @@ mpssas_target_reset_complete(struct mps_softc *sc, struct mps_command *tm) le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), le32toh(reply->TerminationCount)); - targ->flags &= ~MPSSAS_TARGET_INRESET; - if (targ->outstanding == 0) { /* we've finished recovery for this target and all * of its logical units. @@ -1334,7 +1331,7 @@ mpssas_target_reset_complete(struct mps_softc *sc, struct mps_command *tm) #define MPS_RESET_TIMEOUT 30 -static int +int mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type) { MPI2_SCSI_TASK_MANAGE_REQUEST *req; @@ -1360,15 +1357,19 @@ mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type) mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, "sending logical unit reset\n"); tm->cm_complete = mpssas_logical_unit_reset_complete; + mpssas_prepare_for_tm(sc, tm, target, tm->cm_lun); } else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { - /* Target reset method = SAS Hard Link Reset / SATA Link Reset */ + /* + * Target reset method = + * SAS Hard Link Reset / SATA Link Reset + */ req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; tm->cm_targ->target_resets++; - tm->cm_targ->flags |= MPSSAS_TARGET_INRESET; mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO, "sending target reset\n"); tm->cm_complete = mpssas_target_reset_complete; + mpssas_prepare_for_tm(sc, tm, target, CAM_LUN_WILDCARD); } else { mps_dprint(sc, MPS_ERROR, "unexpected reset type 0x%x\n", type); @@ -1515,6 +1516,10 @@ mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_comma targ->aborts++; + mps_dprint(sc, MPS_INFO, "Sending reset from %s for target ID %d\n", + __func__, targ->tid); + mpssas_prepare_for_tm(sc, tm, targ, tm->cm_lun); + err = mps_map_command(sc, tm); if (err) mpssas_log_command(tm, MPS_RECOVERY, @@ -1523,7 +1528,6 @@ mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_comma return err; } - static void mpssas_scsiio_timeout(void *data) { @@ -1669,6 +1673,19 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb) return; } + /* + * If target has a reset in progress, freeze the devq and return. The + * devq will be released when the TM reset is finished. + */ + if (targ->flags & MPSSAS_TARGET_INRESET) { + ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; + mps_dprint(sc, MPS_INFO, "%s: Freezing devq for target ID %d\n", + __func__, targ->tid); + xpt_freeze_devq(ccb->ccb_h.path, 1); + xpt_done(ccb); + return; + } + cm = mps_alloc_command(sc); if (cm == NULL || (sc->mps_flags & MPS_FLAGS_DIAGRESET)) { if (cm != NULL) { @@ -2058,6 +2075,8 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) u8 *TLR_bits, TLR_on; int dir = 0, i; u16 alloc_len; + struct mpssas_target *target; + target_id_t target_id; MPS_FUNCTRACE(sc); mps_dprint(sc, MPS_TRACE, @@ -2071,6 +2090,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) sassc = sc->sassc; ccb = cm->cm_complete_data; csio = &ccb->csio; + target_id = csio->ccb_h.target_id; rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply; /* * XXX KDM if the chain allocation fails, does it matter if we do @@ -2252,9 +2272,10 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) * TLR_bits for the target. */ if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) && - ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) == + ((le32toh(rep->ResponseInfo) & + MPI2_SCSI_RI_MASK_REASONCODE) == MPS_SCSI_RI_INVALID_FRAME)) { - sc->mapping_table[csio->ccb_h.target_id].TLR_bits = + sc->mapping_table[target_id].TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; } @@ -2311,12 +2332,11 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) (csio->data_ptr != NULL) && ((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) && (sc->control_TLR) && - (sc->mapping_table[csio->ccb_h.target_id].device_info & + (sc->mapping_table[target_id].device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)) { vpd_list = (struct scsi_vpd_supported_page_list *) csio->data_ptr; - TLR_bits = &sc->mapping_table[csio->ccb_h.target_id]. - TLR_bits; + TLR_bits = &sc->mapping_table[target_id].TLR_bits; *TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON; alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) + @@ -2329,6 +2349,24 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) } } } + + /* + * If this is a SATA direct-access end device, mark it so that + * a SCSI StartStopUnit command will be sent to it when the + * driver is being shutdown. + */ + if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) && + ((csio->data_ptr[0] & 0x1f) == T_DIRECT) && + (sc->mapping_table[target_id].device_info & + MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && + ((sc->mapping_table[target_id].device_info & + MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == + MPI2_SAS_DEVICE_INFO_END_DEVICE)) { + target = &sassc->targets[target_id]; + target->supports_SSU = TRUE; + mps_dprint(sc, MPS_XINFO, "Target %d supports SSU\n", + target_id); + } break; case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: @@ -3100,6 +3138,8 @@ mpssas_action_resetdev(struct mpssas_softc *sassc, union ccb *ccb) tm->cm_complete = mpssas_resetdev_complete; tm->cm_complete_data = ccb; tm->cm_targ = targ; + targ->flags |= MPSSAS_TARGET_INRESET; + mps_map_command(sc, tm); } @@ -3366,19 +3406,6 @@ mpssas_check_eedp(struct mps_softc *sc, struct cam_path *path, xpt_path_string(local_path, path_str, sizeof(path_str)); - /* - * If this is a SATA direct-access end device, - * mark it so that a SCSI StartStopUnit command - * will be sent to it when the driver is being - * shutdown. - */ - if ((cgd.inq_data.device == T_DIRECT) && - (target->devinfo & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && - ((target->devinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == - MPI2_SAS_DEVICE_INFO_END_DEVICE)) { - lun->stop_at_shutdown = TRUE; - } - mps_dprint(sc, MPS_INFO, "Sending read cap: path %s handle %d\n", path_str, target->handle); @@ -3492,6 +3519,34 @@ mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) #endif /* (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */ +void +mpssas_prepare_for_tm(struct mps_softc *sc, struct mps_command *tm, + struct mpssas_target *target, lun_id_t lun_id) +{ + union ccb *ccb; + path_id_t path_id; + + /* + * Set the INRESET flag for this target so that no I/O will be sent to + * the target until the reset has completed. If an I/O request does + * happen, the devq will be frozen. The CCB holds the path which is + * used to release the devq. The devq is released and the CCB is freed + * when the TM completes. + */ + ccb = xpt_alloc_ccb_nowait(); + if (ccb) { + path_id = cam_sim_path(sc->sassc->sim); + if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, path_id, + target->tid, lun_id) != CAM_REQ_CMP) { + xpt_free_ccb(ccb); + } else { + tm->cm_ccb = ccb; + tm->cm_targ = target; + target->flags |= MPSSAS_TARGET_INRESET; + } + } +} + int mpssas_startup(struct mps_softc *sc) { diff --git a/sys/dev/mps/mps_sas.h b/sys/dev/mps/mps_sas.h index 0a3ddf1..d03258d 100644 --- a/sys/dev/mps/mps_sas.h +++ b/sys/dev/mps/mps_sas.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -35,7 +36,6 @@ struct mpssas_lun { lun_id_t lun_id; uint8_t eedp_formatted; uint32_t eedp_block_size; - uint8_t stop_at_shutdown; }; struct mpssas_target { @@ -52,11 +52,10 @@ struct mpssas_target { #define MPSSAS_TARGET_INREMOVAL (1 << 3) #define MPS_TARGET_FLAGS_RAID_COMPONENT (1 << 4) #define MPS_TARGET_FLAGS_VOLUME (1 << 5) +#define MPS_TARGET_IS_SATA_SSD (1 << 6) #define MPSSAS_TARGET_INRECOVERY (MPSSAS_TARGET_INABORT | \ MPSSAS_TARGET_INRESET | MPSSAS_TARGET_INCHIPRESET) -#define MPSSAS_TARGET_ADD (1 << 29) -#define MPSSAS_TARGET_REMOVE (1 << 30) uint16_t tid; SLIST_HEAD(, mpssas_lun) luns; TAILQ_HEAD(, mps_command) commands; @@ -78,6 +77,8 @@ struct mpssas_target { unsigned int aborts; unsigned int logical_unit_resets; unsigned int target_resets; + uint8_t stop_at_shutdown; + uint8_t supports_SSU; }; struct mpssas_softc { @@ -95,11 +96,9 @@ struct mpssas_softc { struct cam_path *path; struct intr_config_hook sas_ich; struct callout discovery_callout; - u_int discovery_timeouts; struct mps_event_handle *mpssas_eh; u_int startup_refcount; - u_int tm_count; struct proc *sysctl_proc; struct taskqueue *ev_tq; @@ -167,6 +166,8 @@ do { \ void mpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ); void mpssas_discovery_end(struct mpssas_softc *sassc); +void mpssas_prepare_for_tm(struct mps_softc *sc, struct mps_command *tm, + struct mpssas_target *target, lun_id_t lun_id); void mpssas_startup_increment(struct mpssas_softc *sassc); void mpssas_startup_decrement(struct mpssas_softc *sassc); diff --git a/sys/dev/mps/mps_sas_lsi.c b/sys/dev/mps/mps_sas_lsi.c index 5836329..434663a 100644 --- a/sys/dev/mps/mps_sas_lsi.c +++ b/sys/dev/mps/mps_sas_lsi.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,13 +24,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for Avago Technologies (LSI) MPT2 */ /* TODO Move headers to mpsvar */ #include <sys/types.h> @@ -105,7 +106,9 @@ struct _ata_identify_device_data { u16 serial_number[10]; /* 10-19 */ u16 reserved2[7]; /* 20-26 */ u16 model_number[20]; /* 27-46*/ - u16 reserved3[209]; /* 47-255*/ + u16 reserved3[170]; /* 47-216 */ + u16 rotational_speed; /* 217 */ + u16 reserved4[38]; /* 218-255 */ }; static u32 event_count; static void mpssas_fw_work(struct mps_softc *sc, @@ -116,8 +119,9 @@ static int mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate); static int mpssas_get_sata_identify(struct mps_softc *sc, u16 handle, Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo); +static void mpssas_ata_id_timeout(void *data); int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc, - u64 *sas_address, u16 handle, u32 device_info); + u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); static int mpssas_volume_add(struct mps_softc *sc, u16 handle); static void mpssas_SSU_to_SATA_devices(struct mps_softc *sc); @@ -606,14 +610,14 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ struct mpssas_target *targ; Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t config_page; - uint64_t sas_address, sata_sas_address; + uint64_t sas_address; uint64_t parent_sas_address = 0; - u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); u32 device_info, parent_devinfo = 0; unsigned int id; - int ret; - int error = 0; + int ret = 1, error = 0, i; struct mpssas_lun *lun; + u8 is_SATA_SSD = 0; + struct mps_command *cm; sassc = sc->sassc; mpssas_startup_increment(sassc); @@ -645,26 +649,27 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ } /* TODO Check proper endianess */ sas_address = config_page.SASAddress.High; - sas_address = (sas_address << 32) | - config_page.SASAddress.Low; - - if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) - == MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { - if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { - ret = mpssas_get_sas_address_for_sata_disk(sc, - &sata_sas_address, handle, device_info); - if (!ret) - id = mps_mapping_get_sas_id(sc, - sata_sas_address, handle); - else - id = mps_mapping_get_sas_id(sc, - sas_address, handle); - } else - id = mps_mapping_get_sas_id(sc, sas_address, - handle); - } else - id = mps_mapping_get_sas_id(sc, sas_address, handle); + sas_address = (sas_address << 32) | config_page.SASAddress.Low; + /* + * Always get SATA Identify information because this is used to + * determine if Start/Stop Unit should be sent to the drive when the + * system is shutdown. + */ + if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { + ret = mpssas_get_sas_address_for_sata_disk(sc, &sas_address, + handle, device_info, &is_SATA_SSD); + if (ret) { + mps_dprint(sc, MPS_INFO, "%s: failed to get disk type " + "(SSD or HDD) for SATA device with handle 0x%04x\n", + __func__, handle); + } else { + mps_dprint(sc, MPS_INFO, "SAS Address from SATA " + "device = %jx\n", sas_address); + } + } + + id = mps_mapping_get_sas_id(sc, sas_address, handle); if (id == MPS_MAP_BAD_ID) { printf("failure at %s:%d/%s()! Could not get ID for device " "with handle 0x%04x\n", __FILE__, __LINE__, __func__, @@ -696,6 +701,9 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ targ->tid = id; targ->linkrate = (linkrate>>4); targ->flags = 0; + if (is_SATA_SSD) { + targ->flags = MPS_TARGET_IS_SATA_SSD; + } TAILQ_INIT(&targ->commands); TAILQ_INIT(&targ->timedout_commands); while(!SLIST_EMPTY(&targ->luns)) { @@ -706,8 +714,8 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ SLIST_INIT(&targ->luns); mps_describe_devinfo(targ->devinfo, devstring, 80); - mps_dprint(sc, MPS_MAPPING, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring, - mps_describe_table(mps_linkrate_names, targ->linkrate), + mps_dprint(sc, MPS_MAPPING, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", + devstring, mps_describe_table(mps_linkrate_names, targ->linkrate), targ->handle, targ->encl_handle, targ->encl_slot); #if __FreeBSD_version < 1000039 @@ -715,7 +723,50 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ #endif mpssas_rescan_target(sc, targ); mps_dprint(sc, MPS_MAPPING, "Target id 0x%x added\n", targ->tid); + + /* + * Check all commands to see if the SATA_ID_TIMEOUT flag has been set. + * If so, send a Target Reset TM to the target that was just created. + * An Abort Task TM should be used instead of a Target Reset, but that + * would be much more difficult because targets have not been fully + * discovered yet, and LUN's haven't been setup. So, just reset the + * target instead of the LUN. + */ + for (i = 1; i < sc->num_reqs; i++) { + cm = &sc->commands[i]; + if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) { + targ->timeouts++; + cm->cm_state = MPS_CM_STATE_TIMEDOUT; + + if ((targ->tm = mpssas_alloc_tm(sc)) != NULL) { + mps_dprint(sc, MPS_INFO, "%s: sending Target " + "Reset for stuck SATA identify command " + "(cm = %p)\n", __func__, cm); + targ->tm->cm_targ = targ; + mpssas_send_reset(sc, targ->tm, + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); + } else { + mps_dprint(sc, MPS_ERROR, "Failed to allocate " + "tm for Target Reset after SATA ID command " + "timed out (cm %p)\n", cm); + } + /* + * No need to check for more since the target is + * already being reset. + */ + break; + } + } out: + /* + * Free the commands that may not have been freed from the SATA ID call + */ + for (i = 1; i < sc->num_reqs; i++) { + cm = &sc->commands[i]; + if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) { + mps_free_command(sc, cm); + } + } mpssas_startup_decrement(sassc); return (error); @@ -723,7 +774,7 @@ out: int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc, - u64 *sas_address, u16 handle, u32 device_info) + u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD) { Mpi2SataPassthroughReply_t mpi_reply; int i, rc, try_count; @@ -743,16 +794,25 @@ mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc, ioc_status = le16toh(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; sas_status = mpi_reply.SASStatus; - } while ((rc == -EAGAIN || ioc_status || sas_status) && + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + if (sc->spinup_wait_time > 0) { + mps_dprint(sc, MPS_INFO, "Sleeping %d seconds " + "after SATA ID error to wait for spinup\n", + sc->spinup_wait_time); + msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0, + "mpsid", sc->spinup_wait_time * hz); + } + } + } while (((rc && (rc != EWOULDBLOCK)) || ioc_status || sas_status) && (try_count < 5)); if (rc == 0 && !ioc_status && !sas_status) { - mps_dprint(sc, MPS_MAPPING, "%s: got SATA identify successfully " - "for handle = 0x%x with try_count = %d\n", - __func__, handle, try_count); + mps_dprint(sc, MPS_MAPPING, "%s: got SATA identify " + "successfully for handle = 0x%x with try_count = %d\n", + __func__, handle, try_count); } else { mps_dprint(sc, MPS_MAPPING, "%s: handle = 0x%x failed\n", - __func__, handle); + __func__, handle); return -1; } /* Copy & byteswap the 40 byte model number to a buffer */ @@ -763,9 +823,9 @@ mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc, /* Copy & byteswap the 20 byte serial number to a buffer */ for (i = 0; i < MPT2SAS_SN_LEN; i += 2) { buffer[MPT2SAS_MN_LEN + i] = - ((u8 *)ata_identify.serial_number)[i + 1]; + ((u8 *)ata_identify.serial_number)[i + 1]; buffer[MPT2SAS_MN_LEN + i + 1] = - ((u8 *)ata_identify.serial_number)[i]; + ((u8 *)ata_identify.serial_number)[i]; } bufferptr = (u32 *)buffer; /* There are 60 bytes to hash down to 8. 60 isn't divisible by 8, @@ -792,6 +852,10 @@ mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc, (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 | (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] << 8 | (u64)hash_address.wwid[7]; + if (ata_identify.rotational_speed == 1) { + *is_SATA_SSD = 1; + } + return 0; } @@ -831,7 +895,22 @@ mpssas_get_sata_identify(struct mps_softc *sc, u16 handle, cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = buffer; cm->cm_length = htole32(sz); - error = mps_wait_command(sc, cm, 60, CAN_SLEEP); + + /* + * Start a timeout counter specifically for the SATA ID command. This + * is used to fix a problem where the FW does not send a reply sometimes + * when a bad disk is in the topology. So, this is used to timeout the + * command so that processing can continue normally. + */ + mps_dprint(sc, MPS_XINFO, "%s start timeout counter for SATA ID " + "command\n", __func__); + callout_reset(&cm->cm_callout, MPS_ATA_ID_TIMEOUT * hz, + mpssas_ata_id_timeout, cm); + error = mps_wait_command(sc, cm, 60, CAN_SLEEP); + mps_dprint(sc, MPS_XINFO, "%s stop timeout counter for SATA ID " + "command\n", __func__); + callout_stop(&cm->cm_callout); + reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ @@ -854,11 +933,66 @@ mpssas_get_sata_identify(struct mps_softc *sc, u16 handle, goto out; } out: - mps_free_command(sc, cm); - free(buffer, M_MPT2); + /* + * If the SATA_ID_TIMEOUT flag has been set for this command, don't free + * it. The command will be freed after sending a target reset TM. If + * the command did timeout, use EWOULDBLOCK. + */ + if ((cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) == 0) + mps_free_command(sc, cm); + else if (error == 0) + error = EWOULDBLOCK; + free(buffer, M_MPT2); return (error); } +static void +mpssas_ata_id_timeout(void *data) +{ + struct mps_softc *sc; + struct mps_command *cm; + + cm = (struct mps_command *)data; + sc = cm->cm_sc; + mtx_assert(&sc->mps_mtx, MA_OWNED); + + mps_dprint(sc, MPS_INFO, "%s checking ATA ID command %p sc %p\n", + __func__, cm, sc); + if ((callout_pending(&cm->cm_callout)) || + (!callout_active(&cm->cm_callout))) { + mps_dprint(sc, MPS_INFO, "%s ATA ID command almost timed out\n", + __func__); + return; + } + callout_deactivate(&cm->cm_callout); + + /* + * Run the interrupt handler to make sure it's not pending. This + * isn't perfect because the command could have already completed + * and been re-used, though this is unlikely. + */ + mps_intr_locked(sc); + if (cm->cm_state == MPS_CM_STATE_FREE) { + mps_dprint(sc, MPS_INFO, "%s ATA ID command almost timed out\n", + __func__); + return; + } + + mps_dprint(sc, MPS_INFO, "ATA ID command timeout cm %p\n", cm); + + /* + * Send wakeup() to the sleeping thread that issued this ATA ID command. + * wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), and this + * will keep reinit() from being called. This way, an Abort Task TM can + * be issued so that the timed out command can be cleared. The Abort + * Task cannot be sent from here because the driver has not completed + * setting up targets. Instead, the command is flagged so that special + * handling will be used to send the abort. + */ + cm->cm_flags |= MPS_CM_FLAGS_SATA_ID_TIMEOUT; + wakeup(cm); +} + static int mpssas_volume_add(struct mps_softc *sc, u16 handle) { @@ -931,13 +1065,11 @@ mpssas_SSU_to_SATA_devices(struct mps_softc *sc) path_id_t pathid = cam_sim_path(sassc->sim); target_id_t targetid; struct mpssas_target *target; - struct mpssas_lun *lun; char path_str[64]; struct timeval cur_time, start_time; /* - * For each LUN of each target, issue a StartStopUnit command to stop - * the device. + * For each target, issue a StartStopUnit command to stop the device. */ sc->SSU_started = TRUE; sc->SSU_refcount = 0; @@ -947,63 +1079,58 @@ mpssas_SSU_to_SATA_devices(struct mps_softc *sc) continue; } - SLIST_FOREACH(lun, &target->luns, lun_link) { - ccb = xpt_alloc_ccb_nowait(); - if (ccb == NULL) { - mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB " - "to stop unit.\n"); + ccb = xpt_alloc_ccb_nowait(); + if (ccb == NULL) { + mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB to stop " + "unit.\n"); + return; + } + + /* + * The stop_at_shutdown flag will be set if this device is + * a SATA direct-access end device. + */ + if (target->stop_at_shutdown) { + if (xpt_create_path(&ccb->ccb_h.path, + xpt_periph, pathid, targetid, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + mps_dprint(sc, MPS_FAULT, "Unable to create " + "LUN path to stop unit.\n"); + xpt_free_ccb(ccb); return; } + xpt_path_string(ccb->ccb_h.path, path_str, + sizeof(path_str)); + mps_dprint(sc, MPS_INFO, "Sending StopUnit: path %s " + "handle %d\n", path_str, target->handle); + /* - * The stop_at_shutdown flag will be set if this LUN is - * a SATA direct-access end device. + * Issue a START STOP UNIT command for the target. + * Increment the SSU counter to be used to count the + * number of required replies. */ - if (lun->stop_at_shutdown) { - if (xpt_create_path(&ccb->ccb_h.path, - xpt_periph, pathid, targetid, - lun->lun_id) != CAM_REQ_CMP) { - mps_dprint(sc, MPS_FAULT, "Unable to " - "create LUN path to stop unit.\n"); - xpt_free_ccb(ccb); - return; - } - xpt_path_string(ccb->ccb_h.path, path_str, - sizeof(path_str)); - - mps_dprint(sc, MPS_INFO, "Sending StopUnit: " - "path %s handle %d\n", path_str, - target->handle); - - /* - * Issue a START STOP UNIT command for the LUN. - * Increment the SSU counter to be used to - * count the number of required replies. - */ - mps_dprint(sc, MPS_INFO, "Incrementing SSU " - "count\n"); - sc->SSU_refcount++; - ccb->ccb_h.target_id = - xpt_path_target_id(ccb->ccb_h.path); - ccb->ccb_h.target_lun = lun->lun_id; - ccb->ccb_h.ppriv_ptr1 = sassc; - scsi_start_stop(&ccb->csio, - /*retries*/0, - mpssas_stop_unit_done, - MSG_SIMPLE_Q_TAG, - /*start*/FALSE, - /*load/eject*/0, - /*immediate*/FALSE, - MPS_SENSE_LEN, - /*timeout*/10000); - xpt_action(ccb); - } + mps_dprint(sc, MPS_INFO, "Incrementing SSU count\n"); + sc->SSU_refcount++; + ccb->ccb_h.target_id = + xpt_path_target_id(ccb->ccb_h.path); + ccb->ccb_h.ppriv_ptr1 = sassc; + scsi_start_stop(&ccb->csio, + /*retries*/0, + mpssas_stop_unit_done, + MSG_SIMPLE_Q_TAG, + /*start*/FALSE, + /*load/eject*/0, + /*immediate*/FALSE, + MPS_SENSE_LEN, + /*timeout*/10000); + xpt_action(ccb); } } /* * Wait until all of the SSU commands have completed or time has - * expired (60 seconds). pause for 100ms each time through. If any + * expired (60 seconds). Pause for 100ms each time through. If any * command times out, the target will be reset in the SCSI command * timeout routine. */ @@ -1063,6 +1190,8 @@ mpssas_ir_shutdown(struct mps_softc *sc) unsigned int id, found_volume = 0; struct mps_command *cm; Mpi2RaidActionRequest_t *action; + target_id_t targetid; + struct mpssas_target *target; mps_dprint(sc, MPS_TRACE, "%s\n", __func__); @@ -1105,7 +1234,7 @@ mpssas_ir_shutdown(struct mps_softc *sc) action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; mps_lock(sc); - mps_wait_command(sc, cm, 5, CAN_SLEEP); + mps_wait_command(sc, cm, 5, CAN_SLEEP); mps_unlock(sc); /* @@ -1115,5 +1244,47 @@ mpssas_ir_shutdown(struct mps_softc *sc) mps_free_command(sc, cm); out: + /* + * All of the targets must have the correct value set for + * 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable. + * + * The possible values for the 'enable_ssu' variable are: + * 0: disable to SSD and HDD + * 1: disable only to HDD (default) + * 2: disable only to SSD + * 3: enable to SSD and HDD + * anything else will default to 1. + */ + for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) { + target = &sc->sassc->targets[targetid]; + if (target->handle == 0x0) { + continue; + } + + if (target->supports_SSU) { + switch (sc->enable_ssu) { + case MPS_SSU_DISABLE_SSD_DISABLE_HDD: + target->stop_at_shutdown = FALSE; + break; + case MPS_SSU_DISABLE_SSD_ENABLE_HDD: + target->stop_at_shutdown = TRUE; + if (target->flags & MPS_TARGET_IS_SATA_SSD) { + target->stop_at_shutdown = FALSE; + } + break; + case MPS_SSU_ENABLE_SSD_ENABLE_HDD: + target->stop_at_shutdown = TRUE; + break; + case MPS_SSU_ENABLE_SSD_DISABLE_HDD: + default: + target->stop_at_shutdown = TRUE; + if ((target->flags & + MPS_TARGET_IS_SATA_SSD) == 0) { + target->stop_at_shutdown = FALSE; + } + break; + } + } + } mpssas_SSU_to_SATA_devices(sc); } diff --git a/sys/dev/mps/mps_user.c b/sys/dev/mps/mps_user.c index 63f78b6..71a3b9b 100644 --- a/sys/dev/mps/mps_user.c +++ b/sys/dev/mps/mps_user.c @@ -27,10 +27,11 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD userland interface + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface */ /*- - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,7 +55,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -90,6 +91,7 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> #include <cam/cam.h> +#include <cam/cam_ccb.h> #include <cam/scsi/scsi_all.h> #include <dev/mps/mpi/mpi2_type.h> @@ -101,6 +103,7 @@ __FBSDID("$FreeBSD$"); #include <dev/mps/mps_ioctl.h> #include <dev/mps/mpsvar.h> #include <dev/mps/mps_table.h> +#include <dev/mps/mps_sas.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> @@ -700,7 +703,7 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd) mps_printf(sc, "Cannot allocate memory %s %d\n", __func__, __LINE__); return (ENOMEM); - } + } cm->cm_data = buf; cm->cm_length = cmd->len; } else { @@ -767,6 +770,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data) int err = 0, dir = 0, sz; uint8_t function = 0; u_int sense_len; + struct mpssas_target *targ = NULL; /* * Only allow one passthru command at a time. Use the MPS_FLAGS_BUSY @@ -848,11 +852,22 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data) task->TaskMID = cm->cm_desc.Default.SMID; cm->cm_data = NULL; - cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; + cm->cm_desc.HighPriority.RequestFlags = + MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = NULL; cm->cm_complete_data = NULL; - err = mps_wait_command(sc, cm, 30, CAN_SLEEP); + targ = mpssas_find_target_by_handle(sc->sassc, 0, + task->DevHandle); + if (targ == NULL) { + mps_dprint(sc, MPS_INFO, + "%s %d : invalid handle for requested TM 0x%x \n", + __func__, __LINE__, task->DevHandle); + err = 1; + } else { + mpssas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + err = mps_wait_command(sc, cm, 30, CAN_SLEEP); + } if (err != 0) { err = EIO; diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h index bae023e..0a82034 100644 --- a/sys/dev/mps/mpsvar.h +++ b/sys/dev/mps/mpsvar.h @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011, 2012 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * LSI MPT-Fusion Host Adapter FreeBSD + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ @@ -32,7 +33,7 @@ #ifndef _MPSVAR_H #define _MPSVAR_H -#define MPS_DRIVER_VERSION "19.00.00.00-fbsd" +#define MPS_DRIVER_VERSION "20.00.00.00-fbsd" #define MPS_DB_MAX_WAIT 2500 @@ -50,10 +51,13 @@ #define NO_SLEEP 0 #define MPS_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */ +#define MPS_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */ #define MPS_SCSI_RI_INVALID_FRAME (0x00000002) #define MPS_STRING_LENGTH 64 +#define DEFAULT_SPINUP_WAIT 3 /* seconds to wait for spinup */ + #include <sys/endian.h> /* @@ -232,6 +236,7 @@ struct mps_command { #define MPS_CM_FLAGS_CHAIN_FAILED (1 << 9) #define MPS_CM_FLAGS_ERROR_MASK MPS_CM_FLAGS_CHAIN_FAILED #define MPS_CM_FLAGS_USE_CCB (1 << 10) +#define MPS_CM_FLAGS_SATA_ID_TIMEOUT (1 << 11) u_int cm_state; #define MPS_CM_STATE_FREE 0 #define MPS_CM_STATE_BUSY 1 @@ -276,6 +281,8 @@ struct mps_softc { int chain_free; int max_chains; int chain_free_lowwater; + u_int enable_ssu; + int spinup_wait_time; #if __FreeBSD_version >= 900030 uint64_t chain_alloc_fail; #endif @@ -599,6 +606,11 @@ mps_unlock(struct mps_softc *sc) #define MPS_MAPPING (1 << 9) /* Trace device mappings */ #define MPS_TRACE (1 << 10) /* Function-by-function trace */ +#define MPS_SSU_DISABLE_SSD_DISABLE_HDD 0 +#define MPS_SSU_ENABLE_SSD_DISABLE_HDD 1 +#define MPS_SSU_DISABLE_SSD_ENABLE_HDD 2 +#define MPS_SSU_ENABLE_SSD_ENABLE_HDD 3 + #define mps_printf(sc, args...) \ device_printf((sc)->mps_dev, ##args) @@ -764,6 +776,8 @@ void mpssas_realloc_targets(struct mps_softc *sc, int maxtargets); struct mps_command * mpssas_alloc_tm(struct mps_softc *sc); void mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm); void mpssas_release_simq_reinit(struct mpssas_softc *sassc); +int mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, + uint8_t type); SYSCTL_DECL(_hw_mps); |