Index: sys/dev/virtio/scsi/virtio_scsi.c =================================================================== --- sys/dev/virtio/scsi/virtio_scsi.c +++ sys/dev/virtio/scsi/virtio_scsi.c @@ -286,6 +286,7 @@ VTSCSI_LOCK_INIT(sc, device_get_nameunit(dev)); TAILQ_INIT(&sc->vtscsi_req_free); + TAILQ_INIT(&sc->vtscsi_resrc_pend); vtscsi_get_tunables(sc); vtscsi_setup_sysctl(sc); @@ -751,7 +752,10 @@ switch (ccbh->func_code) { case XPT_SCSI_IO: - vtscsi_cam_scsi_io(sc, sim, ccb); + if (!TAILQ_EMPTY(&sc->vtscsi_resrc_pend)) + TAILQ_INSERT_TAIL(&sc->vtscsi_resrc_pend, ccbh, sim_links.tqe); + else + vtscsi_cam_scsi_io(sc, sim, ccb); break; case XPT_SET_TRAN_SETTINGS: @@ -1129,10 +1133,11 @@ if (error) { vtscsi_dprintf(sc, VTSCSI_ERROR, "enqueue error=%d req=%p ccb=%p\n", error, req, ccbh); - - ccbh->status = CAM_REQUEUE_REQ; - vtscsi_freeze_simq(sc, VTSCSI_REQUEST_VQ); - return (error); + ccbh->sim_priv.entries[0].field = (readable + writable); + vtscsi_enqueue_request(sc, req); + TAILQ_INSERT_TAIL(&sc->vtscsi_resrc_pend, ccbh, sim_links.tqe); + sc->vtscsi_stats.num_pends++; + return 0; } ccbh->status |= CAM_SIM_QUEUED; @@ -1383,6 +1388,7 @@ struct ccb_scsiio *csio; struct virtio_scsi_cmd_resp *cmd_resp; cam_status status; + uint16_t nfree; csio = &req->vsr_ccb->csio; ccbh = &csio->ccb_h; @@ -1415,6 +1421,16 @@ ccbh->status = status; xpt_done(req->vsr_ccb); vtscsi_enqueue_request(sc, req); + while (!TAILQ_EMPTY(&sc->vtscsi_resrc_pend)) { + ccbh = TAILQ_FIRST(&sc->vtscsi_resrc_pend); + nfree = virtqueue_nfree(sc->vtscsi_request_vq); + if (nfree >= ccbh->sim_priv.entries[0].field) { + TAILQ_REMOVE(&sc->vtscsi_resrc_pend, ccbh, sim_links.tqe); + vtscsi_cam_scsi_io(sc, sc->vtscsi_sim, (union ccb *)ccbh); + } else + /* Can't satisfy the request. */ + break; + } } static void @@ -2329,6 +2345,8 @@ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dequeue_no_requests", CTLFLAG_RD, &stats->dequeue_no_requests, "No available requests to dequeue"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "num_pends", CTLFLAG_RD, + &stats->num_pends, "SCSI commands pended"); } static void Index: sys/dev/virtio/scsi/virtio_scsivar.h =================================================================== --- sys/dev/virtio/scsi/virtio_scsivar.h +++ sys/dev/virtio/scsi/virtio_scsivar.h @@ -40,6 +40,7 @@ struct vtscsi_statistics { unsigned long scsi_cmd_timeouts; unsigned long dequeue_no_requests; + unsigned long num_pends; }; struct vtscsi_softc { @@ -83,6 +84,8 @@ struct virtio_scsi_event vtscsi_event_bufs[VTSCSI_NUM_EVENT_BUFS]; + TAILQ_HEAD(,ccb_hdr) vtscsi_resrc_pend; + struct vtscsi_statistics vtscsi_stats; };