summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2014-03-24 07:24:21 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2014-03-24 07:24:21 +0000
commitcd98481b1b67fc055b83899ec8ef7d37cf8e2756 (patch)
treed1fe3ffe2f2f99f40c272a05bc1e46c3f8dbe6de /sys
parentbd7e22aee97e1782648380cb11cb1f33af82fe62 (diff)
rework mpii to use tasks instead of scsi_tasks for sas event handling.
scsi_tasks are still backed by workq, and i dont like having to allocate storage to defer work. sas events that cause hotplug events are queued in the softc to be handled by a single task that loops on the queue for work. think levelled interrupts. this has a side effect that interrupts are necessary to enumerate devices for attachment. i wrote this toward the end of last year, but thought it best to wait for 5.5 unlock.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/mpii.c121
1 files changed, 60 insertions, 61 deletions
diff --git a/sys/dev/pci/mpii.c b/sys/dev/pci/mpii.c
index 17555b13b1f..04ae4b07fb1 100644
--- a/sys/dev/pci/mpii.c
+++ b/sys/dev/pci/mpii.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpii.c,v 1.75 2014/03/06 14:08:06 gerhard Exp $ */
+/* $OpenBSD: mpii.c,v 1.76 2014/03/24 07:24:20 dlg Exp $ */
/*
* Copyright (c) 2010, 2012 Mike Belopuhov
* Copyright (c) 2009 James Giannoules
@@ -31,6 +31,7 @@
#include <sys/sensors.h>
#include <sys/dkio.h>
#include <sys/tree.h>
+#include <sys/task.h>
#include <machine/bus.h>
@@ -225,6 +226,10 @@ struct mpii_softc {
struct mpii_dmamem *sc_reply_freeq;
int sc_reply_free_host_index;
+ struct mpii_rcb_list sc_evt_sas_queue;
+ struct mutex sc_evt_sas_mtx;
+ struct task sc_evt_sas_task;
+
struct mpii_rcb_list sc_evt_ack_queue;
struct mutex sc_evt_ack_mtx;
struct scsi_iohandler sc_evt_ack_handler;
@@ -336,11 +341,9 @@ void mpii_eventack(void *, void *);
void mpii_eventack_done(struct mpii_ccb *);
void mpii_event_process(struct mpii_softc *, struct mpii_rcb *);
void mpii_event_done(struct mpii_softc *, struct mpii_rcb *);
-void mpii_event_sas(struct mpii_softc *,
- struct mpii_msg_event_reply *);
+void mpii_event_sas(void *, void *);
void mpii_event_raid(struct mpii_softc *,
struct mpii_msg_event_reply *);
-void mpii_event_defer(void *, void *);
void mpii_sas_remove_device(struct mpii_softc *, u_int16_t);
@@ -569,7 +572,7 @@ mpii_attach(struct device *parent, struct device *self, void *aux)
bzero(&saa, sizeof(saa));
saa.saa_sc_link = &sc->sc_link;
- sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_BIO,
+ sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_BIO | IPL_MPSAFE,
mpii_intr, sc, sc->sc_dev.dv_xname);
if (sc->sc_ih == NULL)
goto free_dev;
@@ -796,7 +799,7 @@ mpii_scsi_probe(struct scsi_link *link)
if ((sc->sc_porttype != MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL) &&
(sc->sc_porttype != MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL))
- return (1);
+ return (ENXIO);
if (sc->sc_devs[link->target] == NULL)
return (1);
@@ -1534,6 +1537,10 @@ mpii_eventnotify(struct mpii_softc *sc)
return (1);
}
+ SIMPLEQ_INIT(&sc->sc_evt_sas_queue);
+ mtx_init(&sc->sc_evt_sas_mtx, IPL_BIO);
+ task_set(&sc->sc_evt_sas_task, mpii_event_sas, sc, NULL);
+
SIMPLEQ_INIT(&sc->sc_evt_ack_queue);
mtx_init(&sc->sc_evt_ack_mtx, IPL_BIO);
scsi_ioh_set(&sc->sc_evt_ack_handler, &sc->sc_iopool,
@@ -1676,18 +1683,31 @@ mpii_event_raid(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
}
void
-mpii_event_sas(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
+mpii_event_sas(void *xsc, void *x)
{
+ struct mpii_softc *sc = xsc;
+ struct mpii_rcb *rcb, *next;
+ struct mpii_msg_event_reply *enp;
struct mpii_evt_sas_tcl *tcl;
struct mpii_evt_phy_entry *pe;
struct mpii_device *dev;
int i;
- tcl = (struct mpii_evt_sas_tcl *)(enp + 1);
+ mtx_enter(&sc->sc_evt_sas_mtx);
+ rcb = SIMPLEQ_FIRST(&sc->sc_evt_sas_queue);
+ if (rcb != NULL) {
+ next = SIMPLEQ_NEXT(rcb, rcb_link);
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_evt_sas_queue, rcb_link);
+ }
+ mtx_leave(&sc->sc_evt_sas_mtx);
- if (tcl->num_entries == 0)
+ if (rcb == NULL)
return;
+ if (next != NULL)
+ task_add(systq, &sc->sc_evt_sas_task);
+ enp = (struct mpii_msg_event_reply *)rcb->rcb_reply;
+ tcl = (struct mpii_evt_sas_tcl *)(enp + 1);
pe = (struct mpii_evt_phy_entry *)(tcl + 1);
for (i = 0; i < tcl->num_entries; i++, pe++) {
@@ -1699,12 +1719,8 @@ mpii_event_sas(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
letoh16(pe->dev_handle));
break;
}
- dev = malloc(sizeof(*dev), M_DEVBUF, M_NOWAIT | M_ZERO);
- if (!dev) {
- printf("%s: failed to allocate a "
- "device structure\n", DEVNAME(sc));
- break;
- }
+
+ dev = malloc(sizeof(*dev), M_DEVBUF, M_WAITOK | M_ZERO);
dev->slot = sc->sc_pd_id_start + tcl->start_phy_num + i;
dev->dev_handle = letoh16(pe->dev_handle);
dev->phy_num = tcl->start_phy_num + i;
@@ -1712,37 +1728,36 @@ mpii_event_sas(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
dev->physical_port = tcl->physical_port;
dev->enclosure = letoh16(tcl->enclosure_handle);
dev->expander = letoh16(tcl->expander_handle);
+
if (mpii_insert_dev(sc, dev)) {
free(dev, M_DEVBUF);
break;
}
- if (sc->sc_scsibus) {
- SET(dev->flags, MPII_DF_ATTACH);
- if (scsi_task(mpii_event_defer, sc,
- dev, 0) != 0)
- printf("%s: unable to run device "
- "attachment routine\n",
- DEVNAME(sc));
- }
+
+ if (sc->sc_scsibus != NULL)
+ scsi_probe_target(sc->sc_scsibus, dev->slot);
break;
+
case MPII_EVENT_SAS_TOPO_PS_RC_MISSING:
- if (!(dev = mpii_find_dev(sc,
- letoh16(pe->dev_handle))))
+ dev = mpii_find_dev(sc, letoh16(pe->dev_handle));
+ if (dev == NULL)
break;
+
mpii_remove_dev(sc, dev);
- if (sc->sc_scsibus) {
- SET(dev->flags, MPII_DF_DETACH);
+ mpii_sas_remove_device(sc, dev->dev_handle);
+ if (sc->sc_scsibus != NULL &&
+ !ISSET(dev->flags, MPII_DF_HIDDEN)) {
scsi_activate(sc->sc_scsibus, dev->slot, -1,
DVACT_DEACTIVATE);
- if (scsi_task(mpii_event_defer, sc,
- dev, 0) != 0)
- printf("%s: unable to run device "
- "detachment routine\n",
- DEVNAME(sc));
+ scsi_detach_target(sc->sc_scsibus, dev->slot,
+ DETACH_FORCE);
}
- break;
+
+ free(dev, M_DEVBUF);
}
}
+
+ mpii_event_done(sc, rcb);
}
void
@@ -1771,8 +1786,11 @@ mpii_event_process(struct mpii_softc *sc, struct mpii_rcb *rcb)
}
break;
case MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
- mpii_event_sas(sc, enp);
- break;
+ mtx_enter(&sc->sc_evt_sas_mtx);
+ SIMPLEQ_INSERT_TAIL(&sc->sc_evt_sas_queue, rcb, rcb_link);
+ mtx_leave(&sc->sc_evt_sas_mtx);
+ task_add(systq, &sc->sc_evt_sas_task);
+ return;
case MPII_EVENT_SAS_DEVICE_STATUS_CHANGE:
break;
case MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
@@ -1794,7 +1812,8 @@ mpii_event_process(struct mpii_softc *sc, struct mpii_rcb *rcb)
if (cold)
break;
- if (!(dev = mpii_find_dev(sc, letoh16(evd->vol_dev_handle))))
+ dev = mpii_find_dev(sc, letoh16(evd->vol_dev_handle));
+ if (dev == NULL)
break;
#if NBIO > 0
if (evd->reason_code == MPII_EVENT_IR_VOL_RC_STATE_CHANGED)
@@ -1820,9 +1839,9 @@ mpii_event_process(struct mpii_softc *sc, struct mpii_rcb *rcb)
(struct mpii_evt_ir_status *)(enp + 1);
struct mpii_device *dev;
- if (!(dev = mpii_find_dev(sc, letoh16(evs->vol_dev_handle))))
- break;
- if (evs->operation == MPII_EVENT_IR_RAIDOP_RESYNC)
+ dev = mpii_find_dev(sc, letoh16(evs->vol_dev_handle));
+ if (dev != NULL &&
+ evs->operation == MPII_EVENT_IR_RAIDOP_RESYNC)
dev->percent = evs->percent;
break;
}
@@ -1849,27 +1868,6 @@ mpii_event_done(struct mpii_softc *sc, struct mpii_rcb *rcb)
}
void
-mpii_event_defer(void *xsc, void *arg)
-{
- struct mpii_softc *sc = xsc;
- struct mpii_device *dev = arg;
-
- if (ISSET(dev->flags, MPII_DF_DETACH)) {
- mpii_sas_remove_device(sc, dev->dev_handle);
- if (!ISSET(dev->flags, MPII_DF_HIDDEN)) {
- scsi_detach_target(sc->sc_scsibus, dev->slot,
- DETACH_FORCE);
- }
- free(dev, M_DEVBUF);
-
- } else if (ISSET(dev->flags, MPII_DF_ATTACH)) {
- CLR(dev->flags, MPII_DF_ATTACH);
- if (!ISSET(dev->flags, MPII_DF_HIDDEN))
- scsi_probe_target(sc->sc_scsibus, dev->slot);
- }
-}
-
-void
mpii_sas_remove_device(struct mpii_softc *sc, u_int16_t handle)
{
struct mpii_msg_scsi_task_request *stq;
@@ -2656,8 +2654,9 @@ mpii_wait_done(struct mpii_ccb *ccb)
mtx_enter(mtx);
ccb->ccb_cookie = NULL;
- wakeup_one(ccb);
mtx_leave(mtx);
+
+ wakeup_one(ccb);
}
void