summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2010-09-13 06:53:44 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2010-09-13 06:53:44 +0000
commit05cc86a36842da2f4003cb72c45c452162152ba4 (patch)
treec11d492c1a0342d1ad7acf5a06f1d91e1be82f7c /sys/dev
parent2032d75d465b2c78bb389f147b63ecd06421db17 (diff)
im not convinced we only have one outstanding event to ack at a time. this
steals^Wleverages the code used in mpii for handling a list of events to acknowlede. tested by hotplugging sas disks.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/mpi.c50
-rw-r--r--sys/dev/ic/mpivar.h8
2 files changed, 44 insertions, 14 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c
index 04f837b7656..4e1da0412a5 100644
--- a/sys/dev/ic/mpi.c
+++ b/sys/dev/ic/mpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpi.c,v 1.158 2010/09/10 07:00:56 dlg Exp $ */
+/* $OpenBSD: mpi.c,v 1.159 2010/09/13 06:53:21 dlg Exp $ */
/*
* Copyright (c) 2005, 2006, 2009 David Gwynne <dlg@openbsd.org>
@@ -2187,6 +2187,12 @@ mpi_eventnotify(struct mpi_softc *sc)
return (1);
}
+ sc->sc_evt_ccb = ccb;
+ 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,
+ mpi_eventack, sc);
+
ccb->ccb_done = mpi_eventnotify_done;
enq = ccb->ccb_cmd;
@@ -2195,8 +2201,6 @@ mpi_eventnotify(struct mpi_softc *sc)
enq->event_switch = MPI_EVENT_SWITCH_ON;
enq->msg_context = htole32(ccb->ccb_id);
- sc->sc_evt_ccb = ccb;
- scsi_ioh_set(&sc->sc_evt_ack, &sc->sc_iopool, mpi_eventack, sc);
mpi_start(sc, ccb);
return (0);
}
@@ -2205,7 +2209,8 @@ void
mpi_eventnotify_done(struct mpi_ccb *ccb)
{
struct mpi_softc *sc = ccb->ccb_sc;
- struct mpi_msg_event_reply *enp = ccb->ccb_rcb->rcb_reply;
+ struct mpi_rcb *rcb = ccb->ccb_rcb;
+ struct mpi_msg_event_reply *enp = rcb->rcb_reply;
DNPRINTF(MPI_D_EVT, "%s: mpi_eventnotify_done\n", DEVNAME(sc));
@@ -2235,7 +2240,7 @@ mpi_eventnotify_done(struct mpi_ccb *ccb)
if (sc->sc_scsibus == NULL)
break;
- mpi_evt_sas(sc, ccb->ccb_rcb);
+ mpi_evt_sas(sc, rcb);
break;
case MPI_EVENT_RESCAN:
@@ -2250,9 +2255,12 @@ mpi_eventnotify_done(struct mpi_ccb *ccb)
break;
}
- if (enp->ack_required)
- scsi_ioh_add(&sc->sc_evt_ack);
- else
+ if (enp->ack_required) {
+ mtx_enter(&sc->sc_evt_ack_mtx);
+ SIMPLEQ_INSERT_TAIL(&sc->sc_evt_ack_queue, rcb, rcb_link);
+ mtx_leave(&sc->sc_evt_ack_mtx);
+ scsi_ioh_add(&sc->sc_evt_ack_handler);
+ } else
mpi_push_reply(sc, ccb->ccb_rcb);
}
@@ -2363,23 +2371,41 @@ mpi_eventack(void *cookie, void *io)
{
struct mpi_softc *sc = cookie;
struct mpi_ccb *ccb = io;
- struct mpi_ccb *eccb = sc->sc_evt_ccb;
- struct mpi_msg_event_reply *enp = eccb->ccb_rcb->rcb_reply;
+ struct mpi_rcb *rcb, *next;
+ struct mpi_msg_event_reply *enp;
struct mpi_msg_eventack_request *eaq;
DNPRINTF(MPI_D_EVT, "%s: event ack\n", DEVNAME(sc));
+ mtx_enter(&sc->sc_evt_ack_mtx);
+ rcb = SIMPLEQ_FIRST(&sc->sc_evt_ack_queue);
+ if (rcb != NULL) {
+ next = SIMPLEQ_NEXT(rcb, rcb_link);
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_evt_ack_queue, rcb_link);
+ }
+ mtx_leave(&sc->sc_evt_ack_mtx);
+
+ if (rcb == NULL) {
+ scsi_io_put(&sc->sc_iopool, ccb);
+ return;
+ }
+
+ enp = rcb->rcb_reply;
+
ccb->ccb_done = mpi_eventack_done;
eaq = ccb->ccb_cmd;
eaq->function = MPI_FUNCTION_EVENT_ACK;
- eaq->msg_context = htole32(ccb->ccb_id);
+ eaq->msg_context = enp->msg_context;
eaq->event = enp->event;
eaq->event_context = enp->event_context;
- mpi_push_reply(sc, eccb->ccb_rcb);
+ mpi_push_reply(sc, rcb);
mpi_start(sc, ccb);
+
+ if (next != NULL)
+ scsi_ioh_add(&sc->sc_evt_ack_handler);
}
void
diff --git a/sys/dev/ic/mpivar.h b/sys/dev/ic/mpivar.h
index bc9875ff2c4..d06f7c70151 100644
--- a/sys/dev/ic/mpivar.h
+++ b/sys/dev/ic/mpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpivar.h,v 1.33 2010/09/10 07:00:56 dlg Exp $ */
+/* $OpenBSD: mpivar.h,v 1.34 2010/09/13 06:53:43 dlg Exp $ */
/*
* Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
@@ -68,10 +68,12 @@ struct mpi_ccb_bundle {
struct mpi_softc;
struct mpi_rcb {
+ SIMPLEQ_ENTRY(mpi_rcb) rcb_link;
void *rcb_reply;
bus_addr_t rcb_offset;
u_int32_t rcb_reply_dva;
};
+SIMPLEQ_HEAD(mpi_rcb_list, mpi_rcb);
struct mpi_ccb {
struct mpi_softc *ccb_sc;
@@ -134,7 +136,9 @@ struct mpi_softc {
int sc_repq;
struct mpi_ccb *sc_evt_ccb;
- struct scsi_iohandler sc_evt_ack;
+ struct mpi_rcb_list sc_evt_ack_queue;
+ struct mutex sc_evt_ack_mtx;
+ struct scsi_iohandler sc_evt_ack_handler;
struct workq_task sc_evt_rescan;
struct mutex sc_evt_rescan_mtx;