Module Name: src
Committed By: jdolecek
Date: Wed Oct 3 19:20:48 UTC 2018
Modified Files:
src/sys/dev/ata [jdolecek-ncqfixes]: TODO.ncq ata.c atavar.h wd.c
src/sys/dev/ic [jdolecek-ncqfixes]: ahcisata_core.c mvsata.c siisata.c
wdc.c
Log Message:
change channel reset and drive reset for all ATA controllers to always
run via thread, and with channel lock held the whole time; the queue is
frozen while reset is pending
for this repurpose ata_reset_channel() into new ata_thread_run()
also adjust some device printfs to not leak xfer pointer, and avoid
aprint_* for non-autoconf messages
To generate a diff of this commit:
cvs rdiff -u -r1.4.2.9 -r1.4.2.10 src/sys/dev/ata/TODO.ncq
cvs rdiff -u -r1.141.6.10 -r1.141.6.11 src/sys/dev/ata/ata.c
cvs rdiff -u -r1.99.2.7 -r1.99.2.8 src/sys/dev/ata/atavar.h
cvs rdiff -u -r1.441.2.6 -r1.441.2.7 src/sys/dev/ata/wd.c
cvs rdiff -u -r1.62.2.5 -r1.62.2.6 src/sys/dev/ic/ahcisata_core.c
cvs rdiff -u -r1.41.2.4 -r1.41.2.5 src/sys/dev/ic/mvsata.c
cvs rdiff -u -r1.35.6.5 -r1.35.6.6 src/sys/dev/ic/siisata.c
cvs rdiff -u -r1.288.6.2 -r1.288.6.3 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.4.2.9 src/sys/dev/ata/TODO.ncq:1.4.2.10
--- src/sys/dev/ata/TODO.ncq:1.4.2.9 Mon Sep 24 19:48:02 2018
+++ src/sys/dev/ata/TODO.ncq Wed Oct 3 19:20:48 2018
@@ -2,8 +2,6 @@ jdolecek-ncqfixes goals:
- fix ahci(4) error handling under paralles - invalid bio via WD_CHAOS_MONKEY
ends up being handled as NOERROR, triggering KASSERT() in wd(4)
- remove controller-specific slot bitmaps (ic/siisata.c, ic/ahcisata_core.c)
-- revert rev 1.431 of wd.c (AT_POOL removal) - ensure still works
- for the reset-via-thread case
Bugs
----
Index: src/sys/dev/ata/ata.c
diff -u src/sys/dev/ata/ata.c:1.141.6.10 src/sys/dev/ata/ata.c:1.141.6.11
--- src/sys/dev/ata/ata.c:1.141.6.10 Mon Sep 24 19:48:02 2018
+++ src/sys/dev/ata/ata.c Wed Oct 3 19:20:48 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.141.6.10 2018/09/24 19:48:02 jdolecek Exp $ */
+/* $NetBSD: ata.c,v 1.141.6.11 2018/10/03 19:20:48 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.141.6.10 2018/09/24 19:48:02 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.141.6.11 2018/10/03 19:20:48 jdolecek Exp $");
#include "opt_ata.h"
@@ -440,7 +440,7 @@ atabus_thread(void *arg)
struct ata_channel *chp = sc->sc_chan;
struct ata_queue *chq = chp->ch_queue;
struct ata_xfer *xfer;
- int i, rv, s;
+ int i, rv;
ata_channel_lock(chp);
chp->ch_flags |= ATACH_TH_RUN;
@@ -462,7 +462,8 @@ atabus_thread(void *arg)
ata_channel_lock(chp);
for (;;) {
- if ((chp->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 &&
+ if ((chp->ch_flags & (ATACH_TH_RESET | ATACH_TH_DRIVE_RESET
+ | ATACH_SHUTDOWN)) == 0 &&
(chq->queue_active == 0 || chq->queue_freeze == 0)) {
chp->ch_flags &= ~ATACH_TH_RUN;
cv_wait(&chp->ch_thr_idle, &chp->ch_lock);
@@ -478,12 +479,24 @@ atabus_thread(void *arg)
ata_channel_lock(chp);
}
if (chp->ch_flags & ATACH_TH_RESET) {
- /* ata_reset_channel() will unfreeze the channel */
- ata_channel_unlock(chp);
- s = splbio();
- ata_reset_channel(chp, AT_WAIT | chp->ch_reset_flags);
- splx(s);
- ata_channel_lock(chp);
+ /* this will unfreeze the channel */
+ ata_thread_run(chp, AT_WAIT | chp->ch_reset_flags,
+ ATACH_TH_RESET, ATACH_NODRIVE);
+ } else if (chp->ch_flags & ATACH_TH_DRIVE_RESET) {
+ for (i = 0; i < chp->ch_ndrives; i++) {
+ struct ata_drive_datas *drvp;
+ int drv_reset_flags;
+
+ drvp = &chp->ch_drive[i];
+ drv_reset_flags = drvp->drive_reset_flags;
+
+ if (drvp->drive_flags & ATACH_TH_DRIVE_RESET) {
+ ata_thread_run(chp,
+ AT_WAIT | drv_reset_flags,
+ ATACH_TH_DRIVE_RESET, i);
+ }
+ }
+ chp->ch_flags &= ~ATACH_TH_DRIVE_RESET;
} else if (chq->queue_active > 0 && chq->queue_freeze == 1) {
/*
* Caller has bumped queue_freeze, decrease it. This
@@ -511,6 +524,11 @@ atabus_thread(void *arg)
}
} else if (chq->queue_freeze > 1)
panic("%s: queue_freeze", __func__);
+
+ /* Try to run down the queue once after each event is handled */
+ ata_channel_unlock(chp);
+ atastart(chp);
+ ata_channel_lock(chp);
}
chp->ch_thread = NULL;
cv_signal(&chp->ch_thr_idle);
@@ -1471,7 +1489,8 @@ ata_timo_xfer_check(struct ata_xfer *xfe
ata_channel_unlock(chp);
device_printf(drvp->drv_softc,
- "xfer %p freed while invoking timeout\n", xfer);
+ "xfer %"PRIxPTR" freed while invoking timeout\n",
+ (intptr_t)xfer & PAGE_MASK);
ata_free_xfer(chp, xfer);
return true;
@@ -1481,7 +1500,8 @@ ata_timo_xfer_check(struct ata_xfer *xfe
ata_channel_unlock(chp);
device_printf(drvp->drv_softc,
- "xfer %p deactivated while invoking timeout\n", xfer);
+ "xfer %"PRIxPTR" deactivated while invoking timeout\n",
+ (intptr_t)xfer & PAGE_MASK);
return true;
}
@@ -1605,44 +1625,28 @@ ata_channel_thaw(struct ata_channel *chp
}
/*
- * ata_reset_channel:
+ * ata_thread_run:
*
- * Reset and ATA channel.
- *
- * MUST BE CALLED AT splbio()!
+ * Reset and ATA channel. Channel lock must be held.
*/
void
-ata_reset_channel(struct ata_channel *chp, int flags)
+ata_thread_run(struct ata_channel *chp, int flags, int type, int drive)
{
struct atac_softc *atac = chp->ch_atac;
- int drive;
bool threset = false;
+ struct ata_drive_datas *drvp;
-#ifdef ATA_DEBUG
- int spl1, spl2;
-
- spl1 = splbio();
- spl2 = splbio();
- if (spl2 != spl1) {
- printf("ata_reset_channel: not at splbio()\n");
- panic("ata_reset_channel");
- }
- splx(spl2);
- splx(spl1);
-#endif /* ATA_DEBUG */
-
- ata_channel_lock(chp);
+ ata_channel_lock_owned(chp);
/*
* If we can poll or wait it's OK, otherwise wake up the
* kernel thread to do it for us.
*/
- ATADEBUG_PRINT(("ata_reset_channel flags 0x%x ch_flags 0x%x\n",
- flags, chp->ch_flags), DEBUG_FUNCS | DEBUG_XFERS);
+ ATADEBUG_PRINT(("%s flags 0x%x ch_flags 0x%x\n",
+ __func__, flags, chp->ch_flags), DEBUG_FUNCS | DEBUG_XFERS);
if ((flags & (AT_POLL | AT_WAIT)) == 0) {
- if (chp->ch_flags & ATACH_TH_RESET) {
+ if (chp->ch_flags & type) {
/* No need to schedule a reset more than one time. */
- ata_channel_unlock(chp);
return;
}
@@ -1651,10 +1655,24 @@ ata_reset_channel(struct ata_channel *ch
* to a thread.
*/
ata_channel_freeze_locked(chp);
- chp->ch_flags |= ATACH_TH_RESET;
- chp->ch_reset_flags = flags & AT_RST_EMERG;
+ chp->ch_flags |= type;
+
+
+ switch (type) {
+ case ATACH_TH_RESET:
+ chp->ch_reset_flags = flags & AT_RST_EMERG;
+ break;
+ case ATACH_TH_DRIVE_RESET:
+ drvp = &chp->ch_drive[drive];
+ drvp->drive_flags |= ATACH_TH_DRIVE_RESET;
+ drvp->drive_reset_flags = flags;
+ break;
+ default:
+ panic("%s: unknown type: %x", __func__, type);
+ /* NOTREACHED */
+ }
+
cv_signal(&chp->ch_thr_idle);
- ata_channel_unlock(chp);
return;
}
@@ -1666,19 +1684,31 @@ ata_reset_channel(struct ata_channel *ch
* the flag now so that the thread won't try to execute it if
* we happen to sleep, and thaw one more time after the reset.
*/
- if (chp->ch_flags & ATACH_TH_RESET) {
- chp->ch_flags &= ~ATACH_TH_RESET;
+ if (chp->ch_flags & type) {
+ chp->ch_flags &= ~type;
threset = true;
}
- ata_channel_unlock(chp);
+ switch (type) {
+ case ATACH_TH_RESET:
+ (*atac->atac_bustype_ata->ata_reset_channel)(chp, flags);
- (*atac->atac_bustype_ata->ata_reset_channel)(chp, flags);
+ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
+ for (drive = 0; drive < chp->ch_ndrives; drive++)
+ chp->ch_drive[drive].state = 0;
+ break;
- ata_channel_lock(chp);
- KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
- for (drive = 0; drive < chp->ch_ndrives; drive++)
- chp->ch_drive[drive].state = 0;
+ case ATACH_TH_DRIVE_RESET:
+ KASSERT(drive <= chp->ch_ndrives);
+ drvp = &chp->ch_drive[drive];
+ (*atac->atac_bustype_ata->ata_reset_drive)(drvp, flags, NULL);
+ drvp->state = 0;
+ break;
+
+ default:
+ panic("%s: unknown type: %x", __func__, type);
+ /* NOTREACHED */
+ }
/*
* Thaw one extra time to clear the freeze done when the reset has
@@ -1693,13 +1723,9 @@ ata_reset_channel(struct ata_channel *ch
/* Signal the thread in case there is an xfer to run */
cv_signal(&chp->ch_thr_idle);
- ata_channel_unlock(chp);
-
if (flags & AT_RST_EMERG) {
/* make sure that we can use polled commands */
ata_queue_reset(chp->ch_queue);
- } else {
- atastart(chp);
}
}
@@ -1846,7 +1872,7 @@ ata_downgrade_mode(struct ata_drive_data
(*atac->atac_set_modes)(chp);
ata_print_modes(chp);
/* reset the channel, which will schedule all drives for setup */
- ata_reset_channel(chp, flags);
+ ata_thread_run(chp, flags, ATACH_TH_RESET, ATACH_NODRIVE);
return 1;
}
#endif /* NATA_DMA */
@@ -2186,7 +2212,6 @@ atabusioctl(dev_t dev, u_long cmd, void
struct ata_channel *chp = sc->sc_chan;
int min_drive, max_drive, drive;
int error;
- int s;
/*
* Enforce write permission for ioctls that change the
@@ -2203,9 +2228,10 @@ atabusioctl(dev_t dev, u_long cmd, void
switch (cmd) {
case ATABUSIORESET:
- s = splbio();
- ata_reset_channel(sc->sc_chan, AT_WAIT | AT_POLL);
- splx(s);
+ ata_channel_lock(chp);
+ ata_thread_run(sc->sc_chan, AT_WAIT | AT_POLL,
+ ATACH_TH_RESET, ATACH_NODRIVE);
+ ata_channel_unlock(chp);
return 0;
case ATABUSIOSCAN:
{
@@ -2283,11 +2309,11 @@ atabus_resume(device_t dv, const pmf_qua
/* unfreeze the queue and reset drives */
ata_channel_thaw_locked(chp);
- ata_channel_unlock(chp);
-
/* reset channel only if there are drives attached */
if (chp->ch_ndrives > 0)
- ata_reset_channel(chp, AT_WAIT);
+ ata_thread_run(chp, AT_WAIT, ATACH_TH_RESET, ATACH_NODRIVE);
+
+ ata_channel_unlock(chp);
out:
return true;
@@ -2336,6 +2362,7 @@ atabus_rescan(device_t self, const char
void
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) {
/*
@@ -2346,7 +2373,6 @@ ata_delay(struct ata_channel *chp, int m
} else {
int pause = mstohz(ms);
- KASSERT(mutex_owned(&chp->ch_lock));
kpause(msg, false, pause > 0 ? pause : 1, &chp->ch_lock);
}
}
Index: src/sys/dev/ata/atavar.h
diff -u src/sys/dev/ata/atavar.h:1.99.2.7 src/sys/dev/ata/atavar.h:1.99.2.8
--- src/sys/dev/ata/atavar.h:1.99.2.7 Sat Sep 22 17:50:09 2018
+++ src/sys/dev/ata/atavar.h Wed Oct 3 19:20:48 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: atavar.h,v 1.99.2.7 2018/09/22 17:50:09 jdolecek Exp $ */
+/* $NetBSD: atavar.h,v 1.99.2.8 2018/10/03 19:20:48 jdolecek Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -274,6 +274,8 @@ struct ata_drive_datas {
#define ATA_DRIVE_WFUA 0x0100 /* drive supports WRITE DMA FUA EXT */
#define ATA_DRIVE_NCQ 0x0200 /* drive supports NCQ feature set */
#define ATA_DRIVE_NCQ_PRIO 0x0400 /* drive supports NCQ PRIO field */
+#define ATA_DRIVE_TH_RESET 0x0800 /* drive waits for thread drive reset */
+ int drive_reset_flags; /* flags for drive reset via thread */
uint8_t drive_type;
#define ATA_DRIVET_NONE 0
@@ -415,6 +417,9 @@ struct ata_channel {
#define ATACH_TH_RESCAN 0x400 /* rescan requested */
#define ATACH_NCQ 0x800 /* channel executing NCQ commands */
#define ATACH_DMA_BEFORE_CMD 0x1000 /* start DMA first */
+#define ATACH_TH_DRIVE_RESET 0x2000 /* thread asked for drive(s) reset */
+
+#define ATACH_NODRIVE 0xff /* no drive selected for reset */
/* for the reset callback */
int ch_reset_flags;
@@ -543,7 +548,7 @@ void ata_timeout(void *);
bool ata_timo_xfer_check(struct ata_xfer *);
void ata_kill_pending(struct ata_drive_datas *);
void ata_kill_active(struct ata_channel *, int, int);
-void ata_reset_channel(struct ata_channel *, int);
+void ata_thread_run(struct ata_channel *, int, int, int);
void ata_channel_freeze(struct ata_channel *);
void ata_channel_thaw(struct ata_channel *);
void ata_channel_lock(struct ata_channel *);
Index: src/sys/dev/ata/wd.c
diff -u src/sys/dev/ata/wd.c:1.441.2.6 src/sys/dev/ata/wd.c:1.441.2.7
--- src/sys/dev/ata/wd.c:1.441.2.6 Sat Sep 22 17:50:09 2018
+++ src/sys/dev/ata/wd.c Wed Oct 3 19:20:48 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: wd.c,v 1.441.2.6 2018/09/22 17:50:09 jdolecek Exp $ */
+/* $NetBSD: wd.c,v 1.441.2.7 2018/10/03 19:20:48 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.441.2.6 2018/09/22 17:50:09 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.441.2.7 2018/10/03 19:20:48 jdolecek Exp $");
#include "opt_ata.h"
#include "opt_wd.h"
@@ -661,8 +661,8 @@ wdstart1(struct wd_softc *wd, struct buf
*/
if (BUF_ISREAD(bp) && xfer->c_retries == 0 && wd->drv_chaos_freq > 0 &&
(++wd->drv_chaos_cnt % wd->drv_chaos_freq) == 0) {
- aprint_normal_dev(dksc->sc_dev, "%s: chaos xfer %p\n",
- __func__, xfer);
+ device_printf(dksc->sc_dev, "%s: chaos xfer %"PRIxPTR"\n",
+ __func__, (intptr_t)xfer & PAGE_MASK);
xfer->c_bio.blkno = 7777777 + wd->sc_capacity;
xfer->c_flags |= C_CHAOS;
}
@@ -840,7 +840,10 @@ wddone(device_t self, struct ata_xfer *x
retry: /* Just reset and retry. Can we do more ? */
if ((xfer->c_flags & C_RECOVERED) == 0) {
int wflags = (xfer->c_flags & C_POLL) ? AT_POLL : 0;
- (*wd->atabus->ata_reset_drive)(wd->drvp, wflags, NULL);
+ ata_channel_lock(wd->drvp->chnl_softc);
+ ata_thread_run(wd->drvp->chnl_softc, wflags,
+ ATACH_TH_DRIVE_RESET, wd->drvp->drive);
+ ata_channel_unlock(wd->drvp->chnl_softc);
}
retry2:
mutex_enter(&wd->sc_lock);
@@ -848,7 +851,8 @@ retry2:
diskerr(bp, "wd", errmsg, LOG_PRINTF,
xfer->c_bio.blkdone, dksc->sc_dkdev.dk_label);
if (xfer->c_retries < WDIORETRIES)
- printf(", xfer %p, retry %d", xfer,
+ printf(", xfer %"PRIxPTR", retry %d",
+ (intptr_t)xfer & PAGE_MASK,
xfer->c_retries + 1);
printf("\n");
if (do_perror)
@@ -911,8 +915,9 @@ out:
break;
case NOERROR:
noerror: if ((xfer->c_bio.flags & ATA_CORR) || xfer->c_retries > 0)
- aprint_error_dev(dksc->sc_dev,
- "soft error (corrected) xfer %p\n", xfer);
+ device_printf(dksc->sc_dev,
+ "soft error (corrected) xfer %"PRIxPTR"\n",
+ (intptr_t)xfer & PAGE_MASK);
#ifdef WD_CHAOS_MONKEY
KASSERT((xfer->c_flags & C_CHAOS) == 0);
#endif
Index: src/sys/dev/ic/ahcisata_core.c
diff -u src/sys/dev/ic/ahcisata_core.c:1.62.2.5 src/sys/dev/ic/ahcisata_core.c:1.62.2.6
--- src/sys/dev/ic/ahcisata_core.c:1.62.2.5 Sat Sep 22 09:22:59 2018
+++ src/sys/dev/ic/ahcisata_core.c Wed Oct 3 19:20:48 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisata_core.c,v 1.62.2.5 2018/09/22 09:22:59 jdolecek Exp $ */
+/* $NetBSD: ahcisata_core.c,v 1.62.2.6 2018/10/03 19:20:48 jdolecek Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.62.2.5 2018/09/22 09:22:59 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.62.2.6 2018/10/03 19:20:48 jdolecek Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -683,7 +683,7 @@ ahci_reset_drive(struct ata_drive_datas
struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac;
uint8_t c_slot;
- ata_channel_lock(chp);
+ ata_channel_lock_owned(chp);
/* get a slot for running the command on */
if (!ata_queue_alloc_slot(chp, &c_slot, ATA_MAX_OPENINGS)) {
@@ -696,13 +696,10 @@ ahci_reset_drive(struct ata_drive_datas
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, c_slot) != 0)
- ata_reset_channel(chp, flags);
+ ahci_do_reset_drive(chp, drvp->drive, flags, sigp, c_slot);
AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE);
ata_queue_free_slot(chp, c_slot);
-
- ata_channel_unlock(chp);
}
/* return error code from ata_bio */
Index: src/sys/dev/ic/mvsata.c
diff -u src/sys/dev/ic/mvsata.c:1.41.2.4 src/sys/dev/ic/mvsata.c:1.41.2.5
--- src/sys/dev/ic/mvsata.c:1.41.2.4 Sat Sep 22 09:22:59 2018
+++ src/sys/dev/ic/mvsata.c Wed Oct 3 19:20:48 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: mvsata.c,v 1.41.2.4 2018/09/22 09:22:59 jdolecek Exp $ */
+/* $NetBSD: mvsata.c,v 1.41.2.5 2018/10/03 19:20:48 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.41.2.4 2018/09/22 09:22:59 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.41.2.5 2018/10/03 19:20:48 jdolecek Exp $");
#include "opt_mvsata.h"
@@ -703,7 +703,7 @@ mvsata_reset_drive(struct ata_drive_data
uint32_t edma_c;
uint32_t sig;
- ata_channel_lock(chp);
+ ata_channel_lock_owned(chp);
edma_c = MVSATA_EDMA_READ_4(mvport, EDMA_CMD);
@@ -726,10 +726,6 @@ mvsata_reset_drive(struct ata_drive_data
mvsata_edma_reset_qptr(mvport);
mvsata_edma_enable(mvport);
}
-
- ata_channel_unlock(chp);
-
- return;
}
#endif /* MVSATA_WITHOUTDMA */
@@ -743,7 +739,7 @@ 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);
+ ata_channel_lock_owned(chp);
mvsata_hreset_port(mvport);
sstat = sata_reset_interface(chp, mvport->port_iot,
@@ -774,10 +770,6 @@ mvsata_reset_channel(struct ata_channel
mvsata_edma_reset_qptr(mvport);
mvsata_edma_enable(mvport);
#endif
-
- ata_channel_unlock(chp);
-
- return;
}
#ifndef MVSATA_WITHOUTDMA
@@ -3563,6 +3555,8 @@ mvsata_edma_disable(struct mvsata_port *
uint32_t idlestatus = EDMA_S_EDMAIDLE | EDMA_S_ECACHEEMPTY;
int t;
+ ata_channel_lock_owned(chp);
+
if (MVSATA_EDMA_READ_4(mvport, EDMA_CMD) & EDMA_CMD_EENEDMA) {
timeout = mstohz(timeout + hztoms(1) - 1);
Index: src/sys/dev/ic/siisata.c
diff -u src/sys/dev/ic/siisata.c:1.35.6.5 src/sys/dev/ic/siisata.c:1.35.6.6
--- src/sys/dev/ic/siisata.c:1.35.6.5 Sat Sep 22 09:22:59 2018
+++ src/sys/dev/ic/siisata.c Wed Oct 3 19:20:48 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.35.6.5 2018/09/22 09:22:59 jdolecek Exp $ */
+/* $NetBSD: siisata.c,v 1.35.6.6 2018/10/03 19:20:48 jdolecek Exp $ */
/* from ahcisata_core.c */
@@ -79,7 +79,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.35.6.5 2018/09/22 09:22:59 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.35.6.6 2018/10/03 19:20:48 jdolecek Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -732,7 +732,7 @@ siisata_reset_drive(struct ata_drive_dat
siisata_reinit_port(chp, drvp->drive);
- ata_channel_lock(chp);
+ ata_channel_lock_owned(chp);
/* get a slot for running the command on */
if (!ata_queue_alloc_slot(chp, &c_slot, ATA_MAX_OPENINGS)) {
@@ -783,8 +783,6 @@ 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? */
@@ -801,11 +799,7 @@ siisata_reset_drive(struct ata_drive_dat
}
}
- ata_channel_lock(chp);
ata_queue_free_slot(chp, c_slot);
- ata_channel_unlock(chp);
-
- return;
}
void
@@ -817,6 +811,8 @@ siisata_reset_channel(struct ata_channel
SIISATA_DEBUG_PRINT(("%s: %s channel %d\n", SIISATANAME(sc), __func__,
chp->ch_channel), DEBUG_FUNCS);
+ ata_channel_lock_owned(chp);
+
if (sata_reset_interface(chp, sc->sc_prt, schp->sch_scontrol,
schp->sch_sstatus, flags) != SStatus_DET_DEV) {
aprint_error("%s port %d: reset failed\n",
@@ -1573,6 +1569,8 @@ siisata_device_reset(struct ata_channel
struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac;
int ps;
+ ata_channel_lock_owned(chp);
+
/*
* This is always called after siisata_reinit_port(), so don't
* need to deal with RESUME and clearing device error state.
Index: src/sys/dev/ic/wdc.c
diff -u src/sys/dev/ic/wdc.c:1.288.6.2 src/sys/dev/ic/wdc.c:1.288.6.3
--- src/sys/dev/ic/wdc.c:1.288.6.2 Mon Sep 17 18:36:14 2018
+++ src/sys/dev/ic/wdc.c Wed Oct 3 19:20:48 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc.c,v 1.288.6.2 2018/09/17 18:36:14 jdolecek Exp $ */
+/* $NetBSD: wdc.c,v 1.288.6.3 2018/10/03 19:20:48 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.288.6.2 2018/09/17 18:36:14 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.288.6.3 2018/10/03 19:20:48 jdolecek Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -932,19 +932,24 @@ wdc_reset_drive(struct ata_drive_datas *
{
struct ata_channel *chp = drvp->chnl_softc;
+ ata_channel_lock_owned(chp);
+
KASSERT(sigp == NULL);
ATADEBUG_PRINT(("wdc_reset_drive %s:%d for drive %d\n",
device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
drvp->drive), DEBUG_FUNCS);
- ata_reset_channel(chp, flags);
+ ata_thread_run(chp, flags, ATACH_TH_RESET, ATACH_NODRIVE);
}
void
wdc_reset_channel(struct ata_channel *chp, int flags)
{
struct ata_xfer *xfer;
+
+ ata_channel_lock_owned(chp);
+
#if NATA_DMA || NATA_PIOBM
struct wdc_softc *wdc = CHAN_TO_WDC(chp);
#endif
@@ -955,9 +960,7 @@ wdc_reset_channel(struct ata_channel *ch
* if the current command is on an ATAPI device, issue a
* ATAPI_SOFT_RESET
*/
- xfer = ata_queue_get_active_xfer(chp);
-
- ata_channel_lock(chp);
+ xfer = ata_queue_get_active_xfer_locked(chp);
if (xfer && xfer->c_chp == chp && (xfer->c_flags & C_ATAPI)) {
wdccommandshort(chp, xfer->c_drive, ATAPI_SOFT_RESET);
@@ -984,9 +987,8 @@ wdc_reset_channel(struct ata_channel *ch
*/
if (xfer) {
if (xfer->c_chp != chp) {
- ata_channel_unlock(chp);
- ata_reset_channel(xfer->c_chp, flags);
- ata_channel_lock(chp);
+ ata_thread_run(xfer->c_chp, flags, ATACH_TH_RESET,
+ ATACH_NODRIVE);
} else {
#if NATA_DMA || NATA_PIOBM
/*
@@ -1004,8 +1006,6 @@ wdc_reset_channel(struct ata_channel *ch
}
ata_kill_active(chp, KILL_RESET, flags);
-
- ata_channel_unlock(chp);
}
static int