Module Name:    src
Committed By:   martin
Date:           Fri Dec 30 14:39:10 UTC 2022

Modified Files:
        src/sys/dev/ata [netbsd-9]: ata.c ata_recovery.c ata_wdc.c atavar.h
            satapmp_subr.c wd.c
        src/sys/dev/ic [netbsd-9]: ahcisata_core.c mvsata.c siisata.c wdc.c
            wdcvar.h
        src/sys/dev/scsipi [netbsd-9]: atapi_wdc.c
        src/sys/dev/usb [netbsd-9]: umass_isdata.c

Log Message:
Pull up following revision(s) (requested by tsutsui in ticket #1557):

        sys/dev/ic/ahcisata_core.c: revision 1.83
        sys/dev/ic/ahcisata_core.c: revision 1.102
        sys/dev/ata/ata.c: revision 1.164
        sys/dev/ata/ata_wdc.c: revision 1.115
        sys/dev/ata/ata_recovery.c: revision 1.4
        sys/dev/ic/siisata.c: revision 1.42
        sys/dev/ic/wdc.c: revision 1.308
        sys/dev/ic/mvsata.c: revision 1.56
        sys/dev/scsipi/atapi_wdc.c: revision 1.138
        sys/dev/ic/siisata.c: revision 1.49
        sys/dev/ata/atavar.h: revision 1.105
        sys/dev/ata/wd.c: revision 1.460
        sys/dev/ata/ata.c: revision 1.155
        sys/dev/ata/wd.c: revision 1.462
        sys/dev/ata/atavar.h: revision 1.109
        sys/dev/ata/satapmp_subr.c: revision 1.16
        sys/dev/ic/wdc.c: revision 1.299
        sys/dev/ic/ahcisata_core.c: revision 1.93
        sys/dev/ata/ata_wdc.c: revision 1.120
        sys/dev/ic/wdcvar.h: revision 1.100
        sys/dev/scsipi/atapi_wdc.c: revision 1.141
        sys/dev/ic/mvsata.c: revision 1.61
        sys/dev/usb/umass_isdata.c      (apply patch)

drop wd lock in wdstart1() before calling the ata_bio hook; when called
from ata thread context, that can still need to sleep for wdc attachments
in wdcwait()

fix use-after-free for ata xfer on bio submission found by KASAN
driver ata_bio hooks read parts of the xfer after ata_exec_xfer()
call in order to determine return value, change so that the hook
doesn't return any value - callers do not care already,
as all I/O requests are asynchronous

this problem was uncovered by recent change for wd(4) to not hold
wd mutex during ata_bio call, the interrupt for the xfer might
thus actually fire immediately

adjust also ata_exec_command driver hooks similarily - remove all
completion and waiting logic from drivers, upper layer ata code
using AT_WAIT/AT_POLL changed to call ata_wait_cmd() itself
PR kern/55169 by Nick Hudson

Function declaration formating whitespace consistency.  NFCI.

PR kern/56403
Fix kernel freeze for wdc(4) variants with ATAC_CAP_NOIRQ:

(1) Change ata_xfer_ops:c_poll from void to int function. When it returns
    ATAPOLL_AGAIN, let ata_xfer_start() iterate itself again.
(2) Let wdc_ata_bio_poll() return ATAPOLL_AGAIN until ATA_ITSDONE is
    achieved.

A similar change has been made for mvsata(4) (see mvsata_bio_poll()),
and no functional changes for other devices.

This is how the drivers worked before jdolecek-ncq branch was merged.
Note that this changes are less likely to cause infinite recursion:

(1) wdc_ata_bio_intr() called from wdc_ata_bio_poll() asserts ATA_ITSDONE
    in its error handling paths via wdc_ata_bio_done().
(2) Return value from c_start (= wdc_ata_bio_start()) is checked in
    ata_xfer_start().

Therefore, errors encountered in ata_xfer_ops:c_poll and c_start routines
terminate the recursion for wdc(4). The situation is similar for mvsata(4).

Still, there is a possibility where ata_xfer_start() takes long time to
finish a normal operation. This can result in a delayed response for lower
priority interrupts. But, I've never observed such a situation, even when
heavy thrashing takes place for swap partition in wd(4).
"Go ahead" by jdolecek@.


To generate a diff of this commit:
cvs rdiff -u -r1.149.2.2 -r1.149.2.3 src/sys/dev/ata/ata.c
cvs rdiff -u -r1.2.8.1 -r1.2.8.2 src/sys/dev/ata/ata_recovery.c
cvs rdiff -u -r1.113 -r1.113.4.1 src/sys/dev/ata/ata_wdc.c
cvs rdiff -u -r1.103 -r1.103.4.1 src/sys/dev/ata/atavar.h
cvs rdiff -u -r1.15 -r1.15.4.1 src/sys/dev/ata/satapmp_subr.c
cvs rdiff -u -r1.452.2.2 -r1.452.2.3 src/sys/dev/ata/wd.c
cvs rdiff -u -r1.75.4.4 -r1.75.4.5 src/sys/dev/ic/ahcisata_core.c
cvs rdiff -u -r1.48 -r1.48.2.1 src/sys/dev/ic/mvsata.c
cvs rdiff -u -r1.39 -r1.39.4.1 src/sys/dev/ic/siisata.c
cvs rdiff -u -r1.291.4.1 -r1.291.4.2 src/sys/dev/ic/wdc.c
cvs rdiff -u -r1.98.10.1 -r1.98.10.2 src/sys/dev/ic/wdcvar.h
cvs rdiff -u -r1.133 -r1.133.4.1 src/sys/dev/scsipi/atapi_wdc.c
cvs rdiff -u -r1.42 -r1.42.4.1 src/sys/dev/usb/umass_isdata.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/ata/ata.c
diff -u src/sys/dev/ata/ata.c:1.149.2.2 src/sys/dev/ata/ata.c:1.149.2.3
--- src/sys/dev/ata/ata.c:1.149.2.2	Tue Aug 30 18:28:42 2022
+++ src/sys/dev/ata/ata.c	Fri Dec 30 14:39:10 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ata.c,v 1.149.2.2 2022/08/30 18:28:42 martin Exp $	*/
+/*	$NetBSD: ata.c,v 1.149.2.3 2022/12/30 14:39:10 martin Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.149.2.2 2022/08/30 18:28:42 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.149.2.3 2022/12/30 14:39:10 martin Exp $");
 
 #include "opt_ata.h"
 
@@ -842,13 +842,8 @@ ata_get_params(struct ata_drive_datas *d
 	xfer->c_ata_c.flags = AT_READ | flags;
 	xfer->c_ata_c.data = tb;
 	xfer->c_ata_c.bcount = ATA_BSIZE;
-	if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
-						xfer) != ATACMD_COMPLETE) {
-		ATADEBUG_PRINT(("ata_get_parms: wdc_exec_command failed\n"),
-		    DEBUG_FUNCS|DEBUG_PROBE);
-		rv = CMD_AGAIN;
-		goto out;
-	}
+	(*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer);
+	ata_wait_cmd(chp, xfer);
 	if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
 		ATADEBUG_PRINT(("ata_get_parms: ata_c.flags=0x%x\n",
 		    xfer->c_ata_c.flags), DEBUG_FUNCS|DEBUG_PROBE);
@@ -932,11 +927,8 @@ ata_set_mode(struct ata_drive_datas *drv
 	xfer->c_ata_c.r_count = mode;
 	xfer->c_ata_c.flags = flags;
 	xfer->c_ata_c.timeout = 1000; /* 1s */
-	if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
-						xfer) != ATACMD_COMPLETE) {
-		rv = CMD_AGAIN;
-		goto out;
-	}
+	(*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer);
+	ata_wait_cmd(chp, xfer);
 	if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
 		rv = CMD_ERR;
 		goto out;
@@ -1218,10 +1210,11 @@ int
 ata_xfer_start(struct ata_xfer *xfer)
 {
 	struct ata_channel *chp = xfer->c_chp;
-	int rv;
+	int rv, status;
 
 	KASSERT(mutex_owned(&chp->ch_lock));
 
+again:
 	rv = xfer->ops->c_start(chp, xfer);
 	switch (rv) {
 	case ATASTART_STARTED:
@@ -1235,8 +1228,10 @@ ata_xfer_start(struct ata_xfer *xfer)
 		/* can happen even in thread context for some ATAPI devices */
 		ata_channel_unlock(chp);
 		KASSERT(xfer->ops != NULL && xfer->ops->c_poll != NULL);
-		xfer->ops->c_poll(chp, xfer);
+		status = xfer->ops->c_poll(chp, xfer);
 		ata_channel_lock(chp);
+		if (status == ATAPOLL_AGAIN)
+			goto again;
 		break;
 	case ATASTART_ABORT:
 		ata_channel_unlock(chp);

Index: src/sys/dev/ata/ata_recovery.c
diff -u src/sys/dev/ata/ata_recovery.c:1.2.8.1 src/sys/dev/ata/ata_recovery.c:1.2.8.2
--- src/sys/dev/ata/ata_recovery.c:1.2.8.1	Tue Feb  8 14:45:00 2022
+++ src/sys/dev/ata/ata_recovery.c	Fri Dec 30 14:39:10 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ata_recovery.c,v 1.2.8.1 2022/02/08 14:45:00 martin Exp $	*/
+/*	$NetBSD: ata_recovery.c,v 1.2.8.2 2022/12/30 14:39:10 martin Exp $	*/
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata_recovery.c,v 1.2.8.1 2022/02/08 14:45:00 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_recovery.c,v 1.2.8.2 2022/12/30 14:39:10 martin Exp $");
 
 #include "opt_ata.h"
 
@@ -103,11 +103,9 @@ ata_read_log_ext_ncq(struct ata_drive_da
 	xfer->c_ata_c.data = tb;
 	xfer->c_ata_c.bcount = sizeof(chp->recovery_blk);
 
-	if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
-						xfer) != ATACMD_COMPLETE) {
-		rv = EAGAIN;
-		goto out;
-	}
+	(*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer);
+	ata_wait_cmd(chp, xfer);
+
 	if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
 		rv = EINVAL;
 		goto out;

Index: src/sys/dev/ata/ata_wdc.c
diff -u src/sys/dev/ata/ata_wdc.c:1.113 src/sys/dev/ata/ata_wdc.c:1.113.4.1
--- src/sys/dev/ata/ata_wdc.c:1.113	Mon Nov 12 18:51:01 2018
+++ src/sys/dev/ata/ata_wdc.c	Fri Dec 30 14:39:10 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ata_wdc.c,v 1.113 2018/11/12 18:51:01 jdolecek Exp $	*/
+/*	$NetBSD: ata_wdc.c,v 1.113.4.1 2022/12/30 14:39:10 martin Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001, 2003 Manuel Bouyer.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.113 2018/11/12 18:51:01 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.113.4.1 2022/12/30 14:39:10 martin Exp $");
 
 #include "opt_ata.h"
 #include "opt_wdc.h"
@@ -102,10 +102,10 @@ extern int wdcdebug_wd_mask; /* inited i
 
 #define ATA_DELAY 10000 /* 10s for a drive I/O */
 
-static int	wdc_ata_bio(struct ata_drive_datas*, struct ata_xfer *);
+static void	wdc_ata_bio(struct ata_drive_datas*, struct ata_xfer *);
 static int	wdc_ata_bio_start(struct ata_channel *,struct ata_xfer *);
 static int	_wdc_ata_bio_start(struct ata_channel *,struct ata_xfer *);
-static void	wdc_ata_bio_poll(struct ata_channel *,struct ata_xfer *);
+static int	wdc_ata_bio_poll(struct ata_channel *,struct ata_xfer *);
 static int	wdc_ata_bio_intr(struct ata_channel *, struct ata_xfer *,
 				 int);
 static void	wdc_ata_bio_kill_xfer(struct ata_channel *,
@@ -140,10 +140,9 @@ static const struct ata_xfer_ops wdc_bio
 };
 
 /*
- * Handle block I/O operation. Return ATACMD_COMPLETE, ATACMD_QUEUED, or
- * ATACMD_TRY_AGAIN. Must be called at splbio().
+ * Handle block I/O operation.
  */
-static int
+static void
 wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
 {
 	struct ata_channel *chp = drvp->chnl_softc;
@@ -171,7 +170,6 @@ wdc_ata_bio(struct ata_drive_datas *drvp
 	xfer->c_bcount = ata_bio->bcount;
 	xfer->ops = &wdc_bio_xfer_ops;
 	ata_exec_xfer(chp, xfer);
-	return (ata_bio->flags & ATA_ITSDONE) ? ATACMD_COMPLETE : ATACMD_QUEUED;
 }
 
 static int
@@ -617,7 +615,7 @@ timeout:
 	return ATASTART_ABORT;
 }
 
-static void
+static int
 wdc_ata_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	/* Wait for at last 400ns for status bit to be valid */
@@ -629,6 +627,7 @@ wdc_ata_bio_poll(struct ata_channel *chp
 	}
 #endif
 	wdc_ata_bio_intr(chp, xfer, 0);
+	return (xfer->c_bio.flags & ATA_ITSDONE) ? ATAPOLL_DONE : ATAPOLL_AGAIN;
 }
 
 static int
@@ -779,7 +778,10 @@ end:
 			/* Start the next operation */
 			ata_xfer_start(xfer);
 		} else {
-			/* Let _wdc_ata_bio_start do the loop */
+			/*
+			 * Let ata_xfer_start() do the loop;
+			 * see wdc_ata_bio_poll().
+			 */
 		}
 		ata_channel_unlock(chp);
 		return 1;

Index: src/sys/dev/ata/atavar.h
diff -u src/sys/dev/ata/atavar.h:1.103 src/sys/dev/ata/atavar.h:1.103.4.1
--- src/sys/dev/ata/atavar.h:1.103	Fri Apr  5 21:31:44 2019
+++ src/sys/dev/ata/atavar.h	Fri Dec 30 14:39:10 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: atavar.h,v 1.103 2019/04/05 21:31:44 bouyer Exp $	*/
+/*	$NetBSD: atavar.h,v 1.103.4.1 2022/12/30 14:39:10 martin Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -178,7 +178,9 @@ struct ata_xfer_ops {
 #define ATASTART_TH		1	/* xfer needs to be run in thread */
 #define ATASTART_POLL		2	/* xfer needs to be polled */
 #define ATASTART_ABORT		3	/* error occurred, abort xfer */
-	void	(*c_poll)(struct ata_channel *, struct ata_xfer *);
+	int	(*c_poll)(struct ata_channel *, struct ata_xfer *);
+#define	ATAPOLL_DONE		0
+#define	ATAPOLL_AGAIN		1
 	void	(*c_abort)(struct ata_channel *, struct ata_xfer *);
 	int	(*c_intr)(struct ata_channel *, struct ata_xfer *, int);
 	void	(*c_kill_xfer)(struct ata_channel *, struct ata_xfer *, int);
@@ -358,10 +360,10 @@ struct ata_drive_datas {
  */
 struct ata_bustype {
 	int	bustype_type;	/* symbolic name of type */
-	int	(*ata_bio)(struct ata_drive_datas *, struct ata_xfer *);
+	void	(*ata_bio)(struct ata_drive_datas *, struct ata_xfer *);
 	void	(*ata_reset_drive)(struct ata_drive_datas *, int, uint32_t *);
 	void	(*ata_reset_channel)(struct ata_channel *, int);
-	int	(*ata_exec_command)(struct ata_drive_datas *,
+	void	(*ata_exec_command)(struct ata_drive_datas *,
 				    struct ata_xfer *);
 
 #define	ATACMD_COMPLETE		0x01

Index: src/sys/dev/ata/satapmp_subr.c
diff -u src/sys/dev/ata/satapmp_subr.c:1.15 src/sys/dev/ata/satapmp_subr.c:1.15.4.1
--- src/sys/dev/ata/satapmp_subr.c:1.15	Mon Oct 22 20:13:47 2018
+++ src/sys/dev/ata/satapmp_subr.c	Fri Dec 30 14:39:10 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: satapmp_subr.c,v 1.15 2018/10/22 20:13:47 jdolecek Exp $	*/
+/*	$NetBSD: satapmp_subr.c,v 1.15.4.1 2022/12/30 14:39:10 martin Exp $	*/
 
 /*
  * Copyright (c) 2012 Manuel Bouyer.  All rights reserved.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: satapmp_subr.c,v 1.15 2018/10/22 20:13:47 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: satapmp_subr.c,v 1.15.4.1 2022/12/30 14:39:10 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -72,13 +72,10 @@ satapmp_read_8(struct ata_channel *chp, 
 	xfer->c_ata_c.flags = AT_LBA48 | AT_READREG | AT_WAIT;
 
 	ata_channel_unlock(chp);
-	if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
-	    xfer) != ATACMD_COMPLETE) {
-		aprint_error_dev(chp->atabus,
-		    "PMP port %d register %d read failed\n", port, reg);
-		error = EIO;
-		goto out;
-	}
+
+	(*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer);
+	ata_wait_cmd(chp, xfer);
+
 	if (xfer->c_ata_c.flags & (AT_TIMEOU | AT_DF)) {
 		aprint_error_dev(chp->atabus,
 		    "PMP port %d register %d read failed, flags 0x%x\n",
@@ -148,13 +145,10 @@ satapmp_write_8(struct ata_channel *chp,
 	xfer->c_ata_c.flags = AT_LBA48 | AT_WAIT;
 
 	ata_channel_unlock(chp);
-	if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
-	    xfer) != ATACMD_COMPLETE) {
-		aprint_error_dev(chp->atabus,
-		    "PMP port %d register %d write failed\n", port, reg);
-		error = EIO;
-		goto out;
-	}
+
+	(*atac->atac_bustype_ata->ata_exec_command)(drvp, xfer);
+	ata_wait_cmd(chp, xfer);
+
 	if (xfer->c_ata_c.flags & (AT_TIMEOU | AT_DF)) {
 		aprint_error_dev(chp->atabus,
 		    "PMP port %d register %d write failed, flags 0x%x\n",

Index: src/sys/dev/ata/wd.c
diff -u src/sys/dev/ata/wd.c:1.452.2.2 src/sys/dev/ata/wd.c:1.452.2.3
--- src/sys/dev/ata/wd.c:1.452.2.2	Sat Mar 21 15:52:09 2020
+++ src/sys/dev/ata/wd.c	Fri Dec 30 14:39:10 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: wd.c,v 1.452.2.2 2020/03/21 15:52:09 martin Exp $ */
+/*	$NetBSD: wd.c,v 1.452.2.3 2022/12/30 14:39:10 martin Exp $ */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.452.2.2 2020/03/21 15:52:09 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.452.2.3 2022/12/30 14:39:10 martin Exp $");
 
 #include "opt_ata.h"
 #include "opt_wd.h"
@@ -201,7 +201,7 @@ static int	wd_discard(device_t, off_t, o
 static void	wdbioretry(void *);
 static void	wdbiorequeue(void *);
 static void	wddone(device_t, struct ata_xfer *);
-static int	wd_get_params(struct wd_softc *, uint8_t, struct ataparams *);
+static int	wd_get_params(struct wd_softc *, struct ataparams *);
 static void	wd_set_geometry(struct wd_softc *);
 static int	wd_flushcache(struct wd_softc *, int, bool);
 static int	wd_trim(struct wd_softc *, daddr_t, long);
@@ -339,7 +339,7 @@ wdattach(device_t parent, device_t self,
 	aprint_normal("\n");
 
 	/* read our drive info */
-	if (wd_get_params(wd, AT_WAIT, &wd->sc_params) != 0) {
+	if (wd_get_params(wd, &wd->sc_params) != 0) {
 		aprint_error_dev(self, "IDENTIFY failed\n");
 		goto out;
 	}
@@ -669,6 +669,7 @@ wdstart1(struct wd_softc *wd, struct buf
 
 	KASSERT(bp == xfer->c_bio.bp || xfer->c_bio.bp == NULL);
 	KASSERT((xfer->c_flags & (C_WAITACT|C_FREE)) == 0);
+	KASSERT(mutex_owned(&wd->sc_lock));
 
 	/* Reset state, so that retries don't use stale info */
 	if (__predict_false(xfer->c_retries > 0)) {
@@ -760,16 +761,12 @@ wdstart1(struct wd_softc *wd, struct buf
 
 	if (xfer->c_retries == 0)
 		wd->inflight++;
-	switch (wd->atabus->ata_bio(wd->drvp, xfer)) {
-	case ATACMD_TRY_AGAIN:
-		panic("wdstart1: try again");
-		break;
-	case ATACMD_QUEUED:
-	case ATACMD_COMPLETE:
-		break;
-	default:
-		panic("wdstart1: bad return code from ata_bio()");
-	}
+	mutex_exit(&wd->sc_lock);
+
+	/* Queue the xfer */
+	wd->atabus->ata_bio(wd->drvp, xfer);
+
+	mutex_enter(&wd->sc_lock);
 }
 
 static int
@@ -1163,7 +1160,7 @@ wd_firstopen(device_t self, dev_t dev, i
 		int param_error;
 
 		/* Load the physical device parameters. */
-		param_error = wd_get_params(wd, AT_WAIT, &wd->sc_params);
+		param_error = wd_get_params(wd, &wd->sc_params);
 		if (param_error != 0) {
 			aprint_error_dev(dksc->sc_dev, "IDENTIFY failed\n");
 			error = EIO;
@@ -1607,18 +1604,9 @@ wd_dumpblocks(device_t dev, void *va, da
 	xfer->c_bio.bcount = nblk * dg->dg_secsize;
 	xfer->c_bio.databuf = va;
 #ifndef WD_DUMP_NOT_TRUSTED
-	switch (err = wd->atabus->ata_bio(wd->drvp, xfer)) {
-	case ATACMD_TRY_AGAIN:
-		panic("wddump: try again");
-		break;
-	case ATACMD_QUEUED:
-		panic("wddump: polled command has been queued");
-		break;
-	case ATACMD_COMPLETE:
-		break;
-	default:
-		panic("wddump: unknown atacmd code %d", err);
-	}
+	/* This will poll until the bio is complete */
+	wd->atabus->ata_bio(wd->drvp, xfer);
+
 	switch(err = xfer->c_bio.error) {
 	case TIMEOUT:
 		printf("wddump: device timed out");
@@ -1705,10 +1693,11 @@ wd_set_geometry(struct wd_softc *wd)
 }
 
 int
-wd_get_params(struct wd_softc *wd, uint8_t flags, struct ataparams *params)
+wd_get_params(struct wd_softc *wd, struct ataparams *params)
 {
 	int retry = 0;
 	struct ata_channel *chp = wd->drvp->chnl_softc;
+	const int flags = AT_WAIT;
 
 again:
 	switch (wd->atabus->ata_get_params(wd->drvp, flags, params)) {
@@ -1753,7 +1742,7 @@ wd_getcache(struct wd_softc *wd, int *bi
 {
 	struct ataparams params;
 
-	if (wd_get_params(wd, AT_WAIT, &params) != 0)
+	if (wd_get_params(wd, &params) != 0)
 		return EIO;
 	if (params.atap_cmd_set1 == 0x0000 ||
 	    params.atap_cmd_set1 == 0xffff ||
@@ -1781,7 +1770,7 @@ wd_setcache(struct wd_softc *wd, int bit
 	struct ata_xfer *xfer;
 	int error;
 
-	if (wd_get_params(wd, AT_WAIT, &params) != 0)
+	if (wd_get_params(wd, &params) != 0)
 		return EIO;
 
 	if (params.atap_cmd_set1 == 0x0000 ||
@@ -1804,12 +1793,9 @@ wd_setcache(struct wd_softc *wd, int bit
 		xfer->c_ata_c.r_features = WDSF_WRITE_CACHE_EN;
 	else
 		xfer->c_ata_c.r_features = WDSF_WRITE_CACHE_DS;
-	if (wd->atabus->ata_exec_command(wd->drvp, xfer) != ATACMD_COMPLETE) {
-		aprint_error_dev(dksc->sc_dev,
-		    "wd_setcache command not complete\n");
-		error = EIO;
-		goto out;
-	}
+
+	wd->atabus->ata_exec_command(wd->drvp, xfer);
+	ata_wait_cmd(wd->drvp->chnl_softc, xfer);
 
 	if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
 		char sbuf[sizeof(at_errbits) + 64];
@@ -1841,12 +1827,10 @@ wd_standby(struct wd_softc *wd, int flag
 	xfer->c_ata_c.r_st_pmask = WDCS_DRDY;
 	xfer->c_ata_c.flags = flags;
 	xfer->c_ata_c.timeout = 30000; /* 30s timeout */
-	if (wd->atabus->ata_exec_command(wd->drvp, xfer) != ATACMD_COMPLETE) {
-		aprint_error_dev(dksc->sc_dev,
-		    "standby immediate command didn't complete\n");
-		error = EIO;
-		goto out;
-	}
+
+	wd->atabus->ata_exec_command(wd->drvp, xfer);
+	ata_wait_cmd(wd->drvp->chnl_softc, xfer);
+
 	if (xfer->c_ata_c.flags & AT_ERROR) {
 		if (xfer->c_ata_c.r_error == WDCE_ABRT) {
 			/* command not supported */
@@ -1898,12 +1882,10 @@ wd_flushcache(struct wd_softc *wd, int f
 	xfer->c_ata_c.r_st_pmask = WDCS_DRDY;
 	xfer->c_ata_c.flags = flags | AT_READREG;
 	xfer->c_ata_c.timeout = 300000; /* 5m timeout */
-	if (wd->atabus->ata_exec_command(wd->drvp, xfer) != ATACMD_COMPLETE) {
-		aprint_error_dev(dksc->sc_dev,
-		    "flush cache command didn't complete\n");
-		error = EIO;
-		goto out_xfer;
-	}
+
+	wd->atabus->ata_exec_command(wd->drvp, xfer);
+	ata_wait_cmd(wd->drvp->chnl_softc, xfer);
+
 	if (xfer->c_ata_c.flags & AT_ERROR) {
 		if (xfer->c_ata_c.r_error == WDCE_ABRT) {
 			/* command not supported */
@@ -1967,13 +1949,10 @@ wd_trim(struct wd_softc *wd, daddr_t bno
 	xfer->c_ata_c.data = req;
 	xfer->c_ata_c.bcount = 512;
 	xfer->c_ata_c.flags |= AT_WRITE | AT_WAIT;
-	if (wd->atabus->ata_exec_command(wd->drvp, xfer) != ATACMD_COMPLETE) {
-		aprint_error_dev(dksc->sc_dev,
-		    "trim command didn't complete\n");
-		kmem_free(req, 512);
-		error = EIO;
-		goto out;
-	}
+
+	wd->atabus->ata_exec_command(wd->drvp, xfer);
+	ata_wait_cmd(wd->drvp->chnl_softc, xfer);
+
 	kmem_free(req, 512);
 	if (xfer->c_ata_c.flags & AT_ERROR) {
 		if (xfer->c_ata_c.r_error == WDCE_ABRT) {
@@ -2168,12 +2147,8 @@ wdioctlstrategy(struct buf *bp)
 	xfer->c_ata_c.data = wi->wi_bp.b_data;
 	xfer->c_ata_c.bcount = wi->wi_bp.b_bcount;
 
-	if (wi->wi_softc->atabus->ata_exec_command(wi->wi_softc->drvp, xfer)
-	    != ATACMD_COMPLETE) {
-		wi->wi_atareq.retsts = ATACMD_ERROR;
-		error = EIO;
-		goto out;
-	}
+	wi->wi_softc->atabus->ata_exec_command(wi->wi_softc->drvp, xfer);
+	ata_wait_cmd(wi->wi_softc->drvp->chnl_softc, xfer);
 
 	if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
 		if (xfer->c_ata_c.flags & AT_ERROR) {

Index: src/sys/dev/ic/ahcisata_core.c
diff -u src/sys/dev/ic/ahcisata_core.c:1.75.4.4 src/sys/dev/ic/ahcisata_core.c:1.75.4.5
--- src/sys/dev/ic/ahcisata_core.c:1.75.4.4	Wed Dec 30 15:12:38 2020
+++ src/sys/dev/ic/ahcisata_core.c	Fri Dec 30 14:39:09 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ahcisata_core.c,v 1.75.4.4 2020/12/30 15:12:38 martin Exp $	*/
+/*	$NetBSD: ahcisata_core.c,v 1.75.4.5 2022/12/30 14:39:09 martin Exp $	*/
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.75.4.4 2020/12/30 15:12:38 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.75.4.5 2022/12/30 14:39:09 martin Exp $");
 
 #include <sys/types.h>
 #include <sys/malloc.h>
@@ -57,25 +57,25 @@ int ahcidebug_mask = 0;
 static void ahci_probe_drive(struct ata_channel *);
 static void ahci_setup_channel(struct ata_channel *);
 
-static int  ahci_ata_bio(struct ata_drive_datas *, struct ata_xfer *);
+static void ahci_ata_bio(struct ata_drive_datas *, struct ata_xfer *);
 static int  ahci_do_reset_drive(struct ata_channel *, int, int, uint32_t *,
 	uint8_t);
 static void ahci_reset_drive(struct ata_drive_datas *, int, uint32_t *);
 static void ahci_reset_channel(struct ata_channel *, int);
-static int  ahci_exec_command(struct ata_drive_datas *, struct ata_xfer *);
+static void ahci_exec_command(struct ata_drive_datas *, struct ata_xfer *);
 static int  ahci_ata_addref(struct ata_drive_datas *);
 static void ahci_ata_delref(struct ata_drive_datas *);
 static void ahci_killpending(struct ata_drive_datas *);
 
-static int ahci_cmd_start(struct ata_channel *, struct ata_xfer *);
+static int  ahci_cmd_start(struct ata_channel *, struct ata_xfer *);
 static int  ahci_cmd_complete(struct ata_channel *, struct ata_xfer *, int);
-static void ahci_cmd_poll(struct ata_channel *, struct ata_xfer *);
+static int  ahci_cmd_poll(struct ata_channel *, struct ata_xfer *);
 static void ahci_cmd_abort(struct ata_channel *, struct ata_xfer *);
 static void ahci_cmd_done(struct ata_channel *, struct ata_xfer *);
 static void ahci_cmd_done_end(struct ata_channel *, struct ata_xfer *);
 static void ahci_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int);
-static int ahci_bio_start(struct ata_channel *, struct ata_xfer *);
-static void ahci_bio_poll(struct ata_channel *, struct ata_xfer *);
+static int  ahci_bio_start(struct ata_channel *, struct ata_xfer *);
+static int  ahci_bio_poll(struct ata_channel *, struct ata_xfer *);
 static void ahci_bio_abort(struct ata_channel *, struct ata_xfer *);
 static int  ahci_bio_complete(struct ata_channel *, struct ata_xfer *, int);
 static void ahci_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ;
@@ -84,7 +84,7 @@ static void ahci_channel_start(struct ah
 				int, int);
 static void ahci_channel_recover(struct ata_channel *, int, uint32_t);
 static int  ahci_dma_setup(struct ata_channel *, int, void *, size_t, int);
-static int ahci_intr_port_common(struct ata_channel *);
+static int  ahci_intr_port_common(struct ata_channel *);
 
 #if NATAPIBUS > 0
 static void ahci_atapibus_attach(struct atabus_softc *);
@@ -92,8 +92,8 @@ static void ahci_atapi_kill_pending(stru
 static void ahci_atapi_minphys(struct buf *);
 static void ahci_atapi_scsipi_request(struct scsipi_channel *,
     scsipi_adapter_req_t, void *);
-static int ahci_atapi_start(struct ata_channel *, struct ata_xfer *);
-static void ahci_atapi_poll(struct ata_channel *, struct ata_xfer *);
+static int  ahci_atapi_start(struct ata_channel *, struct ata_xfer *);
+static int  ahci_atapi_poll(struct ata_channel *, struct ata_xfer *);
 static void ahci_atapi_abort(struct ata_channel *, struct ata_xfer *);
 static int  ahci_atapi_complete(struct ata_channel *, struct ata_xfer *, int);
 static void ahci_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int);
@@ -1128,13 +1128,11 @@ static const struct ata_xfer_ops ahci_cm
 	.c_kill_xfer = ahci_cmd_kill_xfer,
 };
 
-static int
+static void
 ahci_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
 {
 	struct ata_channel *chp = drvp->chnl_softc;
 	struct ata_command *ata_c = &xfer->c_ata_c;
-	int ret;
-	int s;
 
 	AHCIDEBUG_PRINT(("ahci_exec_command port %d CI 0x%x\n",
 	    chp->ch_channel,
@@ -1148,25 +1146,8 @@ ahci_exec_command(struct ata_drive_datas
 	xfer->c_databuf = ata_c->data;
 	xfer->c_bcount = ata_c->bcount;
 	xfer->ops = &ahci_cmd_xfer_ops;
-	s = splbio();
+
 	ata_exec_xfer(chp, xfer);
-#ifdef DIAGNOSTIC
-	if ((ata_c->flags & AT_POLL) != 0 &&
-	    (ata_c->flags & AT_DONE) == 0)
-		panic("ahci_exec_command: polled command not done");
-#endif
-	if (ata_c->flags & AT_DONE) {
-		ret = ATACMD_COMPLETE;
-	} else {
-		if (ata_c->flags & AT_WAIT) {
-			ata_wait_cmd(chp, xfer);
-			ret = ATACMD_COMPLETE;
-		} else {
-			ret = ATACMD_QUEUED;
-		}
-	}
-	splx(s);
-	return ret;
 }
 
 static int
@@ -1227,7 +1208,7 @@ ahci_cmd_start(struct ata_channel *chp, 
 		return ATASTART_POLL;
 }
 
-static void
+static int
 ahci_cmd_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	struct ahci_softc *sc = AHCI_CH2SC(chp);
@@ -1264,6 +1245,8 @@ ahci_cmd_poll(struct ata_channel *chp, s
 	}
 	/* reenable interrupts */
 	AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
+
+	return ATAPOLL_DONE;
 }
 
 static void
@@ -1398,7 +1381,7 @@ static const struct ata_xfer_ops ahci_bi
 	.c_kill_xfer = ahci_bio_kill_xfer,
 };
 
-static int
+static void
 ahci_ata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
 {
 	struct ata_channel *chp = drvp->chnl_softc;
@@ -1415,7 +1398,6 @@ ahci_ata_bio(struct ata_drive_datas *drv
 	xfer->c_bcount = ata_bio->bcount;
 	xfer->ops = &ahci_bio_xfer_ops;
 	ata_exec_xfer(chp, xfer);
-	return (ata_bio->flags & ATA_ITSDONE) ? ATACMD_COMPLETE : ATACMD_QUEUED;
 }
 
 static int
@@ -1473,7 +1455,7 @@ ahci_bio_start(struct ata_channel *chp, 
 		return ATASTART_POLL;
 }
 
-static void
+static int
 ahci_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
@@ -1503,6 +1485,7 @@ ahci_bio_poll(struct ata_channel *chp, s
 	}
 	/* reenable interrupts */
 	AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
+	return ATAPOLL_DONE;
 }
 
 static void
@@ -1970,7 +1953,7 @@ ahci_atapi_start(struct ata_channel *chp
 		return ATASTART_POLL;
 }
 
-static void
+static int
 ahci_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
@@ -2000,6 +1983,7 @@ ahci_atapi_poll(struct ata_channel *chp,
 	}
 	/* reenable interrupts */
 	AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
+	return ATAPOLL_DONE;
 }
 
 static void

Index: src/sys/dev/ic/mvsata.c
diff -u src/sys/dev/ic/mvsata.c:1.48 src/sys/dev/ic/mvsata.c:1.48.2.1
--- src/sys/dev/ic/mvsata.c:1.48	Sun Jun 23 06:33:17 2019
+++ src/sys/dev/ic/mvsata.c	Fri Dec 30 14:39:09 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: mvsata.c,v 1.48 2019/06/23 06:33:17 tsutsui Exp $	*/
+/*	$NetBSD: mvsata.c,v 1.48.2.1 2022/12/30 14:39:09 martin Exp $	*/
 /*
  * Copyright (c) 2008 KIYOHARA Takashi
  * All rights reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.48 2019/06/23 06:33:17 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.48.2.1 2022/12/30 14:39:09 martin Exp $");
 
 #include "opt_mvsata.h"
 
@@ -121,9 +121,9 @@ static void mvsata_probe_drive(struct at
 
 #ifndef MVSATA_WITHOUTDMA
 static void mvsata_reset_channel(struct ata_channel *, int);
-static int mvsata_bio(struct ata_drive_datas *, struct ata_xfer *);
+static void mvsata_bio(struct ata_drive_datas *, struct ata_xfer *);
 static void mvsata_reset_drive(struct ata_drive_datas *, int, uint32_t *);
-static int mvsata_exec_command(struct ata_drive_datas *, struct ata_xfer *);
+static void mvsata_exec_command(struct ata_drive_datas *, struct ata_xfer *);
 static int mvsata_addref(struct ata_drive_datas *);
 static void mvsata_delref(struct ata_drive_datas *);
 static void mvsata_killpending(struct ata_drive_datas *);
@@ -143,14 +143,14 @@ static void mvsata_setup_channel(struct 
 #ifndef MVSATA_WITHOUTDMA
 static int mvsata_bio_start(struct ata_channel *, struct ata_xfer *);
 static int mvsata_bio_intr(struct ata_channel *, struct ata_xfer *, int);
-static void mvsata_bio_poll(struct ata_channel *, struct ata_xfer *);
+static int mvsata_bio_poll(struct ata_channel *, struct ata_xfer *);
 static void mvsata_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int);
 static void mvsata_bio_done(struct ata_channel *, struct ata_xfer *);
 static int mvsata_bio_ready(struct mvsata_port *, struct ata_bio *, int,
 			    int);
 static int mvsata_wdc_cmd_start(struct ata_channel *, struct ata_xfer *);
 static int mvsata_wdc_cmd_intr(struct ata_channel *, struct ata_xfer *, int);
-static void mvsata_wdc_cmd_poll(struct ata_channel *, struct ata_xfer *);
+static int mvsata_wdc_cmd_poll(struct ata_channel *, struct ata_xfer *);
 static void mvsata_wdc_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *,
 				     int);
 static void mvsata_wdc_cmd_done(struct ata_channel *, struct ata_xfer *);
@@ -158,7 +158,7 @@ static void mvsata_wdc_cmd_done_end(stru
 #if NATAPIBUS > 0
 static int mvsata_atapi_start(struct ata_channel *, struct ata_xfer *);
 static int mvsata_atapi_intr(struct ata_channel *, struct ata_xfer *, int);
-static void mvsata_atapi_poll(struct ata_channel *, struct ata_xfer *);
+static int mvsata_atapi_poll(struct ata_channel *, struct ata_xfer *);
 static void mvsata_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *,
 				   int);
 static void mvsata_atapi_reset(struct ata_channel *, struct ata_xfer *);
@@ -996,7 +996,7 @@ static const struct ata_xfer_ops mvsata_
 	.c_kill_xfer = mvsata_bio_kill_xfer,
 };
 
-static int
+static void
 mvsata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
 {
 	struct ata_channel *chp = drvp->chnl_softc;
@@ -1020,7 +1020,6 @@ mvsata_bio(struct ata_drive_datas *drvp,
 	xfer->c_bcount = ata_bio->bcount;
 	xfer->ops = &mvsata_bio_xfer_ops;
 	ata_exec_xfer(chp, xfer);
-	return (ata_bio->flags & ATA_ITSDONE) ? ATACMD_COMPLETE : ATACMD_QUEUED;
 }
 
 static int
@@ -1263,7 +1262,7 @@ timeout:
 	return ATASTART_ABORT;
 }
 
-static void
+static int
 mvsata_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	struct mvsata_port *mvport = (struct mvsata_port *)chp;
@@ -1277,10 +1276,9 @@ mvsata_bio_poll(struct ata_channel *chp,
 		chp->ch_flags &= ~ATACH_DMA_WAIT;
 	}
 
-	if ((xfer->c_bio.flags & ATA_ITSDONE) == 0) {
-		KASSERT(xfer->c_flags & C_TIMEOU);
-		mvsata_bio_intr(chp, xfer, 0);
-	}
+	mvsata_bio_intr(chp, xfer, 0);
+
+	return (xfer->c_bio.flags & ATA_ITSDONE) ? ATAPOLL_DONE : ATAPOLL_AGAIN;
 }
 
 static int
@@ -1403,7 +1401,10 @@ end:
 			/* Start the next operation */
 			ata_xfer_start(xfer);
 		} else {
-			/* Let mvsata_bio_start do the loop */
+			/*
+			 * Let ata_xfer_start() do the loop;
+			 * see mvsata_bio_poll().
+			 */
 		}
 		ata_channel_unlock(chp);
 	} else { /* Done with this transfer */
@@ -1612,12 +1613,11 @@ static const struct ata_xfer_ops mvsata_
 	.c_kill_xfer = mvsata_wdc_cmd_kill_xfer,
 };
 
-static int
+static void
 mvsata_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
 {
 	struct ata_channel *chp = drvp->chnl_softc;
 	struct ata_command *ata_c = &xfer->c_ata_c;
-	int rv, s;
 
 	DPRINTF(DEBUG_FUNCS|DEBUG_XFERS,
 	    ("%s:%d: mvsata_exec_command: drive=%d, bcount=%d,"
@@ -1636,24 +1636,8 @@ mvsata_exec_command(struct ata_drive_dat
 	xfer->c_databuf = ata_c->data;
 	xfer->c_bcount = ata_c->bcount;
 	xfer->ops = &mvsata_wdc_cmd_xfer_ops;
-	s = splbio();
+
 	ata_exec_xfer(chp, xfer);
-#ifdef DIAGNOSTIC
-	if ((ata_c->flags & AT_POLL) != 0 &&
-	    (ata_c->flags & AT_DONE) == 0)
-		panic("mvsata_exec_command: polled command not done");
-#endif
-	if (ata_c->flags & AT_DONE)
-		rv = ATACMD_COMPLETE;
-	else {
-		if (ata_c->flags & AT_WAIT) {
-			ata_wait_cmd(chp, xfer);
-			rv = ATACMD_COMPLETE;
-		} else
-			rv = ATACMD_QUEUED;
-	}
-	splx(s);
-	return rv;
 }
 
 static int
@@ -1715,7 +1699,7 @@ mvsata_wdc_cmd_start(struct ata_channel 
 	return ATASTART_POLL;
 }
 
-static void
+static int
 mvsata_wdc_cmd_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	/*
@@ -1724,6 +1708,7 @@ mvsata_wdc_cmd_poll(struct ata_channel *
 	 */
 	delay(10);	/* 400ns delay */
 	mvsata_wdc_cmd_intr(chp, xfer, 0);
+	return ATAPOLL_DONE;
 }
 
 static int
@@ -2200,7 +2185,7 @@ error:
 	return ATASTART_ABORT;
 }
 
-static void
+static int
 mvsata_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	/*
@@ -2215,7 +2200,7 @@ mvsata_atapi_poll(struct ata_channel *ch
 	mvsata_atapi_intr(chp, xfer, 0);
 
 	if (!poll)
-		return;
+		return ATAPOLL_DONE;
 
 	if (chp->ch_flags & ATACH_DMA_WAIT) {
 		wdc_dmawait(chp, xfer, xfer->c_scsipi->timeout);
@@ -2227,6 +2212,8 @@ mvsata_atapi_poll(struct ata_channel *ch
 		DELAY(1);
 		mvsata_atapi_intr(chp, xfer, 0);
 	}
+
+	return ATAPOLL_DONE;
 }
 
 static int

Index: src/sys/dev/ic/siisata.c
diff -u src/sys/dev/ic/siisata.c:1.39 src/sys/dev/ic/siisata.c:1.39.4.1
--- src/sys/dev/ic/siisata.c:1.39	Mon Nov 19 19:52:08 2018
+++ src/sys/dev/ic/siisata.c	Fri Dec 30 14:39:09 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.39 2018/11/19 19:52:08 jdolecek Exp $ */
+/* $NetBSD: siisata.c,v 1.39.4.1 2022/12/30 14:39:09 martin Exp $ */
 
 /* from ahcisata_core.c */
 
@@ -79,7 +79,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.39 2018/11/19 19:52:08 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.39.4.1 2022/12/30 14:39:09 martin Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -140,7 +140,7 @@ static void siisata_intr_port(struct sii
 void siisata_probe_drive(struct ata_channel *);
 void siisata_setup_channel(struct ata_channel *);
 
-int siisata_ata_bio(struct ata_drive_datas *, struct ata_xfer *);
+void siisata_ata_bio(struct ata_drive_datas *, struct ata_xfer *);
 void siisata_reset_drive(struct ata_drive_datas *, int, uint32_t *);
 void siisata_reset_channel(struct ata_channel *, int);
 int siisata_ata_addref(struct ata_drive_datas *);
@@ -149,7 +149,7 @@ void siisata_killpending(struct ata_driv
 
 int siisata_cmd_start(struct ata_channel *, struct ata_xfer *);
 int siisata_cmd_complete(struct ata_channel *, struct ata_xfer *, int);
-void siisata_cmd_poll(struct ata_channel *, struct ata_xfer *);
+int siisata_cmd_poll(struct ata_channel *, struct ata_xfer *);
 void siisata_cmd_abort(struct ata_channel *, struct ata_xfer *);
 void siisata_cmd_done(struct ata_channel *, struct ata_xfer *, int);
 static void siisata_cmd_done_end(struct ata_channel *, struct ata_xfer *);
@@ -157,10 +157,10 @@ void siisata_cmd_kill_xfer(struct ata_ch
 
 int siisata_bio_start(struct ata_channel *, struct ata_xfer *);
 int siisata_bio_complete(struct ata_channel *, struct ata_xfer *, int);
-void siisata_bio_poll(struct ata_channel *, struct ata_xfer *);
+int siisata_bio_poll(struct ata_channel *, struct ata_xfer *);
 void siisata_bio_abort(struct ata_channel *, struct ata_xfer *);
 void siisata_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int);
-int siisata_exec_command(struct ata_drive_datas *, struct ata_xfer *);
+void siisata_exec_command(struct ata_drive_datas *, struct ata_xfer *);
 
 static int siisata_reinit_port(struct ata_channel *, int);
 static void siisata_device_reset(struct ata_channel *);
@@ -175,7 +175,7 @@ void siisata_atapi_probe_device(struct a
 void siisata_atapi_minphys(struct buf *);
 int siisata_atapi_start(struct ata_channel *,struct ata_xfer *);
 int siisata_atapi_complete(struct ata_channel *, struct ata_xfer *, int);
-void siisata_atapi_poll(struct ata_channel *, struct ata_xfer *);
+int siisata_atapi_poll(struct ata_channel *, struct ata_xfer *);
 void siisata_atapi_abort(struct ata_channel *, struct ata_xfer *);
 void siisata_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int);
 void siisata_atapi_scsipi_request(struct scsipi_channel *,
@@ -930,13 +930,11 @@ static const struct ata_xfer_ops siisata
 	.c_kill_xfer = siisata_cmd_kill_xfer,
 };
 
-int
+void
 siisata_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
 {
 	struct ata_channel *chp = drvp->chnl_softc;
 	struct ata_command *ata_c = &xfer->c_ata_c;
-	int ret;
-	int s;
 
 	SIISATA_DEBUG_PRINT(("%s: %s begins\n",
 	    SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__),
@@ -950,28 +948,12 @@ siisata_exec_command(struct ata_drive_da
 	xfer->c_databuf = ata_c->data;
 	xfer->c_bcount = ata_c->bcount;
 	xfer->ops = &siisata_cmd_xfer_ops;
-	s = splbio();
+
 	ata_exec_xfer(chp, xfer);
-#ifdef DIAGNOSTIC
-	if ((ata_c->flags & AT_POLL) != 0 &&
-	    (ata_c->flags & AT_DONE) == 0)
-		panic("%s: polled command not done", __func__);
-#endif
-	if (ata_c->flags & AT_DONE) {
-		ret = ATACMD_COMPLETE;
-	} else {
-		if (ata_c->flags & AT_WAIT) {
-			ata_wait_cmd(chp, xfer);
-			ret = ATACMD_COMPLETE;
-		} else {
-			ret = ATACMD_QUEUED;
-		}
-	}
-	splx(s);
+
 	SIISATA_DEBUG_PRINT( ("%s: %s ends\n",
 	    SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__),
 	    DEBUG_FUNCS);
-	return ret;
 }
 
 int
@@ -1025,7 +1007,7 @@ siisata_cmd_start(struct ata_channel *ch
 		return ATASTART_POLL;
 }
 
-void
+int
 siisata_cmd_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	struct siisata_channel *schp = (struct siisata_channel *)chp;
@@ -1050,6 +1032,8 @@ siisata_cmd_poll(struct ata_channel *chp
 	SIISATA_DEBUG_PRINT(("%s: %s: done\n",
 	    SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__),
 	    DEBUG_FUNCS);
+
+	return ATAPOLL_DONE;
 }
 
 void
@@ -1190,7 +1174,7 @@ static const struct ata_xfer_ops siisata
 	.c_kill_xfer = siisata_bio_kill_xfer,
 };
 
-int
+void
 siisata_ata_bio(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
 {
 	struct ata_channel *chp = drvp->chnl_softc;
@@ -1200,8 +1184,6 @@ siisata_ata_bio(struct ata_drive_datas *
 	    SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__),
 	    DEBUG_FUNCS);
 
-	if (xfer == NULL)
-		return ATACMD_TRY_AGAIN;
 	if (ata_bio->flags & ATA_POLL)
 		xfer->c_flags |= C_POLL;
 	xfer->c_drive = drvp->drive;
@@ -1209,8 +1191,6 @@ siisata_ata_bio(struct ata_drive_datas *
 	xfer->c_bcount = ata_bio->bcount;
 	xfer->ops = &siisata_bio_xfer_ops;
 	ata_exec_xfer(chp, xfer);
-	return (ata_bio->flags & ATA_ITSDONE) ?
-	    ATACMD_COMPLETE : ATACMD_QUEUED;
 }
 
 int
@@ -1256,7 +1236,7 @@ siisata_bio_start(struct ata_channel *ch
 		return ATASTART_POLL;
 }
 
-void
+int
 siisata_bio_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	struct siisata_channel *schp = (struct siisata_channel *)chp;
@@ -1280,6 +1260,8 @@ siisata_bio_poll(struct ata_channel *chp
 	SIISATA_DEBUG_PRINT(("%s: %s: done\n",
 	    SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__),
 	    DEBUG_FUNCS);
+
+	return ATAPOLL_DONE;
 }
 
 void
@@ -1865,7 +1847,7 @@ siisata_atapi_start(struct ata_channel *
 		return ATASTART_POLL;
 }
 
-void
+int
 siisata_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	struct siisata_channel *schp = (struct siisata_channel *)chp;
@@ -1888,6 +1870,8 @@ siisata_atapi_poll(struct ata_channel *c
 	SIISATA_DEBUG_PRINT(("%s: %s: done\n",
 	    SIISATANAME((struct siisata_softc *)chp->ch_atac), __func__),
             DEBUG_FUNCS);
+
+	return ATAPOLL_DONE;
 }
 
 void

Index: src/sys/dev/ic/wdc.c
diff -u src/sys/dev/ic/wdc.c:1.291.4.1 src/sys/dev/ic/wdc.c:1.291.4.2
--- src/sys/dev/ic/wdc.c:1.291.4.1	Mon Sep 23 07:09:47 2019
+++ src/sys/dev/ic/wdc.c	Fri Dec 30 14:39:09 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: wdc.c,v 1.291.4.1 2019/09/23 07:09:47 martin Exp $ */
+/*	$NetBSD: wdc.c,v 1.291.4.2 2022/12/30 14:39:09 martin Exp $ */
 
 /*
  * Copyright (c) 1998, 2001, 2003 Manuel Bouyer.  All rights reserved.
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.291.4.1 2019/09/23 07:09:47 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.291.4.2 2022/12/30 14:39:09 martin Exp $");
 
 #include "opt_ata.h"
 #include "opt_wdc.h"
@@ -148,7 +148,7 @@ static int	wdcreset(struct ata_channel *
 static void	__wdcerror(struct ata_channel *, const char *);
 static int	__wdcwait_reset(struct ata_channel *, int, int);
 static void	__wdccommand_done(struct ata_channel *, struct ata_xfer *);
-static void	__wdccommand_poll(struct ata_channel *, struct ata_xfer *);
+static int	__wdccommand_poll(struct ata_channel *, struct ata_xfer *);
 static void	__wdccommand_done_end(struct ata_channel *, struct ata_xfer *);
 static void	__wdccommand_kill_xfer(struct ata_channel *,
 			               struct ata_xfer *, int);
@@ -1390,12 +1390,11 @@ static const struct ata_xfer_ops wdc_cmd
 	.c_kill_xfer = __wdccommand_kill_xfer,
 };
 
-int
+void
 wdc_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
 {
 	struct ata_channel *chp = drvp->chnl_softc;
 	struct ata_command *ata_c = &xfer->c_ata_c;
-	int s, ret;
 
 	ATADEBUG_PRINT(("wdc_exec_command %s:%d:%d\n",
 	    device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
@@ -1413,25 +1412,7 @@ wdc_exec_command(struct ata_drive_datas 
 	xfer->c_bcount = ata_c->bcount;
 	xfer->ops = &wdc_cmd_xfer_ops;
 
-	s = splbio();
 	ata_exec_xfer(chp, xfer);
-#ifdef DIAGNOSTIC
-	if ((ata_c->flags & AT_POLL) != 0 &&
-	    (ata_c->flags & AT_DONE) == 0)
-		panic("wdc_exec_command: polled command not done");
-#endif
-	if (ata_c->flags & AT_DONE) {
-		ret = ATACMD_COMPLETE;
-	} else {
-		if (ata_c->flags & AT_WAIT) {
-			ata_wait_cmd(chp, xfer);
-			ret = ATACMD_COMPLETE;
-		} else {
-			ret = ATACMD_QUEUED;
-		}
-	}
-	splx(s);
-	return ret;
 }
 
 static int
@@ -1498,10 +1479,11 @@ __wdccommand_start(struct ata_channel *c
 	return ATASTART_POLL;
 }
 
-static void
+static int
 __wdccommand_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	__wdccommand_intr(chp, xfer, 0);
+	return ATAPOLL_DONE;
 }
 
 static int

Index: src/sys/dev/ic/wdcvar.h
diff -u src/sys/dev/ic/wdcvar.h:1.98.10.1 src/sys/dev/ic/wdcvar.h:1.98.10.2
--- src/sys/dev/ic/wdcvar.h:1.98.10.1	Mon Sep 23 07:09:47 2019
+++ src/sys/dev/ic/wdcvar.h	Fri Dec 30 14:39:10 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: wdcvar.h,v 1.98.10.1 2019/09/23 07:09:47 martin Exp $	*/
+/*	$NetBSD: wdcvar.h,v 1.98.10.2 2022/12/30 14:39:10 martin Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
@@ -175,7 +175,7 @@ void	wdc_reset_drive(struct ata_drive_da
 void	wdc_reset_channel(struct ata_channel *, int);
 void	wdc_do_reset(struct ata_channel *, int);
 
-int	wdc_exec_command(struct ata_drive_datas *, struct ata_xfer *);
+void	wdc_exec_command(struct ata_drive_datas *, struct ata_xfer *);
 
 /*
  * ST506 spec says that if READY or SEEKCMPLT go off, then the read or write

Index: src/sys/dev/scsipi/atapi_wdc.c
diff -u src/sys/dev/scsipi/atapi_wdc.c:1.133 src/sys/dev/scsipi/atapi_wdc.c:1.133.4.1
--- src/sys/dev/scsipi/atapi_wdc.c:1.133	Mon Nov 12 20:54:03 2018
+++ src/sys/dev/scsipi/atapi_wdc.c	Fri Dec 30 14:39:10 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: atapi_wdc.c,v 1.133 2018/11/12 20:54:03 jdolecek Exp $	*/
+/*	$NetBSD: atapi_wdc.c,v 1.133.4.1 2022/12/30 14:39:10 martin Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.133 2018/11/12 20:54:03 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.133.4.1 2022/12/30 14:39:10 martin Exp $");
 
 #ifndef ATADEBUG
 #define ATADEBUG
@@ -90,7 +90,7 @@ static int	wdc_atapi_intr(struct ata_cha
 static void	wdc_atapi_kill_xfer(struct ata_channel *,
 				    struct ata_xfer *, int);
 static void	wdc_atapi_phase_complete(struct ata_xfer *, int);
-static void	wdc_atapi_poll(struct ata_channel *, struct ata_xfer *);
+static int	wdc_atapi_poll(struct ata_channel *, struct ata_xfer *);
 static void	wdc_atapi_done(struct ata_channel *, struct ata_xfer *);
 static void	wdc_atapi_reset(struct ata_channel *, struct ata_xfer *);
 static void	wdc_atapi_scsipi_request(struct scsipi_channel *,
@@ -222,12 +222,10 @@ wdc_atapi_get_params(struct scsipi_chann
 	xfer->c_ata_c.r_st_pmask = 0;
 	xfer->c_ata_c.flags = AT_WAIT | AT_POLL;
 	xfer->c_ata_c.timeout = WDC_RESET_WAIT;
-	if (wdc_exec_command(&chp->ch_drive[drive], xfer) != ATACMD_COMPLETE) {
-		printf("wdc_atapi_get_params: ATAPI_SOFT_RESET failed for"
-		    " drive %s:%d:%d: driver failed\n",
-		    device_xname(atac->atac_dev), chp->ch_channel, drive);
-		panic("wdc_atapi_get_params");
-	}
+
+	wdc_exec_command(&chp->ch_drive[drive], xfer);
+	ata_wait_cmd(chp, xfer);
+
 	if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
 		ATADEBUG_PRINT(("wdc_atapi_get_params: ATAPI_SOFT_RESET "
 		    "failed for drive %s:%d:%d: error 0x%x\n",
@@ -705,7 +703,7 @@ error:
 	return ATASTART_ABORT;
 }
 
-static void
+static int
 wdc_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer)
 {
 	/*
@@ -720,7 +718,7 @@ wdc_atapi_poll(struct ata_channel *chp, 
 	wdc_atapi_intr(chp, xfer, 0);
 
 	if (!poll)
-		return;
+		return ATAPOLL_DONE;
 
 #if NATA_DMA
 	if (chp->ch_flags & ATACH_DMA_WAIT) {
@@ -733,6 +731,8 @@ wdc_atapi_poll(struct ata_channel *chp, 
 		DELAY(1);
 		wdc_atapi_intr(chp, xfer, 0);
 	}
+
+	return ATAPOLL_DONE;
 }
 
 static int

Index: src/sys/dev/usb/umass_isdata.c
diff -u src/sys/dev/usb/umass_isdata.c:1.42 src/sys/dev/usb/umass_isdata.c:1.42.4.1
--- src/sys/dev/usb/umass_isdata.c:1.42	Sun Feb 10 19:23:55 2019
+++ src/sys/dev/usb/umass_isdata.c	Fri Dec 30 14:39:10 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: umass_isdata.c,v 1.42 2019/02/10 19:23:55 jdolecek Exp $	*/
+/*	$NetBSD: umass_isdata.c,v 1.42.4.1 2022/12/30 14:39:10 martin Exp $	*/
 
 /*
  * TODO:
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umass_isdata.c,v 1.42 2019/02/10 19:23:55 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umass_isdata.c,v 1.42.4.1 2022/12/30 14:39:10 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -115,11 +115,11 @@ int	uisdatadebug = 0;
 #define DPRINTFN(n,x)
 #endif
 
-int  uisdata_bio(struct ata_drive_datas *, struct ata_xfer *);
-int  uisdata_bio1(struct ata_drive_datas *, struct ata_xfer *);
+void uisdata_bio(struct ata_drive_datas *, struct ata_xfer *);
+void uisdata_bio1(struct ata_drive_datas *, struct ata_xfer *);
 void uisdata_reset_drive(struct ata_drive_datas *, int, uint32_t *);
 void uisdata_reset_channel(struct ata_channel *, int);
-int  uisdata_exec_command(struct ata_drive_datas *, struct ata_xfer *);
+void uisdata_exec_command(struct ata_drive_datas *, struct ata_xfer *);
 int  uisdata_get_params(struct ata_drive_datas *, uint8_t, struct ataparams *);
 int  uisdata_addref(struct ata_drive_datas *);
 void uisdata_delref(struct ata_drive_datas *);
@@ -274,7 +274,7 @@ uisdata_bio_cb(struct umass_softc *sc, v
 		ata_bio->bcount += residue;
 	} else if (ata_bio->bcount > 0) {
 		DPRINTF(("%s: continue\n", __func__));
-		(void)uisdata_bio1(&scbus->sc_drv_data, xfer); /*XXX save drv*/
+		uisdata_bio1(&scbus->sc_drv_data, xfer); /*XXX save drv*/
 		splx(s);
 		return;
 	}
@@ -289,17 +289,17 @@ uisdata_bio_cb(struct umass_softc *sc, v
 	splx(s);
 }
 
-int
+void
 uisdata_bio(struct ata_drive_datas *drv, struct ata_xfer *xfer)
 {
 	struct umass_softc *sc = CH2SELF(drv->chnl_softc);
 	struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus;
 
 	scbus->sc_skip = 0;
-	return uisdata_bio1(drv, xfer);
+	uisdata_bio1(drv, xfer);
 }
 
-int
+void
 uisdata_bio1(struct ata_drive_datas *drv, struct ata_xfer *xfer)
 {
 	struct umass_softc *sc = CH2SELF(drv->chnl_softc);
@@ -320,7 +320,6 @@ uisdata_bio1(struct ata_drive_datas *drv
 		printf("%s: ATA_POLL not supported\n", __func__);
 		ata_bio->error = TIMEOUT;
 		ata_bio->flags |= ATA_ITSDONE;
-		return ATACMD_COMPLETE;
 	}
 
 	if (ata_bio->flags & ATA_LBA) {
@@ -390,11 +389,8 @@ uisdata_bio1(struct ata_drive_datas *drv
 		if (tsleep(ata_bio, PZERO, "uisdatabl", 0)) {
 			ata_bio->error = TIMEOUT;
 			ata_bio->flags |= ATA_ITSDONE;
-			return ATACMD_COMPLETE;
 		}
 	}
-
-	return ata_bio->flags & ATA_ITSDONE ? ATACMD_COMPLETE : ATACMD_QUEUED;
 }
 
 void
@@ -430,7 +426,7 @@ uisdata_exec_cb(struct umass_softc *sc, 
 	}
 }
 
-int
+void
 uisdata_exec_command(struct ata_drive_datas *drv, struct ata_xfer *xfer)
 {
 	struct umass_softc *sc = CH2SELF(drv->chnl_softc);
@@ -455,7 +451,7 @@ uisdata_exec_command(struct ata_drive_da
 	if (cmd->bcount > UMASS_MAX_TRANSFER_SIZE) {
 		printf("uisdata_exec_command: large datalen %d\n", cmd->bcount);
 		cmd->flags |= AT_ERROR;
-		goto done;
+		return;
 	}
 
 	memset(&ata, 0, sizeof(ata));
@@ -472,7 +468,7 @@ uisdata_exec_command(struct ata_drive_da
 		printf("uisdata_exec_command: bad command 0x%02x\n",
 		       cmd->r_command);
 		cmd->flags |= AT_ERROR;
-		goto done;
+		return;
 	}
 
 	DPRINTF(("%s: execute ATA command 0x%02x, drive=%d\n", __func__,
@@ -488,12 +484,9 @@ uisdata_exec_command(struct ata_drive_da
 		DPRINTF(("%s: tsleep %p\n", __func__, cmd));
 		if (tsleep(cmd, PZERO, "uisdataex", 0)) {
 			cmd->flags |= AT_ERROR;
-			goto done;
+			return;
 		}
 	}
-
-done:
-	return ATACMD_COMPLETE;
 }
 
 int
@@ -560,11 +553,8 @@ uisdata_get_params(struct ata_drive_data
 	xfer->c_ata_c.flags = AT_READ | flags;
 	xfer->c_ata_c.data = tb;
 	xfer->c_ata_c.bcount = DEV_BSIZE;
-	if (uisdata_exec_command(drvp, xfer) != ATACMD_COMPLETE) {
-		DPRINTF(("uisdata_get_parms: uisdata_exec_command failed\n"));
-		rv = CMD_AGAIN;
-		goto out;
-	}
+	uisdata_exec_command(drvp, xfer);
+	ata_wait_cmd(drvp->chnl_softc, xfer);
 	if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
 		DPRINTF(("uisdata_get_parms: ata_c.flags=0x%x\n",
 			 xfer->c_ata_c.flags));

Reply via email to