summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2016-10-21 05:38:54 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2016-10-21 05:38:54 +0000
commitd66165444be3ed84f18a8d5a2fe5afc088beb166 (patch)
tree1304a67f3ac452e9cd927c7d0c6e09b8e6cc79fb
parentfceff95fd1ee05b1d9f92665c8d289ab6d3c91c3 (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.c54
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);