The wrong commit message was given with r283632. This is the correct message.

- Updated all files with 2015 Avago copyright, and updated LSI's copyright
  dates.

- Changed all of the PCI device strings from LSI to Avago Technologies (LSI).

- Added a sysctl variable to control how StartStopUnit behavior works. User can
  select to spin down disks based on if disk is SSD or HDD.

- Inquiry data is required to tell if a disk will support SSU at shutdown or
  not. Due to the addition of mpssas_async, which gets Advanced Info but not
  Inquiry data, the setting of supports_SSU was moved to the
  mpssas_scsiio_complete function, which snoops for any Inquiry commands. And,
  since disks are shutdown as a target and not a LUN, this process was
  simplified by basing it on targets and not LUNs.

- Added a sysctl variable that sets the amount of time to retry after sending a
  failed SATA ID command. This helps with some bad disks and large disks that
  require a lot of time to spin up. Part of this change was to add a callout to
  handle timeouts with the SATA ID command. The callout function is called
  mpssas_ata_id_timeout(). (Fixes PR 191348)

- Changed the way resets work by allowing I/O to continue to devices that are
  not currently under a reset condition. This uses devq's instead of simq's and
  makes use of the MPSSAS_TARGET_INRESET flag. This change also adds a function
  called mpssas_prepare_tm().

- Some changes were made to reduce code duplication when getting a SAS address
  for a SATA disk.

- Fixed some formatting and whitespace.

- Bump version of mps driver to 9.255.01.00-fbsd

PR:		191348
Reviewed by:	ken, scottl
Approved by:	ken, scottl
MFC after:	1 week
This commit is contained in:
Stephen McConnell 2015-05-28 18:24:22 +00:00
parent c91d307f52
commit a2c1487946
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=283661
23 changed files with 767 additions and 473 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/* Communications core for LSI MPT2 */
/* Communications core for Avago Technologies (LSI) MPT3 */
/* TODO Move headers to mprvar */
#include <sys/types.h>
@ -72,7 +75,6 @@ __FBSDID("$FreeBSD$");
#include <dev/mpr/mpr_ioctl.h>
#include <dev/mpr/mprvar.h>
#include <dev/mpr/mpr_table.h>
#include <dev/mpr/mpr_sas.h>
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;

View File

@ -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 <sys/cdefs.h>

View File

@ -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$
*/

View File

@ -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 <sys/cdefs.h>
@ -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 &

View File

@ -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

View File

@ -27,7 +27,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/* PCI/PCI-X/PCIe bus interface for the LSI MPT2 controllers */
/* PCI/PCI-X/PCIe bus interface for the Avago Tech (LSI) MPT3 controllers */
/* TODO Move headers to mprvar */
#include <sys/types.h>
@ -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 }
};

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/* Communications core for LSI MPT2 */
/* Communications core for LSI MPT3 */
/* TODO Move headers to mprvar */
#include <sys/types.h>
@ -105,7 +106,9 @@ struct _ata_identify_device_data {
u16 serial_number[10]; /* 10-19 */
u16 reserved2[7]; /* 20-26 */
u16 model_number[20]; /* 27-46*/
u16 reserved3[209]; /* 47-255*/
u16 reserved3[170]; /* 47-216 */
u16 rotational_speed; /* 217 */
u16 reserved4[38]; /* 218-255 */
};
static u32 event_count;
static void 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 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
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);
}

View File

@ -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 <sys/rman.h>
#include <cam/cam.h>
#include <cam/scsi/scsi_all.h>
#include <cam/cam_ccb.h>
#include <dev/mpr/mpi/mpi2_type.h>
#include <dev/mpr/mpi/mpi2.h>
@ -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, &params)) != 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 @@ mpr_release_fw_diag_buffer(struct mpr_softc *sc,
}
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;

View File

@ -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 <sys/endian.h>
/*
@ -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);