Fix several problems with mapping code.
Reviewed by: ken, scottl, asomers, ambrisko, mav Approved by: ken, mav MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D10878
This commit is contained in:
parent
0edcc5b8d5
commit
635e58c715
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=318895
@ -1,8 +1,8 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2010 Spectra Logic Corporation
|
||||
.\" Copyright (c) 2014 LSI Corp
|
||||
.\" Copyright (c) 2016 Avago Technologies
|
||||
.\" Copyright (c) 2016 Broadcom Ltd.
|
||||
.\" Copyright (c) 2015-2017 Avago Technologies
|
||||
.\" Copyright (c) 2015-2017 Broadcom Ltd.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -38,7 +38,7 @@
|
||||
.\" $Id: //depot/SpectraBSD/head/share/man/man4/mps.4#6 $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 5, 2016
|
||||
.Dd May 25, 2017
|
||||
.Dt MPS 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -241,13 +241,13 @@ Send SSU to HDDs, but not to SSDs.
|
||||
Send SSU to both HDDs and SSDs.
|
||||
.El
|
||||
.Pp
|
||||
To control the feature for a specific adapter, set this tunable value in
|
||||
To control this feature for a specific adapter, set this tunable value in
|
||||
.Xr loader.conf 5 :
|
||||
.Bd -literal -offset indent
|
||||
dev.mps.X.enable_ssu
|
||||
.Ed
|
||||
.Pp
|
||||
The same set of values are valid when setting this tunable for all adapters.
|
||||
The same set of values are valid as when setting this tunable for all adapters.
|
||||
.Pp
|
||||
SATA disks that take several seconds to spin up and fail the SATA Identify
|
||||
command might not be discovered by the driver.
|
||||
@ -273,6 +273,45 @@ dev.mps.X.spinup_wait_time=NNNN
|
||||
tunable.
|
||||
NNNN is the number of seconds to wait for SATA devices to spin up when they fail
|
||||
the initial SATA Identify command.
|
||||
.Pp
|
||||
The driver can map devices discovered by the adapter so that target IDs
|
||||
corresponding to a specific device persist across resets and reboots.
|
||||
In some cases it is possible for devices to lose their mapped IDs due to
|
||||
unexpected behavior from certain hardware, such as some types of enclosures.
|
||||
To overcome this problem, a tunable is provided that will force the driver to
|
||||
map devices using the Phy number associated with the device.
|
||||
This feature is not recommended if the topology includes multiple
|
||||
enclosures/expanders.
|
||||
If multiple enclosures/expanders are present in the topology, Phy numbers are
|
||||
repeated, causing all devices at these Phy numbers except the first device to
|
||||
fail enumeration.
|
||||
To control this feature for all adapters, set the
|
||||
.Bd -literal -offset indent
|
||||
hw.mps.use_phy_num
|
||||
.Ed
|
||||
.Pp
|
||||
tunable in
|
||||
.Xr loader.conf 5
|
||||
to one of these values:
|
||||
.Bl -tag -width 6n -offset indent
|
||||
.It -1
|
||||
Only use Phy numbers to map devices and bypass the driver's mapping logic.
|
||||
.It 0
|
||||
Never use Phy numbers to map devices.
|
||||
.It 1
|
||||
Use Phy numbers to map devices, but only if the driver's mapping logic fails
|
||||
to map the device that is being enumerated.
|
||||
This is the default value.
|
||||
.El
|
||||
.Pp
|
||||
To control this feature for a specific adapter, set this tunable value in
|
||||
.Xr loader.conf 5 :
|
||||
.Bd -literal -offset indent
|
||||
dev.mps.X.use_phy_num
|
||||
.Ed
|
||||
.Pp
|
||||
The same set of values are valid as when setting this tunable for all adapters.
|
||||
.Pp
|
||||
.Sh DEBUGGING
|
||||
To enable debugging prints from the
|
||||
.Nm
|
||||
|
@ -505,7 +505,8 @@ mps_iocfacts_allocate(struct mps_softc *sc, uint8_t attaching)
|
||||
*/
|
||||
if (reallocating) {
|
||||
mps_iocfacts_free(sc);
|
||||
mpssas_realloc_targets(sc, saved_facts.MaxTargets);
|
||||
mpssas_realloc_targets(sc, saved_facts.MaxTargets +
|
||||
saved_facts.MaxVolumes);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1518,6 +1519,7 @@ mps_attach(struct mps_softc *sc)
|
||||
|
||||
mtx_init(&sc->mps_mtx, "MPT2SAS lock", NULL, MTX_DEF);
|
||||
callout_init_mtx(&sc->periodic, &sc->mps_mtx, 0);
|
||||
callout_init_mtx(&sc->device_check_callout, &sc->mps_mtx, 0);
|
||||
TAILQ_INIT(&sc->event_list);
|
||||
timevalclear(&sc->lastfail);
|
||||
|
||||
@ -1682,6 +1684,7 @@ mps_free(struct mps_softc *sc)
|
||||
mps_unlock(sc);
|
||||
/* Lock must not be held for this */
|
||||
callout_drain(&sc->periodic);
|
||||
callout_drain(&sc->device_check_callout);
|
||||
|
||||
if (((error = mps_detach_log(sc)) != 0) ||
|
||||
((error = mps_detach_sas(sc)) != 0))
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -733,7 +733,7 @@ mps_attach_sas(struct mps_softc *sc)
|
||||
* of MaxTargets here so that we don't get into trouble later. This
|
||||
* should move into the reinit logic.
|
||||
*/
|
||||
sassc->maxtargets = sc->facts->MaxTargets;
|
||||
sassc->maxtargets = sc->facts->MaxTargets + sc->facts->MaxVolumes;
|
||||
sassc->targets = malloc(sizeof(struct mpssas_target) *
|
||||
sassc->maxtargets, M_MPT2, M_WAITOK|M_ZERO);
|
||||
if(!sassc->targets) {
|
||||
@ -910,6 +910,25 @@ mpssas_discovery_end(struct mpssas_softc *sassc)
|
||||
if (sassc->flags & MPSSAS_DISCOVERY_TIMEOUT_PENDING)
|
||||
callout_stop(&sassc->discovery_callout);
|
||||
|
||||
/*
|
||||
* After discovery has completed, check the mapping table for any
|
||||
* missing devices and update their missing counts. Only do this once
|
||||
* whenever the driver is initialized so that missing counts aren't
|
||||
* updated unnecessarily. Note that just because discovery has
|
||||
* completed doesn't mean that events have been processed yet. The
|
||||
* check_devices function is a callout timer that checks if ALL devices
|
||||
* are missing. If so, it will wait a little longer for events to
|
||||
* complete and keep resetting itself until some device in the mapping
|
||||
* table is not missing, meaning that event processing has started.
|
||||
*/
|
||||
if (sc->track_mapping_events) {
|
||||
mps_dprint(sc, MPS_XINFO | MPS_MAPPING, "Discovery has "
|
||||
"completed. Check for missing devices in the mapping "
|
||||
"table.\n");
|
||||
callout_reset(&sc->device_check_callout,
|
||||
MPS_MISSING_CHECK_DELAY * hz, mps_mapping_check_devices,
|
||||
sc);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -942,7 +961,12 @@ mpssas_action(struct cam_sim *sim, union ccb *ccb)
|
||||
cpi->hba_eng_cnt = 0;
|
||||
cpi->max_target = sassc->maxtargets - 1;
|
||||
cpi->max_lun = 255;
|
||||
cpi->initiator_id = sassc->maxtargets - 1;
|
||||
|
||||
/*
|
||||
* initiator_id is set here to an ID outside the set of valid
|
||||
* target IDs (including volumes).
|
||||
*/
|
||||
cpi->initiator_id = sassc->maxtargets;
|
||||
strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
|
||||
strlcpy(cpi->hba_vid, "Avago Tech", HBA_IDLEN);
|
||||
strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
|
||||
|
@ -217,9 +217,11 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
|
||||
switch (phy->PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK) {
|
||||
case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
|
||||
if (mpssas_add_device(sc,
|
||||
le16toh(phy->AttachedDevHandle), phy->LinkRate)){
|
||||
printf("%s: failed to add device with "
|
||||
"handle 0x%x\n", __func__,
|
||||
le16toh(phy->AttachedDevHandle),
|
||||
phy->LinkRate)){
|
||||
mps_dprint(sc, MPS_ERROR, "%s: "
|
||||
"failed to add device with handle "
|
||||
"0x%x\n", __func__,
|
||||
le16toh(phy->AttachedDevHandle));
|
||||
mpssas_prepare_remove(sassc, le16toh(
|
||||
phy->AttachedDevHandle));
|
||||
@ -283,8 +285,8 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
|
||||
|
||||
element =
|
||||
(Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
|
||||
id = mps_mapping_get_raid_id_from_handle
|
||||
(sc, element->VolDevHandle);
|
||||
id = mps_mapping_get_raid_tid_from_handle(sc,
|
||||
element->VolDevHandle);
|
||||
|
||||
mps_mapping_ir_config_change_event(sc, event_data);
|
||||
|
||||
@ -293,7 +295,8 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
|
||||
case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
|
||||
case MPI2_EVENT_IR_CHANGE_RC_ADDED:
|
||||
if (!foreign_config) {
|
||||
if (mpssas_volume_add(sc, le16toh(element->VolDevHandle))){
|
||||
if (mpssas_volume_add(sc,
|
||||
le16toh(element->VolDevHandle))){
|
||||
printf("%s: failed to add RAID "
|
||||
"volume with handle 0x%x\n",
|
||||
__func__, le16toh(element->
|
||||
@ -333,12 +336,16 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
|
||||
* Phys Disk of a volume has been created. Hide
|
||||
* it from the OS.
|
||||
*/
|
||||
targ = mpssas_find_target_by_handle(sassc, 0, element->PhysDiskDevHandle);
|
||||
targ = mpssas_find_target_by_handle(sassc, 0,
|
||||
element->PhysDiskDevHandle);
|
||||
if (targ == NULL)
|
||||
break;
|
||||
|
||||
/* Set raid component flags only if it is not WD.
|
||||
* OR WrapDrive with WD_HIDE_ALWAYS/WD_HIDE_IF_VOLUME is set in NVRAM
|
||||
/*
|
||||
* Set raid component flags only if it is not
|
||||
* WD. OR WrapDrive with
|
||||
* WD_HIDE_ALWAYS/WD_HIDE_IF_VOLUME is set in
|
||||
* NVRAM
|
||||
*/
|
||||
if((!sc->WD_available) ||
|
||||
((sc->WD_available &&
|
||||
@ -674,10 +681,17 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
|
||||
* 1 - use the PhyNum field as a fallback to the mapping logic
|
||||
* 0 - never use the PhyNum field
|
||||
* -1 - only use the PhyNum field
|
||||
*
|
||||
* Note that using the Phy number to map a device can cause device adds
|
||||
* to fail if multiple enclosures/expanders are in the topology. For
|
||||
* example, if two devices are in the same slot number in two different
|
||||
* enclosures within the topology, only one of those devices will be
|
||||
* added. PhyNum mapping should not be used if multiple enclosures are
|
||||
* in the topology.
|
||||
*/
|
||||
id = MPS_MAP_BAD_ID;
|
||||
if (sc->use_phynum != -1)
|
||||
id = mps_mapping_get_sas_id(sc, sas_address, handle);
|
||||
id = mps_mapping_get_tid(sc, sas_address, handle);
|
||||
if (id == MPS_MAP_BAD_ID) {
|
||||
if ((sc->use_phynum == 0)
|
||||
|| ((id = config_page.PhyNum) > sassc->maxtargets)) {
|
||||
@ -688,19 +702,31 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
mps_dprint(sc, MPS_MAPPING, "%s: Target ID for added device is %d.\n",
|
||||
__func__, id);
|
||||
|
||||
if (mpssas_check_id(sassc, id) != 0) {
|
||||
device_printf(sc->mps_dev, "Excluding target id %d\n", id);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only do the ID check and reuse check if the target is not from a
|
||||
* RAID Component. For Physical Disks of a Volume, the ID will be reused
|
||||
* when a volume is deleted because the mapping entry for the PD will
|
||||
* still be in the mapping table. The ID check should not be done here
|
||||
* either since this PD is already being used.
|
||||
*/
|
||||
targ = &sassc->targets[id];
|
||||
if (targ->handle != 0x0) {
|
||||
mps_dprint(sc, MPS_MAPPING, "Attempting to reuse target id "
|
||||
"%d handle 0x%04x\n", id, targ->handle);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
if (!(targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT)) {
|
||||
if (mpssas_check_id(sassc, id) != 0) {
|
||||
device_printf(sc->mps_dev, "Excluding target id %d\n",
|
||||
id);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (targ->handle != 0x0) {
|
||||
mps_dprint(sc, MPS_MAPPING, "Attempting to reuse "
|
||||
"target id %d handle 0x%04x\n", id, targ->handle);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
mps_dprint(sc, MPS_MAPPING, "SAS Address from SAS device page0 = %jx\n",
|
||||
@ -787,7 +813,6 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
|
||||
}
|
||||
mpssas_startup_decrement(sassc);
|
||||
return (error);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
@ -1040,7 +1065,7 @@ mpssas_volume_add(struct mps_softc *sc, u16 handle)
|
||||
goto out;
|
||||
}
|
||||
|
||||
id = mps_mapping_get_raid_id(sc, wwid, handle);
|
||||
id = mps_mapping_get_raid_tid(sc, wwid, handle);
|
||||
if (id == MPS_MAP_BAD_ID) {
|
||||
printf("%s: could not get ID for volume with handle 0x%04x and "
|
||||
"WWID 0x%016llx\n", __func__, handle,
|
||||
@ -1099,7 +1124,7 @@ mpssas_SSU_to_SATA_devices(struct mps_softc *sc)
|
||||
*/
|
||||
sc->SSU_started = TRUE;
|
||||
sc->SSU_refcount = 0;
|
||||
for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
|
||||
for (targetid = 0; targetid < sc->max_devices; targetid++) {
|
||||
target = &sassc->targets[targetid];
|
||||
if (target->handle == 0x0) {
|
||||
continue;
|
||||
@ -1281,7 +1306,7 @@ mpssas_ir_shutdown(struct mps_softc *sc)
|
||||
* 3: enable to SSD and HDD
|
||||
* anything else will default to 1.
|
||||
*/
|
||||
for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
|
||||
for (targetid = 0; targetid < sc->max_devices; targetid++) {
|
||||
target = &sc->sassc->targets[targetid];
|
||||
if (target->handle == 0x0) {
|
||||
continue;
|
||||
|
@ -2052,7 +2052,7 @@ mps_user_btdh(struct mps_softc *sc, mps_btdh_mapping_t *data)
|
||||
data->DevHandle = dev_handle;
|
||||
} else {
|
||||
bus = 0;
|
||||
target = mps_mapping_get_sas_id_from_handle(sc, dev_handle);
|
||||
target = mps_mapping_get_tid_from_handle(sc, dev_handle);
|
||||
data->Bus = bus;
|
||||
data->TargetID = target;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
#ifndef _MPSVAR_H
|
||||
#define _MPSVAR_H
|
||||
|
||||
#define MPS_DRIVER_VERSION "21.01.00.00-fbsd"
|
||||
#define MPS_DRIVER_VERSION "21.02.00.00-fbsd"
|
||||
|
||||
#define MPS_DB_MAX_WAIT 2500
|
||||
|
||||
@ -53,6 +53,7 @@
|
||||
|
||||
#define MPS_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */
|
||||
#define MPS_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */
|
||||
#define MPS_MISSING_CHECK_DELAY 10 /* 10 seconds between missing check */
|
||||
|
||||
#define MPS_SCSI_RI_INVALID_FRAME (0x00000002)
|
||||
#define MPS_STRING_LENGTH 64
|
||||
@ -70,7 +71,6 @@
|
||||
#define MPS_MAX_MISSING_COUNT 0x0F
|
||||
#define MPS_DEV_RESERVED 0x20000000
|
||||
#define MPS_MAP_IN_USE 0x10000000
|
||||
#define MPS_RAID_CHANNEL 1
|
||||
#define MPS_MAP_BAD_ID 0xFFFFFFFF
|
||||
|
||||
/*
|
||||
@ -107,7 +107,6 @@ typedef uint64_t u64;
|
||||
* @phy_bits: bitfields indicating controller phys
|
||||
* @dpm_entry_num: index of this device in device persistent map table
|
||||
* @dev_handle: device handle for the device pointed by this entry
|
||||
* @channel: target channel
|
||||
* @id: target id
|
||||
* @missing_count: number of times the device not detected by driver
|
||||
* @hide_flag: Hide this physical disk/not (foreign configuration)
|
||||
@ -119,8 +118,7 @@ struct dev_mapping_table {
|
||||
u32 phy_bits;
|
||||
u16 dpm_entry_num;
|
||||
u16 dev_handle;
|
||||
u8 reserved1;
|
||||
u8 channel;
|
||||
u16 reserved1;
|
||||
u16 id;
|
||||
u8 missing_count;
|
||||
u8 init_complete;
|
||||
@ -293,6 +291,7 @@ struct mps_softc {
|
||||
struct mps_command *commands;
|
||||
struct mps_chain *chains;
|
||||
struct callout periodic;
|
||||
struct callout device_check_callout;
|
||||
|
||||
struct mpssas_softc *sassc;
|
||||
char tmp_string[MPS_STRING_LENGTH];
|
||||
@ -377,13 +376,10 @@ struct mps_softc {
|
||||
uint8_t max_volumes;
|
||||
uint8_t num_enc_table_entries;
|
||||
uint8_t num_rsvd_entries;
|
||||
uint8_t num_channels;
|
||||
uint16_t max_dpm_entries;
|
||||
uint8_t is_dpm_enable;
|
||||
uint8_t track_mapping_events;
|
||||
uint32_t pending_map_events;
|
||||
uint8_t mt_full_retry;
|
||||
uint8_t mt_add_device_failed;
|
||||
|
||||
/* FW diag Buffer List */
|
||||
mps_fw_diagnostic_buffer_t
|
||||
@ -732,19 +728,18 @@ void mps_wd_config_pages(struct mps_softc *sc);
|
||||
int mps_mapping_initialize(struct mps_softc *);
|
||||
void mps_mapping_topology_change_event(struct mps_softc *,
|
||||
Mpi2EventDataSasTopologyChangeList_t *);
|
||||
int mps_mapping_is_reinit_required(struct mps_softc *);
|
||||
void mps_mapping_free_memory(struct mps_softc *sc);
|
||||
int mps_config_set_dpm_pg0(struct mps_softc *, Mpi2ConfigReply_t *,
|
||||
Mpi2DriverMappingPage0_t *, u16 );
|
||||
void mps_mapping_exit(struct mps_softc *);
|
||||
void mps_mapping_check_devices(struct mps_softc *, int);
|
||||
void mps_mapping_check_devices(void *);
|
||||
int mps_mapping_allocate_memory(struct mps_softc *sc);
|
||||
unsigned int mps_mapping_get_sas_id(struct mps_softc *, uint64_t , u16);
|
||||
unsigned int mps_mapping_get_sas_id_from_handle(struct mps_softc *sc,
|
||||
unsigned int mps_mapping_get_tid(struct mps_softc *, uint64_t , u16);
|
||||
unsigned int mps_mapping_get_tid_from_handle(struct mps_softc *sc,
|
||||
u16 handle);
|
||||
unsigned int mps_mapping_get_raid_id(struct mps_softc *sc, u64 wwid,
|
||||
u16 handle);
|
||||
unsigned int mps_mapping_get_raid_id_from_handle(struct mps_softc *sc,
|
||||
unsigned int mps_mapping_get_raid_tid(struct mps_softc *sc, u64 wwid,
|
||||
u16 volHandle);
|
||||
unsigned int mps_mapping_get_raid_tid_from_handle(struct mps_softc *sc,
|
||||
u16 volHandle);
|
||||
void mps_mapping_enclosure_dev_status_change_event(struct mps_softc *,
|
||||
Mpi2EventDataSasEnclDevStatusChange_t *event_data);
|
||||
|
Loading…
Reference in New Issue
Block a user