diff options
author | scottl <scottl@FreeBSD.org> | 2013-08-09 01:09:02 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2013-08-09 01:09:02 +0000 |
commit | d1c9a480cbae281f1f04c590e3a63b8fa0cfb03b (patch) | |
tree | ac7cfbf26f838c299a9cfa43cf4d82c7be05d44e | |
parent | 40b11a17462845928214986df55e541227bdeda1 (diff) | |
download | FreeBSD-src-d1c9a480cbae281f1f04c590e3a63b8fa0cfb03b.zip FreeBSD-src-d1c9a480cbae281f1f04c590e3a63b8fa0cfb03b.tar.gz |
Sometimes a device misbehaves so badly that it disrupts the entire system.
Add a tunable that allows such a device to be excluded from the driver.
The id parameter is the target id that the driver assigns to a given device.
dev.mps.X.exclude_ids=<id>,<id>
Obtained from: Netflix
MFC after: 3 days
-rw-r--r-- | sys/dev/mps/mps.c | 5 | ||||
-rw-r--r-- | sys/dev/mps/mps_sas.c | 17 | ||||
-rw-r--r-- | sys/dev/mps/mps_sas.h | 1 | ||||
-rw-r--r-- | sys/dev/mps/mps_sas_lsi.c | 7 | ||||
-rw-r--r-- | sys/dev/mps/mpsvar.h | 2 |
5 files changed, 32 insertions, 0 deletions
diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c index b6c549a..5a6718f 100644 --- a/sys/dev/mps/mps.c +++ b/sys/dev/mps/mps.c @@ -1371,6 +1371,11 @@ mps_get_tunables(struct mps_softc *sc) snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.max_chains", device_get_unit(sc->mps_dev)); TUNABLE_INT_FETCH(tmpstr, &sc->max_chains); + + bzero(sc->exclude_ids, sizeof(sc->exclude_ids)); + snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.exclude_ids", + device_get_unit(sc->mps_dev)); + TUNABLE_STR_FETCH(tmpstr, sc->exclude_ids, sizeof(sc->exclude_ids)); } static void diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c index 9a4964a..51df10c 100644 --- a/sys/dev/mps/mps_sas.c +++ b/sys/dev/mps/mps_sas.c @@ -3553,3 +3553,20 @@ mpssas_portenable_complete(struct mps_softc *sc, struct mps_command *cm) xpt_release_simq(sassc->sim, 1); } +int +mpssas_check_id(struct mpssas_softc *sassc, int id) +{ + struct mps_softc *sc = sassc->sc; + char *ids; + char *name; + + ids = &sc->exclude_ids[0]; + while((name = strsep(&ids, ",")) != NULL) { + if (name[0] == '\0') + continue; + if (strtol(name, NULL, 0) == (long)id) + return (1); + } + + return (0); +} diff --git a/sys/dev/mps/mps_sas.h b/sys/dev/mps/mps_sas.h index 662a29a..f6a0820 100644 --- a/sys/dev/mps/mps_sas.h +++ b/sys/dev/mps/mps_sas.h @@ -158,3 +158,4 @@ void mpssas_startup_decrement(struct mpssas_softc *sassc); struct mps_command * mpssas_alloc_tm(struct mps_softc *sc); void mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm); void mpssas_firmware_event_work(void *arg, int pending); +int mpssas_check_id(struct mpssas_softc *sassc, int id); diff --git a/sys/dev/mps/mps_sas_lsi.c b/sys/dev/mps/mps_sas_lsi.c index 85d6d1f..ca7ba4a 100644 --- a/sys/dev/mps/mps_sas_lsi.c +++ b/sys/dev/mps/mps_sas_lsi.c @@ -669,6 +669,13 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ error = ENXIO; goto out; } + + if (mpssas_check_id(sassc, id) != 0) { + device_printf(sc->mps_dev, "Excluding target id %d\n", id); + error = ENXIO; + goto out; + } + mps_dprint(sc, MPS_MAPPING, "SAS Address from SAS device page0 = %jx\n", sas_address); targ = &sassc->targets[id]; diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h index 5f8a015..15b660f 100644 --- a/sys/dev/mps/mpsvar.h +++ b/sys/dev/mps/mpsvar.h @@ -414,6 +414,8 @@ struct mps_softc { uint16_t DD_block_exponent; uint64_t DD_max_lba; struct mps_column_map DD_column_map[MPS_MAX_DISKS_IN_VOL]; + + char exclude_ids[80]; }; struct mps_config_params { |