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;