this gets rid of NO_CCB in vdsk. it considers space on the tx ring
as the resource the iopool is managing, but gated by the availability
of the service domain. it takes advantage of the newly available
scsi_iopool_run() interface to restart io when the domain providing
a disk comes back.

is anyone able to test this?

Index: vdsk.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/dev/vdsk.c,v
retrieving revision 1.33
diff -u -p -r1.33 vdsk.c
--- vdsk.c      12 May 2013 19:33:01 -0000      1.33
+++ vdsk.c      18 Jan 2014 20:35:06 -0000
@@ -158,6 +158,7 @@ struct vdsk_softc {
        struct vdsk_dring *sc_vd;
        struct vdsk_soft_desc *sc_vsd;
 
+       struct scsi_iopool sc_iopool;
        struct scsi_adapter sc_switch;
        struct scsi_link sc_link;
 
@@ -198,6 +199,9 @@ void        vdsk_send_attr_info(struct vdsk_sof
 void   vdsk_send_dring_reg(struct vdsk_softc *);
 void   vdsk_send_rdx(struct vdsk_softc *);
 
+void * vdsk_io_get(void *);
+void   vdsk_io_put(void *, void *);
+
 void   vdsk_scsi_cmd(struct scsi_xfer *);
 int    vdsk_dev_probe(struct scsi_link *);
 void   vdsk_dev_free(struct scsi_link *);
@@ -340,6 +344,8 @@ vdsk_attach(struct device *parent, struc
        if (sc->sc_vio_state != VIO_ESTABLISHED)
                return;
 
+       scsi_iopool_init(&sc->sc_iopool, sc, vdsk_io_get, vdsk_io_put);
+
        sc->sc_switch.scsi_cmd = vdsk_scsi_cmd;
        sc->sc_switch.scsi_minphys = scsi_minphys;
        sc->sc_switch.dev_probe = vdsk_dev_probe;
@@ -351,6 +357,7 @@ vdsk_attach(struct device *parent, struc
        sc->sc_link.luns = 1; /* XXX slices should be presented as luns? */
        sc->sc_link.adapter_target = 2;
        sc->sc_link.openings = sc->sc_vd->vd_nentries - 1;
+       sc->sc_link.pool = &sc->sc_iopool;
 
        bzero(&saa, sizeof(saa));
        saa.saa_sc_link = &sc->sc_link;
@@ -656,6 +663,9 @@ vdsk_rx_vio_rdx(struct vdsk_softc *sc, s
                DPRINTF(("CTRL/0x%02x/RDX (VIO)\n", tag->stype));
                break;
        }
+
+       if (sc->sc_vio_state == VIO_ESTABLISHED)
+               scsi_iopool_run(&sc->sc_iopool);
 }
 
 void
@@ -718,7 +728,6 @@ vdsk_rx_vio_dring_data(struct vdsk_softc
 
                        sc->sc_vd->vd_desc[cons++].hdr.dstate = VIO_DESC_FREE;
                        cons &= (sc->sc_vd->vd_nentries - 1);
-                       sc->sc_tx_cnt--;
                }
                sc->sc_tx_cons = cons;
                break;
@@ -917,6 +926,40 @@ vdsk_dring_free(bus_dma_tag_t t, struct 
        free(vd, M_DEVBUF);
 }
 
+void *
+vdsk_io_get(void *xsc)
+{
+       struct vdsk_softc *sc = xsc;
+       void *rv = sc; /* just has to be !NULL */
+       int s;
+
+       s = splbio();
+       if (sc->sc_vio_state != VIO_ESTABLISHED &&
+           sc->sc_tx_cnt >= sc->sc_vd->vd_nentries)
+               rv = NULL;
+       else
+               sc->sc_tx_cnt++;
+       splx(s);
+
+       return (rv);
+}
+
+void
+vdsk_io_put(void *xsc, void *io)
+{
+       struct vdsk_softc *sc = xsc;
+       int s;
+
+#ifdef DIAGNOSTIC
+       if (sc != io)
+               panic("vsdk_io_put: unexpected io");
+#endif
+
+       s = splbio();
+       sc->sc_tx_cnt--;
+       splx(s);
+}
+
 void
 vdsk_scsi_cmd(struct scsi_xfer *xs)
 {
@@ -1005,14 +1048,6 @@ vdsk_scsi_cmd(struct scsi_xfer *xs)
        int timeout;
 
        s = splbio();
-       if (sc->sc_vio_state != VIO_ESTABLISHED ||
-           sc->sc_tx_cnt >= sc->sc_vd->vd_nentries) {
-               xs->error = XS_NO_CCB;
-               scsi_done(xs);
-               splx(s);
-               return;
-       }
-
        desc = sc->sc_tx_prod;
 
        ncookies = 0;
@@ -1055,7 +1090,6 @@ vdsk_scsi_cmd(struct scsi_xfer *xs)
 
        sc->sc_tx_prod++;
        sc->sc_tx_prod &= (sc->sc_vd->vd_nentries - 1);
-       sc->sc_tx_cnt++;
 
        bzero(&dm, sizeof(dm));
        dm.tag.type = VIO_TYPE_DATA;

Reply via email to