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 the SATA/NCQ recovery to run in t...
details: https://anonhg.NetBSD.org/src/rev/eab9edd86f17
branches: jdolecek-ncqfixes
changeset: 445166:eab9edd86f17
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Mon Oct 15 21:18:53 2018 +0000
description:
change the SATA/NCQ recovery to run in the atabus thread
diffstat:
sys/dev/ata/TODO.ncq | 3 -
sys/dev/ata/ata.c | 73 +++++++++++++++++++++++++++++++++------------
sys/dev/ata/ata_recovery.c | 23 ++++++++------
sys/dev/ata/ata_wdc.c | 5 +-
sys/dev/ata/atavar.h | 17 ++++++----
sys/dev/ic/ahcisata_core.c | 41 +++++++++++--------------
sys/dev/ic/mvsata.c | 39 +++++++++++------------
sys/dev/ic/siisata.c | 32 ++++++++-----------
sys/dev/usb/umass_isdata.c | 5 +-
9 files changed, 132 insertions(+), 106 deletions(-)
diffs (truncated from 675 to 300 lines):
diff -r a793e28b1da3 -r eab9edd86f17 sys/dev/ata/TODO.ncq
--- a/sys/dev/ata/TODO.ncq Sun Oct 14 16:13:51 2018 +0000
+++ b/sys/dev/ata/TODO.ncq Mon Oct 15 21:18:53 2018 +0000
@@ -1,9 +1,6 @@
jdolecek-ncqfixes goals:
- re-check READ LOG EXT handling under native and Parallels to make sure
the NOERROR under Parallels is their bug and not ours
-- run recovery via atathread, move to new function and share ahci/siisata/mvsata
-- maybe do device error handling in not-interrupt-context (maybe this should be
- done on a mpata branch?)
Bugs
----
diff -r a793e28b1da3 -r eab9edd86f17 sys/dev/ata/ata.c
--- a/sys/dev/ata/ata.c Sun Oct 14 16:13:51 2018 +0000
+++ b/sys/dev/ata/ata.c Mon Oct 15 21:18:53 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.141.6.17 2018/10/14 16:13:51 jdolecek Exp $ */
+/* $NetBSD: ata.c,v 1.141.6.18 2018/10/15 21:18:53 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.17 2018/10/14 16:13:51 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.141.6.18 2018/10/15 21:18:53 jdolecek Exp $");
#include "opt_ata.h"
@@ -129,7 +129,6 @@
static void atabusconfig_thread(void *);
static void ata_channel_idle(struct ata_channel *);
-static void ata_channel_thaw_locked(struct ata_channel *);
static void ata_activate_xfer_locked(struct ata_channel *, struct ata_xfer *);
static void ata_channel_freeze_locked(struct ata_channel *);
static void ata_thread_wake_locked(struct ata_channel *);
@@ -463,7 +462,7 @@
ata_channel_lock(chp);
for (;;) {
if ((chp->ch_flags & (ATACH_TH_RESET | ATACH_TH_DRIVE_RESET
- | ATACH_SHUTDOWN)) == 0 &&
+ | ATACH_TH_RECOVERY | 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);
@@ -483,6 +482,7 @@
ata_thread_run(chp, AT_WAIT,
ATACH_TH_RESET, ATACH_NODRIVE);
} else if (chp->ch_flags & ATACH_TH_DRIVE_RESET) {
+ /* this will unfreeze the channel */
for (i = 0; i < chp->ch_ndrives; i++) {
struct ata_drive_datas *drvp;
@@ -494,6 +494,16 @@
}
}
chp->ch_flags &= ~ATACH_TH_DRIVE_RESET;
+ } else if (chp->ch_flags & ATACH_TH_RECOVERY) {
+ /*
+ * This will unfreeze the channel; drops locks during
+ * run, so must wrap in splbio()/splx() to avoid
+ * spurious interrupts. XXX MPSAFE
+ */
+ int s = splbio();
+ ata_thread_run(chp, AT_WAIT, ATACH_TH_RECOVERY,
+ chp->recovery_tfd);
+ splx(s);
} else if (chq->queue_active > 0 && chq->queue_freeze == 1) {
/*
* Caller has bumped queue_freeze, decrease it. This
@@ -522,10 +532,12 @@
} 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);
+ /* Try to run down the queue once channel is unfrozen */
+ if (chq->queue_freeze == 0) {
+ ata_channel_unlock(chp);
+ atastart(chp);
+ ata_channel_lock(chp);
+ }
}
chp->ch_thread = NULL;
cv_signal(&chp->ch_thr_idle);
@@ -1499,7 +1511,7 @@
ata_channel_unlock(chp);
}
-static void
+void
ata_channel_thaw_locked(struct ata_channel *chp)
{
KASSERT(mutex_owned(&chp->ch_lock));
@@ -1511,21 +1523,13 @@
chp->ch_queue->queue_freeze), DEBUG_FUNCS | DEBUG_XFERS);
}
-void
-ata_channel_thaw(struct ata_channel *chp)
-{
- ata_channel_lock(chp);
- ata_channel_thaw_locked(chp);
- ata_channel_unlock(chp);
-}
-
/*
* ata_thread_run:
*
- * Reset and ATA channel. Channel lock must be held.
+ * Reset and ATA channel. Channel lock must be held. arg is type-specific.
*/
void
-ata_thread_run(struct ata_channel *chp, int flags, int type, int drive)
+ata_thread_run(struct ata_channel *chp, int flags, int type, int arg)
{
struct atac_softc *atac = chp->ch_atac;
bool threset = false;
@@ -1548,6 +1552,9 @@
}
break;
case ATACH_TH_DRIVE_RESET:
+ {
+ int drive = arg;
+
KASSERT(drive <= chp->ch_ndrives);
drvp = &chp->ch_drive[drive];
@@ -1557,6 +1564,15 @@
}
drvp->drive_flags |= ATA_DRIVE_TH_RESET;
break;
+ }
+ case ATACH_TH_RECOVERY:
+ {
+ uint32_t tfd = (uint32_t)arg;
+
+ KASSERT((chp->ch_flags & ATACH_RECOVERING) == 0);
+ chp->recovery_tfd = tfd;
+ break;
+ }
default:
panic("%s: unknown type: %x", __func__, type);
/* NOTREACHED */
@@ -1591,16 +1607,33 @@
(*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++)
+ for (int drive = 0; drive < chp->ch_ndrives; drive++)
chp->ch_drive[drive].state = 0;
break;
case ATACH_TH_DRIVE_RESET:
+ {
+ int drive = arg;
+
KASSERT(drive <= chp->ch_ndrives);
drvp = &chp->ch_drive[drive];
(*atac->atac_bustype_ata->ata_reset_drive)(drvp, flags, NULL);
drvp->state = 0;
break;
+ }
+
+ case ATACH_TH_RECOVERY:
+ {
+ uint32_t tfd = (uint32_t)arg;
+
+ KASSERT((chp->ch_flags & ATACH_RECOVERING) == 0);
+ KASSERT(atac->atac_bustype_ata->ata_recovery != NULL);
+
+ SET(chp->ch_flags, ATACH_RECOVERING);
+ (*atac->atac_bustype_ata->ata_recovery)(chp, flags, tfd);
+ CLR(chp->ch_flags, ATACH_RECOVERING);
+ break;
+ }
default:
panic("%s: unknown type: %x", __func__, type);
diff -r a793e28b1da3 -r eab9edd86f17 sys/dev/ata/ata_recovery.c
--- a/sys/dev/ata/ata_recovery.c Sun Oct 14 16:13:51 2018 +0000
+++ b/sys/dev/ata/ata_recovery.c Mon Oct 15 21:18:53 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata_recovery.c,v 1.1.2.1 2018/10/11 20:57:51 jdolecek Exp $ */
+/* $NetBSD: ata_recovery.c,v 1.1.2.2 2018/10/15 21:18:53 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.1.2.1 2018/10/11 20:57:51 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_recovery.c,v 1.1.2.2 2018/10/15 21:18:53 jdolecek Exp $");
#include "opt_ata.h"
@@ -67,9 +67,9 @@
ata_read_log_ext_ncq(struct ata_drive_datas *drvp, uint8_t flags,
uint8_t *slot, uint8_t *status, uint8_t *err)
{
- struct ata_xfer *xfer = &drvp->recovery_xfer;
int rv;
struct ata_channel *chp = drvp->chnl_softc;
+ struct ata_xfer *xfer = &chp->recovery_xfer;
struct atac_softc *atac = chp->ch_atac;
uint8_t *tb, cksum, page;
@@ -82,8 +82,8 @@
memset(xfer, 0, sizeof(*xfer));
- tb = drvp->recovery_blk;
- memset(tb, 0, sizeof(drvp->recovery_blk));
+ tb = chp->recovery_blk;
+ memset(tb, 0, sizeof(chp->recovery_blk));
/*
* We could use READ LOG DMA EXT if drive supports it (i.e.
@@ -101,7 +101,7 @@
xfer->c_ata_c.flags = AT_READ | AT_LBA | AT_LBA48 | flags;
xfer->c_ata_c.timeout = 1000; /* 1s */
xfer->c_ata_c.data = tb;
- xfer->c_ata_c.bcount = sizeof(drvp->recovery_blk);
+ xfer->c_ata_c.bcount = sizeof(chp->recovery_blk);
if ((*atac->atac_bustype_ata->ata_exec_command)(drvp,
xfer) != ATACMD_COMPLETE) {
@@ -114,7 +114,7 @@
}
cksum = 0;
- for (int i = 0; i < sizeof(drvp->recovery_blk); i++)
+ for (int i = 0; i < sizeof(chp->recovery_blk); i++)
cksum += tb[i];
if (cksum != 0) {
device_printf(drvp->drv_softc,
@@ -167,13 +167,16 @@
struct ata_xfer *xfer;
const uint8_t ch_openings = ata_queue_openings(chp);
- ata_channel_lock(chp);
+ ata_channel_lock_owned(chp);
+
ata_queue_hold(chp);
- ata_channel_unlock(chp);
KASSERT(drive < chp->ch_ndrives);
drvp = &chp->ch_drive[drive];
+ /* Drop the lock for the READ LOG EXT request */
+ ata_channel_unlock(chp);
+
/*
* When running NCQ commands, READ LOG EXT is necessary to clear the
* error condition and unblock the device.
@@ -243,5 +246,5 @@
out:
/* Nothing more to do */
- return;
+ ata_channel_lock(chp);
}
diff -r a793e28b1da3 -r eab9edd86f17 sys/dev/ata/ata_wdc.c
--- a/sys/dev/ata/ata_wdc.c Sun Oct 14 16:13:51 2018 +0000
+++ b/sys/dev/ata/ata_wdc.c Mon Oct 15 21:18:53 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata_wdc.c,v 1.110.4.3 2018/09/17 20:54:41 jdolecek Exp $ */
+/* $NetBSD: ata_wdc.c,v 1.110.4.4 2018/10/15 21:18:53 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.110.4.3 2018/09/17 20:54:41 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.110.4.4 2018/10/15 21:18:53 jdolecek Exp $");
#include "opt_ata.h"
#include "opt_wdc.h"
@@ -128,6 +128,7 @@
wdc_ata_addref,
wdc_ata_delref,
ata_kill_pending,
+ NULL,
};
static const struct ata_xfer_ops wdc_bio_xfer_ops = {
diff -r a793e28b1da3 -r eab9edd86f17 sys/dev/ata/atavar.h
--- a/sys/dev/ata/atavar.h Sun Oct 14 16:13:51 2018 +0000
+++ b/sys/dev/ata/atavar.h Mon Oct 15 21:18:53 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: atavar.h,v 1.99.2.11 2018/10/11 20:57:51 jdolecek Exp $ */
+/* $NetBSD: atavar.h,v 1.99.2.12 2018/10/15 21:18:53 jdolecek Exp $ */
Home |
Main Index |
Thread Index |
Old Index