Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/jdolecek-ncq]: src/sys/dev convert the atabus thread to use the channel ...
details: https://anonhg.NetBSD.org/src/rev/83be5d2453c2
branches: jdolecek-ncq
changeset: 822998:83be5d2453c2
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Sat Aug 12 14:41:54 2017 +0000
description:
convert the atabus thread to use the channel lock and a condvar, adjust
code which sets the relevant channel flags to take the lock while doing so
diffstat:
sys/dev/ata/TODO.ncq | 2 -
sys/dev/ata/ata.c | 111 ++++++++++++++++++++++++++++++--------------
sys/dev/ata/ata_wdc.c | 7 +-
sys/dev/ata/atavar.h | 4 +-
sys/dev/ic/mvsata.c | 10 +--
sys/dev/ic/wdc.c | 7 +-
sys/dev/scsipi/atapi_wdc.c | 7 +-
7 files changed, 91 insertions(+), 57 deletions(-)
diffs (truncated from 480 to 300 lines):
diff -r e56cf35aaa91 -r 83be5d2453c2 sys/dev/ata/TODO.ncq
--- a/sys/dev/ata/TODO.ncq Sat Aug 12 13:41:46 2017 +0000
+++ b/sys/dev/ata/TODO.ncq Sat Aug 12 14:41:54 2017 +0000
@@ -15,8 +15,6 @@
kill active transfers after software drive reset - race timeout vs.
error recovery
-atabus_thread() protect run by mutex/condvar
-
Other random notes (do outside the NCQ branch):
-----------------------------------------------------
implement support for PM FIS-based switching, remove restriction in atastart()
diff -r e56cf35aaa91 -r 83be5d2453c2 sys/dev/ata/ata.c
--- a/sys/dev/ata/ata.c Sat Aug 12 13:41:46 2017 +0000
+++ b/sys/dev/ata/ata.c Sat Aug 12 14:41:54 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata.c,v 1.132.8.25 2017/08/12 09:52:28 jdolecek Exp $ */
+/* $NetBSD: ata.c,v 1.132.8.26 2017/08/12 14:41:54 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.25 2017/08/12 09:52:28 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.132.8.26 2017/08/12 14:41:54 jdolecek Exp $");
#include "opt_ata.h"
@@ -131,7 +131,7 @@
static void ata_channel_idle(struct ata_channel *);
static void ata_activate_xfer_locked(struct ata_channel *, struct ata_xfer *);
-
+static void ata_channel_freeze_locked(struct ata_channel *);
/*
* atabus_init:
*
@@ -322,6 +322,7 @@
ata_channel_init(struct ata_channel *chp)
{
mutex_init(&chp->ch_lock, MUTEX_DEFAULT, IPL_BIO);
+ cv_init(&chp->ch_thr_idle, "atath");
}
/*
@@ -347,6 +348,7 @@
ata_channel_destroy(struct ata_channel *chp)
{
mutex_destroy(&chp->ch_lock);
+ cv_destroy(&chp->ch_thr_idle);
}
/*
@@ -369,12 +371,12 @@
struct ata_channel *chp = atabus_sc->sc_chan;
struct atac_softc *atac = chp->ch_atac;
struct atabus_initq *atabus_initq = NULL;
- int i, s, error;
+ int i, error;
/* we are in the atabus's thread context */
- s = splbio();
+ mutex_enter(&chp->ch_lock);
chp->ch_flags |= ATACH_TH_RUN;
- splx(s);
+ mutex_exit(&chp->ch_lock);
/*
* Probe for the drives attached to controller, unless a PMP
@@ -391,9 +393,9 @@
}
/* next operations will occurs in a separate thread */
- s = splbio();
+ mutex_enter(&chp->ch_lock);
chp->ch_flags &= ~ATACH_TH_RUN;
- splx(s);
+ mutex_exit(&chp->ch_lock);
/* Make sure the devices probe in atabus order to avoid jitter. */
mutex_enter(&atabus_qlock);
@@ -405,6 +407,8 @@
}
mutex_exit(&atabus_qlock);
+ mutex_enter(&chp->ch_lock);
+
/* If no drives, abort here */
if (chp->ch_drive == NULL)
goto out;
@@ -419,6 +423,8 @@
if (chp->ch_flags & ATACH_SHUTDOWN)
goto out;
+ mutex_exit(&chp->ch_lock);
+
if ((error = kthread_create(PRI_NONE, 0, NULL, atabusconfig_thread,
atabus_sc, &atabus_cfg_lwp,
"%scnf", device_xname(atac->atac_dev))) != 0)
@@ -427,6 +433,8 @@
return;
out:
+ mutex_exit(&chp->ch_lock);
+
mutex_enter(&atabus_qlock);
TAILQ_REMOVE(&atabus_initq_head, atabus_initq, atabus_initq);
cv_broadcast(&atabus_qcv);
@@ -578,9 +586,9 @@
struct ata_channel *chp = sc->sc_chan;
struct ata_queue *chq = chp->ch_queue;
struct ata_xfer *xfer;
- int i, s;
+ int i;
- s = splbio();
+ mutex_enter(&chp->ch_lock);
chp->ch_flags |= ATACH_TH_RUN;
/*
@@ -594,32 +602,36 @@
chp->ch_drive[i].drive_flags = 0;
chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
}
- splx(s);
+ mutex_exit(&chp->ch_lock);
atabusconfig(sc);
- s = splbio();
+ mutex_enter(&chp->ch_lock);
for (;;) {
if ((chp->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 &&
(chq->queue_active == 0 || chq->queue_freeze == 0)) {
chp->ch_flags &= ~ATACH_TH_RUN;
- (void) tsleep(&chp->ch_thread, PRIBIO, "atath", 0);
+ cv_wait(&chp->ch_thr_idle, &chp->ch_lock);
chp->ch_flags |= ATACH_TH_RUN;
}
if (chp->ch_flags & ATACH_SHUTDOWN) {
break;
}
if (chp->ch_flags & ATACH_TH_RESCAN) {
+ chp->ch_flags &= ~ATACH_TH_RESCAN;
+ mutex_exit(&chp->ch_lock);
atabusconfig(sc);
- chp->ch_flags &= ~ATACH_TH_RESCAN;
+ mutex_enter(&chp->ch_lock);
}
if (chp->ch_flags & ATACH_TH_RESET) {
/*
* ata_reset_channel() will freeze 2 times, so
* unfreeze one time. Not a problem as we're at splbio
*/
+ mutex_exit(&chp->ch_lock);
ata_channel_thaw(chp);
ata_reset_channel(chp, AT_WAIT | chp->ch_reset_flags);
+ mutex_enter(&chp->ch_lock);
} else if (chq->queue_active > 0 && chq->queue_freeze == 1) {
/*
* Caller has bumped queue_freeze, decrease it. This
@@ -627,20 +639,31 @@
*/
KASSERT((chp->ch_flags & ATACH_NCQ) == 0);
KASSERT(chq->queue_active == 1);
+ mutex_exit(&chp->ch_lock);
ata_channel_thaw(chp);
xfer = ata_queue_get_active_xfer(chp);
KASSERT(xfer != NULL);
(*xfer->c_start)(xfer->c_chp, xfer);
+ mutex_enter(&chp->ch_lock);
} else if (chq->queue_freeze > 1)
- panic("ata_thread: queue_freeze");
+ panic("%s: queue_freeze", __func__);
}
- splx(s);
chp->ch_thread = NULL;
- wakeup(&chp->ch_flags);
+ cv_signal(&chp->ch_thr_idle);
+ mutex_exit(&chp->ch_lock);
kthread_exit(0);
}
+void
+ata_thread_wake(struct ata_channel *chp)
+{
+ mutex_enter(&chp->ch_lock);
+ ata_channel_freeze_locked(chp);
+ cv_signal(&chp->ch_thr_idle);
+ mutex_exit(&chp->ch_lock);
+}
+
/*
* atabus_match:
*
@@ -711,18 +734,16 @@
struct atabus_softc *sc = device_private(self);
struct ata_channel *chp = sc->sc_chan;
device_t dev = NULL;
- int s, i, error = 0;
+ int i, error = 0;
/* Shutdown the channel. */
- s = splbio(); /* XXX ALSO NEED AN INTERLOCK HERE. */
+ mutex_enter(&chp->ch_lock);
chp->ch_flags |= ATACH_SHUTDOWN;
- splx(s);
-
- wakeup(&chp->ch_thread);
-
- while (chp->ch_thread != NULL)
- (void) tsleep(&chp->ch_flags, PRIBIO, "atadown", 0);
-
+ while (chp->ch_thread != NULL) {
+ cv_signal(&chp->ch_thr_idle);
+ cv_wait(&chp->ch_thr_idle, &chp->ch_lock);
+ }
+ mutex_exit(&chp->ch_lock);
/*
* Detach atapibus and its children.
@@ -1663,16 +1684,26 @@
mutex_exit(&chp->ch_lock);
}
+static void
+ata_channel_freeze_locked(struct ata_channel *chp)
+{
+ chp->ch_queue->queue_freeze++;
+}
+
void
ata_channel_freeze(struct ata_channel *chp)
{
- chp->ch_queue->queue_freeze++; /* XXX MPSAFE */
+ mutex_enter(&chp->ch_lock);
+ ata_channel_freeze_locked(chp);
+ mutex_exit(&chp->ch_lock);
}
void
ata_channel_thaw(struct ata_channel *chp)
{
- chp->ch_queue->queue_freeze--; /* XXX MPSAFE */
+ mutex_enter(&chp->ch_lock);
+ chp->ch_queue->queue_freeze--;
+ mutex_exit(&chp->ch_lock);
}
/*
@@ -1715,19 +1746,24 @@
ata_channel_thaw(chp);
return;
}
+ mutex_enter(&chp->ch_lock);
chp->ch_flags |= ATACH_TH_RESET;
chp->ch_reset_flags = flags & AT_RST_EMERG;
- wakeup(&chp->ch_thread);
+ cv_signal(&chp->ch_thr_idle);
+ mutex_exit(&chp->ch_lock);
return;
}
(*atac->atac_bustype_ata->ata_reset_channel)(chp, flags);
+ mutex_enter(&chp->ch_lock);
KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
for (drive = 0; drive < chp->ch_ndrives; drive++)
chp->ch_drive[drive].state = 0;
chp->ch_flags &= ~ATACH_TH_RESET;
+ mutex_exit(&chp->ch_lock);
+
if (flags & AT_RST_EMERG) {
/* make sure that we can use polled commands */
ata_queue_reset(chp->ch_queue);
@@ -2303,26 +2339,27 @@
{
struct atabus_softc *sc = device_private(dv);
struct ata_channel *chp = sc->sc_chan;
- int s;
/*
* XXX joerg: with wdc, the first channel unfreezes the controler.
* Move this the reset and queue idling into wdc.
*/
- s = splbio();
+ mutex_enter(&chp->ch_lock);
if (chp->ch_queue->queue_freeze == 0) {
- splx(s);
- return true;
+ mutex_exit(&chp->ch_lock);
+ goto out;
}
KASSERT(chp->ch_queue->queue_freeze > 0);
+ mutex_exit(&chp->ch_lock);
+
Home |
Main Index |
Thread Index |
Old Index