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, &params) != 0)
+	if (wd_get_params(wd, &params) != 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, &params) != 0)
+	if (wd_get_params(wd, &params) != 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",

Reply via email to