Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/jdolecek-ncqfixes]: src/sys/dev change channel reset and drive reset for...
details: https://anonhg.NetBSD.org/src/rev/bb273976c514
branches: jdolecek-ncqfixes
changeset: 1025085:bb273976c514
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Wed Oct 03 19:20:48 2018 +0000
description:
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
diffstat:
sys/dev/ata/TODO.ncq | 2 -
sys/dev/ata/ata.c | 146 ++++++++++++++++++++++++++------------------
sys/dev/ata/atavar.h | 9 ++-
sys/dev/ata/wd.c | 21 ++++--
sys/dev/ic/ahcisata_core.c | 11 +--
sys/dev/ic/mvsata.c | 18 +---
sys/dev/ic/siisata.c | 16 ++--
sys/dev/ic/wdc.c | 22 +++---
8 files changed, 134 insertions(+), 111 deletions(-)
diffs (truncated from 660 to 300 lines):
diff -r fd98814e6c7d -r bb273976c514 sys/dev/ata/TODO.ncq
--- a/sys/dev/ata/TODO.ncq Mon Sep 24 21:19:50 2018 +0000
+++ b/sys/dev/ata/TODO.ncq Wed Oct 03 19:20:48 2018 +0000
@@ -2,8 +2,6 @@
- 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
----
diff -r fd98814e6c7d -r bb273976c514 sys/dev/ata/ata.c
--- a/sys/dev/ata/ata.c Mon Sep 24 21:19:50 2018 +0000
+++ b/sys/dev/ata/ata.c Wed Oct 03 19:20:48 2018 +0000
@@ -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 @@
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 @@
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 @@
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 @@
}
} 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_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_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_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;
-
-#ifdef ATA_DEBUG
- int spl1, spl2;
+ struct ata_drive_datas *drvp;
- 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 @@
* 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 @@
* 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 @@
/* 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 @@
(*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 @@
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 @@
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 @@
/* 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 @@
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) {
Home |
Main Index |
Thread Index |
Old Index