summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2010-07-09 22:33:22 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2010-07-09 22:33:22 +0000
commit39a01e6a9fabc042f5f0cbc690235e62446158a9 (patch)
tree7a317ec0d8eb1d1116048976324b06c131a0b9bc /sys/dev/pci
parentbde66da2738d9e8292c0f830a2d34d4d8bc231dd (diff)
rewrite the polling codepath in mpii.
it basically has the poll code swap the ccb completion path out for something that clears the flag the poll code is looping on. it just runs the interrupt handler to try and get that ccb back off the hardware. the reply queue is now protected by a semaphore, meaning that if one cpu is already pulling stuff off the chip, another cpu may try to also pull stuff off, but will return immediately cos the first cpu will end up doing the work it wants anyway. i did it this way so the ccb completion paths wouldnt be run while a mutex was held, and to avoid reordering of ccb completions and updates to the reply queue consumer that could be caused by allowing concurrent runs of the interrupt handler to step on each other. there is a big change here in that polling doesnt time out anymore. it keeps trying until it succeeds, or it keeps trying. i think it is dangerous to complete a ccb until th echip has returned it. the only safe alternative is to do a full reset of the chip, but that is a massive amount of work. reviewed by mikeb ok krw@ testing by me on real and logical disks
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/mpii.c184
1 files changed, 98 insertions, 86 deletions
diff --git a/sys/dev/pci/mpii.c b/sys/dev/pci/mpii.c
index cdedf0e198b..c04c585dacf 100644
--- a/sys/dev/pci/mpii.c
+++ b/sys/dev/pci/mpii.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpii.c,v 1.31 2010/07/07 10:29:17 dlg Exp $ */
+/* $OpenBSD: mpii.c,v 1.32 2010/07/09 22:33:21 dlg Exp $ */
/*
* Copyright (c) 2010 Mike Belopuhov <mkb@crypt.org.ru>
* Copyright (c) 2009 James Giannoules
@@ -1788,6 +1788,8 @@ struct mpii_softc {
bus_dma_tag_t sc_dmat;
struct mutex sc_req_mtx;
+ struct mutex sc_rep_mtx;
+ u_int sc_rep_sem;
u_int8_t sc_porttype;
int sc_request_depth;
@@ -1893,13 +1895,16 @@ int mpii_remove_dev(struct mpii_softc *, struct mpii_device *);
struct mpii_device *mpii_find_dev(struct mpii_softc *, u_int16_t);
void mpii_start(struct mpii_softc *, struct mpii_ccb *);
-int mpii_complete(struct mpii_softc *, struct mpii_ccb *, int);
-int mpii_poll(struct mpii_softc *, struct mpii_ccb *, int);
+int mpii_poll(struct mpii_softc *, struct mpii_ccb *);
+void mpii_poll_done(struct mpii_ccb *);
int mpii_reply(struct mpii_softc *, struct mpii_reply_descr *);
void mpii_wait(struct mpii_softc *, struct mpii_ccb *);
void mpii_wait_done(struct mpii_ccb *);
+int mpii_sem_enter(struct mpii_softc *);
+int mpii_sem_leave(struct mpii_softc *);
+
void mpii_init_queues(struct mpii_softc *);
int mpii_load_xs(struct mpii_ccb *);
@@ -2037,6 +2042,7 @@ mpii_attach(struct device *parent, struct device *self, void *aux)
sc->sc_dmat = pa->pa_dmat;
mtx_init(&sc->sc_req_mtx, IPL_BIO);
+ mtx_init(&sc->sc_rep_mtx, IPL_BIO);
/* find the appropriate memory base */
for (r = PCI_MAPREG_START; r < PCI_MAPREG_END; r += sizeof(memtype)) {
@@ -2240,41 +2246,75 @@ mpii_detach(struct device *self, int flags)
return (0);
}
+int
+mpii_sem_enter(struct mpii_softc *sc)
+{
+ int rv = 1;
+
+ mtx_enter(&sc->sc_rep_mtx);
+ sc->sc_rep_sem++;
+ if (sc->sc_rep_sem > 1)
+ rv = 0;
+ mtx_leave(&sc->sc_rep_mtx);
+
+ return (rv);
+}
+
+int
+mpii_sem_leave(struct mpii_softc *sc)
+{
+ int rv = 1;
+
+ mtx_enter(&sc->sc_rep_mtx);
+ sc->sc_rep_sem--;
+ if (sc->sc_rep_sem > 0)
+ rv = 0;
+ mtx_leave(&sc->sc_rep_mtx);
+
+ return (rv);
+}
int
mpii_intr(void *arg)
{
struct mpii_softc *sc = arg;
- struct mpii_reply_descr *rdp;
+ struct mpii_reply_descr *postq = sc->sc_reply_postq_kva, *rdp;
int rv = 0;
+ if (!mpii_sem_enter(sc))
+ return (0);
do {
- bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
- 0, 8 * sc->sc_reply_post_qdepth, BUS_DMASYNC_POSTWRITE);
- rdp = &sc->sc_reply_postq_kva[sc->sc_reply_post_host_index];
- if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
- MPII_REPLY_DESCR_UNUSED)
- break;
- if (rdp->data == 0xffffffff) {
- /*
- * ioc is still writing to the reply post queue
- * race condition - bail!
- */
- printf("%s: ioc is writing a reply @ %d/%d (kva %p)\n",
- DEVNAME(sc), sc->sc_reply_post_host_index,
- sc->sc_reply_post_qdepth, rdp);
- break;
+ for (;;) {
+ bus_dmamap_sync(sc->sc_dmat,
+ MPII_DMA_MAP(sc->sc_reply_postq),
+ 0, 8 * sc->sc_reply_post_qdepth,
+ BUS_DMASYNC_POSTWRITE);
+
+ rdp = &postq[sc->sc_reply_post_host_index];
+ if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
+ MPII_REPLY_DESCR_UNUSED)
+ break;
+ if (rdp->data == 0xffffffff) {
+ /*
+ * ioc is still writing to the reply post queue
+ * race condition - bail!
+ */
+ break;
+ }
+
+ mpii_reply(sc, rdp);
+
+ sc->sc_reply_post_host_index =
+ (sc->sc_reply_post_host_index + 1) %
+ sc->sc_reply_post_qdepth;
+
+ rv = 1;
}
- mpii_reply(sc, rdp);
- sc->sc_reply_post_host_index =
- (sc->sc_reply_post_host_index + 1) %
- sc->sc_reply_post_qdepth;
- rv |= 1;
- } while (1);
+ if (rv)
+ mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
- if (rv)
- mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
+ } while (!mpii_sem_leave(sc));
return (rv);
}
@@ -2980,7 +3020,7 @@ mpii_portfacts(struct mpii_softc *sc)
pfq->vp_id = 0;
pfq->vf_id = 0;
- if (mpii_poll(sc, ccb, 50000) != 0) {
+ if (mpii_poll(sc, ccb) != 0) {
DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts poll\n",
DEVNAME(sc));
goto err;
@@ -3078,7 +3118,7 @@ mpii_portenable(struct mpii_softc *sc)
peq->function = MPII_FUNCTION_PORT_ENABLE;
peq->vf_id = sc->sc_vf_id;
- if (mpii_poll(sc, ccb, 80000) != 0) {
+ if (mpii_poll(sc, ccb) != 0) {
DNPRINTF(MPII_D_MISC, "%s: mpii_portenable poll\n",
DEVNAME(sc));
return (1);
@@ -3639,7 +3679,7 @@ mpii_req_cfg_header(struct mpii_softc *sc, u_int8_t type, u_int8_t number,
ccb->ccb_done = mpii_empty_done;
if (ISSET(flags, MPII_PG_POLL)) {
- if (mpii_poll(sc, ccb, 5000) != 0) {
+ if (mpii_poll(sc, ccb) != 0) {
DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n",
DEVNAME(sc));
return (1);
@@ -3759,7 +3799,7 @@ mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int flags,
ccb->ccb_done = mpii_empty_done;
if (ISSET(flags, MPII_PG_POLL)) {
- if (mpii_poll(sc, ccb, 5000) != 0) {
+ if (mpii_poll(sc, ccb) != 0) {
DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n",
DEVNAME(sc));
return (1);
@@ -4163,53 +4203,42 @@ mpii_start(struct mpii_softc *sc, struct mpii_ccb *ccb)
}
int
-mpii_complete(struct mpii_softc *sc, struct mpii_ccb *ccb, int timeout)
+mpii_poll(struct mpii_softc *sc, struct mpii_ccb *ccb)
{
- struct mpii_reply_descr *rdp;
- int smid = -1;
+ void (*done)(struct mpii_ccb *);
+ void *cookie;
+ int rv = 1;
- DNPRINTF(MPII_D_INTR, "%s: mpii_complete timeout %d\n", DEVNAME(sc),
- timeout);
+ DNPRINTF(MPII_D_INTR, "%s: mpii_complete %d\n", DEVNAME(sc));
- timeout *= 100;
+ done = ccb->ccb_done;
+ cookie = ccb->ccb_cookie;
- do {
- /* avoid excessive polling */
- if (!mpii_reply_waiting(sc)) {
- if (timeout-- == 0)
- return (1);
- delay(10);
- continue;
- }
+ ccb->ccb_done = mpii_poll_done;
+ ccb->ccb_cookie = &rv;
- bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
- 0, 8 * sc->sc_reply_post_qdepth, BUS_DMASYNC_POSTWRITE);
+ mpii_start(sc, ccb);
- rdp = &sc->sc_reply_postq_kva[sc->sc_reply_post_host_index];
- if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
- MPII_REPLY_DESCR_UNUSED)
- continue;
- if (rdp->data == 0xffffffff) {
- /*
- * ioc is still writing to the reply post queue
- * race condition - bail!
- */
- printf("%s: ioc is writing a reply\n", DEVNAME(sc));
- continue;
- }
+ while (rv == 1) {
+ /* avoid excessive polling */
+ if (mpii_reply_waiting(sc))
+ mpii_intr(sc);
+ else
+ delay(10);
+ }
- smid = mpii_reply(sc, rdp);
+ ccb->ccb_cookie = cookie;
+ done(ccb);
- DNPRINTF(MPII_D_INTR, "%s: mpii_complete call to mpii_reply"
- "returned: %d\n", DEVNAME(sc), smid);
+ return (0);
+}
- sc->sc_reply_post_host_index =
- (sc->sc_reply_post_host_index + 1) %
- sc->sc_reply_post_qdepth;
- mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
- } while (ccb->ccb_smid != smid);
+void
+mpii_poll_done(struct mpii_ccb *ccb)
+{
+ int *rv = ccb->ccb_cookie;
- return (0);
+ *rv = 0;
}
int
@@ -4271,23 +4300,6 @@ mpii_init_queues(struct mpii_softc *sc)
mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
}
-int
-mpii_poll(struct mpii_softc *sc, struct mpii_ccb *ccb, int timeout)
-{
- int error;
- int s;
-
- DNPRINTF(MPII_D_CMD, "%s: mpii_poll: ccb %p cmd 0x%08x\n",
- DEVNAME(sc), ccb, ccb->ccb_cmd);
-
- s = splbio();
- mpii_start(sc, ccb);
- error = mpii_complete(sc, ccb, timeout);
- splx(s);
-
- return (error);
-}
-
void
mpii_wait(struct mpii_softc *sc, struct mpii_ccb *ccb)
{
@@ -4413,7 +4425,7 @@ mpii_scsi_cmd(struct scsi_xfer *xs)
io->sgl_offset0);
if (xs->flags & SCSI_POLL) {
- if (mpii_poll(sc, ccb, xs->timeout) != 0) {
+ if (mpii_poll(sc, ccb) != 0) {
xs->error = XS_DRIVER_STUFFUP;
scsi_done(xs);
}