From 2ca937d2ad2b7713580fd26fcc5ec72006142ee7 Mon Sep 17 00:00:00 2001 From: Stephen McConnell Date: Wed, 27 May 2015 20:37:34 +0000 Subject: [PATCH] This setting of stop_at_shutdown should have been removed with r279253 Approved by: ken MFC after: 1 week --- sys/dev/mpr/mpi/mpi2.h | 8 +- sys/dev/mpr/mpi/mpi2_cnfg.h | 8 +- sys/dev/mpr/mpi/mpi2_hbd.h | 8 +- sys/dev/mpr/mpi/mpi2_history.txt | 8 +- sys/dev/mpr/mpi/mpi2_init.h | 8 +- sys/dev/mpr/mpi/mpi2_ioc.h | 8 +- sys/dev/mpr/mpi/mpi2_ra.h | 8 +- sys/dev/mpr/mpi/mpi2_raid.h | 8 +- sys/dev/mpr/mpi/mpi2_sas.h | 8 +- sys/dev/mpr/mpi/mpi2_targ.h | 8 +- sys/dev/mpr/mpi/mpi2_tool.h | 8 +- sys/dev/mpr/mpi/mpi2_type.h | 8 +- sys/dev/mpr/mpr.c | 90 +++--- sys/dev/mpr/mpr_config.c | 5 +- sys/dev/mpr/mpr_ioctl.h | 7 +- sys/dev/mpr/mpr_mapping.c | 72 +++-- sys/dev/mpr/mpr_mapping.h | 10 +- sys/dev/mpr/mpr_pci.c | 14 +- sys/dev/mpr/mpr_sas.c | 476 +++++++++++++++++-------------- sys/dev/mpr/mpr_sas.h | 31 +- sys/dev/mpr/mpr_sas_lsi.c | 360 ++++++++++++++++------- sys/dev/mpr/mpr_user.c | 41 ++- sys/dev/mpr/mprvar.h | 38 ++- 23 files changed, 767 insertions(+), 473 deletions(-) diff --git a/sys/dev/mpr/mpi/mpi2.h b/sys/dev/mpr/mpi/mpi2.h index 10f17aba067e..42fdec20c503 100644 --- a/sys/dev/mpr/mpi/mpi2.h +++ b/sys/dev/mpr/mpi/mpi2.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,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-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2.h diff --git a/sys/dev/mpr/mpi/mpi2_cnfg.h b/sys/dev/mpr/mpi/mpi2_cnfg.h index d82750f80913..3b0eb637a9e2 100644 --- a/sys/dev/mpr/mpi/mpi2_cnfg.h +++ b/sys/dev/mpr/mpi/mpi2_cnfg.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,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-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_cnfg.h diff --git a/sys/dev/mpr/mpi/mpi2_hbd.h b/sys/dev/mpr/mpi/mpi2_hbd.h index d0cc09f905a0..520407b39948 100644 --- a/sys/dev/mpr/mpi/mpi2_hbd.h +++ b/sys/dev/mpr/mpi/mpi2_hbd.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,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-2011 LSI Corporation. + * Copyright (c) 2009-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_hbd.h diff --git a/sys/dev/mpr/mpi/mpi2_history.txt b/sys/dev/mpr/mpi/mpi2_history.txt index 296b75b87859..9fca7966f65a 100644 --- a/sys/dev/mpr/mpi/mpi2_history.txt +++ b/sys/dev/mpr/mpi/mpi2_history.txt @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,7 +27,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,8 @@ Fusion-MPT MPI 2.0 / 2.5 Header File Change History ============================== - Copyright (c) 2000-2013 LSI Corporation. + Copyright (c) 2000-2015 LSI Corporation. + Copyright (c) 2013-2015 Avago Technologies --------------------------------------- Header Set Release Version: 02.00.33 diff --git a/sys/dev/mpr/mpi/mpi2_init.h b/sys/dev/mpr/mpi/mpi2_init.h index 62b0cfed120a..5f475c0e26ba 100644 --- a/sys/dev/mpr/mpi/mpi2_init.h +++ b/sys/dev/mpr/mpi/mpi2_init.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,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-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_init.h diff --git a/sys/dev/mpr/mpi/mpi2_ioc.h b/sys/dev/mpr/mpi/mpi2_ioc.h index 38a46f5280bc..54f39a5adc71 100644 --- a/sys/dev/mpr/mpi/mpi2_ioc.h +++ b/sys/dev/mpr/mpi/mpi2_ioc.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,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-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_ioc.h diff --git a/sys/dev/mpr/mpi/mpi2_ra.h b/sys/dev/mpr/mpi/mpi2_ra.h index 76db06b71b98..02304aaa002e 100644 --- a/sys/dev/mpr/mpi/mpi2_ra.h +++ b/sys/dev/mpr/mpi/mpi2_ra.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,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 LSI Corporation. + * Copyright (c) 2012-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_ra.h diff --git a/sys/dev/mpr/mpi/mpi2_raid.h b/sys/dev/mpr/mpi/mpi2_raid.h index c6bb59864a3c..52ebf07ee096 100644 --- a/sys/dev/mpr/mpi/mpi2_raid.h +++ b/sys/dev/mpr/mpi/mpi2_raid.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,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-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_raid.h diff --git a/sys/dev/mpr/mpi/mpi2_sas.h b/sys/dev/mpr/mpi/mpi2_sas.h index 2a107f1e1617..7cae2c3d4adf 100644 --- a/sys/dev/mpr/mpi/mpi2_sas.h +++ b/sys/dev/mpr/mpi/mpi2_sas.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,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-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_sas.h diff --git a/sys/dev/mpr/mpi/mpi2_targ.h b/sys/dev/mpr/mpi/mpi2_targ.h index 506e64f6370c..85b5ac562610 100644 --- a/sys/dev/mpr/mpi/mpi2_targ.h +++ b/sys/dev/mpr/mpi/mpi2_targ.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,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) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_targ.h diff --git a/sys/dev/mpr/mpi/mpi2_tool.h b/sys/dev/mpr/mpi/mpi2_tool.h index 94542cc7959b..59917c0077f5 100644 --- a/sys/dev/mpr/mpi/mpi2_tool.h +++ b/sys/dev/mpr/mpi/mpi2_tool.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,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-2013 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_tool.h diff --git a/sys/dev/mpr/mpi/mpi2_type.h b/sys/dev/mpr/mpi/mpi2_type.h index da3aefb968f4..b063683263d0 100644 --- a/sys/dev/mpr/mpi/mpi2_type.h +++ b/sys/dev/mpr/mpi/mpi2_type.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2013 LSI Corp. + * Copyright (c) 2012-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,13 +27,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-2007 LSI Corporation. + * Copyright (c) 2000-2015 LSI Corporation. + * Copyright (c) 2013-2015 Avago Technologies * * * Name: mpi2_type.h diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index d3fb9a0682b8..07e73c54e8be 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2012-2014 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,12 +25,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * */ #include __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ #include @@ -72,7 +75,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include static int mpr_diag_reset(struct mpr_softc *sc, int sleep_flag); static int mpr_init_queues(struct mpr_softc *sc); @@ -352,11 +354,9 @@ mpr_transition_operational(struct mpr_softc *sc) static int mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) { - int error, i; + int error; Mpi2IOCFactsReply_t saved_facts; uint8_t saved_mode, reallocating; - struct mprsas_lun *lun, *lun_tmp; - struct mprsas_target *targ; mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); @@ -513,27 +513,7 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) */ if (reallocating) { mpr_iocfacts_free(sc); - - /* - * The number of targets is based on IOC Facts, so free all of - * the allocated LUNs for each target and then the target buffer - * itself. - */ - for (i=0; i< saved_facts.MaxTargets; i++) { - targ = &sc->sassc->targets[i]; - SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, - lun_tmp) { - free(lun, M_MPR); - } - } - free(sc->sassc->targets, M_MPR); - - sc->sassc->targets = malloc(sizeof(struct mprsas_target) * - sc->facts->MaxTargets, M_MPR, M_WAITOK|M_ZERO); - if (!sc->sassc->targets) { - panic("%s failed to alloc targets with error %d\n", - __func__, ENOMEM); - } + mprsas_realloc_targets(sc, saved_facts.MaxTargets); } /* @@ -775,7 +755,7 @@ mpr_reinit(struct mpr_softc *sc) /* the end of discovery will release the simq, so we're done. */ mpr_dprint(sc, MPR_INFO, "%s finished sc %p post %u free %u\n", __func__, sc, sc->replypostindex, sc->replyfreeindex); - mprsas_release_simq_reinit(sassc); + mprsas_release_simq_reinit(sassc); return 0; } @@ -816,7 +796,8 @@ mpr_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag) * 0.5 milisecond */ if (mtx_owned(&sc->mpr_mtx) && sleep_flag == CAN_SLEEP) - msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba", hz/1000); + msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba", + hz/1000); else if (sleep_flag == CAN_SLEEP) pause("mprdba", hz/1000); else @@ -982,7 +963,7 @@ mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm) reply_descriptor rd; MPR_FUNCTRACE(sc); - mpr_dprint(sc, MPR_TRACE, "%s SMID %u cm %p ccb %p\n", __func__, + mpr_dprint(sc, MPR_TRACE, "SMID %u cm %p ccb %p\n", cm->cm_desc.Default.SMID, cm, cm->cm_ccb); if (sc->mpr_flags & MPR_FLAGS_ATTACH_DONE && !(sc->mpr_flags & @@ -1372,6 +1353,8 @@ mpr_get_tunables(struct mpr_softc *sc) sc->disable_msix = 0; sc->disable_msi = 0; sc->max_chains = MPR_CHAIN_FRAMES; + sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD; + sc->spinup_wait_time = DEFAULT_SPINUP_WAIT; /* * Grab the global variables. @@ -1380,6 +1363,8 @@ mpr_get_tunables(struct mpr_softc *sc) TUNABLE_INT_FETCH("hw.mpr.disable_msix", &sc->disable_msix); TUNABLE_INT_FETCH("hw.mpr.disable_msi", &sc->disable_msi); TUNABLE_INT_FETCH("hw.mpr.max_chains", &sc->max_chains); + TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu); + TUNABLE_INT_FETCH("hw.mpr.spinup_wait_time", &sc->spinup_wait_time); /* Grab the unit-instance variables */ snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level", @@ -1402,6 +1387,14 @@ mpr_get_tunables(struct mpr_softc *sc) snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.exclude_ids", device_get_unit(sc->mpr_dev)); TUNABLE_STR_FETCH(tmpstr, sc->exclude_ids, sizeof(sc->exclude_ids)); + + snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.enable_ssu", + device_get_unit(sc->mpr_dev)); + TUNABLE_INT_FETCH(tmpstr, &sc->enable_ssu); + + snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.spinup_wait_time", + device_get_unit(sc->mpr_dev)); + TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time); } static void @@ -1474,11 +1467,20 @@ mpr_setup_sysctl(struct mpr_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 @@ -2096,7 +2098,7 @@ mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle, (reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) error = ENXIO; - if(reply) + if (reply) mpr_print_event(sc, reply); mpr_dprint(sc, MPR_TRACE, "%s finished error %d\n", __func__, error); @@ -2163,8 +2165,8 @@ mpr_deregister_events(struct mpr_softc *sc, struct mpr_event_handle *handle) * Add a chain element as the next SGE for the specified command. * Reset cm_sge and cm_sgesize to indicate all the available space. Chains are * only required for IEEE commands. Therefore there is no code for commands - * that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands shouldn't - * be requesting chains). + * that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands + * shouldn't be requesting chains). */ static int mpr_add_chain(struct mpr_command *cm, int segsleft) @@ -2246,9 +2248,9 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) /* * Add one scatter-gather element to the scatter-gather list for a command. - * Maintain cm_sglsize and cm_sge as the remaining size and pointer to the next - * SGE to fill in, respectively. In Gen3, the MPI SGL does not have a chain, - * so don't consider any chain additions. + * Maintain cm_sglsize and cm_sge as the remaining size and pointer to the + * next SGE to fill in, respectively. In Gen3, the MPI SGL does not have a + * chain, so don't consider any chain additions. */ int mpr_push_sge(struct mpr_command *cm, MPI2_SGE_SIMPLE64 *sge, size_t len, @@ -2660,7 +2662,7 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm) } } - if(error) { + if (error) { mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s\n", __func__); rc = mpr_reinit(sc); mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? @@ -2717,9 +2719,12 @@ mpr_read_config_page(struct mpr_softc *sc, struct mpr_config_params *params) cm->cm_data = params->buffer; cm->cm_length = params->length; - cm->cm_sge = &req->PageBufferSGE; - cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); - cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; + if (cm->cm_data != NULL) { + cm->cm_sge = &req->PageBufferSGE; + cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); + cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN; + } else + cm->cm_sge = NULL; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_complete_data = params; @@ -2776,9 +2781,12 @@ mpr_config_complete(struct mpr_softc *sc, struct mpr_command *cm) goto done; } params->status = reply->IOCStatus; - if (params->hdr.Ext.ExtPageType != 0) { + if (params->hdr.Struct.PageType == MPI2_CONFIG_PAGETYPE_EXTENDED) { params->hdr.Ext.ExtPageType = reply->ExtPageType; params->hdr.Ext.ExtPageLength = reply->ExtPageLength; + params->hdr.Ext.PageType = reply->Header.PageType; + params->hdr.Ext.PageNumber = reply->Header.PageNumber; + params->hdr.Ext.PageVersion = reply->Header.PageVersion; } else { params->hdr.Struct.PageType = reply->Header.PageType; params->hdr.Struct.PageNumber = reply->Header.PageNumber; diff --git a/sys/dev/mpr/mpr_config.c b/sys/dev/mpr/mpr_config.c index 125451608dee..c0ea3d5ffb08 100644 --- a/sys/dev/mpr/mpr_config.c +++ b/sys/dev/mpr/mpr_config.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 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 diff --git a/sys/dev/mpr/mpr_ioctl.h b/sys/dev/mpr/mpr_ioctl.h index 5ec482f311b0..aa1a4cbf7697 100644 --- a/sys/dev/mpr/mpr_ioctl.h +++ b/sys/dev/mpr/mpr_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-2014 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/mpr/mpr_mapping.c b/sys/dev/mpr/mpr_mapping.c index 7f0fc00a9c52..110e6a3b943f 100644 --- a/sys/dev/mpr/mpr_mapping.c +++ b/sys/dev/mpr/mpr_mapping.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 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 @@ -326,11 +327,13 @@ _mapping_get_high_missing_mt_idx(struct mpr_softc *sc) { u32 map_idx, high_idx = MPR_ENCTABLE_BAD_IDX; u8 high_missing_count = 0; - u32 start_idx, end_idx, start_idx_ir = 0, end_idx_ir; + u32 start_idx, end_idx, start_idx_ir, end_idx_ir; struct dev_mapping_table *mt_entry; u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); start_idx = 0; + start_idx_ir = 0; + end_idx_ir = 0; end_idx = sc->max_devices; if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) start_idx = 1; @@ -887,14 +890,14 @@ _mapping_get_dev_info(struct mpr_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]; @@ -908,41 +911,36 @@ _mapping_get_dev_info(struct mpr_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 = mprsas_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; - } + 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 = mprsas_get_sas_address_for_sata_disk(sc, + &sas_address, phy_change->dev_handle, device_info, + &phy_change->is_SATA_SSD); + if (rc) { + mpr_dprint(sc, MPR_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 { mpr_dprint(sc, MPR_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; } - } 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) { @@ -950,10 +948,10 @@ _mapping_get_dev_info(struct mpr_softc *sc, topo_change->enc_handle); if (enc_idx == MPR_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); + mpr_dprint(sc, MPR_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/mpr/mpr_mapping.h b/sys/dev/mpr/mpr_mapping.h index 3250c424e2a4..c00a3b795122 100644 --- a/sys/dev/mpr/mpr_mapping.h +++ b/sys/dev/mpr/mpr_mapping.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 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 mprsas_get_sas_address_for_sata_disk(struct mpr_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/mpr/mpr_pci.c b/sys/dev/mpr/mpr_pci.c index e19f33adceb4..7430eac03b3a 100644 --- a/sys/dev/mpr/mpr_pci.c +++ b/sys/dev/mpr/mpr_pci.c @@ -27,7 +27,7 @@ #include __FBSDID("$FreeBSD$"); -/* PCI/PCI-X/PCIe bus interface for the LSI MPT2 controllers */ +/* PCI/PCI-X/PCIe bus interface for the Avago Tech (LSI) MPT3 controllers */ /* TODO Move headers to mprvar */ #include @@ -99,17 +99,17 @@ struct mpr_ident { const char *desc; } mpr_identifiers[] = { { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004, - 0xffff, 0xffff, 0, "LSI SAS3004" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3004" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008, - 0xffff, 0xffff, 0, "LSI SAS3008" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3008" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1, - 0xffff, 0xffff, 0, "LSI SAS3108_1" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_1" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2, - 0xffff, 0xffff, 0, "LSI SAS3108_2" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_2" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5, - 0xffff, 0xffff, 0, "LSI SAS3108_5" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_5" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6, - 0xffff, 0xffff, 0, "LSI SAS3108_6" }, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_6" }, { 0, 0, 0, 0, 0, NULL } }; diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index 32c3a4633a1f..eac336068295 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011-2014 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,12 +24,15 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * */ #include __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ #include @@ -122,14 +126,10 @@ static void mprsas_scsiio_complete(struct mpr_softc *, struct mpr_command *); static void mprsas_action_resetdev(struct mprsas_softc *, union ccb *); static void mprsas_resetdev_complete(struct mpr_softc *, struct mpr_command *); -static int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, +static int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, struct mpr_command *cm); -static int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, - uint8_t type); static void mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg); -static void mprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, - struct ccb_getdev *cgd); #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) static void mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, @@ -142,13 +142,12 @@ static void mprsas_portenable_complete(struct mpr_softc *sc, struct mpr_command *cm); #if __FreeBSD_version >= 900026 -static void -mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm); +static void mprsas_smpio_complete(struct mpr_softc *sc, + struct mpr_command *cm); static void mprsas_send_smpcmd(struct mprsas_softc *sassc, - union ccb *ccb, uint64_t sasaddr); -static void -mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); -#endif + union ccb *ccb, uint64_t sasaddr); +static void mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); +#endif //FreeBSD_version >= 900026 struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *sassc, int start, @@ -230,7 +229,7 @@ mprsas_startup_decrement(struct mprsas_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. */ @@ -241,35 +240,31 @@ mprsas_alloc_tm(struct mpr_softc *sc) MPR_FUNCTRACE(sc); tm = mpr_alloc_high_priority_command(sc); - if (tm != NULL) { - if (sc->sassc->tm_count++ == 0) { - mpr_dprint(sc, MPR_RECOVERY, - "%s freezing simq\n", __func__); - xpt_freeze_simq(sc->sassc->sim, 1); - } - mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, - sc->sassc->tm_count); - } return tm; } void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm) { - mpr_dprint(sc, MPR_TRACE, "%s", __func__); + MPR_FUNCTRACE(sc); 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) { - mpr_dprint(sc, MPR_RECOVERY, "%s releasing simq\n", __func__); - xpt_release_simq(sc->sassc->sim, 1); + if (tm->cm_targ != NULL) { + tm->cm_targ->flags &= ~MPRSAS_TARGET_INRESET; + } + if (tm->cm_ccb) { + mpr_dprint(sc, MPR_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); } - mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, - sc->sassc->tm_count); mpr_free_high_priority_command(sc, tm); } @@ -298,8 +293,8 @@ mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ) return; } - if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, - targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, targetid, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "unable to create path for rescan\n"); xpt_free_ccb(ccb); return; @@ -473,11 +468,16 @@ mprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mprsas_remove_volume; cm->cm_complete_data = (void *)(uintptr_t)handle; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + mpr_map_command(sc, cm); } /* - * The MPT2 firmware performs debounce on the link to avoid transient link + * The MPT3 firmware performs debounce on the link to avoid transient link * errors and false removals. When it does decide that link has been lost * and a device needs to go away, it expects that the host will perform a * target reset and then an op remove. The reset has the side-effect of @@ -532,6 +532,11 @@ mprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mprsas_remove_device; cm->cm_complete_data = (void *)(uintptr_t)handle; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + mpr_map_command(sc, cm); } @@ -596,10 +601,10 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) mpr_map_command(sc, tm); - mpr_dprint(sc, MPR_XINFO, "clearing target %u handle 0x%04x\n", + mpr_dprint(sc, MPR_INFO, "clearing target %u handle 0x%04x\n", targ->tid, handle); if (targ->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " "connector name (%4s)\n", targ->encl_level, targ->encl_slot, targ->connector_name); } @@ -608,7 +613,7 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) mpr_dprint(sc, MPR_XINFO, "Completing missed command %p\n", tm); ccb = tm->cm_complete_data; - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); mprsas_scsiio_complete(sc, tm); } } @@ -726,7 +731,7 @@ mpr_attach_sas(struct mpr_softc *sc) } /* - * XXX MaxTargets could change during a reinit. since we don't + * XXX MaxTargets could change during a reinit. Since we don't * resize the targets[] array during such an event, cache the value * of MaxTargets here so that we don't get into trouble later. This * should move into the reinit logic. @@ -782,7 +787,7 @@ mpr_attach_sas(struct mpr_softc *sc) } /* - * Assume that discovery events will start right away. Freezing + * Assume that discovery events will start right away. * * Hold off boot until discovery is complete. */ @@ -790,9 +795,7 @@ mpr_attach_sas(struct mpr_softc *sc) sc->sassc->startup_refcount = 0; mprsas_startup_increment(sassc); - callout_init(&sassc->discovery_callout, 1 /*mprafe*/); - - sassc->tm_count = 0; + callout_init(&sassc->discovery_callout, 1 /*mpsafe*/); /* * Register for async events so we can determine the EEDP @@ -962,7 +965,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) sassc = cam_sim_softc(sim); MPR_FUNCTRACE(sassc->sc); - mpr_dprint(sassc->sc, MPR_TRACE, "%s func 0x%x\n", __func__, + mpr_dprint(sassc->sc, MPR_TRACE, "ccb func_code 0x%x\n", ccb->ccb_h.func_code); mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); @@ -985,7 +988,7 @@ mprsas_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); @@ -1005,7 +1008,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) */ cpi->maxio = 256 * 1024; #endif - cpi->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; } case XPT_GET_TRAN_SETTINGS: @@ -1024,7 +1027,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) cts->ccb_h.target_id)); targ = &sassc->targets[cts->ccb_h.target_id]; if (targ->handle == 0x0) { - cts->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); break; } @@ -1054,12 +1057,12 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) scsi->valid = CTS_SCSI_VALID_TQ; scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; - cts->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; } case XPT_CALC_GEOMETRY: cam_calc_geometry(&ccb->ccg, /*extended*/1); - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_RESET_DEV: mpr_dprint(sassc->sc, MPR_XINFO, @@ -1071,7 +1074,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) case XPT_TERM_IO: mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action faking success for abort or reset\n"); - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_SCSI_IO: mprsas_action_scsiio(sassc, ccb); @@ -1082,7 +1085,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) return; #endif default: - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + mprsas_set_ccbstatus(ccb, CAM_FUNC_NOTAVAIL); break; } xpt_done(ccb); @@ -1102,7 +1105,7 @@ mprsas_announce_reset(struct mpr_softc *sc, uint32_t ac_code, if (xpt_create_path(&path, NULL, path_id, target_id, lun_id) != CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "unable to create path for reset " - "notification\n"); + "notification\n"); return; } @@ -1131,8 +1134,8 @@ mprsas_complete_all_commands(struct mpr_softc *sc) if (cm->cm_complete != NULL) { mprsas_log_command(cm, MPR_RECOVERY, - "completing cm %p state %x ccb %p for diag reset\n", - cm, cm->cm_state, cm->cm_ccb); + "completing cm %p state %x ccb %p for diag " + "reset\n", cm, cm->cm_state, cm->cm_ccb); cm->cm_complete(sc, cm); completed = 1; } @@ -1145,6 +1148,14 @@ mprsas_complete_all_commands(struct mpr_softc *sc) completed = 1; } + if (cm->cm_sc->io_cmds_active != 0) { + cm->cm_sc->io_cmds_active--; + } else { + mpr_dprint(cm->cm_sc, MPR_INFO, "Warning: " + "io_cmds_active is out of sync - resynching to " + "0\n"); + } + if ((completed == 0) && (cm->cm_state != MPR_CM_STATE_FREE)) { /* this should never happen, but if it does, log */ mprsas_log_command(cm, MPR_RECOVERY, @@ -1180,9 +1191,8 @@ mprsas_handle_reinit(struct mpr_softc *sc) /* complete and cleanup after all outstanding commands */ mprsas_complete_all_commands(sc); - mpr_dprint(sc, MPR_INIT, "%s startup %u tm %u after command " - "completion\n", __func__, sc->sassc->startup_refcount, - sc->sassc->tm_count); + mpr_dprint(sc, MPR_INIT, "%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 @@ -1244,7 +1254,6 @@ mprsas_logical_unit_reset_complete(struct mpr_softc *sc, "NULL reset reply for tm %p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ - targ->flags &= ~MPRSAS_TARGET_INRESET; targ->tm = NULL; mprsas_free_tm(sc, tm); } @@ -1322,8 +1331,8 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) * task management commands don't have S/G lists. */ if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { - mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x for target reset! " - "This should not happen!\n", __func__, tm->cm_flags); + mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for target " + "reset! This should not happen!\n", __func__, tm->cm_flags); mprsas_free_tm(sc, tm); return; } @@ -1333,7 +1342,6 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) "NULL reset reply for tm %p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ - targ->flags &= ~MPRSAS_TARGET_INRESET; targ->tm = NULL; mprsas_free_tm(sc, tm); } @@ -1349,8 +1357,6 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), le32toh(reply->TerminationCount)); - targ->flags &= ~MPRSAS_TARGET_INRESET; - if (targ->outstanding == 0) { /* we've finished recovery for this target and all * of its logical units. @@ -1378,7 +1384,7 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) #define MPR_RESET_TIMEOUT 30 -static int +int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) { MPI2_SCSI_TASK_MANAGE_REQUEST *req; @@ -1387,8 +1393,8 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) target = tm->cm_targ; if (target->handle == 0) { - mpr_dprint(sc, MPR_ERROR,"%s null devhandle for target_id %d\n", - __func__, target->tid); + mpr_dprint(sc, MPR_ERROR, "%s null devhandle for target_id " + "%d\n", __func__, target->tid); return -1; } @@ -1404,6 +1410,7 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, "sending logical unit reset\n"); tm->cm_complete = mprsas_logical_unit_reset_complete; + mprsas_prepare_for_tm(sc, tm, target, tm->cm_lun); } else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { /* @@ -1412,20 +1419,20 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) */ req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; tm->cm_targ->target_resets++; - tm->cm_targ->flags |= MPRSAS_TARGET_INRESET; mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, "sending target reset\n"); tm->cm_complete = mprsas_target_reset_complete; + mprsas_prepare_for_tm(sc, tm, target, CAM_LUN_WILDCARD); } else { mpr_dprint(sc, MPR_ERROR, "unexpected reset type 0x%x\n", type); return -1; } - mpr_dprint(sc, MPR_XINFO, "to target %u handle 0x%04x\n", target->tid, + mpr_dprint(sc, MPR_INFO, "to target %u handle 0x%04x\n", target->tid, target->handle); if (target->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " "connector name (%4s)\n", target->encl_level, target->encl_slot, target->connector_name); } @@ -1441,8 +1448,7 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) err = mpr_map_command(sc, tm); if (err) mprsas_log_command(tm, MPR_RECOVERY, - "error %d sending reset type %u\n", - err, type); + "error %d sending reset type %u\n", err, type); return err; } @@ -1573,6 +1579,10 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, targ->aborts++; + mpr_dprint(sc, MPR_INFO, "Sending reset from %s for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, tm, targ, tm->cm_lun); + err = mpr_map_command(sc, tm); if (err) mprsas_log_command(tm, MPR_RECOVERY, @@ -1581,7 +1591,6 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, return err; } - static void mprsas_scsiio_timeout(void *data) { @@ -1617,11 +1626,11 @@ mprsas_scsiio_timeout(void *data) targ = cm->cm_targ; targ->timeouts++; - mprsas_log_command(cm, MPR_XINFO, "command timeout cm %p ccb %p " + mprsas_log_command(cm, MPR_ERROR, "command timeout cm %p ccb %p " "target %u, handle(0x%04x)\n", cm, cm->cm_ccb, targ->tid, targ->handle); if (targ->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_ERROR, "At enclosure level %d, slot %d, " "connector name (%4s)\n", targ->encl_level, targ->encl_slot, targ->connector_name); } @@ -1629,8 +1638,7 @@ mprsas_scsiio_timeout(void *data) /* XXX first, check the firmware state, to see if it's still * operational. if not, do a diag reset. */ - - cm->cm_ccb->ccb_h.status = CAM_CMD_TIMEOUT; + mprsas_set_ccbstatus(cm->cm_ccb, CAM_CMD_TIMEOUT); cm->cm_state = MPR_CM_STATE_TIMEDOUT; TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery); @@ -1681,19 +1689,22 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) mtx_assert(&sc->mpr_mtx, MA_OWNED); csio = &ccb->csio; + KASSERT(csio->ccb_h.target_id < sassc->maxtargets, + ("Target %d out of bounds in XPT_SCSI_IO\n", + csio->ccb_h.target_id)); targ = &sassc->targets[csio->ccb_h.target_id]; mpr_dprint(sc, MPR_TRACE, "ccb %p target flag %x\n", ccb, targ->flags); if (targ->handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s NULL handle for target %u\n", __func__, csio->ccb_h.target_id); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } if (targ->flags & MPR_TARGET_FLAGS_RAID_COMPONENT) { - mpr_dprint(sc, MPR_TRACE, "%s Raid component no SCSI IO " + mpr_dprint(sc, MPR_ERROR, "%s Raid component no SCSI IO " "supported %u\n", __func__, csio->ccb_h.target_id); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } @@ -1702,7 +1713,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) * Progress" and was actually aborted by the upper layer. Check for * this here and complete the command without error. */ - if (ccb->ccb_h.status != CAM_REQ_INPROG) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_INPROG) { mpr_dprint(sc, MPR_TRACE, "%s Command is not in progress for " "target %u\n", __func__, csio->ccb_h.target_id); xpt_done(ccb); @@ -1715,16 +1726,29 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) */ if (targ->flags & MPRSAS_TARGET_INREMOVAL) { if (targ->devinfo == 0) - csio->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - csio->ccb_h.status = CAM_SEL_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); xpt_done(ccb); return; } if ((sc->mpr_flags & MPR_FLAGS_SHUTDOWN) != 0) { - mpr_dprint(sc, MPR_TRACE, "%s shutting down\n", __func__); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mpr_dprint(sc, MPR_INFO, "%s shutting down\n", __func__); + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + xpt_done(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 & MPRSAS_TARGET_INRESET) { + ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; + mpr_dprint(sc, MPR_INFO, "%s: Freezing devq for target ID %d\n", + __func__, targ->tid); + xpt_freeze_devq(ccb->ccb_h.path, 1); xpt_done(ccb); return; } @@ -1807,7 +1831,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) if (MPR_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) { mpr_free_command(sc, cm); - ccb->ccb_h.status = CAM_LUN_INVALID; + mprsas_set_ccbstatus(ccb, CAM_LUN_INVALID); xpt_done(ccb); return; } @@ -1904,7 +1928,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) } callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0, - mprsas_scsiio_timeout, cm, 0); + mprsas_scsiio_timeout, cm, 0); targ->issued++; targ->outstanding++; @@ -2102,7 +2126,7 @@ mpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb_scsiio *csio, desc_scsi_state, scsi_state); if (sc->mpr_debug & MPR_XINFO && - scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { + scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : Start :\n"); scsi_sense_print(csio); mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : End :\n"); @@ -2126,6 +2150,8 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) u8 *TLR_bits, TLR_on; int dir = 0, i; u16 alloc_len; + struct mprsas_target *target; + target_id_t target_id; MPR_FUNCTRACE(sc); mpr_dprint(sc, MPR_TRACE, @@ -2139,6 +2165,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_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 @@ -2197,7 +2224,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * because there can be no reply when we haven't actually * gone out to the hardware. */ - ccb->ccb_h.status = CAM_REQUEUE_REQ; + mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); /* * Currently the only error included in the mask is @@ -2214,7 +2241,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) xpt_freeze_simq(sassc->sim, 1); sassc->flags |= MPRSAS_QUEUE_FROZEN; mpr_dprint(sc, MPR_INFO, "Error sending command, " - "freezing SIM queue\n"); + "freezing SIM queue\n"); } } @@ -2224,7 +2251,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * commands that were sent. All SSU commands should be completed before * shutdown completes, meaning SSU_refcount will be 0 after SSU_started * is TRUE. - */ + */ if (sc->SSU_started && (csio->cdb_io.cdb_bytes[0] == START_STOP_UNIT)) { mpr_dprint(sc, MPR_INFO, "Decrementing SSU count.\n"); sc->SSU_refcount--; @@ -2232,12 +2259,12 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) /* Take the fast path to completion */ if (cm->cm_reply == NULL) { - if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { + if (mprsas_get_ccbstatus(ccb) == CAM_REQ_INPROG) { if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) - ccb->ccb_h.status = CAM_SCSI_BUS_RESET; + mprsas_set_ccbstatus(ccb, CAM_SCSI_BUS_RESET); else { - ccb->ccb_h.status = CAM_REQ_CMP; - ccb->csio.scsi_status = SCSI_STATUS_OK; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + csio->scsi_status = SCSI_STATUS_OK; } if (sassc->flags & MPRSAS_QUEUE_FROZEN) { ccb->ccb_h.status |= CAM_RELEASE_SIMQ; @@ -2252,10 +2279,10 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * CAM_REQ_CMP. The first is if MPR_CM_FLAGS_ERROR_MASK is * set, the second is in the MPR_FLAGS_DIAGRESET above. */ - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { /* * Freeze the dev queue so that commands are - * executed in the correct order with after error + * executed in the correct order after error * recovery. */ ccb->ccb_h.status |= CAM_DEV_QFRZN; @@ -2285,7 +2312,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) /* Completion failed at the transport level. */ if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS | MPI2_SCSI_STATE_TERMINATED)) { - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); break; } @@ -2294,7 +2321,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * recover the command. */ if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) { - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; + mprsas_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL); break; } @@ -2306,7 +2333,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) && ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) == MPR_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; } @@ -2318,16 +2345,16 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) */ if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) || (rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) { - ccb->ccb_h.status = CAM_REQ_ABORTED; + mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); break; } /* Handle normal status and sense */ csio->scsi_status = rep->SCSIStatus; if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; + mprsas_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR); if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) { int sense_len, returned_sense_len; @@ -2362,12 +2389,11 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_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) + @@ -2380,6 +2406,24 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_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; + mpr_dprint(sc, MPR_XINFO, "Target %d supports SSU\n", + target_id); + } break; case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: @@ -2390,13 +2434,13 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * failed. */ if (cm->cm_targ->devinfo == 0) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); break; case MPI2_IOCSTATUS_INVALID_SGL: mpr_print_scsiio_cmd(sc, cm); - ccb->ccb_h.status = CAM_UNREC_HBA_ERROR; + mprsas_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR); break; case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: /* @@ -2409,14 +2453,14 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * on the console. */ if (cm->cm_state == MPR_CM_STATE_TIMEDOUT) - ccb->ccb_h.status = CAM_CMD_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_CMD_TIMEOUT); else - ccb->ccb_h.status = CAM_REQ_ABORTED; + mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); break; case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: /* resid is ignored for this condition */ csio->resid = 0; - ccb->ccb_h.status = CAM_DATA_RUN_ERR; + mprsas_set_ccbstatus(ccb, CAM_DATA_RUN_ERR); break; case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: @@ -2425,7 +2469,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * transient transport-related) errors, retry these without * decrementing the retry count. */ - ccb->ccb_h.status = CAM_REQUEUE_REQ; + mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); mprsas_log_command(cm, MPR_INFO, "terminated ioc %x scsi %x state %x xfer %u\n", le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, @@ -2447,7 +2491,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, le32toh(rep->TransferCount)); csio->resid = cm->cm_length; - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); break; } @@ -2460,7 +2504,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) "queue\n"); } - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { ccb->ccb_h.status |= CAM_DEV_QFRZN; xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); } @@ -2487,16 +2531,16 @@ mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) * in the standard request size. */ if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { - mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x on SMP request!\n", - __func__, cm->cm_flags); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x on SMP " + "request!\n", __func__, cm->cm_flags); + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply; if (rpl == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: NULL cm_reply!\n", __func__); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } @@ -2509,17 +2553,17 @@ mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) { mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus %04x SASStatus %02x\n", __func__, le16toh(rpl->IOCStatus), rpl->SASStatus); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } - mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address " - "%#jx completed successfully\n", __func__, (uintmax_t)sasaddr); + mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address %#jx " + "completed successfully\n", __func__, (uintmax_t)sasaddr); if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_SMP_STATUS_ERROR; + mprsas_set_ccbstatus(ccb, CAM_SMP_STATUS_ERROR); bailout: /* @@ -2558,7 +2602,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, */ mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " "supported\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; case CAM_DATA_SG: @@ -2571,7 +2615,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, mpr_dprint(sc, MPR_ERROR, "%s: multiple request or response buffer segments " "not supported for SMP\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2605,7 +2649,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, response = ccb->smpio.smp_response; break; default: - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2614,9 +2658,9 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, * XXX We don't yet support physical addresses here. */ if (ccb->ccb_h.flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS)) { - mpr_printf(sc, "%s: physical addresses not supported\n", - __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " + "supported\n", __func__); + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2635,7 +2679,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, mpr_dprint(sc, MPR_ERROR, "%s: multiple request or " "response buffer segments not supported for SMP\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2673,7 +2717,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, if (cm == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: cannot allocate command\n", __func__); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2760,7 +2804,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, bailout_error: mpr_free_command(sc, cm); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2783,7 +2827,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (targ->handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s: target %d does not exist!\n", __func__, ccb->ccb_h.target_id); - ccb->ccb_h.status = CAM_SEL_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); xpt_done(ccb); return; } @@ -2831,7 +2875,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (targ->parent_handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " "a valid parent handle!\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } #ifdef OLD_MPR_PROBE @@ -2841,7 +2885,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (parent_target == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " "a valid parent target!\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2850,9 +2894,8 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " "does not have an SMP target!\n", __func__, targ->handle, parent_target->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; - } sasaddr = parent_target->sasaddr; @@ -2862,7 +2905,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " "does not have an SMP target!\n", __func__, targ->handle, targ->parent_handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2870,7 +2913,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent handle " "%d does not have a valid SAS address!\n", __func__, targ->handle, targ->parent_handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2882,7 +2925,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (sasaddr == 0) { mpr_dprint(sc, MPR_INFO, "%s: unable to find SAS address for " "handle %d\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } mprsas_send_smpcmd(sassc, ccb, sasaddr); @@ -2914,7 +2957,7 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) if (tm == NULL) { mpr_dprint(sc, MPR_ERROR, "command alloc failure in mprsas_action_resetdev\n"); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2933,7 +2976,12 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; tm->cm_complete = mprsas_resetdev_complete; tm->cm_complete_data = ccb; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); tm->cm_targ = targ; + targ->flags |= MPRSAS_TARGET_INRESET; + mpr_map_command(sc, tm); } @@ -2962,7 +3010,7 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for reset of " "handle %#04x! This should not happen!\n", __func__, tm->cm_flags, req->DevHandle); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } @@ -2971,12 +3019,12 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, CAM_LUN_WILDCARD); } else - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); bailout: @@ -2995,7 +3043,8 @@ mprsas_poll(struct cam_sim *sim) /* frequent debug messages during a panic just slow * everything down too much. */ - mpr_printf(sassc->sc, "%s clearing MPR_TRACE\n", __func__); + mpr_dprint(sassc->sc, MPR_XINFO, "%s clearing MPR_TRACE\n", + __func__); sassc->sc->mpr_debug &= ~MPR_TRACE; } @@ -3094,7 +3143,7 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0) cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE); - if (((cdai.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) + if ((mprsas_get_ccbstatus((union ccb *)&cdai) == CAM_REQ_CMP) && (rcap_buf.prot & SRC16_PROT_EN)) { lun->eedp_formatted = TRUE; lun->eedp_block_size = scsi_4btoul(rcap_buf.length); @@ -3121,8 +3170,6 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, #endif cgd = arg; - mprsas_prepare_ssu(sc, path, cgd); - #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) mprsas_check_eedp(sc, path, cgd); @@ -3134,64 +3181,6 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, } } -static void -mprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, - struct ccb_getdev *cgd) -{ - struct mprsas_softc *sassc = sc->sassc; - path_id_t pathid; - target_id_t targetid; - lun_id_t lunid; - struct mprsas_target *target; - struct mprsas_lun *lun; - uint8_t found_lun; - - sassc = sc->sassc; - pathid = cam_sim_path(sassc->sim); - targetid = xpt_path_target_id(path); - lunid = xpt_path_lun_id(path); - - KASSERT(targetid < sassc->maxtargets, - ("Target %d out of bounds in mprsas_prepare_ssu\n", targetid)); - target = &sassc->targets[targetid]; - if (target->handle == 0x0) - return; - - /* - * If LUN is already in list, don't create a new one. - */ - found_lun = FALSE; - SLIST_FOREACH(lun, &target->luns, lun_link) { - if (lun->lun_id == lunid) { - found_lun = TRUE; - break; - } - } - if (!found_lun) { - lun = malloc(sizeof(struct mprsas_lun), M_MPR, - M_NOWAIT | M_ZERO); - if (lun == NULL) { - mpr_dprint(sc, MPR_ERROR, "Unable to alloc LUN for " - "preparing SSU.\n"); - return; - } - lun->lun_id = lunid; - SLIST_INSERT_HEAD(&target->luns, lun, lun_link); - } - - /* - * 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 & 0x1F) == 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; - } -} - #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) static void @@ -3212,7 +3201,6 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, uint8_t found_lun; char path_str[64]; - sassc = sc->sassc; pathid = cam_sim_path(sassc->sim); targetid = xpt_path_target_id(path); lunid = xpt_path_lun_id(path); @@ -3288,7 +3276,7 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp), M_MPR, M_NOWAIT | M_ZERO); if (rcap_buf == NULL) { - mpr_dprint(sc, MPR_FAULT, "Unable to alloc read capacity " + mpr_dprint(sc, MPR_ERROR, "Unable to alloc read capacity " "buffer for EEDP support.\n"); xpt_free_path(ccb->ccb_h.path); xpt_free_ccb(ccb); @@ -3341,7 +3329,7 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) xpt_release_devq(done_ccb->ccb_h.path, /*count*/ 1, /*run_queue*/TRUE); } - + rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; /* @@ -3359,21 +3347,21 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) /* * Got the LUN in the target's LUN list. Fill it in with EEDP - * info. If the READ CAP 16 command had some SCSI error (common + * info. If the READ CAP 16 command had some SCSI error (common * if command is not supported), mark the lun as not supporting * EEDP and set the block size to 0. */ - if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) - || (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { + if ((mprsas_get_ccbstatus(done_ccb) != CAM_REQ_CMP) || + (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { lun->eedp_formatted = FALSE; lun->eedp_block_size = 0; break; } if (rcap_buf->protect & 0x01) { - mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for " - "target ID %d is formatted for EEDP " - "support.\n", done_ccb->ccb_h.target_lun, + mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for target ID " + "%d is formatted for EEDP support.\n", + done_ccb->ccb_h.target_lun, done_ccb->ccb_h.target_id); lun->eedp_formatted = TRUE; lun->eedp_block_size = scsi_4btoul(rcap_buf->length); @@ -3389,6 +3377,34 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) #endif /* (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */ +void +mprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm, + struct mprsas_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 |= MPRSAS_TARGET_INRESET; + } + } +} + int mprsas_startup(struct mpr_softc *sc) { @@ -3489,3 +3505,33 @@ mprsas_check_id(struct mprsas_softc *sassc, int id) return (0); } + +void +mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets) +{ + struct mprsas_softc *sassc; + struct mprsas_lun *lun, *lun_tmp; + struct mprsas_target *targ; + int i; + + sassc = sc->sassc; + /* + * The number of targets is based on IOC Facts, so free all of + * the allocated LUNs for each target and then the target buffer + * itself. + */ + for (i=0; i< maxtargets; i++) { + targ = &sassc->targets[i]; + SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) { + free(lun, M_MPR); + } + } + free(sassc->targets, M_MPR); + + sassc->targets = malloc(sizeof(struct mprsas_target) * maxtargets, + M_MPR, M_WAITOK|M_ZERO); + if (!sassc->targets) { + panic("%s failed to alloc targets with error %d\n", + __func__, ENOMEM); + } +} diff --git a/sys/dev/mpr/mpr_sas.h b/sys/dev/mpr/mpr_sas.h index 9d3116af29d0..ebeed300c9fb 100644 --- a/sys/dev/mpr/mpr_sas.h +++ b/sys/dev/mpr/mpr_sas.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 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 mprsas_lun { lun_id_t lun_id; uint8_t eedp_formatted; uint32_t eedp_block_size; - uint8_t stop_at_shutdown; }; struct mprsas_target { @@ -55,11 +55,10 @@ struct mprsas_target { #define MPRSAS_TARGET_INREMOVAL (1 << 3) #define MPR_TARGET_FLAGS_RAID_COMPONENT (1 << 4) #define MPR_TARGET_FLAGS_VOLUME (1 << 5) +#define MPR_TARGET_IS_SATA_SSD (1 << 6) #define MPRSAS_TARGET_INRECOVERY (MPRSAS_TARGET_INABORT | \ MPRSAS_TARGET_INRESET | MPRSAS_TARGET_INCHIPRESET) -#define MPRSAS_TARGET_ADD (1 << 29) -#define MPRSAS_TARGET_REMOVE (1 << 30) uint16_t tid; SLIST_HEAD(, mprsas_lun) luns; TAILQ_HEAD(, mpr_command) commands; @@ -82,6 +81,8 @@ struct mprsas_target { unsigned int logical_unit_resets; unsigned int target_resets; uint8_t scsi_req_desc_type; + uint8_t stop_at_shutdown; + uint8_t supports_SSU; }; struct mprsas_softc { @@ -92,7 +93,6 @@ struct mprsas_softc { #define MPRSAS_DISCOVERY_TIMEOUT_PENDING (1 << 2) #define MPRSAS_QUEUE_FROZEN (1 << 3) #define MPRSAS_SHUTDOWN (1 << 4) -#define MPRSAS_SCANTHREAD (1 << 5) u_int maxtargets; struct mprsas_target *targets; struct cam_devq *devq; @@ -103,7 +103,6 @@ struct mprsas_softc { struct mpr_event_handle *mprsas_eh; u_int startup_refcount; - u_int tm_count; struct proc *sysctl_proc; struct taskqueue *ev_tq; @@ -150,6 +149,19 @@ mprsas_set_lun(uint8_t *lun, u_int ccblun) return (0); } +static __inline void +mprsas_set_ccbstatus(union ccb *ccb, int status) +{ + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= status; +} + +static __inline int +mprsas_get_ccbstatus(union ccb *ccb) +{ + return (ccb->ccb_h.status & CAM_STATUS_MASK); +} + #define MPR_SET_SINGLE_LUN(req, lun) \ do { \ bzero((req)->LUN, 8); \ @@ -158,11 +170,10 @@ do { \ void mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ); void mprsas_discovery_end(struct mprsas_softc *sassc); +void mprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm, + struct mprsas_target *target, lun_id_t lun_id); void mprsas_startup_increment(struct mprsas_softc *sassc); void mprsas_startup_decrement(struct mprsas_softc *sassc); -void mprsas_release_simq_reinit(struct mprsas_softc *sassc); -struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc); -void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm); void mprsas_firmware_event_work(void *arg, int pending); int mprsas_check_id(struct mprsas_softc *sassc, int id); diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c index 32e9b3a07804..7d6ef7070f7d 100644 --- a/sys/dev/mpr/mpr_sas_lsi.c +++ b/sys/dev/mpr/mpr_sas_lsi.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2011-2014 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 __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for LSI MPT3 */ /* TODO Move headers to mprvar */ #include @@ -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 mprsas_fw_work(struct mpr_softc *sc, @@ -116,8 +119,9 @@ static int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate); static int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo); +static void mprsas_ata_id_timeout(void *data); int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, - u64 *sas_address, u16 handle, u32 device_info); + u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); static int mprsas_volume_add(struct mpr_softc *sc, u16 handle); static void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc); @@ -325,7 +329,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) return; } - mpr_dprint(sc, MPR_INFO, "Sending FP action " + mpr_dprint(sc, MPR_EVENT, "Sending FP action " "from " "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST " ":\n"); @@ -350,9 +354,9 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) if (reply && (le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) { - mpr_dprint(sc, MPR_INFO, "%s: error " - "sending RaidActionPage; iocstatus " - "= 0x%x\n", __func__, + mpr_dprint(sc, MPR_ERROR, "%s: error " + "sending RaidActionPage; " + "iocstatus = 0x%x\n", __func__, le16toh(reply->IOCStatus)); } @@ -360,7 +364,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) mpr_free_command(sc, cm); } skip_fp_send: - mpr_dprint(sc, MPR_INFO, "Received " + mpr_dprint(sc, MPR_EVENT, "Received " "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST Reason " "code %x:\n", element->ReasonCode); switch (element->ReasonCode) { @@ -421,7 +425,6 @@ skip_fp_send: break; targ->flags |= MPR_TARGET_FLAGS_RAID_COMPONENT; mprsas_rescan_target(sc, targ); - break; case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: /* @@ -678,14 +681,13 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ struct mprsas_target *targ; Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t config_page; - uint64_t sas_address, sata_sas_address; - uint64_t parent_sas_address = 0; - u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); + uint64_t sas_address, parent_sas_address = 0; u32 device_info, parent_devinfo = 0; unsigned int id; - int ret; - int error = 0; + int ret = 1, error = 0, i; struct mprsas_lun *lun; + u8 is_SATA_SSD = 0; + struct mpr_command *cm; sassc = sc->sassc; mprsas_startup_increment(sassc); @@ -717,26 +719,29 @@ mprsas_add_device(struct mpr_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; + sas_address = (sas_address << 32) | config_page.SASAddress.Low; + mpr_dprint(sc, MPR_INFO, "SAS Address from SAS device page0 = %jx\n", + sas_address); - 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 = mprsas_get_sas_address_for_sata_disk(sc, - &sata_sas_address, handle, device_info); - if (!ret) - id = mpr_mapping_get_sas_id(sc, - sata_sas_address, handle); - else - id = mpr_mapping_get_sas_id(sc, - sas_address, handle); - } else - id = mpr_mapping_get_sas_id(sc, sas_address, - handle); - } else - id = mpr_mapping_get_sas_id(sc, sas_address, handle); + /* + * 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 = mprsas_get_sas_address_for_sata_disk(sc, &sas_address, + handle, device_info, &is_SATA_SSD); + if (ret) { + mpr_dprint(sc, MPR_ERROR, "%s: failed to get disk type " + "(SSD or HDD) for SATA device with handle 0x%04x\n", + __func__, handle); + } else { + mpr_dprint(sc, MPR_INFO, "SAS Address from SATA " + "device = %jx\n", sas_address); + } + } + id = mpr_mapping_get_sas_id(sc, sas_address, handle); if (id == MPR_MAP_BAD_ID) { printf("failure at %s:%d/%s()! Could not get ID for device " "with handle 0x%04x\n", __FILE__, __LINE__, __func__, @@ -750,7 +755,7 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ error = ENXIO; goto out; } - + mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n", sas_address); targ = &sassc->targets[id]; @@ -773,6 +778,9 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ targ->tid = id; targ->linkrate = (linkrate>>4); targ->flags = 0; + if (is_SATA_SSD) { + targ->flags = MPR_TARGET_IS_SATA_SSD; + } if (le16toh(config_page.Flags) & MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) { targ->scsi_req_desc_type = @@ -792,12 +800,12 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ SLIST_INIT(&targ->luns); mpr_describe_devinfo(targ->devinfo, devstring, 80); - mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "Found device <%s> <%s> " + mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found device <%s> <%s> " "handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring, mpr_describe_table(mpr_linkrate_names, targ->linkrate), targ->handle, targ->encl_handle, targ->encl_slot); if (targ->encl_level_valid) { - mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "At enclosure level %d " + mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d " "and connector name (%4s)\n", targ->encl_level, targ->connector_name); } @@ -807,15 +815,57 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ #endif mprsas_rescan_target(sc, targ); mpr_dprint(sc, MPR_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 & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { + targ->timeouts++; + cm->cm_state = MPR_CM_STATE_TIMEDOUT; + + if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) { + mpr_dprint(sc, MPR_INFO, "%s: sending Target " + "Reset for stuck SATA identify command " + "(cm = %p)\n", __func__, cm); + targ->tm->cm_targ = targ; + mprsas_send_reset(sc, targ->tm, + MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); + } else { + mpr_dprint(sc, MPR_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 & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { + mpr_free_command(sc, cm); + } + } mprsas_startup_decrement(sassc); return (error); - } int mprsas_get_sas_address_for_sata_disk(struct mpr_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; @@ -835,7 +885,16 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_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) { + mpr_dprint(sc, MPR_INFO, "Sleeping %d seconds " + "after SATA ID error to wait for spinup\n", + sc->spinup_wait_time); + msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, + "mprid", sc->spinup_wait_time * hz); + } + } + } while (((rc && (rc != EWOULDBLOCK)) || ioc_status || sas_status) && (try_count < 5)); if (rc == 0 && !ioc_status && !sas_status) { @@ -884,6 +943,10 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_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; } @@ -923,14 +986,29 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = buffer; cm->cm_length = htole32(sz); + + /* + * 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. + */ + mpr_dprint(sc, MPR_XINFO, "%s start timeout counter for SATA ID " + "command\n", __func__); + callout_reset(&cm->cm_callout, MPR_ATA_ID_TIMEOUT * hz, + mprsas_ata_id_timeout, cm); error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); + mpr_dprint(sc, MPR_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 */ /* * If the request returns an error then we need to do a diag * reset - */ + */ printf("%s: request for page completed with error %d", __func__, error); error = ENXIO; @@ -946,11 +1024,66 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, goto out; } out: - mpr_free_command(sc, cm); - free(buffer, M_MPR); + /* + * 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 & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0) + mpr_free_command(sc, cm); + else if (error == 0) + error = EWOULDBLOCK; + free(buffer, M_MPR); return (error); } +static void +mprsas_ata_id_timeout(void *data) +{ + struct mpr_softc *sc; + struct mpr_command *cm; + + cm = (struct mpr_command *)data; + sc = cm->cm_sc; + mtx_assert(&sc->mpr_mtx, MA_OWNED); + + mpr_dprint(sc, MPR_INFO, "%s checking ATA ID command %p sc %p\n", + __func__, cm, sc); + if ((callout_pending(&cm->cm_callout)) || + (!callout_active(&cm->cm_callout))) { + mpr_dprint(sc, MPR_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. + */ + mpr_intr_locked(sc); + if (cm->cm_state == MPR_CM_STATE_FREE) { + mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed " + "out\n", __func__); + return; + } + + mpr_dprint(sc, MPR_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 |= MPR_CM_FLAGS_SATA_ID_TIMEOUT; + wakeup(cm); +} + static int mprsas_volume_add(struct mpr_softc *sc, u16 handle) { @@ -1024,15 +1157,13 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) path_id_t pathid = cam_sim_path(sassc->sim); target_id_t targetid; struct mprsas_target *target; - struct mprsas_lun *lun; char path_str[64]; struct timeval cur_time, start_time; mpr_lock(sc); /* - * 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; @@ -1042,59 +1173,52 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) continue; } - SLIST_FOREACH(lun, &target->luns, lun_link) { - ccb = xpt_alloc_ccb_nowait(); - if (ccb == NULL) { - mpr_unlock(sc); - mpr_dprint(sc, MPR_FAULT, "Unable to alloc " - "CCB to stop unit.\n"); + ccb = xpt_alloc_ccb_nowait(); + if (ccb == NULL) { + mpr_dprint(sc, MPR_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) { + mpr_dprint(sc, MPR_ERROR, "Unable to create " + "path to stop unit.\n"); + xpt_free_ccb(ccb); return; } + xpt_path_string(ccb->ccb_h.path, path_str, + sizeof(path_str)); + + mpr_dprint(sc, MPR_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) { - mpr_dprint(sc, MPR_FAULT, "Unable to " - "create LUN path to stop unit.\n"); - xpt_free_ccb(ccb); - mpr_unlock(sc); - return; - } - xpt_path_string(ccb->ccb_h.path, path_str, - sizeof(path_str)); - - mpr_dprint(sc, MPR_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. - */ - mpr_dprint(sc, MPR_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, - mprsas_stop_unit_done, - MSG_SIMPLE_Q_TAG, - /*start*/FALSE, - /*load/eject*/0, - /*immediate*/FALSE, - MPR_SENSE_LEN, - /*timeout*/10000); - xpt_action(ccb); - } + mpr_dprint(sc, MPR_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, + mprsas_stop_unit_done, + MSG_SIMPLE_Q_TAG, + /*start*/FALSE, + /*load/eject*/0, + /*immediate*/FALSE, + MPR_SENSE_LEN, + /*timeout*/10000); + xpt_action(ccb); } } @@ -1102,7 +1226,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) /* * 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. */ @@ -1112,7 +1236,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) getmicrotime(&cur_time); if ((cur_time.tv_sec - start_time.tv_sec) > 60) { - mpr_dprint(sc, MPR_FAULT, "Time has expired waiting " + mpr_dprint(sc, MPR_ERROR, "Time has expired waiting " "for SSU commands to complete.\n"); break; } @@ -1162,6 +1286,8 @@ mprsas_ir_shutdown(struct mpr_softc *sc) unsigned int id, found_volume = 0; struct mpr_command *cm; Mpi2RaidActionRequest_t *action; + target_id_t targetid; + struct mprsas_target *target; mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); @@ -1214,5 +1340,47 @@ mprsas_ir_shutdown(struct mpr_softc *sc) mpr_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 MPR_SSU_DISABLE_SSD_DISABLE_HDD: + target->stop_at_shutdown = FALSE; + break; + case MPR_SSU_DISABLE_SSD_ENABLE_HDD: + target->stop_at_shutdown = TRUE; + if (target->flags & MPR_TARGET_IS_SATA_SSD) { + target->stop_at_shutdown = FALSE; + } + break; + case MPR_SSU_ENABLE_SSD_ENABLE_HDD: + target->stop_at_shutdown = TRUE; + break; + case MPR_SSU_ENABLE_SSD_DISABLE_HDD: + default: + target->stop_at_shutdown = TRUE; + if ((target->flags & + MPR_TARGET_IS_SATA_SSD) == 0) { + target->stop_at_shutdown = FALSE; + } + break; + } + } + } mprsas_SSU_to_SATA_devices(sc); } diff --git a/sys/dev/mpr/mpr_user.c b/sys/dev/mpr/mpr_user.c index 60680f5288a3..37d946718b23 100644 --- a/sys/dev/mpr/mpr_user.c +++ b/sys/dev/mpr/mpr_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-2014 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,7 +91,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include @@ -284,8 +285,7 @@ mpr_user_read_cfg_header(struct mpr_softc *sc, static int mpr_user_read_cfg_page(struct mpr_softc *sc, - struct mpr_cfg_page_req *page_req, - void *buf) + struct mpr_cfg_page_req *page_req, void *buf) { MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr; struct mpr_config_params params; @@ -328,6 +328,10 @@ mpr_user_read_extcfg_header(struct mpr_softc *sc, hdr->PageNumber = ext_page_req->header.PageNumber; hdr->ExtPageType = ext_page_req->header.ExtPageType; params.page_address = le32toh(ext_page_req->page_address); + params.buffer = NULL; + params.length = 0; + params.callback = NULL; + if ((error = mpr_read_config_page(sc, ¶ms)) != 0) { /* * Leave the request. Without resetting the chip, it's @@ -365,8 +369,8 @@ mpr_user_read_extcfg_page(struct mpr_softc *sc, params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; params.page_address = le32toh(ext_page_req->page_address); hdr->PageVersion = reqhdr->PageVersion; - hdr->PageNumber = reqhdr->PageNumber; hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + hdr->PageNumber = reqhdr->PageNumber; hdr->ExtPageType = reqhdr->ExtPageType; hdr->ExtPageLength = reqhdr->ExtPageLength; params.buffer = buf; @@ -541,6 +545,8 @@ mpi_pre_fw_upload(struct mpr_command *cm, struct mpr_usr_command *cmd) req->ImageOffset = 0; req->ImageSize = cmd->len; + cm->cm_flags |= MPR_CM_FLAGS_DATAIN; + return (mpr_push_ieee_sge(cm, &req->SGL, 0)); } @@ -834,11 +840,22 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_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 = mpr_wait_command(sc, cm, 30, CAN_SLEEP); + targ = mprsas_find_target_by_handle(sc->sassc, 0, + task->DevHandle); + if (targ == NULL) { + mpr_dprint(sc, MPR_INFO, + "%s %d : invalid handle for requested TM 0x%x \n", + __func__, __LINE__, task->DevHandle); + err = 1; + } else { + mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + err = mpr_wait_command(sc, cm, 30, CAN_SLEEP); + } if (err != 0) { err = EIO; @@ -1029,7 +1046,7 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data) if (cm->cm_flags & MPR_CM_FLAGS_DATAIN) dir = BUS_DMASYNC_POSTREAD; else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT) - dir = BUS_DMASYNC_POSTWRITE;; + dir = BUS_DMASYNC_POSTWRITE; bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir); bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); @@ -1351,8 +1368,8 @@ done: } static int -mpr_diag_register(struct mpr_softc *sc, - mpr_fw_diag_register_t *diag_register, uint32_t *return_code) +mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register, + uint32_t *return_code) { mpr_fw_diagnostic_buffer_t *pBuffer; uint8_t extended_type, buffer_type, i; diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h index 9752dcd35f6f..acac44c5baec 100644 --- a/sys/dev/mpr/mprvar.h +++ b/sys/dev/mpr/mprvar.h @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011-2014 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,13 +25,15 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * * $FreeBSD$ */ #ifndef _MPRVAR_H #define _MPRVAR_H -#define MPR_DRIVER_VERSION "05.255.05.00-fbsd" +#define MPR_DRIVER_VERSION "09.255.01.00-fbsd" #define MPR_DB_MAX_WAIT 2500 @@ -47,16 +50,19 @@ #define MPR_FUNCTRACE(sc) \ mpr_dprint((sc), MPR_TRACE, "%s\n", __func__) -#define CAN_SLEEP 1 -#define NO_SLEEP 0 +#define CAN_SLEEP 1 +#define NO_SLEEP 0 #define MPR_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */ +#define MPR_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */ #define IFAULT_IOP_OVER_TEMP_THRESHOLD_EXCEEDED 0x2810 #define MPR_SCSI_RI_INVALID_FRAME (0x00000002) #define MPR_STRING_LENGTH 64 +#define DEFAULT_SPINUP_WAIT 3 /* seconds to wait for spinup */ + #include /* @@ -213,13 +219,14 @@ struct mpr_command { #define MPR_CM_FLAGS_CHAIN_FAILED (1 << 8) #define MPR_CM_FLAGS_ERROR_MASK MPR_CM_FLAGS_CHAIN_FAILED #define MPR_CM_FLAGS_USE_CCB (1 << 9) +#define MPR_CM_FLAGS_SATA_ID_TIMEOUT (1 << 10) u_int cm_state; #define MPR_CM_STATE_FREE 0 #define MPR_CM_STATE_BUSY 1 #define MPR_CM_STATE_TIMEDOUT 2 bus_dmamap_t cm_dmamap; struct scsi_sense_data *cm_sense; - TAILQ_HEAD(, mpr_chain) cm_chain_list; + TAILQ_HEAD(, mpr_chain) cm_chain_list; uint32_t cm_req_busaddr; uint32_t cm_sense_busaddr; struct callout cm_callout; @@ -256,6 +263,8 @@ struct mpr_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 @@ -270,7 +279,7 @@ struct mpr_softc { char tmp_string[MPR_STRING_LENGTH]; TAILQ_HEAD(, mpr_command) req_list; TAILQ_HEAD(, mpr_command) high_priority_req_list; - TAILQ_HEAD(, mpr_chain) chain_list; + TAILQ_HEAD(, mpr_chain) chain_list; TAILQ_HEAD(, mpr_command) tm_list; int replypostindex; int replyfreeindex; @@ -291,7 +300,7 @@ struct mpr_softc { uint8_t event_mask[16]; TAILQ_HEAD(, mpr_event_handle) event_list; - struct mpr_event_handle *mpr_log_eh; + struct mpr_event_handle *mpr_log_eh; struct mtx mpr_mtx; struct intr_config_hook mpr_ich; @@ -565,6 +574,11 @@ mpr_unlock(struct mpr_softc *sc) #define MPR_MAPPING (1 << 9) /* Trace device mappings */ #define MPR_TRACE (1 << 10) /* Function-by-function trace */ +#define MPR_SSU_DISABLE_SSD_DISABLE_HDD 0 +#define MPR_SSU_ENABLE_SSD_DISABLE_HDD 1 +#define MPR_SSU_DISABLE_SSD_ENABLE_HDD 2 +#define MPR_SSU_ENABLE_SSD_ENABLE_HDD 3 + #define mpr_printf(sc, args...) \ device_printf((sc)->mpr_dev, ##args) @@ -600,9 +614,6 @@ do { \ #define MPR_EVENTFIELD(sc, facts, attr, fmt) \ mpr_dprint_field((sc), MPR_EVENT, #attr ": " #fmt "\n", (facts)->attr) -#define CAN_SLEEP 1 -#define NO_SLEEP 0 - static __inline void mpr_from_u64(uint64_t data, U64 *mpr) { @@ -613,7 +624,6 @@ mpr_from_u64(uint64_t data, U64 *mpr) static __inline uint64_t mpr_to_u64(U64 *data) { - return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low)); } @@ -727,6 +737,12 @@ void mprsas_prepare_volume_remove(struct mprsas_softc *sassc, int mprsas_startup(struct mpr_softc *sc); struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *, int, uint16_t); +void mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets); +struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc); +void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm); +void mprsas_release_simq_reinit(struct mprsas_softc *sassc); +int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, + uint8_t type); SYSCTL_DECL(_hw_mpr);