Module Name: src
Committed By: jdolecek
Date: Mon Apr 13 10:49:35 UTC 2020
Modified Files:
src/sys/dev/ata: ata.c ata_recovery.c ata_wdc.c atavar.h satapmp_subr.c
wd.c
src/sys/dev/ic: ahcisata_core.c mvsata.c siisata.c wdc.c wdcvar.h
src/sys/dev/scsipi: atapi_wdc.c
Log Message:
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
To generate a diff of this commit:
cvs rdiff -u -r1.154 -r1.155 src/sys/dev/ata/ata.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/ata/ata_recovery.c
cvs rdiff -u -r1.114 -r1.115 src/sys/dev/ata/ata_wdc.c
cvs rdiff -u -r1.104 -r1.105 src/sys/dev/ata/atavar.h
cvs rdiff -u -r1.15 -r1.16 src/sys/dev/ata/satapmp_subr.c
cvs rdiff -u -r1.461 -r1.462 src/sys/dev/ata/wd.c
cvs rdiff -u -r1.82 -r1.83 src/sys/dev/ic/ahcisata_core.c
cvs rdiff -u -r1.55 -r1.56 src/sys/dev/ic/mvsata.c
cvs rdiff -u -r1.41 -r1.42 src/sys/dev/ic/siisata.c
cvs rdiff -u -r1.298 -r1.299 src/sys/dev/ic/wdc.c
cvs rdiff -u -r1.99 -r1.100 src/sys/dev/ic/wdcvar.h
cvs rdiff -u -r1.137 -r1.138 src/sys/dev/scsipi/atapi_wdc.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.154 src/sys/dev/ata/ata.c:1.155
--- src/sys/dev/ata/ata.c:1.154 Sat Apr 4 21:36:15 2020
+++ src/sys/dev/ata/ata.c Mon Apr 13 10:49:34 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.154 2020/04/04 21:36:15 jdolecek Exp $ */
+/* $NetBSD: ata.c,v 1.155 2020/04/13 10:49:34 jdolecek 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.154 2020/04/04 21:36:15 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.155 2020/04/13 10:49:34 jdolecek Exp $");
#include "opt_ata.h"
@@ -847,13 +847,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);
@@ -937,11 +932,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;
Index: src/sys/dev/ata/ata_recovery.c
diff -u src/sys/dev/ata/ata_recovery.c:1.3 src/sys/dev/ata/ata_recovery.c:1.4
--- src/sys/dev/ata/ata_recovery.c:1.3 Sat Apr 4 22:30:02 2020
+++ src/sys/dev/ata/ata_recovery.c Mon Apr 13 10:49:34 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: ata_recovery.c,v 1.3 2020/04/04 22:30:02 jdolecek Exp $ */
+/* $NetBSD: ata_recovery.c,v 1.4 2020/04/13 10:49:34 jdolecek 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.3 2020/04/04 22:30:02 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_recovery.c,v 1.4 2020/04/13 10:49:34 jdolecek 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.114 src/sys/dev/ata/ata_wdc.c:1.115
--- src/sys/dev/ata/ata_wdc.c:1.114 Sat Apr 4 21:36:15 2020
+++ src/sys/dev/ata/ata_wdc.c Mon Apr 13 10:49:34 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: ata_wdc.c,v 1.114 2020/04/04 21:36:15 jdolecek Exp $ */
+/* $NetBSD: ata_wdc.c,v 1.115 2020/04/13 10:49:34 jdolecek 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.114 2020/04/04 21:36:15 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.115 2020/04/13 10:49:34 jdolecek Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -102,7 +102,7 @@ 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 *);
@@ -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
Index: src/sys/dev/ata/atavar.h
diff -u src/sys/dev/ata/atavar.h:1.104 src/sys/dev/ata/atavar.h:1.105
--- src/sys/dev/ata/atavar.h:1.104 Sat Apr 4 21:36:15 2020
+++ src/sys/dev/ata/atavar.h Mon Apr 13 10:49:34 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: atavar.h,v 1.104 2020/04/04 21:36:15 jdolecek Exp $ */
+/* $NetBSD: atavar.h,v 1.105 2020/04/13 10:49:34 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -358,10 +358,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.16
--- src/sys/dev/ata/satapmp_subr.c:1.15 Mon Oct 22 20:13:47 2018
+++ src/sys/dev/ata/satapmp_subr.c Mon Apr 13 10:49:34 2020
@@ -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.16 2020/04/13 10:49:34 jdolecek 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.16 2020/04/13 10:49:34 jdolecek 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.461 src/sys/dev/ata/wd.c:1.462
--- src/sys/dev/ata/wd.c:1.461 Mon Apr 13 08:05:02 2020
+++ src/sys/dev/ata/wd.c Mon Apr 13 10:49:34 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: wd.c,v 1.461 2020/04/13 08:05:02 maxv Exp $ */
+/* $NetBSD: wd.c,v 1.462 2020/04/13 10:49:34 jdolecek 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.461 2020/04/13 08:05:02 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.462 2020/04/13 10:49:34 jdolecek 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);
@@ -336,7 +336,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;
}
@@ -760,16 +760,8 @@ wdstart1(struct wd_softc *wd, struct buf
wd->inflight++;
mutex_exit(&wd->sc_lock);
- 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()");
- }
+ /* Queue the xfer */
+ wd->atabus->ata_bio(wd->drvp, xfer);
mutex_enter(&wd->sc_lock);
}
@@ -1165,7 +1157,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;
@@ -1609,18 +1601,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");
@@ -1707,10 +1690,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)) {
@@ -1755,7 +1739,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 ||
@@ -1783,7 +1767,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 ||
@@ -1806,12 +1790,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];
@@ -1843,12 +1824,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 */
@@ -1900,12 +1879,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 */
@@ -1969,13 +1946,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) {
@@ -2170,12 +2144,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.82 src/sys/dev/ic/ahcisata_core.c:1.83
--- src/sys/dev/ic/ahcisata_core.c:1.82 Wed Feb 19 16:04:39 2020
+++ src/sys/dev/ic/ahcisata_core.c Mon Apr 13 10:49:34 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisata_core.c,v 1.82 2020/02/19 16:04:39 riastradh Exp $ */
+/* $NetBSD: ahcisata_core.c,v 1.83 2020/04/13 10:49:34 jdolecek Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.82 2020/02/19 16:04:39 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.83 2020/04/13 10:49:34 jdolecek Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -57,12 +57,12 @@ 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 *);
@@ -1101,13 +1101,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,
@@ -1121,25 +1119,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
@@ -1374,7 +1355,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;
@@ -1391,7 +1372,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
Index: src/sys/dev/ic/mvsata.c
diff -u src/sys/dev/ic/mvsata.c:1.55 src/sys/dev/ic/mvsata.c:1.56
--- src/sys/dev/ic/mvsata.c:1.55 Sat Apr 4 21:36:15 2020
+++ src/sys/dev/ic/mvsata.c Mon Apr 13 10:49:34 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: mvsata.c,v 1.55 2020/04/04 21:36:15 jdolecek Exp $ */
+/* $NetBSD: mvsata.c,v 1.56 2020/04/13 10:49:34 jdolecek 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.55 2020/04/04 21:36:15 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.56 2020/04/13 10:49:34 jdolecek 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 *);
@@ -985,7 +985,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;
@@ -1009,7 +1009,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
@@ -1601,12 +1600,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,"
@@ -1625,24 +1623,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
Index: src/sys/dev/ic/siisata.c
diff -u src/sys/dev/ic/siisata.c:1.41 src/sys/dev/ic/siisata.c:1.42
--- src/sys/dev/ic/siisata.c:1.41 Wed Feb 19 16:04:39 2020
+++ src/sys/dev/ic/siisata.c Mon Apr 13 10:49:34 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.41 2020/02/19 16:04:39 riastradh Exp $ */
+/* $NetBSD: siisata.c,v 1.42 2020/04/13 10:49:34 jdolecek Exp $ */
/* from ahcisata_core.c */
@@ -79,7 +79,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.41 2020/02/19 16:04:39 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.42 2020/04/13 10:49:34 jdolecek 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 *);
@@ -160,7 +160,7 @@ int siisata_bio_complete(struct ata_chan
void 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 *);
@@ -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
@@ -1190,7 +1172,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 +1182,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 +1189,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
Index: src/sys/dev/ic/wdc.c
diff -u src/sys/dev/ic/wdc.c:1.298 src/sys/dev/ic/wdc.c:1.299
--- src/sys/dev/ic/wdc.c:1.298 Sat Apr 4 21:36:15 2020
+++ src/sys/dev/ic/wdc.c Mon Apr 13 10:49:34 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc.c,v 1.298 2020/04/04 21:36:15 jdolecek Exp $ */
+/* $NetBSD: wdc.c,v 1.299 2020/04/13 10:49:34 jdolecek 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.298 2020/04/04 21:36:15 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.299 2020/04/13 10:49:34 jdolecek Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -1391,12 +1391,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,
@@ -1414,25 +1413,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
Index: src/sys/dev/ic/wdcvar.h
diff -u src/sys/dev/ic/wdcvar.h:1.99 src/sys/dev/ic/wdcvar.h:1.100
--- src/sys/dev/ic/wdcvar.h:1.99 Sat Sep 14 17:11:39 2019
+++ src/sys/dev/ic/wdcvar.h Mon Apr 13 10:49:34 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: wdcvar.h,v 1.99 2019/09/14 17:11:39 tsutsui Exp $ */
+/* $NetBSD: wdcvar.h,v 1.100 2020/04/13 10:49:34 jdolecek 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.137 src/sys/dev/scsipi/atapi_wdc.c:1.138
--- src/sys/dev/scsipi/atapi_wdc.c:1.137 Sat Apr 4 21:36:15 2020
+++ src/sys/dev/scsipi/atapi_wdc.c Mon Apr 13 10:49:34 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: atapi_wdc.c,v 1.137 2020/04/04 21:36:15 jdolecek Exp $ */
+/* $NetBSD: atapi_wdc.c,v 1.138 2020/04/13 10:49:34 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.137 2020/04/04 21:36:15 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.138 2020/04/13 10:49:34 jdolecek Exp $");
#ifndef ATADEBUG
#define ATADEBUG
@@ -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",