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, ¶ms) != 0) + if (wd_get_params(wd, ¶ms) != 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, ¶ms) != 0) + if (wd_get_params(wd, ¶ms) != 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));