summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/mpii.c197
1 files changed, 93 insertions, 104 deletions
diff --git a/sys/dev/pci/mpii.c b/sys/dev/pci/mpii.c
index 87b9835b288..8eefe69903c 100644
--- a/sys/dev/pci/mpii.c
+++ b/sys/dev/pci/mpii.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpii.c,v 1.47 2011/07/21 01:03:30 sthen Exp $ */
+/* $OpenBSD: mpii.c,v 1.48 2011/08/29 12:42:18 dlg Exp $ */
/*
* Copyright (c) 2010 Mike Belopuhov <mkb@crypt.org.ru>
* Copyright (c) 2009 James Giannoules
@@ -1815,10 +1815,10 @@ struct mpii_ccb {
void (*ccb_done)(struct mpii_ccb *);
struct mpii_rcb *ccb_rcb;
- SLIST_ENTRY(mpii_ccb) ccb_link;
+ SIMPLEQ_ENTRY(mpii_ccb) ccb_link;
};
-SLIST_HEAD(mpii_ccb_list, mpii_ccb);
+SIMPLEQ_HEAD(mpii_ccb_list, mpii_ccb);
struct mpii_softc {
struct device sc_dev;
@@ -1844,7 +1844,6 @@ struct mpii_softc {
struct mutex sc_req_mtx;
struct mutex sc_rep_mtx;
- u_int sc_rep_sem;
u_int8_t sc_porttype;
int sc_request_depth;
@@ -1967,14 +1966,11 @@ struct mpii_device *mpii_find_dev(struct mpii_softc *, u_int16_t);
void mpii_start(struct mpii_softc *, struct mpii_ccb *);
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 *);
+struct mpii_rcb *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 *);
@@ -2161,24 +2157,19 @@ mpii_attach(struct device *parent, struct device *self, void *aux)
}
printf(": %s\n", pci_intr_string(sc->sc_pc, ih));
- sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_BIO,
- mpii_intr, sc, sc->sc_dev.dv_xname);
- if (sc->sc_ih == NULL)
- goto unmap;
-
if (mpii_init(sc) != 0) {
printf("%s: unable to initialize ioc\n", DEVNAME(sc));
- goto deintr;
+ goto unmap;
}
if (mpii_iocfacts(sc) != 0) {
printf("%s: unable to get iocfacts\n", DEVNAME(sc));
- goto deintr;
+ goto unmap;
}
if (mpii_alloc_ccbs(sc) != 0) {
/* error already printed */
- goto deintr;
+ goto unmap;
}
if (mpii_alloc_replies(sc) != 0) {
@@ -2254,6 +2245,11 @@ 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,
+ mpii_intr, sc, sc->sc_dev.dv_xname);
+ if (sc->sc_ih == NULL)
+ goto free_dev;
+
/* config_found() returns the scsibus attached to us */
sc->sc_scsibus = (struct scsibus_softc *) config_found(&sc->sc_dev,
&saa, scsiprint);
@@ -2303,10 +2299,6 @@ free_ccbs:
mpii_dmamem_free(sc, sc->sc_requests);
free(sc->sc_ccbs, M_DEVBUF);
-deintr:
- pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
- sc->sc_ih = NULL;
-
unmap:
bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
sc->sc_ios = 0;
@@ -2330,76 +2322,75 @@ mpii_detach(struct device *self, int flags)
}
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_rcb_list evts = SIMPLEQ_HEAD_INITIALIZER(evts);
+ struct mpii_ccb_list ccbs = SIMPLEQ_HEAD_INITIALIZER(ccbs);
struct mpii_softc *sc = arg;
struct mpii_reply_descr *postq = sc->sc_reply_postq_kva, *rdp;
+ struct mpii_ccb *ccb;
+ struct mpii_rcb *rcb;
+ int smid;
int rv = 0;
- if (!mpii_sem_enter(sc))
- return (0);
- do {
+ mtx_enter(&sc->sc_rep_mtx);
+ bus_dmamap_sync(sc->sc_dmat,
+ MPII_DMA_MAP(sc->sc_reply_postq),
+ 0, 8 * sc->sc_reply_post_qdepth,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
- for (;;) {
- bus_dmamap_sync(sc->sc_dmat,
- MPII_DMA_MAP(sc->sc_reply_postq),
- 0, 8 * sc->sc_reply_post_qdepth,
- BUS_DMASYNC_POSTWRITE);
+ for (;;) {
+ 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;
+ }
- 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;
- }
+ smid = letoh16(rdp->smid);
+ rcb = mpii_reply(sc, rdp);
- mpii_reply(sc, rdp);
+ if (smid) {
+ ccb = &sc->sc_ccbs[smid - 1];
+ ccb->ccb_state = MPII_CCB_READY;
+ ccb->ccb_rcb = rcb;
+ SIMPLEQ_INSERT_TAIL(&ccbs, ccb, ccb_link);
+ } else
+ SIMPLEQ_INSERT_TAIL(&evts, rcb, rcb_link);
- sc->sc_reply_post_host_index =
- (sc->sc_reply_post_host_index + 1) %
- sc->sc_reply_post_qdepth;
+ sc->sc_reply_post_host_index++;
+ sc->sc_reply_post_host_index %= sc->sc_reply_post_qdepth;
+ rv = 1;
+ }
- rv = 1;
- }
- if (rv)
- mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
+ bus_dmamap_sync(sc->sc_dmat,
+ MPII_DMA_MAP(sc->sc_reply_postq),
+ 0, 8 * sc->sc_reply_post_qdepth,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- } while (!mpii_sem_leave(sc));
+ if (rv)
+ mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
- return (rv);
+ mtx_leave(&sc->sc_rep_mtx);
+
+ if (rv == 0)
+ return (0);
+
+ while ((ccb = SIMPLEQ_FIRST(&ccbs)) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&ccbs, ccb_link);
+ ccb->ccb_done(ccb);
+ }
+ while ((rcb = SIMPLEQ_FIRST(&evts)) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&evts, rcb_link);
+ mpii_event_process(sc, rcb);
+ }
+
+ return (1);
}
int
@@ -3945,17 +3936,14 @@ mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int flags,
return (rv);
}
-int
+struct mpii_rcb *
mpii_reply(struct mpii_softc *sc, struct mpii_reply_descr *rdp)
{
- struct mpii_ccb *ccb = NULL;
struct mpii_rcb *rcb = NULL;
u_int32_t rfid;
- int smid;
DNPRINTF(MPII_D_INTR, "%s: mpii_reply\n", DEVNAME(sc));
- smid = letoh16(rdp->smid);
if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
MPII_REPLY_DESCR_ADDRESS_REPLY) {
rfid = (letoh32(rdp->frame_addr) -
@@ -3968,25 +3956,13 @@ mpii_reply(struct mpii_softc *sc, struct mpii_reply_descr *rdp)
rcb = &sc->sc_rcbs[rfid];
}
- DNPRINTF(MPII_D_INTR, "%s: mpii_reply reply_flags: %d smid: %d "
- "reply: %p\n", DEVNAME(sc), rdp->reply_flags, smid,
- rcb->rcb_reply);
-
memset(rdp, 0xff, sizeof(*rdp));
bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
8 * sc->sc_reply_post_host_index, 8,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
- if (smid) {
- ccb = &sc->sc_ccbs[smid - 1];
- ccb->ccb_state = MPII_CCB_READY;
- ccb->ccb_rcb = rcb;
- ccb->ccb_done(ccb);
- } else
- mpii_event_process(sc, rcb);
-
- return (smid);
+ return (rcb);
}
struct mpii_dmamem *
@@ -4109,8 +4085,8 @@ mpii_alloc_ccbs(struct mpii_softc *sc)
u_int8_t *cmd;
int i;
- SLIST_INIT(&sc->sc_ccb_free);
- SLIST_INIT(&sc->sc_ccb_tmos);
+ SIMPLEQ_INIT(&sc->sc_ccb_free);
+ SIMPLEQ_INIT(&sc->sc_ccb_tmos);
mtx_init(&sc->sc_ccb_free_mtx, IPL_BIO);
mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
scsi_ioh_set(&sc->sc_ccb_tmo_handler, &sc->sc_iopool,
@@ -4195,7 +4171,7 @@ mpii_put_ccb(void *cookie, void *io)
bzero(ccb->ccb_cmd, MPII_REQUEST_SIZE);
mtx_enter(&sc->sc_ccb_free_mtx);
- SLIST_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_link);
+ SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_link);
mtx_leave(&sc->sc_ccb_free_mtx);
}
@@ -4206,9 +4182,9 @@ mpii_get_ccb(void *cookie)
struct mpii_ccb *ccb;
mtx_enter(&sc->sc_ccb_free_mtx);
- ccb = SLIST_FIRST(&sc->sc_ccb_free);
+ ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free);
if (ccb != NULL) {
- SLIST_REMOVE_HEAD(&sc->sc_ccb_free, ccb_link);
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ccb_link);
ccb->ccb_state = MPII_CCB_READY;
}
mtx_leave(&sc->sc_ccb_free_mtx);
@@ -4554,7 +4530,7 @@ mpii_scsi_cmd_tmo(void *xccb)
mtx_enter(&sc->sc_ccb_mtx);
if (ccb->ccb_state == MPII_CCB_QUEUED) {
ccb->ccb_state = MPII_CCB_TIMEOUT;
- SLIST_INSERT_HEAD(&sc->sc_ccb_tmos, ccb, ccb_link);
+ SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_tmos, ccb, ccb_link);
}
mtx_leave(&sc->sc_ccb_mtx);
@@ -4570,9 +4546,9 @@ mpii_scsi_cmd_tmo_handler(void *cookie, void *io)
struct mpii_msg_scsi_task_request *stq;
mtx_enter(&sc->sc_ccb_mtx);
- ccb = SLIST_FIRST(&sc->sc_ccb_tmos);
+ ccb = SIMPLEQ_FIRST(&sc->sc_ccb_tmos);
if (ccb != NULL) {
- SLIST_REMOVE_HEAD(&sc->sc_ccb_tmos, ccb_link);
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_tmos, ccb_link);
ccb->ccb_state = MPII_CCB_QUEUED;
}
/* should remove any other ccbs for the same dev handle */
@@ -4601,6 +4577,7 @@ mpii_scsi_cmd_tmo_done(struct mpii_ccb *tccb)
void
mpii_scsi_cmd_done(struct mpii_ccb *ccb)
{
+ struct mpii_ccb *tccb;
struct mpii_msg_scsi_io_error *sie;
struct mpii_softc *sc = ccb->ccb_sc;
struct scsi_xfer *xs = ccb->ccb_cookie;
@@ -4609,8 +4586,20 @@ mpii_scsi_cmd_done(struct mpii_ccb *ccb)
timeout_del(&xs->stimeout);
mtx_enter(&sc->sc_ccb_mtx);
- if (ccb->ccb_state == MPII_CCB_TIMEOUT)
- SLIST_REMOVE(&sc->sc_ccb_tmos, ccb, mpii_ccb, ccb_link);
+ if (ccb->ccb_state == MPII_CCB_TIMEOUT) {
+ /* ENOSIMPLEQ_REMOVE :( */
+ if (ccb == SIMPLEQ_FIRST(&sc->sc_ccb_tmos))
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_tmos, ccb_link);
+ else {
+ SIMPLEQ_FOREACH(tccb, &sc->sc_ccb_tmos, ccb_link) {
+ if (SIMPLEQ_NEXT(tccb, ccb_link) == ccb) {
+ SIMPLEQ_REMOVE_NEXT(&sc->sc_ccb_tmos,
+ tccb, ccb_link);
+ break;
+ }
+ }
+ }
+ }
ccb->ccb_state = MPII_CCB_READY;
mtx_leave(&sc->sc_ccb_mtx);