diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2016-10-21 05:38:54 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2016-10-21 05:38:54 +0000 |
commit | d66165444be3ed84f18a8d5a2fe5afc088beb166 (patch) | |
tree | 1304a67f3ac452e9cd927c7d0c6e09b8e6cc79fb | |
parent | fceff95fd1ee05b1d9f92665c8d289ab6d3c91c3 (diff) |
mitigate against mpii device attachment racing with mountroot
mpii devices get attached by processing sas discovery events after
threads are running, but if you have a lean (in terms of devices)
and fast machine, these events might run after mountroot.
this change has mpii use config_pending_incr() before it attaches
scsibus, and runs config_pending_decr() after the first scan of the
bus is complete.
to make sure config_pending_decr() is run after the scsi attach/detach
events are processed, the MPII_EVENT_SAS_DISCOVERY events are
deferred to the same context that the MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST
events run in.
ok jmatthew@
-rw-r--r-- | sys/dev/pci/mpii.c | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/sys/dev/pci/mpii.c b/sys/dev/pci/mpii.c index 90a24e9dd14..fc5e5ae9fc8 100644 --- a/sys/dev/pci/mpii.c +++ b/sys/dev/pci/mpii.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpii.c,v 1.105 2016/09/14 01:14:54 jmatthew Exp $ */ +/* $OpenBSD: mpii.c,v 1.106 2016/10/21 05:38:53 dlg Exp $ */ /* * Copyright (c) 2010, 2012 Mike Belopuhov * Copyright (c) 2009 James Giannoules @@ -164,6 +164,7 @@ struct mpii_softc { int sc_flags; #define MPII_F_RAID (1<<1) #define MPII_F_SAS3 (1<<2) +#define MPII_F_CONFIG_PENDING (1<<3) struct scsibus_softc *sc_scsibus; @@ -344,6 +345,8 @@ void mpii_event_done(struct mpii_softc *, struct mpii_rcb *); void mpii_event_sas(void *); void mpii_event_raid(struct mpii_softc *, struct mpii_msg_event_reply *); +void mpii_event_discovery(struct mpii_softc *, + struct mpii_msg_event_reply *); void mpii_sas_remove_device(struct mpii_softc *, u_int16_t); @@ -590,6 +593,10 @@ mpii_attach(struct device *parent, struct device *self, void *aux) if (sc->sc_ih == NULL) goto free_devs; + /* force autoconf to wait for the first sas discovery to complete */ + SET(sc->sc_flags, MPII_F_CONFIG_PENDING); + config_pending_incr(); + /* config_found() returns the scsibus attached to us */ sc->sc_scsibus = (struct scsibus_softc *) config_found(&sc->sc_dev, &saa, scsiprint); @@ -1795,6 +1802,19 @@ mpii_event_sas(void *xsc) task_add(systq, &sc->sc_evt_sas_task); enp = (struct mpii_msg_event_reply *)rcb->rcb_reply; + switch (lemtoh16(&enp->event)) { + case MPII_EVENT_SAS_DISCOVERY: + mpii_event_discovery(sc, enp); + goto done; + case MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST: + /* handle below */ + break; + default: + panic("%s: unexpected event %#x in sas event queue", + DEVNAME(sc), lemtoh16(&enp->event)); + /* NOTREACHED */ + } + tcl = (struct mpii_evt_sas_tcl *)(enp + 1); pe = (struct mpii_evt_phy_entry *)(tcl + 1); @@ -1846,10 +1866,30 @@ mpii_event_sas(void *xsc) } } +done: mpii_event_done(sc, rcb); } void +mpii_event_discovery(struct mpii_softc *sc, struct mpii_msg_event_reply *enp) +{ + struct mpii_evt_sas_discovery *esd = + (struct mpii_evt_sas_discovery *)(enp + 1); + + if (esd->reason_code == MPII_EVENT_SAS_DISC_REASON_CODE_COMPLETED) { + if (esd->discovery_status != 0) { + printf("%s: sas discovery completed with status %#x\n", + DEVNAME(sc), esd->discovery_status); + } + + if (ISSET(sc->sc_flags, MPII_F_CONFIG_PENDING)) { + CLR(sc->sc_flags, MPII_F_CONFIG_PENDING); + config_pending_decr(); + } + } +} + +void mpii_event_process(struct mpii_softc *sc, struct mpii_rcb *rcb) { struct mpii_msg_event_reply *enp; @@ -1863,17 +1903,7 @@ mpii_event_process(struct mpii_softc *sc, struct mpii_rcb *rcb) case MPII_EVENT_EVENT_CHANGE: /* should be properly ignored */ break; - case MPII_EVENT_SAS_DISCOVERY: { - struct mpii_evt_sas_discovery *esd = - (struct mpii_evt_sas_discovery *)(enp + 1); - - if (esd->reason_code == - MPII_EVENT_SAS_DISC_REASON_CODE_COMPLETED && - esd->discovery_status != 0) - printf("%s: sas discovery completed with status %#x\n", - DEVNAME(sc), esd->discovery_status); - } - break; + case MPII_EVENT_SAS_DISCOVERY: case MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST: mtx_enter(&sc->sc_evt_sas_mtx); SIMPLEQ_INSERT_TAIL(&sc->sc_evt_sas_queue, rcb, rcb_link); |