if you have a twe, let me first say how sorry i am for you.

this cuts twe over to using iopools. it gets the usual benefits of
more reliable ioctl paths, better io scheduling between volumes and
the pt busses, and a removal of NO_CCB.

it is a bit more than a straight conversion, it also moves the
draining of the async event notification over to iohandlers. this
simplifies them a bit and makes them reliable when the controller
is under load.

i dont have an twe, so i cant test this. id like more than an ok
from gcc before committing this.

Index: twe.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/twe.c,v
retrieving revision 1.38
diff -u -p -r1.38 twe.c
--- twe.c       20 Sep 2010 06:17:49 -0000      1.38
+++ twe.c       3 Apr 2011 14:23:55 -0000
@@ -70,8 +70,8 @@ struct scsi_adapter twe_switch = {
        twe_scsi_cmd, tweminphys, 0, 0,
 };
 
-static __inline struct twe_ccb *twe_get_ccb(struct twe_softc *sc);
-static __inline void twe_put_ccb(struct twe_ccb *ccb);
+void *twe_get_ccb(void *);
+void twe_put_ccb(void *, void *);
 void twe_dispose(struct twe_softc *sc);
 int  twe_cmd(struct twe_ccb *ccb, int flags, int wait);
 int  twe_start(struct twe_ccb *ccb, int wait);
@@ -80,28 +80,33 @@ int  twe_done(struct twe_softc *sc, stru
 void twe_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size);
 void twe_thread_create(void *v);
 void twe_thread(void *v);
+void twe_aen(void *, void *);
 
-
-static __inline struct twe_ccb *
-twe_get_ccb(sc)
-       struct twe_softc *sc;
+void *
+twe_get_ccb(void *xsc)
 {
+       struct twe_softc *sc = xsc;
        struct twe_ccb *ccb;
 
+       mtx_enter(&sc->sc_ccb_mtx);
        ccb = TAILQ_LAST(&sc->sc_free_ccb, twe_queue_head);
-       if (ccb)
+       if (ccb != NULL)
                TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_link);
-       return ccb;
+       mtx_leave(&sc->sc_ccb_mtx);
+
+       return (ccb);
 }
 
-static __inline void
-twe_put_ccb(ccb)
-       struct twe_ccb *ccb;
+void
+twe_put_ccb(void *xsc, void *xccb)
 {
-       struct twe_softc *sc = ccb->ccb_sc;
+       struct twe_softc *sc = xsc;
+       struct twe_ccb *ccb = xccb;
 
        ccb->ccb_state = TWE_CCB_FREE;
+       mtx_enter(&sc->sc_ccb_mtx);
        TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
+       mtx_leave(&sc->sc_ccb_mtx);
 }
 
 void
@@ -176,6 +181,10 @@ twe_attach(sc)
        TAILQ_INIT(&sc->sc_ccbq);
        TAILQ_INIT(&sc->sc_free_ccb);
        TAILQ_INIT(&sc->sc_done_ccb);
+       mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
+       scsi_iopool_init(&sc->sc_iopool, sc, twe_get_ccb, twe_put_ccb);
+
+       scsi_ioh_set(&sc->sc_aen, &sc->sc_iopool, twe_aen, sc);
 
        pa = sc->sc_cmdmap->dm_segs[0].ds_addr +
            sizeof(struct twe_cmd) * (TWE_MAXCMDS - 1);
@@ -238,9 +247,10 @@ twe_attach(sc)
                /* drain aen queue */
                for (veseen_srst = 0, aen = -1; aen != TWE_AEN_QEMPTY; ) {
 
-                       if ((ccb = twe_get_ccb(sc)) == NULL) {
+                       ccb = scsi_io_get(&sc->sc_iopool, 0);
+                       if (ccb == NULL) {
                                errstr = ": out of ccbs\n";
-                               continue;
+                               break;
                        }
 
                        ccb->ccb_xs = NULL;
@@ -256,10 +266,13 @@ twe_attach(sc)
                        pb->param_id = 2;
                        pb->param_size = 2;
 
-                       if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
+                       error = twe_cmd(ccb, BUS_DMA_NOWAIT, 1);
+                       scsi_io_put(&sc->sc_iopool, ccb);
+                       if (error) {
                                errstr = ": error draining attention queue\n";
                                break;
                        }
+
                        aen = *(u_int16_t *)pb->data;
                        TWE_DPRINTF(TWE_D_AEN, ("aen=%x ", aen));
                        if (aen == TWE_AEN_SRST)
@@ -305,7 +318,8 @@ twe_attach(sc)
                return 1;
        }
 
-       if ((ccb = twe_get_ccb(sc)) == NULL) {
+       ccb = scsi_io_get(&sc->sc_iopool, 0);
+       if (ccb == NULL) {
                printf(": out of ccbs\n");
                twe_dispose(sc);
                return 1;
@@ -323,7 +337,10 @@ twe_attach(sc)
        pb->table_id = TWE_PARAM_UC;
        pb->param_id = TWE_PARAM_UC;
        pb->param_size = TWE_MAX_UNITS;
-       if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
+
+       error = twe_cmd(ccb, BUS_DMA_NOWAIT, 1);
+       scsi_io_put(&sc->sc_iopool, ccb);
+       if (error) {
                printf(": failed to fetch unit parameters\n");
                twe_dispose(sc);
                return 1;
@@ -336,7 +353,8 @@ twe_attach(sc)
                if (pb->data[i] == 0)
                        continue;
 
-               if ((ccb = twe_get_ccb(sc)) == NULL) {
+               ccb = scsi_io_get(&sc->sc_iopool, 0);
+               if (ccb == NULL) {
                        printf(": out of ccbs\n");
                        twe_dispose(sc);
                        return 1;
@@ -354,14 +372,16 @@ twe_attach(sc)
                cap->table_id = TWE_PARAM_UI + i;
                cap->param_id = 4;
                cap->param_size = 4;    /* 4 bytes */
+
                lock = TWE_LOCK(sc);
-               if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
-                       TWE_UNLOCK(sc, lock);
+               twe_cmd(ccb, BUS_DMA_NOWAIT, 1);
+               TWE_UNLOCK(sc, lock);
+               scsi_io_put(&sc->sc_iopool, ccb);
+               if (error) {
                        printf("%s: error fetching capacity for unit %d\n",
                            sc->sc_dev.dv_xname, i);
                        continue;
                }
-               TWE_UNLOCK(sc, lock);
 
                nunits++;
                sc->sc_hdr[i].hd_present = 1;
@@ -381,6 +401,7 @@ twe_attach(sc)
        sc->sc_link.adapter_target = TWE_MAX_UNITS;
        sc->sc_link.openings = TWE_MAXCMDS / nunits;
        sc->sc_link.adapter_buswidth = TWE_MAX_UNITS;
+       sc->sc_link.pool = &sc->sc_iopool;
 
        bzero(&saa, sizeof(saa));
        saa.saa_sc_link = &sc->sc_link;
@@ -493,7 +514,6 @@ twe_cmd(ccb, flags, wait)
                    BUS_DMA_NOWAIT);
                if (error) {
                        TWE_DPRINTF(TWE_D_DMA, ("2buf alloc failed(%d) ", 
error));
-                       twe_put_ccb(ccb);
                        return (ENOMEM);
                }
 
@@ -502,7 +522,6 @@ twe_cmd(ccb, flags, wait)
                if (error) {
                        TWE_DPRINTF(TWE_D_DMA, ("2buf map failed(%d) ", error));
                        bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, 
ccb->ccb_2nseg);
-                       twe_put_ccb(ccb);
                        return (ENOMEM);
                }
                bcopy(ccb->ccb_realdata, ccb->ccb_data, ccb->ccb_length);
@@ -528,7 +547,6 @@ twe_cmd(ccb, flags, wait)
                                bus_dmamem_free(sc->dmat, ccb->ccb_2bseg,
                                    ccb->ccb_2nseg);
                        }
-                       twe_put_ccb(ccb);
                        return error;
                }
                /* load addresses into command */
@@ -579,7 +597,6 @@ twe_cmd(ccb, flags, wait)
                        bus_dmamem_free(sc->dmat, ccb->ccb_2bseg,
                            ccb->ccb_2nseg);
                }
-               twe_put_ccb(ccb);
                return (error);
        }
 
@@ -728,7 +745,6 @@ twe_done(sc, ccb)
        }
 
        lock = TWE_LOCK(sc);
-       twe_put_ccb(ccb);
 
        if (xs) {
                xs->resid = 0;
@@ -771,7 +787,7 @@ twe_scsi_cmd(xs)
 {
        struct scsi_link *link = xs->sc_link;
        struct twe_softc *sc = link->adapter_softc;
-       struct twe_ccb *ccb;
+       struct twe_ccb *ccb = xs->io;
        struct twe_cmd *cmd;
        struct scsi_inquiry_data inq;
        struct scsi_sense_data sd;
@@ -893,13 +909,6 @@ twe_scsi_cmd(xs)
                default:                op = TWE_CMD_NOP;       break;
                }
 
-               if ((ccb = twe_get_ccb(sc)) == NULL) {
-                       xs->error = XS_NO_CCB;
-                       scsi_done(xs);
-                       TWE_UNLOCK(sc, lock);
-                       return;
-               }
-
                ccb->ccb_xs = xs;
                ccb->ccb_data = xs->data;
                ccb->ccb_length = xs->datalen;
@@ -940,9 +949,7 @@ twe_intr(v)
 {
        struct twe_softc *sc = v;
        struct twe_ccb  *ccb;
-       struct twe_cmd  *cmd;
        u_int32_t       status;
-       twe_lock_t      lock;
        int             rv = 0;
 
        status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
@@ -993,8 +1000,6 @@ twe_intr(v)
                wakeup(sc);
 
        if (status & TWE_STAT_ATTNI) {
-               u_int16_t aen;
-
                /*
                 * we know no attentions of interest right now.
                 * one of those would be mirror degradation i think.
@@ -1004,37 +1009,52 @@ twe_intr(v)
                bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
                    TWE_CTRL_CATTNI);
 
-               lock = TWE_LOCK(sc);
-               for (aen = -1; aen != TWE_AEN_QEMPTY; ) {
-                       u_int8_t param_buf[2 * TWE_SECTOR_SIZE + TWE_ALIGN - 1];
-                       struct twe_param *pb = (void *) (((u_long)param_buf +
-                           TWE_ALIGN - 1) & ~(TWE_ALIGN - 1));
+               scsi_ioh_add(&sc->sc_aen);
+       }
 
-                       if ((ccb = twe_get_ccb(sc)) == NULL)
-                               break;
+       return rv;
+}
 
-                       ccb->ccb_xs = NULL;
-                       ccb->ccb_data = pb;
-                       ccb->ccb_length = TWE_SECTOR_SIZE;
-                       ccb->ccb_state = TWE_CCB_READY;
-                       cmd = ccb->ccb_cmd;
-                       cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
-                       cmd->cmd_op = TWE_CMD_GPARAM;
-                       cmd->cmd_flags = 0;
-                       cmd->cmd_param.count = 1;
+void
+twe_aen(void *cookie, void *io)
+{
+       struct twe_softc *sc = cookie;
+       struct twe_ccb *ccb = io;
+       struct twe_cmd *cmd = ccb->ccb_cmd;
 
-                       pb->table_id = TWE_PARAM_AEN;
-                       pb->param_id = 2;
-                       pb->param_size = 2;
-                       if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
-                               printf(": error draining attention queue\n");
-                               break;
-                       }
-                       aen = *(u_int16_t *)pb->data;
-                       TWE_DPRINTF(TWE_D_AEN, ("aen=%x ", aen));
-               }
-               TWE_UNLOCK(sc, lock);
+       u_int8_t param_buf[2 * TWE_SECTOR_SIZE + TWE_ALIGN - 1];
+       struct twe_param *pb = (void *) (((u_long)param_buf +
+           TWE_ALIGN - 1) & ~(TWE_ALIGN - 1));
+       u_int16_t aen;
+
+       twe_lock_t lock;
+       int error;
+
+       ccb->ccb_xs = NULL;
+       ccb->ccb_data = pb;
+       ccb->ccb_length = TWE_SECTOR_SIZE;
+       ccb->ccb_state = TWE_CCB_READY;
+       cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
+       cmd->cmd_op = TWE_CMD_GPARAM;
+       cmd->cmd_flags = 0;
+       cmd->cmd_param.count = 1;
+
+       pb->table_id = TWE_PARAM_AEN;
+       pb->param_id = 2;
+       pb->param_size = 2;
+
+       lock = TWE_LOCK(sc);
+       error = twe_cmd(ccb, BUS_DMA_NOWAIT, 1);
+       TWE_UNLOCK(sc, lock);
+       scsi_io_put(&sc->sc_iopool, ccb);
+
+       if (error) {
+               printf("%s: error draining attention queue\n",
+                   sc->sc_dev.dv_xname);
+               return;
        }
 
-       return rv;
+       aen = *(u_int16_t *)pb->data;
+       if (aen != TWE_AEN_QEMPTY) 
+               scsi_ioh_add(&sc->sc_aen);
 }
Index: twevar.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/twevar.h,v
retrieving revision 1.9
diff -u -p -r1.9 twevar.h
--- twevar.h    16 Feb 2009 21:19:07 -0000      1.9
+++ twevar.h    3 Apr 2011 14:23:55 -0000
@@ -67,8 +67,12 @@ struct twe_softc {
        twe_queue_head  sc_ccbq;
        twe_queue_head  sc_ccb2q;
        twe_queue_head  sc_done_ccb;
+       struct mutex    sc_ccb_mtx;
+       struct scsi_iopool sc_iopool;
 
        struct timeout  sc_enqueue_tmo;
+
+       struct scsi_iohandler sc_aen;
 
        struct {
                int     hd_present;

Reply via email to