summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2010-07-06 07:18:19 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2010-07-06 07:18:19 +0000
commitfd9d325d7abe216efd49db531c0f68af097fc940 (patch)
tree7133cecc347cc588f5a334a2e9f921cddd15fa71 /sys/dev
parent32835cbe3ad31fcb9a9111a9c4949497ddf84aaf (diff)
if we get an event notification that requires acknowledgement while
we're busy, we might not be able to allocate a ccb via scsi_ioh_get if the pool is empty. this means we wont ack the event, which in turn means we wont receive further event notifications. this cuts the event ack code over to using a scsi_iohandler. the eventack iohandler will be called as soon as a ccb becomes available for it to use. this guarantees reliable event handling and acknowledgement, despite how busy the controller might be. this has bugging me ever since i wrote the event handling code. tested by hotplugging sata disks.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/mpi.c33
-rw-r--r--sys/dev/ic/mpivar.h3
2 files changed, 15 insertions, 21 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c
index 845c5413de1..26d4ccf284c 100644
--- a/sys/dev/ic/mpi.c
+++ b/sys/dev/ic/mpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpi.c,v 1.154 2010/07/06 06:50:42 dlg Exp $ */
+/* $OpenBSD: mpi.c,v 1.155 2010/07/06 07:18:18 dlg Exp $ */
/*
* Copyright (c) 2005, 2006, 2009 David Gwynne <dlg@openbsd.org>
@@ -137,8 +137,7 @@ int mpi_scsi_probe_virtual(struct scsi_link *);
int mpi_eventnotify(struct mpi_softc *);
void mpi_eventnotify_done(struct mpi_ccb *);
-void mpi_eventack(struct mpi_softc *,
- struct mpi_msg_event_reply *);
+void mpi_eventack(void *, void *);
void mpi_eventack_done(struct mpi_ccb *);
void mpi_evt_sas(struct mpi_softc *, struct mpi_rcb *);
@@ -2191,6 +2190,7 @@ mpi_eventnotify(struct mpi_softc *sc)
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);
}
@@ -2239,15 +2239,9 @@ mpi_eventnotify_done(struct mpi_ccb *ccb)
}
if (enp->ack_required)
- mpi_eventack(sc, enp);
- mpi_push_reply(sc, ccb->ccb_rcb);
-
-#if 0
- /* fc hbas have a bad habit of setting this without meaning it. */
- if ((enp->msg_flags & MPI_EVENT_FLAGS_REPLY_KEPT) == 0) {
- scsi_io_put(&sc->sc_iopool, ccb);
- }
-#endif
+ scsi_ioh_add(&sc->sc_evt_ack);
+ else
+ mpi_push_reply(sc, ccb->ccb_rcb);
}
void
@@ -2293,16 +2287,15 @@ mpi_evt_sas(struct mpi_softc *sc, struct mpi_rcb *rcb)
}
void
-mpi_eventack(struct mpi_softc *sc, struct mpi_msg_event_reply *enp)
+mpi_eventack(void *cookie, void *io)
{
- struct mpi_ccb *ccb;
+ 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_msg_eventack_request *eaq;
- ccb = scsi_io_get(&sc->sc_iopool, SCSI_NOSLEEP);
- if (ccb == NULL) {
- DNPRINTF(MPI_D_EVT, "%s: mpi_eventack ccb_get\n", DEVNAME(sc));
- return;
- }
+ DNPRINTF(MPI_D_EVT, "%s: event ack\n", DEVNAME(sc));
ccb->ccb_done = mpi_eventack_done;
eaq = ccb->ccb_cmd;
@@ -2313,8 +2306,8 @@ mpi_eventack(struct mpi_softc *sc, struct mpi_msg_event_reply *enp)
eaq->event = enp->event;
eaq->event_context = enp->event_context;
+ mpi_push_reply(sc, eccb->ccb_rcb);
mpi_start(sc, ccb);
- return;
}
void
diff --git a/sys/dev/ic/mpivar.h b/sys/dev/ic/mpivar.h
index b5e43f0251d..eed69bfe6e5 100644
--- a/sys/dev/ic/mpivar.h
+++ b/sys/dev/ic/mpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpivar.h,v 1.31 2010/04/06 01:24:43 dlg Exp $ */
+/* $OpenBSD: mpivar.h,v 1.32 2010/07/06 07:18:18 dlg Exp $ */
/*
* Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
@@ -134,6 +134,7 @@ struct mpi_softc {
int sc_repq;
struct mpi_ccb *sc_evt_ccb;
+ struct scsi_iohandler sc_evt_ack;
size_t sc_fw_len;
struct mpi_dmamem *sc_fw;