Module Name: src
Committed By: jdolecek
Date: Tue Sep 19 21:06:25 UTC 2017
Modified Files:
src/sys/dev/ata [jdolecek-ncq]: TODO.ncq ata.c atavar.h sata_subr.c
satapmp_subr.c satapmpvar.h
src/sys/dev/ic [jdolecek-ncq]: ahcisata_core.c mvsata.c siisata.c wdc.c
Log Message:
replace all remaining tsleep()/wakeup() calls with condition variables, or
calls to ata_delay(), as appropriate; change ata_delay() to require the
channel lock on entry, and pass the lock to kpause() for unlocking while
sleeping
To generate a diff of this commit:
cvs rdiff -u -r1.1.2.41 -r1.1.2.42 src/sys/dev/ata/TODO.ncq
cvs rdiff -u -r1.132.8.32 -r1.132.8.33 src/sys/dev/ata/ata.c
cvs rdiff -u -r1.92.8.25 -r1.92.8.26 src/sys/dev/ata/atavar.h
cvs rdiff -u -r1.21 -r1.21.24.1 src/sys/dev/ata/sata_subr.c
cvs rdiff -u -r1.12.24.5 -r1.12.24.6 src/sys/dev/ata/satapmp_subr.c
cvs rdiff -u -r1.3 -r1.3.30.1 src/sys/dev/ata/satapmpvar.h
cvs rdiff -u -r1.57.6.28 -r1.57.6.29 src/sys/dev/ic/ahcisata_core.c
cvs rdiff -u -r1.35.6.25 -r1.35.6.26 src/sys/dev/ic/mvsata.c
cvs rdiff -u -r1.30.4.37 -r1.30.4.38 src/sys/dev/ic/siisata.c
cvs rdiff -u -r1.283.2.15 -r1.283.2.16 src/sys/dev/ic/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/TODO.ncq
diff -u src/sys/dev/ata/TODO.ncq:1.1.2.41 src/sys/dev/ata/TODO.ncq:1.1.2.42
--- src/sys/dev/ata/TODO.ncq:1.1.2.41 Wed Sep 13 19:55:12 2017
+++ src/sys/dev/ata/TODO.ncq Tue Sep 19 21:06:25 2017
@@ -4,10 +4,6 @@ test wd* at umass?, confirm the ata_chan
mvsata - resest MVSATA_WITHOUTDMA
-the changes to lock channel lock cause now mi_switch() with spinlock held
-when invoking ata_delay() (which calls kpause()) or on tsleep, need
-to refactor
-
Other random notes (do outside the NCQ branch):
-----------------------------------------------------
do biodone() in wddone() starting the dump to not leak bufs when dumping from
Index: src/sys/dev/ata/ata.c
diff -u src/sys/dev/ata/ata.c:1.132.8.32 src/sys/dev/ata/ata.c:1.132.8.33
--- src/sys/dev/ata/ata.c:1.132.8.32 Mon Sep 11 22:16:18 2017
+++ src/sys/dev/ata/ata.c Tue Sep 19 21:06:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.132.8.32 2017/09/11 22:16:18 jdolecek Exp $ */
+/* $NetBSD: ata.c,v 1.132.8.33 2017/09/19 21:06:25 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.132.8.32 2017/09/11 22:16:18 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.132.8.33 2017/09/19 21:06:25 jdolecek Exp $");
#include "opt_ata.h"
@@ -279,6 +279,7 @@ ata_xfer_init(struct ata_xfer *xfer, uin
xfer->c_slot = slot;
cv_init(&xfer->c_active, "ataact");
+ cv_init(&xfer->c_finish, "atafin");
callout_init(&xfer->c_timo_callout, 0); /* XXX MPSAFE */
callout_init(&xfer->c_retry_callout, 0); /* XXX MPSAFE */
}
@@ -291,6 +292,7 @@ ata_xfer_destroy(struct ata_xfer *xfer)
callout_halt(&xfer->c_retry_callout, NULL); /* XXX MPSAFE */
callout_destroy(&xfer->c_retry_callout);
cv_destroy(&xfer->c_active);
+ cv_destroy(&xfer->c_finish);
}
struct ata_queue *
@@ -310,6 +312,7 @@ ata_queue_alloc(uint8_t openings)
cv_init(&chq->queue_busy, "ataqbusy");
cv_init(&chq->queue_drain, "atdrn");
+ cv_init(&chq->queue_idle, "qidl");
for (uint8_t i = 0; i < openings; i++)
ata_xfer_init(&chq->queue_xfers[i], i);
@@ -1194,13 +1197,13 @@ ata_dmaerr(struct ata_drive_datas *drvp,
static void
ata_channel_idle(struct ata_channel *chp)
{
- int s = splbio();
- ata_channel_freeze(chp);
+ ata_channel_lock(chp);
+ ata_channel_freeze_locked(chp);
while (chp->ch_queue->queue_active > 0) {
chp->ch_queue->queue_flags |= QF_IDLE_WAIT;
- tsleep(&chp->ch_queue->queue_flags, PRIBIO, "qidl", 0);
+ cv_timedwait(&chp->ch_queue->queue_idle, &chp->ch_lock, 1);
}
- splx(s);
+ ata_channel_unlock(chp);
}
/*
@@ -1246,6 +1249,8 @@ ata_exec_xfer(struct ata_channel *chp, s
* while we were waiting.
*/
if ((xfer->c_flags & (C_FREE|C_WAITTIMO)) == C_FREE) {
+ ata_channel_unlock(chp);
+
ata_free_xfer(chp, xfer);
return;
}
@@ -1305,7 +1310,7 @@ again:
if (__predict_false(!recovery && chq->queue_freeze > 0)) {
if (chq->queue_flags & QF_IDLE_WAIT) {
chq->queue_flags &= ~QF_IDLE_WAIT;
- wakeup(&chq->queue_flags);
+ cv_signal(&chp->ch_queue->queue_idle);
}
goto out; /* queue frozen */
}
@@ -1673,7 +1678,7 @@ out:
/*
* Kill off all active xfers for a ata_channel.
*
- * Must be called at splbio().
+ * Must be called with channel lock held.
*/
void
ata_kill_active(struct ata_channel *chp, int reason, int flags)
@@ -1681,6 +1686,8 @@ ata_kill_active(struct ata_channel *chp,
struct ata_queue * const chq = chp->ch_queue;
struct ata_xfer *xfer, *xfernext;
+ KASSERT(mutex_owned(&chp->ch_lock));
+
TAILQ_FOREACH_SAFE(xfer, &chq->active_xfers, c_activechain, xfernext) {
(*xfer->c_kill_xfer)(xfer->c_chp, xfer, reason);
}
@@ -2000,7 +2007,7 @@ ata_probe_caps(struct ata_drive_datas *d
struct ata_channel *chp = drvp->chnl_softc;
struct atac_softc *atac = chp->ch_atac;
device_t drv_dev = drvp->drv_softc;
- int i, printed = 0, s;
+ int i, printed = 0;
const char *sep = "";
int cf_flags;
@@ -2015,15 +2022,15 @@ ata_probe_caps(struct ata_drive_datas *d
* Re-do an IDENTIFY with 32-bit transfers,
* and compare results.
*/
- s = splbio();
+ ata_channel_lock(chp);
drvp->drive_flags |= ATA_DRIVE_CAP32;
- splx(s);
+ ata_channel_unlock(chp);
ata_get_params(drvp, AT_WAIT, ¶ms2);
if (memcmp(¶ms, ¶ms2, sizeof(struct ataparams)) != 0) {
/* Not good. fall back to 16bits */
- s = splbio();
+ ata_channel_lock(chp);
drvp->drive_flags &= ~ATA_DRIVE_CAP32;
- splx(s);
+ ata_channel_unlock(chp);
} else {
aprint_verbose_dev(drv_dev, "32-bit data port\n");
}
@@ -2101,9 +2108,9 @@ ata_probe_caps(struct ata_drive_datas *d
*/
return;
}
- s = splbio();
+ ata_channel_lock(chp);
drvp->drive_flags |= ATA_DRIVE_MODE;
- splx(s);
+ ata_channel_unlock(chp);
printed = 0;
for (i = 7; i >= 0; i--) {
if ((params.atap_dmamode_supp & (1 << i)) == 0)
@@ -2127,9 +2134,9 @@ ata_probe_caps(struct ata_drive_datas *d
continue;
drvp->DMA_mode = i;
drvp->DMA_cap = i;
- s = splbio();
+ ata_channel_lock(chp);
drvp->drive_flags |= ATA_DRIVE_DMA;
- splx(s);
+ ata_channel_unlock(chp);
}
#endif
break;
@@ -2168,9 +2175,9 @@ ata_probe_caps(struct ata_drive_datas *d
continue;
drvp->UDMA_mode = i;
drvp->UDMA_cap = i;
- s = splbio();
+ ata_channel_lock(chp);
drvp->drive_flags |= ATA_DRIVE_UDMA;
- splx(s);
+ ata_channel_unlock(chp);
}
#endif
break;
@@ -2178,7 +2185,7 @@ ata_probe_caps(struct ata_drive_datas *d
}
}
- s = splbio();
+ ata_channel_lock(chp);
drvp->drive_flags &= ~ATA_DRIVE_NOSTREAM;
if (drvp->drive_type == ATA_DRIVET_ATAPI) {
if (atac->atac_cap & ATAC_CAP_ATAPI_NOSTREAM)
@@ -2187,7 +2194,7 @@ ata_probe_caps(struct ata_drive_datas *d
if (atac->atac_cap & ATAC_CAP_ATA_NOSTREAM)
drvp->drive_flags |= ATA_DRIVE_NOSTREAM;
}
- splx(s);
+ ata_channel_unlock(chp);
/* Try to guess ATA version here, if it didn't get reported */
if (drvp->ata_vers == 0) {
@@ -2201,11 +2208,11 @@ ata_probe_caps(struct ata_drive_datas *d
}
cf_flags = device_cfdata(drv_dev)->cf_flags;
if (cf_flags & ATA_CONFIG_PIO_SET) {
- s = splbio();
+ ata_channel_lock(chp);
drvp->PIO_mode =
(cf_flags & ATA_CONFIG_PIO_MODES) >> ATA_CONFIG_PIO_OFF;
drvp->drive_flags |= ATA_DRIVE_MODE;
- splx(s);
+ ata_channel_unlock(chp);
}
#if NATA_DMA
if ((atac->atac_cap & ATAC_CAP_DMA) == 0) {
@@ -2213,7 +2220,7 @@ ata_probe_caps(struct ata_drive_datas *d
return;
}
if (cf_flags & ATA_CONFIG_DMA_SET) {
- s = splbio();
+ ata_channel_lock(chp);
if ((cf_flags & ATA_CONFIG_DMA_MODES) ==
ATA_CONFIG_DMA_DISABLE) {
drvp->drive_flags &= ~ATA_DRIVE_DMA;
@@ -2222,7 +2229,7 @@ ata_probe_caps(struct ata_drive_datas *d
ATA_CONFIG_DMA_OFF;
drvp->drive_flags |= ATA_DRIVE_DMA | ATA_DRIVE_MODE;
}
- splx(s);
+ ata_channel_unlock(chp);
}
/*
@@ -2239,7 +2246,7 @@ ata_probe_caps(struct ata_drive_datas *d
}
/* Probe NCQ support - READ/WRITE FPDMA QUEUED command support */
- s = splbio();
+ ata_channel_lock(chp);
drvp->drv_openings = 1;
if (params.atap_sata_caps & SATA_NATIVE_CMDQ) {
if (atac->atac_cap & ATAC_CAP_NCQ)
@@ -2254,7 +2261,7 @@ ata_probe_caps(struct ata_drive_datas *d
aprint_verbose(" w/PRIO");
}
}
- splx(s);
+ ata_channel_unlock(chp);
if (printed)
aprint_verbose("\n");
@@ -2265,7 +2272,7 @@ ata_probe_caps(struct ata_drive_datas *d
return;
}
if (cf_flags & ATA_CONFIG_UDMA_SET) {
- s = splbio();
+ ata_channel_lock(chp);
if ((cf_flags & ATA_CONFIG_UDMA_MODES) ==
ATA_CONFIG_UDMA_DISABLE) {
drvp->drive_flags &= ~ATA_DRIVE_UDMA;
@@ -2274,7 +2281,7 @@ ata_probe_caps(struct ata_drive_datas *d
ATA_CONFIG_UDMA_OFF;
drvp->drive_flags |= ATA_DRIVE_UDMA | ATA_DRIVE_MODE;
}
- splx(s);
+ ata_channel_unlock(chp);
}
#endif /* NATA_UDMA */
#endif /* NATA_DMA */
@@ -2472,8 +2479,10 @@ atabus_rescan(device_t self, const char
}
void
-ata_delay(int ms, const char *msg, int flags)
+ata_delay(struct ata_channel *chp, int ms, const char *msg, int flags)
{
+ KASSERT(mutex_owned(&chp->ch_lock));
+
if ((flags & (AT_WAIT | AT_POLL)) == AT_POLL) {
/*
* can't use kpause(), we may be in interrupt context
@@ -2482,7 +2491,7 @@ ata_delay(int ms, const char *msg, int f
delay(ms * 1000);
} else {
int pause = mstohz(ms);
- kpause(msg, false, pause > 0 ? pause : 1, NULL);
+ kpause(msg, false, pause > 0 ? pause : 1, &chp->ch_lock);
}
}
@@ -2580,3 +2589,19 @@ ata_channel_lock_owned(struct ata_channe
{
KASSERT(mutex_owned(&chp->ch_lock));
}
+
+void
+ata_wait_xfer(struct ata_channel *chp, struct ata_xfer *xfer)
+{
+ KASSERT(mutex_owned(&chp->ch_lock));
+
+ cv_wait(&xfer->c_finish, &chp->ch_lock);
+}
+
+void
+ata_wake_xfer(struct ata_channel *chp, struct ata_xfer *xfer)
+{
+ KASSERT(mutex_owned(&chp->ch_lock));
+
+ cv_signal(&xfer->c_finish);
+}
Index: src/sys/dev/ata/atavar.h
diff -u src/sys/dev/ata/atavar.h:1.92.8.25 src/sys/dev/ata/atavar.h:1.92.8.26
--- src/sys/dev/ata/atavar.h:1.92.8.25 Sun Sep 10 19:31:15 2017
+++ src/sys/dev/ata/atavar.h Tue Sep 19 21:06:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: atavar.h,v 1.92.8.25 2017/09/10 19:31:15 jdolecek Exp $ */
+/* $NetBSD: atavar.h,v 1.92.8.26 2017/09/19 21:06:25 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -134,6 +134,7 @@ struct ata_xfer {
struct callout c_timo_callout; /* timeout callout handle */
struct callout c_retry_callout; /* retry callout handle */
kcondvar_t c_active; /* somebody actively waiting for xfer */
+ kcondvar_t c_finish; /* somebody waiting for xfer finish */
int8_t c_slot; /* queue slot # */
#define c_startzero c_chp
@@ -182,7 +183,7 @@ struct ata_xfer {
#define C_TIMEOU 0x0002 /* xfer processing timed out */
#define C_POLL 0x0004 /* command is polled */
#define C_DMA 0x0008 /* command uses DMA */
-#define C_WAIT 0x0010 /* can use tsleep */
+#define C_WAIT 0x0010 /* can use kpause */
#define C_WAITACT 0x0020 /* wakeup when active */
#define C_FREE 0x0040 /* call ata_free_xfer() asap */
#define C_PIOBM 0x0080 /* command uses busmastering PIO */
@@ -220,6 +221,7 @@ struct ata_queue {
int queue_freeze; /* freeze count for the queue */
kcondvar_t queue_busy; /* c: waiting of xfer */
kcondvar_t queue_drain; /* c: waiting of queue drain */
+ kcondvar_t queue_idle; /* c: waiting of queue idle */
TAILQ_HEAD(, ata_xfer) active_xfers; /* active commands */
uint32_t active_xfers_used; /* mask of active commands */
uint32_t queue_xfers_avail; /* available xfers mask */
@@ -515,6 +517,8 @@ void ata_free_xfer(struct ata_channel *,
void ata_deactivate_xfer(struct ata_channel *, struct ata_xfer *);
void ata_exec_xfer(struct ata_channel *, struct ata_xfer *);
int ata_xfer_start(struct ata_xfer *xfer);
+void ata_wait_xfer(struct ata_channel *, struct ata_xfer *xfer);
+void ata_wake_xfer(struct ata_channel *, struct ata_xfer *xfer);
void ata_timeout(void *);
bool ata_timo_xfer_check(struct ata_xfer *);
@@ -550,7 +554,7 @@ struct ata_xfer *
struct ata_xfer *
ata_queue_drive_active_xfer(struct ata_channel *, int);
-void ata_delay(int, const char *, int);
+void ata_delay(struct ata_channel *, int, const char *, int);
bool ata_waitdrain_xfer_check(struct ata_channel *, struct ata_xfer *);
Index: src/sys/dev/ata/sata_subr.c
diff -u src/sys/dev/ata/sata_subr.c:1.21 src/sys/dev/ata/sata_subr.c:1.21.24.1
--- src/sys/dev/ata/sata_subr.c:1.21 Wed Apr 3 17:15:07 2013
+++ src/sys/dev/ata/sata_subr.c Tue Sep 19 21:06:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sata_subr.c,v 1.21 2013/04/03 17:15:07 bouyer Exp $ */
+/* $NetBSD: sata_subr.c,v 1.21.24.1 2017/09/19 21:06:25 jdolecek Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
* Common functions for Serial ATA.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sata_subr.c,v 1.21 2013/04/03 17:15:07 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sata_subr.c,v 1.21.24.1 2017/09/19 21:06:25 jdolecek Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -85,6 +85,8 @@ sata_reset_interface(struct ata_channel
uint32_t scontrol, sstatus;
int i;
+ ata_channel_lock_owned(chp);
+
/* bring the PHYs online.
* The work-around for errata #1 of the Intel GD31244 says that we must
* write 0 to the port first to be sure of correctly initializing
@@ -92,19 +94,19 @@ sata_reset_interface(struct ata_channel
*/
bus_space_write_4(sata_t, scontrol_r, 0, 0);
scontrol = SControl_IPM_NONE | SControl_SPD_ANY | SControl_DET_INIT;
- bus_space_write_4 (sata_t, scontrol_r, 0, scontrol);
+ bus_space_write_4(sata_t, scontrol_r, 0, scontrol);
- ata_delay(50, "sataup", flags);
+ ata_delay(chp, 50, "sataup", flags);
scontrol &= ~SControl_DET_INIT;
bus_space_write_4(sata_t, scontrol_r, 0, scontrol);
- ata_delay(50, "sataup", flags);
+ ata_delay(chp, 50, "sataup", flags);
/* wait up to 1s for device to come up */
for (i = 0; i < 100; i++) {
sstatus = bus_space_read_4(sata_t, sstatus_r, 0);
if ((sstatus & SStatus_DET_mask) == SStatus_DET_DEV)
break;
- ata_delay(10, "sataup", flags);
+ ata_delay(chp, 10, "sataup", flags);
}
/*
* if we have a link up without device, wait a few more seconds
@@ -112,7 +114,7 @@ sata_reset_interface(struct ata_channel
*/
if ((sstatus & SStatus_DET_mask) == SStatus_DET_DEV_NE) {
for (i = 0; i < 500; i++) {
- ata_delay(10, "sataup", flags);
+ ata_delay(chp, 10, "sataup", flags);
sstatus = bus_space_read_4(sata_t, sstatus_r, 0);
if ((sstatus & SStatus_DET_mask) == SStatus_DET_DEV)
break;
@@ -152,7 +154,8 @@ void
sata_interpret_sig(struct ata_channel *chp, int port, uint32_t sig)
{
int err;
- int s;
+
+ ata_channel_lock_owned(chp);
/* some ATAPI devices have bogus lower two bytes, sigh */
if ((sig & 0xffff0000) == 0xeb140000) {
@@ -169,7 +172,6 @@ sata_interpret_sig(struct ata_channel *c
}
KASSERT(port < chp->ch_ndrives);
- s = splbio();
switch(sig) {
case 0x96690101:
KASSERT(port == 0 || port == PMP_PORT_CTL);
@@ -195,5 +197,4 @@ sata_interpret_sig(struct ata_channel *c
"Assuming it's a disk.\n", sig, port);
break;
}
- splx(s);
}
Index: src/sys/dev/ata/satapmp_subr.c
diff -u src/sys/dev/ata/satapmp_subr.c:1.12.24.5 src/sys/dev/ata/satapmp_subr.c:1.12.24.6
--- src/sys/dev/ata/satapmp_subr.c:1.12.24.5 Wed Jul 26 18:12:12 2017
+++ src/sys/dev/ata/satapmp_subr.c Tue Sep 19 21:06:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: satapmp_subr.c,v 1.12.24.5 2017/07/26 18:12:12 jdolecek Exp $ */
+/* $NetBSD: satapmp_subr.c,v 1.12.24.6 2017/09/19 21:06:25 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.12.24.5 2017/07/26 18:12:12 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: satapmp_subr.c,v 1.12.24.6 2017/09/19 21:06:25 jdolecek Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -48,9 +48,9 @@ __KERNEL_RCSID(0, "$NetBSD: satapmp_subr
#include <dev/ata/satareg.h>
static int
-satapmp_read_8(struct ata_channel *chp, int port, int reg, uint64_t *value)
+satapmp_read_8(struct ata_channel *chp, int port, int reg, uint64_t *value,
+ struct ata_xfer *xfer)
{
- struct ata_xfer *xfer;
struct atac_softc *atac = chp->ch_atac;
struct ata_drive_datas *drvp;
int error = 0;
@@ -60,10 +60,7 @@ satapmp_read_8(struct ata_channel *chp,
KASSERT(chp->ch_ndrives >= PMP_MAX_DRIVES);
drvp = &chp->ch_drive[PMP_PORT_CTL];
KASSERT(drvp->drive == PMP_PORT_CTL);
-
- xfer = ata_get_xfer(chp);
- if (xfer == NULL)
- return EINTR;
+ ata_channel_lock_owned(chp);
xfer->c_ata_c.r_command = PMPC_READ_PORT;
xfer->c_ata_c.r_features = reg;
@@ -73,6 +70,7 @@ satapmp_read_8(struct ata_channel *chp,
xfer->c_ata_c.r_st_pmask = WDCS_DRDY;
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,
@@ -101,17 +99,18 @@ satapmp_read_8(struct ata_channel *chp,
((uint64_t)((xfer->c_ata_c.r_count >> 0) & 0xff) << 0);
out:
- ata_free_xfer(chp, xfer);
+ ata_channel_lock(chp);
return error;
}
static inline int
-satapmp_read(struct ata_channel *chp, int port, int reg, uint32_t *value)
+satapmp_read(struct ata_channel *chp, int port, int reg, uint32_t *value,
+ struct ata_xfer *xfer)
{
uint64_t value64;
int ret;
- ret = satapmp_read_8(chp, port, reg, &value64);
+ ret = satapmp_read_8(chp, port, reg, &value64, xfer);
if (ret)
return ret;
@@ -120,9 +119,9 @@ satapmp_read(struct ata_channel *chp, in
}
static int
-satapmp_write_8(struct ata_channel *chp, int port, int reg, uint64_t value)
+satapmp_write_8(struct ata_channel *chp, int port, int reg, uint64_t value,
+ struct ata_xfer *xfer)
{
- struct ata_xfer *xfer;
struct atac_softc *atac = chp->ch_atac;
struct ata_drive_datas *drvp;
int error = 0;
@@ -132,10 +131,7 @@ satapmp_write_8(struct ata_channel *chp,
KASSERT(chp->ch_ndrives >= PMP_MAX_DRIVES);
drvp = &chp->ch_drive[PMP_PORT_CTL];
KASSERT(drvp->drive == PMP_PORT_CTL);
-
- xfer = ata_get_xfer(chp);
- if (xfer == NULL)
- return EINTR;
+ ata_channel_lock_owned(chp);
xfer->c_ata_c.r_command = PMPC_WRITE_PORT;
xfer->c_ata_c.r_features = reg;
@@ -149,6 +145,7 @@ satapmp_write_8(struct ata_channel *chp,
xfer->c_ata_c.r_st_pmask = WDCS_DRDY;
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,
@@ -172,14 +169,15 @@ satapmp_write_8(struct ata_channel *chp,
}
out:
- ata_free_xfer(chp, xfer);
+ ata_channel_lock(chp);
return error;
}
static inline int
-satapmp_write(struct ata_channel *chp, int port, int reg, uint32_t value)
+satapmp_write(struct ata_channel *chp, int port, int reg, uint32_t value,
+ struct ata_xfer *xfer)
{
- return satapmp_write_8(chp, port, reg, value);
+ return satapmp_write_8(chp, port, reg, value, xfer);
}
/*
@@ -187,30 +185,34 @@ satapmp_write(struct ata_channel *chp, i
* XXX duplicate of sata_reset_interface()
*/
static uint32_t
-satapmp_reset_device_port(struct ata_channel *chp, int port)
+satapmp_reset_device_port(struct ata_channel *chp, int port,
+ struct ata_xfer *xfer)
{
uint32_t scontrol, sstatus;
int i;
+ ata_channel_lock_owned(chp);
+
/* bring the PHY online */
scontrol = SControl_IPM_NONE | SControl_SPD_ANY | SControl_DET_INIT;
- if (satapmp_write(chp, port, PMP_PSCR_SControl, scontrol) != 0)
+ if (satapmp_write(chp, port, PMP_PSCR_SControl, scontrol, xfer) != 0)
return 0;
- tsleep(chp, PRIBIO, "sataup", mstohz(50));
+ ata_delay(chp, 50, "sataup", AT_WAIT);
scontrol &= ~SControl_DET_INIT;
- if (satapmp_write(chp, port, PMP_PSCR_SControl, scontrol) != 0)
+ if (satapmp_write(chp, port, PMP_PSCR_SControl, scontrol, xfer) != 0)
return 0;
- tsleep(chp, PRIBIO, "sataup", mstohz(50));
+ ata_delay(chp, 50, "sataup", AT_WAIT);
/* wait up to 1s for device to come up */
for (i = 0; i < 100; i++) {
- if (satapmp_read(chp, port, PMP_PSCR_SStatus, &sstatus) != 0)
+ if (satapmp_read(chp, port, PMP_PSCR_SStatus, &sstatus,
+ xfer) != 0)
return 0;
if ((sstatus & SStatus_DET_mask) == SStatus_DET_DEV)
break;
- tsleep(chp, PRIBIO, "sataup", mstohz(10));
+ ata_delay(chp, 10, "sataup", AT_WAIT);
}
switch (sstatus & SStatus_DET_mask) {
@@ -238,25 +240,31 @@ satapmp_reset_device_port(struct ata_cha
}
void
-satapmp_rescan(struct ata_channel *chp) {
+satapmp_rescan(struct ata_channel *chp, struct ata_xfer *xfer)
+{
int i;
uint32_t sig;
KASSERT(chp->ch_satapmp_nports <= PMP_PORT_CTL);
KASSERT(chp->ch_satapmp_nports <= chp->ch_ndrives);
+ ata_channel_lock_owned(chp);
for (i = 0; i < chp->ch_satapmp_nports; i++) {
if (chp->ch_drive[i].drive_type != ATA_DRIVET_NONE ||
- satapmp_reset_device_port(chp, i) != SStatus_DET_DEV) {
+ satapmp_reset_device_port(chp, i, xfer)
+ != SStatus_DET_DEV) {
continue;
}
- if (satapmp_write(chp, i, PMP_PSCR_SError, 0xffffffff) != 0) {
+ if (satapmp_write(chp, i, PMP_PSCR_SError, 0xffffffff, xfer)
+ != 0) {
aprint_error("%s PMP port %d: can't write SError\n",
device_xname(chp->atabus), i);
continue;
}
+ ata_channel_unlock(chp);
chp->ch_atac->atac_bustype_ata->ata_reset_drive(
&chp->ch_drive[i], AT_WAIT, &sig);
+ ata_channel_lock(chp);
sata_interpret_sig(chp, i, sig);
}
@@ -266,14 +274,23 @@ void
satapmp_attach(struct ata_channel *chp)
{
uint32_t id, rev, inf;
+ struct ata_xfer *xfer;
- if (satapmp_read(chp, PMP_PORT_CTL, PMP_GSCR_ID, &id) != 0 ||
- satapmp_read(chp, PMP_PORT_CTL, PMP_GSCR_REV, &rev) != 0 ||
- satapmp_read(chp, PMP_PORT_CTL, PMP_GSCR_INF, &inf) != 0) {
- aprint_normal_dev(chp->atabus, "can't read PMP registers\n");
+ xfer = ata_get_xfer(chp);
+ if (xfer == NULL) {
+ aprint_normal_dev(chp->atabus, "no available xfer\n");
return;
}
+ ata_channel_lock(chp);
+
+ if (satapmp_read(chp, PMP_PORT_CTL, PMP_GSCR_ID, &id, xfer) != 0 ||
+ satapmp_read(chp, PMP_PORT_CTL, PMP_GSCR_REV, &rev, xfer) != 0 ||
+ satapmp_read(chp, PMP_PORT_CTL, PMP_GSCR_INF, &inf, xfer) != 0) {
+ aprint_normal_dev(chp->atabus, "can't read PMP registers\n");
+ goto out;
+ }
+
aprint_normal("%s at %s channel %d: SATA port multiplier, %d ports\n",
device_xname(chp->atabus),
device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
@@ -293,5 +310,9 @@ satapmp_attach(struct ata_channel *chp)
chp->ch_satapmp_nports = PMP_INF_NPORTS(inf);
/* reset and bring up PHYs */
- satapmp_rescan(chp);
+ satapmp_rescan(chp, xfer);
+
+out:
+ ata_channel_unlock(chp);
+ ata_free_xfer(chp, xfer);
}
Index: src/sys/dev/ata/satapmpvar.h
diff -u src/sys/dev/ata/satapmpvar.h:1.3 src/sys/dev/ata/satapmpvar.h:1.3.30.1
--- src/sys/dev/ata/satapmpvar.h:1.3 Wed Aug 1 09:02:03 2012
+++ src/sys/dev/ata/satapmpvar.h Tue Sep 19 21:06:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: satapmpvar.h,v 1.3 2012/08/01 09:02:03 bouyer Exp $ */
+/* $NetBSD: satapmpvar.h,v 1.3.30.1 2017/09/19 21:06:25 jdolecek Exp $ */
/*
@@ -29,7 +29,7 @@
#define _DEV_ATA_SATAPMPVAR_H_
void satapmp_attach(struct ata_channel *);
-void satapmp_rescan(struct ata_channel *);
+void satapmp_rescan(struct ata_channel *, struct ata_xfer *);
#endif /* _DEV_ATA_SATAPMPVAR_H_ */
Index: src/sys/dev/ic/ahcisata_core.c
diff -u src/sys/dev/ic/ahcisata_core.c:1.57.6.28 src/sys/dev/ic/ahcisata_core.c:1.57.6.29
--- src/sys/dev/ic/ahcisata_core.c:1.57.6.28 Tue Sep 19 17:52:52 2017
+++ src/sys/dev/ic/ahcisata_core.c Tue Sep 19 21:06:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisata_core.c,v 1.57.6.28 2017/09/19 17:52:52 jdolecek Exp $ */
+/* $NetBSD: ahcisata_core.c,v 1.57.6.29 2017/09/19 21:06:25 jdolecek Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.57.6.28 2017/09/19 17:52:52 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.57.6.29 2017/09/19 21:06:25 jdolecek Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -58,7 +58,8 @@ static void ahci_probe_drive(struct ata_
static void ahci_setup_channel(struct ata_channel *);
static int ahci_ata_bio(struct ata_drive_datas *, struct ata_xfer *);
-static int ahci_do_reset_drive(struct ata_channel *, int, int, uint32_t *);
+static int ahci_do_reset_drive(struct ata_channel *, int, int, uint32_t *,
+ struct ata_xfer *xfer);
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 *);
@@ -678,12 +679,23 @@ ahci_reset_drive(struct ata_drive_datas
{
struct ata_channel *chp = drvp->chnl_softc;
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
+ struct ata_xfer *xfer;
+
+ xfer = ata_get_xfer_ext(chp, C_RECOVERY, 0);
+
+ ata_channel_lock(chp);
+
AHCI_WRITE(sc, AHCI_GHC,
AHCI_READ(sc, AHCI_GHC) & ~AHCI_GHC_IE);
ahci_channel_stop(sc, chp, flags);
- if (ahci_do_reset_drive(chp, drvp->drive, flags, sigp) != 0)
+ if (ahci_do_reset_drive(chp, drvp->drive, flags, sigp, xfer) != 0)
ata_reset_channel(chp, flags);
AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
+
+ ata_channel_unlock(chp);
+
+ ata_free_xfer(chp, xfer);
+
return;
}
@@ -731,7 +743,7 @@ ahci_exec_fis(struct ata_channel *chp, i
AHCINAME(sc), chp->ch_channel, is);
return ERR_DF;
}
- ata_delay(10, "ahcifis", flags);
+ ata_delay(chp, 10, "ahcifis", flags);
}
aprint_debug("%s channel %d: timeout sending FIS\n",
@@ -741,7 +753,7 @@ ahci_exec_fis(struct ata_channel *chp, i
static int
ahci_do_reset_drive(struct ata_channel *chp, int drive, int flags,
- uint32_t *sigp)
+ uint32_t *sigp, struct ata_xfer *xfer)
{
struct ahci_channel *achp = (struct ahci_channel *)chp;
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
@@ -749,9 +761,10 @@ ahci_do_reset_drive(struct ata_channel *
struct ahci_cmd_header *cmd_h;
int i;
uint32_t sig;
- struct ata_xfer *xfer = NULL;
KASSERT((AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) & AHCI_P_CMD_CR) == 0);
+ ata_channel_lock_owned(chp);
+
again:
/* clear port interrupt register */
AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
@@ -774,8 +787,6 @@ again:
goto skip_reset;
/* polled command, assume interrupts are disabled */
- /* use available slot to send reset, if none available fail */
- xfer = ata_get_xfer_ext(chp, C_RECOVERY, 0);
cmd_h = &achp->ahcic_cmdh[xfer->c_slot];
cmd_tbl = achp->ahcic_cmd_tbl[xfer->c_slot];
@@ -837,7 +848,7 @@ skip_reset:
sig = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel));
if ((__SHIFTOUT(sig, AHCI_P_TFD_ST) & WDCS_BSY) == 0)
break;
- ata_delay(10, "ahcid2h", flags);
+ ata_delay(chp, 10, "ahcid2h", flags);
}
if (i == AHCI_RST_WAIT) {
aprint_error("%s: BSY never cleared, TD 0x%x\n",
@@ -855,10 +866,8 @@ skip_reset:
AHCINAME(sc), chp->ch_channel, sig,
AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel))), DEBUG_PROBE);
end:
- if (xfer != NULL)
- ata_free_xfer(chp, xfer);
ahci_channel_stop(sc, chp, flags);
- ata_delay(500, "ahcirst", flags);
+ ata_delay(chp, 500, "ahcirst", flags);
/* clear port interrupt register */
AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
ahci_channel_start(sc, chp, flags,
@@ -873,6 +882,8 @@ ahci_reset_channel(struct ata_channel *c
struct ahci_channel *achp = (struct ahci_channel *)chp;
int i, tfd;
+ ata_channel_lock(chp);
+
ahci_channel_stop(sc, chp, flags);
if (sata_reset_interface(chp, sc->sc_ahcit, achp->ahcic_scontrol,
achp->ahcic_sstatus, flags) != SStatus_DET_DEV) {
@@ -880,7 +891,7 @@ ahci_reset_channel(struct ata_channel *c
/* XXX and then ? */
}
ata_kill_active(chp, KILL_RESET, flags);
- ata_delay(500, "ahcirst", flags);
+ ata_delay(chp, 500, "ahcirst", flags);
/* clear port interrupt register */
AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
/* clear SErrors and start operations */
@@ -891,7 +902,7 @@ ahci_reset_channel(struct ata_channel *c
tfd = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel));
if ((AHCI_TFD_ST(tfd) & WDCS_BSY) == 0)
break;
- ata_delay(10, "ahcid2h", flags);
+ ata_delay(chp, 10, "ahcid2h", flags);
}
if ((AHCI_TFD_ST(tfd) & WDCS_BSY) != 0)
aprint_error("%s: BSY never cleared, TD 0x%x\n",
@@ -901,6 +912,8 @@ ahci_reset_channel(struct ata_channel *c
/* clear port interrupt register */
AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff);
+ ata_channel_unlock(chp);
+
return;
}
@@ -928,6 +941,17 @@ ahci_probe_drive(struct ata_channel *chp
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
struct ahci_channel *achp = (struct ahci_channel *)chp;
uint32_t sig;
+ struct ata_xfer *xfer;
+
+ xfer = ata_get_xfer_ext(chp, 0, 0);
+ if (xfer == NULL) {
+ aprint_error_dev(sc->sc_atac.atac_dev,
+ "%s: failed to get xfer port %d\n",
+ __func__, chp->ch_channel);
+ return;
+ }
+
+ ata_channel_lock(chp);
/* bring interface up, accept FISs, power up and spin up device */
AHCI_WRITE(sc, AHCI_P_CMD(chp->ch_channel),
@@ -937,11 +961,12 @@ ahci_probe_drive(struct ata_channel *chp
switch (sata_reset_interface(chp, sc->sc_ahcit, achp->ahcic_scontrol,
achp->ahcic_sstatus, AT_WAIT)) {
case SStatus_DET_DEV:
- tsleep(&sc, PRIBIO, "ahcidv", mstohz(500));
+ ata_delay(chp, 500, "ahcidv", AT_WAIT);
if (sc->sc_ahci_cap & AHCI_CAP_SPM) {
- ahci_do_reset_drive(chp, PMP_PORT_CTL, AT_WAIT, &sig);
+ ahci_do_reset_drive(chp, PMP_PORT_CTL, AT_WAIT, &sig,
+ xfer);
} else {
- ahci_do_reset_drive(chp, 0, AT_WAIT, &sig);
+ ahci_do_reset_drive(chp, 0, AT_WAIT, &sig, xfer);
}
sata_interpret_sig(chp, 0, sig);
/* if we have a PMP attached, inform the controller */
@@ -961,12 +986,13 @@ ahci_probe_drive(struct ata_channel *chp
AHCI_P_IX_OFS | AHCI_P_IX_DPS | AHCI_P_IX_UFS |
AHCI_P_IX_PSS | AHCI_P_IX_DHRS | AHCI_P_IX_SDBS);
/* wait 500ms before actually starting operations */
- tsleep(&sc, PRIBIO, "ahciprb", mstohz(500));
+ ata_delay(chp, 500, "ahciprb", AT_WAIT);
break;
default:
break;
}
+ ata_channel_unlock(chp);
}
static void
@@ -1010,9 +1036,12 @@ ahci_exec_command(struct ata_drive_datas
ret = ATACMD_COMPLETE;
} else {
if (ata_c->flags & AT_WAIT) {
- while ((ata_c->flags & AT_DONE) == 0) {
- tsleep(ata_c, PRIBIO, "ahcicmd", 0);
+ ata_channel_lock(chp);
+ if ((ata_c->flags & AT_DONE) == 0) {
+ ata_wait_xfer(chp, xfer);
+ KASSERT((ata_c->flags & AT_DONE) != 0);
}
+ ata_channel_unlock(chp);
ret = ATACMD_COMPLETE;
} else {
ret = ATACMD_QUEUED;
@@ -1089,14 +1118,18 @@ ahci_cmd_poll(struct ata_channel *chp, s
struct ahci_softc *sc = AHCI_CH2SC(chp);
struct ahci_channel *achp = (struct ahci_channel *)chp;
+ ata_channel_lock(chp);
+
/*
* Polled command.
*/
for (int i = 0; i < xfer->c_ata_c.timeout / 10; i++) {
if (xfer->c_ata_c.flags & AT_DONE)
break;
+ ata_channel_unlock(chp);
ahci_intr_port(sc, achp);
- ata_delay(10, "ahcipl", xfer->c_ata_c.flags);
+ ata_channel_lock(chp);
+ ata_delay(chp, 10, "ahcipl", xfer->c_ata_c.flags);
}
AHCIDEBUG_PRINT(("%s port %d poll end GHC 0x%x IS 0x%x list 0x%x%x fis 0x%x%x CMD 0x%x CI 0x%x\n", AHCINAME(sc), chp->ch_channel,
AHCI_READ(sc, AHCI_GHC), AHCI_READ(sc, AHCI_IS),
@@ -1107,6 +1140,9 @@ ahci_cmd_poll(struct ata_channel *chp, s
AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)),
AHCI_READ(sc, AHCI_P_CI(chp->ch_channel))),
DEBUG_XFERS);
+
+ ata_channel_unlock(chp);
+
if ((xfer->c_ata_c.flags & AT_DONE) == 0) {
xfer->c_ata_c.flags |= AT_TIMEOU;
xfer->c_intr(chp, xfer, 0);
@@ -1239,11 +1275,15 @@ static void
ahci_cmd_done_end(struct ata_channel *chp, struct ata_xfer *xfer)
{
struct ata_command *ata_c = &xfer->c_ata_c;
-
+
+ ata_channel_lock(chp);
+
ata_c->flags |= AT_DONE;
if (ata_c->flags & AT_WAIT)
- wakeup(ata_c);
+ ata_wake_xfer(chp, xfer);
+
+ ata_channel_unlock(chp);
return;
}
@@ -1482,7 +1522,7 @@ ahci_channel_stop(struct ahci_softc *sc,
if ((AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) & AHCI_P_CMD_CR)
== 0)
break;
- ata_delay(10, "ahcistop", flags);
+ ata_delay(chp, 10, "ahcistop", flags);
}
if (AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) & AHCI_P_CMD_CR) {
printf("%s: channel wouldn't stop\n", AHCINAME(sc));
@@ -1514,7 +1554,7 @@ ahci_channel_start(struct ahci_softc *sc
if ((AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) &
AHCI_P_CMD_CLO) == 0)
break;
- ata_delay(10, "ahciclo", flags);
+ ata_delay(chp, 10, "ahciclo", flags);
}
if (AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) & AHCI_P_CMD_CLO) {
printf("%s: channel wouldn't CLO\n", AHCINAME(sc));
Index: src/sys/dev/ic/mvsata.c
diff -u src/sys/dev/ic/mvsata.c:1.35.6.25 src/sys/dev/ic/mvsata.c:1.35.6.26
--- src/sys/dev/ic/mvsata.c:1.35.6.25 Sun Sep 10 19:31:15 2017
+++ src/sys/dev/ic/mvsata.c Tue Sep 19 21:06:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: mvsata.c,v 1.35.6.25 2017/09/10 19:31:15 jdolecek Exp $ */
+/* $NetBSD: mvsata.c,v 1.35.6.26 2017/09/19 21:06:25 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.35.6.25 2017/09/10 19:31:15 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.35.6.26 2017/09/19 21:06:25 jdolecek Exp $");
#include "opt_mvsata.h"
@@ -677,6 +677,8 @@ mvsata_probe_drive(struct ata_channel *c
struct mvsata_port * const mvport = (struct mvsata_port *)chp;
uint32_t sstat, sig;
+ ata_channel_lock(chp);
+
sstat = sata_reset_interface(chp, mvport->port_iot,
mvport->port_sata_scontrol, mvport->port_sata_sstatus, AT_WAIT);
switch (sstat) {
@@ -688,6 +690,8 @@ mvsata_probe_drive(struct ata_channel *c
default:
break;
}
+
+ ata_channel_unlock(chp);
}
#ifndef MVSATA_WITHOUTDMA
@@ -699,6 +703,8 @@ mvsata_reset_drive(struct ata_drive_data
uint32_t edma_c;
uint32_t sig;
+ ata_channel_lock(chp);
+
edma_c = MVSATA_EDMA_READ_4(mvport, EDMA_CMD);
DPRINTF(DEBUG_FUNCS,
@@ -720,6 +726,9 @@ mvsata_reset_drive(struct ata_drive_data
mvsata_edma_reset_qptr(mvport);
mvsata_edma_enable(mvport);
}
+
+ ata_channel_unlock(chp);
+
return;
}
@@ -733,6 +742,8 @@ mvsata_reset_channel(struct ata_channel
DPRINTF(DEBUG_FUNCS, ("%s: mvsata_reset_channel: channel=%d\n",
device_xname(MVSATA_DEV2(mvport)), chp->ch_channel));
+ ata_channel_lock(chp);
+
mvsata_hreset_port(mvport);
sstat = sata_reset_interface(chp, mvport->port_iot,
mvport->port_sata_scontrol, mvport->port_sata_sstatus, flags);
@@ -760,6 +771,9 @@ mvsata_reset_channel(struct ata_channel
mvsata_edma_config(mvport, mvport->port_edmamode_curr);
mvsata_edma_reset_qptr(mvport);
mvsata_edma_enable(mvport);
+
+ ata_channel_unlock(chp);
+
return;
}
@@ -1689,8 +1703,12 @@ mvsata_exec_command(struct ata_drive_dat
rv = ATACMD_COMPLETE;
else {
if (ata_c->flags & AT_WAIT) {
- while ((ata_c->flags & AT_DONE) == 0)
- tsleep(ata_c, PRIBIO, "mvsatacmd", 0);
+ ata_channel_lock(chp);
+ if ((ata_c->flags & AT_DONE) == 0) {
+ ata_wait_xfer(chp, xfer);
+ KASSERT((ata_c->flags & AT_DONE) != 0);
+ }
+ ata_channel_unlock(chp);
rv = ATACMD_COMPLETE;
} else
rv = ATACMD_QUEUED;
@@ -1801,7 +1819,7 @@ mvsata_wdc_cmd_intr(struct ata_channel *
drive_flags = chp->ch_drive[xfer->c_drive].drive_flags;
if ((ata_c->flags & (AT_WAIT | AT_POLL)) == (AT_WAIT | AT_POLL))
- /* both wait and poll, we can tsleep here */
+ /* both wait and poll, we can kpause here */
wflags = AT_WAIT | AT_POLL;
else
wflags = AT_POLL;
@@ -2009,9 +2027,11 @@ mvsata_wdc_cmd_done_end(struct ata_chann
mvsata_edma_enable(mvport);
}
+ ata_channel_lock(chp);
ata_c->flags |= AT_DONE;
if (ata_c->flags & AT_WAIT)
- wakeup(ata_c);
+ ata_wake_xfer(chp, xfer);
+ ata_channel_unlock(chp);
}
#if NATAPIBUS > 0
@@ -3481,10 +3501,13 @@ mvsata_reset_hc(struct mvsata_hc *mvhc)
static uint32_t
mvsata_softreset(struct mvsata_port *mvport, int flags)
{
+ struct ata_channel *chp = &mvport->port_ata_channel;
uint32_t sig0 = ~0;
int timeout;
uint8_t st0;
+ ata_channel_lock_owned(chp);
+
MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_RST | WDCTL_IDS | WDCTL_4BIT);
delay(10);
(void) MVSATA_WDC_READ_1(mvport, SRB_FE);
@@ -3502,7 +3525,7 @@ mvsata_softreset(struct mvsata_port *mvp
sig0 |= MVSATA_WDC_READ_1(mvport, SRB_LBAH) << 24;
goto out;
}
- ata_delay(10, "atarst", flags);
+ ata_delay(chp, 10, "atarst", flags);
}
aprint_error("%s:%d:%d: %s: timeout\n",
@@ -3541,6 +3564,7 @@ mvsata_edma_enable(struct mvsata_port *m
static int
mvsata_edma_disable(struct mvsata_port *mvport, int timeout, int wflags)
{
+ struct ata_channel *chp = &mvport->port_ata_channel;
uint32_t status, command;
int ms;
@@ -3549,7 +3573,7 @@ mvsata_edma_disable(struct mvsata_port *
status = MVSATA_EDMA_READ_4(mvport, EDMA_S);
if (status & EDMA_S_EDMAIDLE)
break;
- ata_delay(1, "mvsata_edma1", wflags);
+ ata_delay(chp, 1, "mvsata_edma1", wflags);
}
if (ms == timeout) {
aprint_error("%s:%d:%d: unable to disable EDMA\n",
@@ -3565,7 +3589,7 @@ mvsata_edma_disable(struct mvsata_port *
command = MVSATA_EDMA_READ_4(mvport, EDMA_CMD);
if (!(command & EDMA_CMD_EENEDMA))
break;
- ata_delay(1, "mvsata_edma2", wflags);
+ ata_delay(chp, 1, "mvsata_edma2", wflags);
}
if (ms == timeout) {
aprint_error("%s:%d:%d: unable to re-enable EDMA\n",
Index: src/sys/dev/ic/siisata.c
diff -u src/sys/dev/ic/siisata.c:1.30.4.37 src/sys/dev/ic/siisata.c:1.30.4.38
--- src/sys/dev/ic/siisata.c:1.30.4.37 Sun Sep 10 19:31:15 2017
+++ src/sys/dev/ic/siisata.c Tue Sep 19 21:06:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.30.4.37 2017/09/10 19:31:15 jdolecek Exp $ */
+/* $NetBSD: siisata.c,v 1.30.4.38 2017/09/19 21:06:25 jdolecek Exp $ */
/* from ahcisata_core.c */
@@ -79,7 +79,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.30.4.37 2017/09/10 19:31:15 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.30.4.38 2017/09/19 21:06:25 jdolecek Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -743,6 +743,8 @@ siisata_reset_drive(struct ata_drive_dat
KASSERT(drvp->drive <= PMP_PORT_CTL);
prb->prb_fis[rhd_c] = drvp->drive;
+ ata_channel_lock(chp);
+
siisata_disable_port_interrupt(chp);
siisata_activate_prb(schp, xfer->c_slot);
@@ -756,7 +758,7 @@ siisata_reset_drive(struct ata_drive_dat
}
if (pss & PR_PSS_ATTENTION)
break;
- ata_delay(10, "siiprb", flags);
+ ata_delay(chp, 10, "siiprb", flags);
}
siisata_deactivate_prb(schp, xfer->c_slot);
@@ -777,6 +779,8 @@ siisata_reset_drive(struct ata_drive_dat
siisata_enable_port_interrupt(chp);
+ ata_channel_unlock(chp);
+
if (timed_out) {
/* timeout */
siisata_device_reset(chp); /* XXX is this right? */
@@ -857,11 +861,13 @@ siisata_probe_drive(struct ata_channel *
xfer = ata_get_xfer_ext(chp, 0, 0);
if (xfer == NULL) {
aprint_error_dev(sc->sc_atac.atac_dev,
- "failed to get xfer port %d\n",
- chp->ch_channel);
+ "%s: failed to get xfer port %d\n",
+ __func__, chp->ch_channel);
return;
}
+ ata_channel_lock(chp);
+
/*
* disable port interrupt as we're polling for PHY up and
* prb completion
@@ -884,7 +890,7 @@ siisata_probe_drive(struct ata_channel *
break;
}
- ata_delay(10, "siiprbrd", AT_WAIT);
+ ata_delay(chp, 10, "siiprbrd", AT_WAIT);
}
if (timed_out) {
aprint_error_dev(sc->sc_atac.atac_dev,
@@ -914,7 +920,7 @@ siisata_probe_drive(struct ata_channel *
break;
}
- ata_delay(10, "siiprb", AT_WAIT);
+ ata_delay(chp, 10, "siiprb", AT_WAIT);
}
siisata_deactivate_prb(schp, xfer->c_slot);
@@ -951,6 +957,8 @@ siisata_probe_drive(struct ata_channel *
siisata_enable_port_interrupt(chp);
+ ata_channel_unlock(chp);
+
ata_free_xfer(chp, xfer);
SIISATA_DEBUG_PRINT(("%s: %s: port %d done\n", SIISATANAME(sc),
@@ -999,13 +1007,16 @@ siisata_exec_command(struct ata_drive_da
ret = ATACMD_COMPLETE;
} else {
if (ata_c->flags & AT_WAIT) {
- while ((ata_c->flags & AT_DONE) == 0) {
+ ata_channel_lock(chp);
+ if ((ata_c->flags & AT_DONE) == 0) {
SIISATA_DEBUG_PRINT(("%s: %s: sleeping\n",
SIISATANAME(
(struct siisata_softc *)chp->ch_atac),
__func__), DEBUG_FUNCS);
- tsleep(ata_c, PRIBIO, "siicmd", 0);
+ ata_wait_xfer(chp, xfer);
+ KASSERT((ata_c->flags & AT_DONE) != 0);
}
+ ata_channel_unlock(chp);
ret = ATACMD_COMPLETE;
} else {
ret = ATACMD_QUEUED;
@@ -1213,8 +1224,6 @@ siisata_cmd_done(struct ata_channel *chp
ata_c->flags |= AT_XFDONE;
siisata_cmd_done_end(chp, xfer);
- if ((ATACH_ST(tfd) & WDCS_ERR) == 0)
- atastart(chp);
}
static void
@@ -1222,10 +1231,14 @@ siisata_cmd_done_end(struct ata_channel
{
struct ata_command *ata_c = &xfer->c_ata_c;
+ ata_channel_lock(chp);
+
ata_c->flags |= AT_DONE;
if (ata_c->flags & AT_WAIT)
- wakeup(ata_c);
+ ata_wake_xfer(chp, xfer);
+
+ ata_channel_unlock(chp);
return;
}
Index: src/sys/dev/ic/wdc.c
diff -u src/sys/dev/ic/wdc.c:1.283.2.15 src/sys/dev/ic/wdc.c:1.283.2.16
--- src/sys/dev/ic/wdc.c:1.283.2.15 Mon Sep 11 22:19:23 2017
+++ src/sys/dev/ic/wdc.c Tue Sep 19 21:06:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc.c,v 1.283.2.15 2017/09/11 22:19:23 jdolecek Exp $ */
+/* $NetBSD: wdc.c,v 1.283.2.16 2017/09/19 21:06:25 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.283.2.15 2017/09/11 22:19:23 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.283.2.16 2017/09/19 21:06:25 jdolecek Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -107,7 +107,7 @@ __KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.28
#define WDCNDELAY_DEBUG 50
#endif
-/* When polling wait that much and then tsleep for 1/hz seconds */
+/* When polling wait that much and then kpause for 1/hz seconds */
#define WDCDELAY_POLL 1 /* ms */
/* timeout for the control commands */
@@ -140,7 +140,7 @@ const struct ata_bustype wdc_ata_bustype
/* Flags to wdcreset(). */
#define RESET_POLL 1
-#define RESET_SLEEP 0 /* wdcreset() will use tsleep() */
+#define RESET_SLEEP 0 /* wdcreset() will use kpause() */
static int wdcprobe1(struct ata_channel *, int);
static int wdcreset(struct ata_channel *, int);
@@ -206,10 +206,14 @@ wdc_sataprobe(struct ata_channel *chp)
{
struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
uint8_t st = 0, sc __unused, sn __unused, cl, ch;
- int i, s;
+ int i;
KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
+ /* do this before we take lock */
+
+ ata_channel_lock(chp);
+
/* reset the PHY and bring online */
switch (sata_reset_interface(chp, wdr->sata_iot, wdr->sata_control,
wdr->sata_status, AT_WAIT)) {
@@ -223,7 +227,7 @@ wdc_sataprobe(struct ata_channel *chp)
wdr->cmd_iohs[wd_status], 0);
if ((st & WDCS_BSY) == 0)
break;
- tsleep(&chp, PRIBIO, "sataprb", 1);
+ ata_delay(chp, 1, "sataprb", AT_WAIT);
}
if (i == WDC_PROBE_WAIT * hz)
aprint_error_dev(chp->ch_atac->atac_dev,
@@ -246,12 +250,10 @@ wdc_sataprobe(struct ata_channel *chp)
* sc and sn are supposed to be 0x1 for ATAPI, but in some
* cases we get wrong values here, so ignore it.
*/
- s = splbio();
if (cl == 0x14 && ch == 0xeb)
chp->ch_drive[0].drive_type = ATA_DRIVET_ATAPI;
else
chp->ch_drive[0].drive_type = ATA_DRIVET_ATA;
- splx(s);
/*
* issue a reset in case only the interface part of the drive
@@ -264,6 +266,8 @@ wdc_sataprobe(struct ata_channel *chp)
default:
break;
}
+
+ ata_channel_unlock(chp);
}
#endif /* NSATA > 0 */
@@ -290,7 +294,7 @@ wdc_drvprobe(struct ata_channel *chp)
struct wdc_softc *wdc = CHAN_TO_WDC(chp);
struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
u_int8_t st0 = 0, st1 = 0;
- int i, j, error, s, tfd;
+ int i, j, error, tfd;
if (atabus_alloc_drives(chp, wdc->wdc_maxdrives) != 0)
return;
@@ -300,7 +304,7 @@ wdc_drvprobe(struct ata_channel *chp)
return;
}
- s = splbio();
+ ata_channel_lock(chp);
/* for ATA/OLD drives, wait for DRDY, 3s timeout */
for (i = 0; i < mstohz(3000); i++) {
/*
@@ -335,12 +339,12 @@ wdc_drvprobe(struct ata_channel *chp)
(st1 & WDCS_DRDY)))
break;
#ifdef WDC_NO_IDS
- /* cannot tsleep here (can't enable IPL_BIO interrups),
+ /* cannot kpause here (can't enable IPL_BIO interrups),
* delay instead
*/
delay(1000000 / hz);
#else
- tsleep(¶ms, PRIBIO, "atadrdy", 1);
+ ata_delay(chp, 1, "atadrdy", AT_WAIT);
#endif
}
if ((st0 & WDCS_DRDY) == 0 &&
@@ -349,7 +353,7 @@ wdc_drvprobe(struct ata_channel *chp)
if (chp->ch_ndrives > 1 && (st1 & WDCS_DRDY) == 0 &&
chp->ch_drive[1].drive_type != ATA_DRIVET_ATAPI)
chp->ch_drive[1].drive_type = ATA_DRIVET_NONE;
- splx(s);
+ ata_channel_unlock(chp);
ATADEBUG_PRINT(("%s:%d: wait DRDY st0 0x%x st1 0x%x\n",
device_xname(atac->atac_dev),
@@ -370,9 +374,9 @@ wdc_drvprobe(struct ata_channel *chp)
/* If controller can't do 16bit flag the drives as 32bit */
if ((atac->atac_cap &
(ATAC_CAP_DATA16 | ATAC_CAP_DATA32)) == ATAC_CAP_DATA32) {
- s = splbio();
+ ata_channel_lock(chp);
chp->ch_drive[i].drive_flags |= ATA_DRIVE_CAP32;
- splx(s);
+ ata_channel_unlock(chp);
}
if (chp->ch_drive[i].drive_type == ATA_DRIVET_NONE)
continue;
@@ -390,7 +394,9 @@ wdc_drvprobe(struct ata_channel *chp)
error = ata_get_params(&chp->ch_drive[i],
AT_WAIT | AT_POLL, ¶ms);
if (error != CMD_OK) {
- tsleep(¶ms, PRIBIO, "atacnf", mstohz(1000));
+ ata_channel_lock(chp);
+ ata_delay(chp, 1000, "atacnf", AT_WAIT);
+ ata_channel_unlock(chp);
/* Shortcut in case we've been shutdown */
if (chp->ch_flags & ATACH_SHUTDOWN)
@@ -403,14 +409,13 @@ wdc_drvprobe(struct ata_channel *chp)
ATADEBUG_PRINT(("%s:%d:%d: IDENTIFY failed (%d)\n",
device_xname(atac->atac_dev),
chp->ch_channel, i, error), DEBUG_PROBE);
- s = splbio();
+ ata_channel_lock(chp);
if (chp->ch_drive[i].drive_type != ATA_DRIVET_ATA ||
(wdc->cap & WDC_CAPABILITY_PREATA) == 0) {
chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
- splx(s);
+ ata_channel_unlock(chp);
continue;
}
- splx(s);
/*
* Pre-ATA drive ?
* Test registers writability (Error register not
@@ -433,9 +438,8 @@ wdc_drvprobe(struct ata_channel *chp)
"writability failed\n",
device_xname(atac->atac_dev),
chp->ch_channel, i), DEBUG_PROBE);
- s = splbio();
chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
- splx(s);
+ ata_channel_unlock(chp);
continue;
}
if (wdc_wait_for_ready(chp, 10000, 0, &tfd) ==
@@ -443,9 +447,8 @@ wdc_drvprobe(struct ata_channel *chp)
ATADEBUG_PRINT(("%s:%d:%d: not ready\n",
device_xname(atac->atac_dev),
chp->ch_channel, i), DEBUG_PROBE);
- s = splbio();
chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
- splx(s);
+ ata_channel_unlock(chp);
continue;
}
bus_space_write_1(wdr->cmd_iot,
@@ -456,11 +459,9 @@ wdc_drvprobe(struct ata_channel *chp)
ATADEBUG_PRINT(("%s:%d:%d: WDCC_RECAL failed\n",
device_xname(atac->atac_dev),
chp->ch_channel, i), DEBUG_PROBE);
- s = splbio();
chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
- splx(s);
+ ata_channel_unlock(chp);
} else {
- s = splbio();
for (j = 0; j < chp->ch_ndrives; j++) {
if (chp->ch_drive[i].drive_type !=
ATA_DRIVET_NONE) {
@@ -468,7 +469,7 @@ wdc_drvprobe(struct ata_channel *chp)
ATA_DRIVET_OLD;
}
}
- splx(s);
+ ata_channel_unlock(chp);
}
}
}
@@ -493,7 +494,6 @@ wdcprobe1(struct ata_channel *chp, int p
u_int8_t st0 = 0, st1 = 0, sc __unused, sn __unused, cl, ch;
u_int8_t ret_value = 0x03;
u_int8_t drive;
- int s;
/* XXX if poll, wdc_probe_count is 0. */
int wdc_probe_count =
poll ? (WDC_PROBE_WAIT / WDCDELAY)
@@ -503,7 +503,7 @@ wdcprobe1(struct ata_channel *chp, int p
* Sanity check to see if the wdc channel responds at all.
*/
- s = splbio();
+ ata_channel_lock(chp);
if ((wdc->cap & WDC_CAPABILITY_NO_EXTRA_RESETS) == 0) {
while (wdc_probe_count-- > 0) {
if (wdc->select)
@@ -656,7 +656,7 @@ wdcprobe1(struct ata_channel *chp, int p
}
if (ret_value == 0) {
- splx(s);
+ ata_channel_unlock(chp);
return 0;
}
}
@@ -697,16 +697,14 @@ wdcprobe1(struct ata_channel *chp, int p
#ifdef WDC_NO_IDS
ret_value = __wdcwait_reset(chp, ret_value, RESET_POLL);
#else
- splx(s);
ret_value = __wdcwait_reset(chp, ret_value, poll);
- s = splbio();
#endif
ATADEBUG_PRINT(("%s:%d: after reset, ret_value=%#x\n",
__func__, chp->ch_channel, ret_value), DEBUG_PROBE);
/* if reset failed, there's nothing here */
if (ret_value == 0) {
- splx(s);
+ ata_channel_unlock(chp);
return 0;
}
@@ -759,7 +757,7 @@ wdcprobe1(struct ata_channel *chp, int p
(void)bus_space_read_1(wdr->cmd_iot,
wdr->cmd_iohs[wd_status], 0);
}
- splx(s);
+ ata_channel_unlock(chp);
return (ret_value);
}
@@ -925,12 +923,12 @@ wdc_reset_channel(struct ata_channel *ch
* ATAPI_SOFT_RESET
*/
xfer = ata_queue_get_active_xfer(chp);
+
+ ata_channel_lock(chp);
+
if (xfer && xfer->c_chp == chp && (xfer->c_flags & C_ATAPI)) {
wdccommandshort(chp, xfer->c_drive, ATAPI_SOFT_RESET);
- if (flags & AT_WAIT)
- tsleep(&flags, PRIBIO, "atardl", mstohz(1) + 1);
- else
- delay(1000);
+ ata_delay(chp, 1000, "atardl", flags);
}
/* reset the channel */
@@ -943,10 +941,7 @@ wdc_reset_channel(struct ata_channel *ch
* wait a bit after reset; in case the DMA engines needs some time
* to recover.
*/
- if (flags & AT_WAIT)
- tsleep(&flags, PRIBIO, "atardl", mstohz(1) + 1);
- else
- delay(1000);
+ ata_delay(chp, 1000, "atardl", flags);
/*
* Look for pending xfers. If we have a shared queue, we'll also reset
@@ -955,9 +950,11 @@ wdc_reset_channel(struct ata_channel *ch
* it is queued for retry immediatelly without waiting for I/O timeout.
*/
if (xfer) {
- if (xfer->c_chp != chp)
+ if (xfer->c_chp != chp) {
+ ata_channel_unlock(chp);
ata_reset_channel(xfer->c_chp, flags);
- else {
+ ata_channel_lock(chp);
+ } else {
#if NATA_DMA || NATA_PIOBM
/*
* If we're waiting for DMA, stop the
@@ -974,6 +971,8 @@ wdc_reset_channel(struct ata_channel *ch
}
ata_kill_active(chp, KILL_RESET, flags);
+
+ ata_channel_unlock(chp);
}
static int
@@ -984,6 +983,8 @@ wdcreset(struct ata_channel *chp, int po
struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
int drv_mask1, drv_mask2;
+ ata_channel_lock_owned(chp);
+
#ifdef WDC_NO_IDS
poll = RESET_POLL;
#endif
@@ -1051,6 +1052,7 @@ __wdcwait_reset(struct ata_channel *chp,
struct wdc_softc *wdc = CHAN_TO_WDC(chp);
struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
int timeout, nloop;
+ int wflags = poll ? AT_POLL : AT_WAIT;
u_int8_t st0 = 0, st1 = 0;
#ifdef ATADEBUG
u_int8_t sc0 = 0, sn0 = 0, cl0 = 0, ch0 = 0;
@@ -1123,10 +1125,7 @@ __wdcwait_reset(struct ata_channel *chp,
goto end;
}
}
- if (poll)
- delay(WDCDELAY);
- else
- tsleep(&nloop, PRIBIO, "atarst", 1);
+ ata_delay(chp, WDCDELAY, "atarst", wflags);
}
/* Reset timed out. Maybe it's because drv_mask was not right */
if (st0 & WDCS_BSY)
@@ -1219,7 +1218,7 @@ out:
}
/*
- * Call __wdcwait(), polling using tsleep() or waking up the kernel
+ * Call __wdcwait(), polling using kpause() or waking up the kernel
* thread if possible
*/
int
@@ -1376,9 +1375,12 @@ wdc_exec_command(struct ata_drive_datas
ret = ATACMD_COMPLETE;
} else {
if (ata_c->flags & AT_WAIT) {
- while ((ata_c->flags & AT_DONE) == 0) {
- tsleep(ata_c, PRIBIO, "wdccmd", 0);
+ ata_channel_lock(chp);
+ if ((ata_c->flags & AT_DONE) == 0) {
+ ata_wait_xfer(chp, xfer);
+ KASSERT((ata_c->flags & AT_DONE) != 0);
}
+ ata_channel_unlock(chp);
ret = ATACMD_COMPLETE;
} else {
ret = ATACMD_QUEUED;
@@ -1490,7 +1492,7 @@ __wdccommand_intr(struct ata_channel *ch
wflags = AT_POLL;
#else
if ((ata_c->flags & (AT_WAIT | AT_POLL)) == (AT_WAIT | AT_POLL)) {
- /* both wait and poll, we can tsleep here */
+ /* both wait and poll, we can kpause here */
wflags = AT_WAIT | AT_POLL;
} else {
wflags = AT_POLL;
@@ -1676,10 +1678,11 @@ __wdccommand_done_end(struct ata_channel
{
struct ata_command *ata_c = &xfer->c_ata_c;
+ ata_channel_lock(chp);
ata_c->flags |= AT_DONE;
if (ata_c->flags & AT_WAIT)
- wakeup(ata_c);
- return;
+ ata_wake_xfer(chp, xfer);
+ ata_channel_unlock(chp);
}
static void