? ChangeLog
Index: wd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/wd.c,v
retrieving revision 1.443
diff -p -u -r1.443 wd.c
--- wd.c	24 Oct 2018 19:46:44 -0000	1.443
+++ wd.c	10 Mar 2019 17:42:01 -0000
@@ -321,6 +321,7 @@ wdattach(device_t parent, device_t self,
 	SLIST_INIT(&wd->sc_bslist);
 #endif
 	wd->atabus = adev->adev_bustype;
+	wd->inflight = 0;
 	wd->drvp = adev->adev_drv_data;
 
 	wd->drvp->drv_openings = 1;
@@ -724,6 +730,7 @@ wdstart1(struct wd_softc *wd, struct buf
 		xfer->c_bio.flags |= ATA_FUA;
 	}
 
+	wd->inflight++;
 	switch (wd->atabus->ata_bio(wd->drvp, xfer)) {
 	case ATACMD_TRY_AGAIN:
 		panic("wdstart1: try again");
@@ -744,10 +751,25 @@ wd_diskstart(device_t dev, struct buf *b
 	struct dk_softc *dksc = &wd->sc_dksc;
 #endif
 	struct ata_xfer *xfer;
+	struct ata_channel *chp;
+	unsigned openings;
 
 	mutex_enter(&wd->sc_lock);
 
-	xfer = ata_get_xfer(wd->drvp->chnl_softc, false);
+	chp = wd->drvp->chnl_softc;
+
+	ata_channel_lock(chp);
+	openings = ata_queue_openings(chp);
+	ata_channel_unlock(chp);
+
+	openings = uimin(openings, wd->drvp->drv_openings);
+
+	if (wd->inflight >= openings) {
+		mutex_exit(&wd->sc_lock);
+		return EAGAIN;
+	}
+
+	xfer = ata_get_xfer(chp, false);
 	if (xfer == NULL) {
 		ATADEBUG_PRINT(("wd_diskstart %s no xfer\n",
 		    dksc->sc_xname), DEBUG_XFERS);
@@ -947,7 +969,9 @@ noerror:	if ((xfer->c_bio.flags & ATA_CO
 
 	ata_free_xfer(wd->drvp->chnl_softc, xfer);
 
+	wd->inflight--;
 	dk_done(dksc, bp);
+	dk_start(dksc, NULL);
 }
 
 static void
Index: wdvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/wdvar.h,v
retrieving revision 1.47
diff -p -u -r1.47 wdvar.h
--- wdvar.h	22 Oct 2018 20:13:47 -0000	1.47
+++ wdvar.h	10 Mar 2019 17:42:01 -0000
@@ -86,6 +86,8 @@ struct wd_softc {
 	int drv_chaos_freq;		/* frequency of simulated bio errors */
 	int drv_chaos_cnt;		/* count of processed bio read xfers */
 #endif
+	unsigned inflight;
 };
 
 #endif /* _DEV_ATA_WDVAR_H_ */
