Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-8]: src/sys/dev/sbus Pull up following revision(s) (requested by ...
details: https://anonhg.NetBSD.org/src/rev/700cde4e10df
branches: netbsd-8
changeset: 434559:700cde4e10df
user: snj <snj%NetBSD.org@localhost>
date: Sat Jan 13 22:15:30 2018 +0000
description:
Pull up following revision(s) (requested by mrg in ticket #503):
sys/dev/sbus/dbri.c: up to 1.38
sys/dev/sbus/dbrivar.h: up to 1.15
fix audiomp bugs:
- switch from tsleep/wakeup to condvar
- fix locking in a bunch of places. there were several locking
against myself issues.
also:
- don't let dbri_process_interrupt_buffer() loop more than once
over the array of intrs.
this fixes hangs when using audio on ss20 in -current, but does
not make audio work. it eventually times out with eg:
dbri0: switching to control mode timed out (0 f6)
and may leave a sample in the audio buffer repeating.
--
fix several KASSERT()s and locking in a few places.
fixes DIAGNOSTIC kernels and still plays.
diffstat:
sys/dev/sbus/dbri.c | 101 ++++++++++++++++++++++++++++++++----------------
sys/dev/sbus/dbrivar.h | 5 +-
2 files changed, 72 insertions(+), 34 deletions(-)
diffs (truncated from 335 to 300 lines):
diff -r 3d1f6ed05454 -r 700cde4e10df sys/dev/sbus/dbri.c
--- a/sys/dev/sbus/dbri.c Sat Jan 13 22:10:55 2018 +0000
+++ b/sys/dev/sbus/dbri.c Sat Jan 13 22:15:30 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dbri.c,v 1.35.22.1 2018/01/13 05:40:25 snj Exp $ */
+/* $NetBSD: dbri.c,v 1.35.22.2 2018/01/13 22:15:30 snj Exp $ */
/*
* Copyright (C) 1997 Rudolf Koenig (rfkoenig%immd4.informatik.uni-erlangen.de@localhost)
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dbri.c,v 1.35.22.1 2018/01/13 05:40:25 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dbri.c,v 1.35.22.2 2018/01/13 22:15:30 snj Exp $");
#include "audio.h"
#if NAUDIO > 0
@@ -369,9 +369,13 @@
sc->sc_bufsiz = size;
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
- mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
+ mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
- bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_SCHED, dbri_intr,
+#ifndef DBRI_SPIN
+ cv_init(&sc->sc_cv, "dbricv");
+#endif
+
+ bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_AUDIO, dbri_intr,
sc);
sc->sc_locked = 0;
@@ -448,23 +452,32 @@
{
struct dbri_softc *sc = device_private(dev);
- if (sc->sc_init_done != 0)
+ mutex_spin_enter(&sc->sc_intr_lock);
+ if (sc->sc_init_done != 0) {
+ mutex_spin_exit(&sc->sc_intr_lock);
return 0;
-
+ }
sc->sc_init_done = 1;
dbri_init(sc);
+
+ /* talking to the codec needs working interrupts */
if (mmcodec_init(sc) == -1) {
+ mutex_spin_exit(&sc->sc_intr_lock);
printf("%s: no codec detected, aborting\n",
device_xname(dev));
return 0;
}
+ mutex_spin_exit(&sc->sc_intr_lock);
/* Attach ourselves to the high level audio interface */
audio_attach_mi(&dbri_hw_if, sc, sc->sc_dev);
/* power down until open() */
+ mutex_spin_enter(&sc->sc_intr_lock);
dbri_set_power(sc, 0);
+ mutex_spin_exit(&sc->sc_intr_lock);
+
return 0;
}
@@ -536,6 +549,8 @@
bus_addr_t dmaaddr;
int n;
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
+
dbri_reset(sc);
sc->sc_mm.status = 0;
@@ -566,6 +581,7 @@
*(cmd++) = dmaaddr;
dbri_command_send(sc, cmd);
+
return (0);
}
@@ -607,7 +623,7 @@
bus_space_tag_t iot = sc->sc_iot;
int maxloops = 1000000;
- mutex_spin_enter(&sc->sc_intr_lock);
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
sc->sc_locked--;
@@ -645,8 +661,6 @@
}
}
- mutex_spin_exit(&sc->sc_intr_lock);
-
return;
}
@@ -654,6 +668,9 @@
dbri_process_interrupt_buffer(struct dbri_softc *sc)
{
int32_t i;
+ int orig_irqp = sc->sc_irqp;
+
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
while ((i = sc->sc_dma->intr[sc->sc_irqp]) != 0) {
sc->sc_dma->intr[sc->sc_irqp] = 0;
@@ -665,6 +682,10 @@
sc->sc_irqp++;
dbri_process_interrupt(sc, i);
+
+ /* don't loop more than once. */
+ if (orig_irqp == sc->sc_irqp)
+ break;
}
return;
@@ -692,6 +713,7 @@
int td;
struct dbri_desc *dd;
+ DPRINTF("%s:%d tx complete\n", __func__, channel);
td = sc->sc_pipe[channel].desc;
dd = &sc->sc_desc[td];
@@ -700,15 +722,15 @@
break;
}
case DBRI_INTR_FXDT: /* fixed data change */
- DPRINTF("dbri_intr: Fixed data change (%d: %x)\n", channel,
+ DPRINTF("%s:%d: Fixed data change: %x\n", __func__, channel,
val);
if (sc->sc_pipe[channel].sdp & DBRI_SDP_MSB)
val = reverse_bytes(val, sc->sc_pipe[channel].length);
if (sc->sc_pipe[channel].prec)
*(sc->sc_pipe[channel].prec) = val;
#ifndef DBRI_SPIN
- DPRINTF("%s: wakeup %p\n", device_xname(sc->sc_dev), sc);
- wakeup(sc);
+ DPRINTF("%s: cv_broadcast %p\n", device_xname(sc->sc_dev), sc);
+ cv_broadcast(&sc->sc_cv);
#endif
break;
case DBRI_INTR_SBRI:
@@ -719,6 +741,7 @@
int td;
struct dbri_desc *dd;
+ DPRINTF("dbri_intr: buffer ready (%d)\n", channel);
td = sc->sc_pipe[channel].desc;
dd = &sc->sc_desc[td];
@@ -972,11 +995,15 @@
bus_space_handle_t ioh = sc->sc_ioh;
uint32_t val;
uint32_t tmp;
- int bail = 0;
-#if DBRI_SPIN
+ int ret = 0;
+#ifdef DBRI_SPIN
int i;
+#else
+ int error, bail = 0;
#endif
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
+
/*
* Temporarily mute outputs and wait 125 us to make sure that it
* happens. This avoids clicking noises.
@@ -1028,34 +1055,45 @@
tmp |= DBRI_CHI_ACTIVATE;
bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
-#if DBRI_SPIN
+#ifdef DBRI_SPIN
i = 1024;
- while (((sc->sc_mm.status & 0xe4) != 0x20) && --i) {
+ while (((sc->sc_mm.status & 0xe4) != CS4215_ONE) && (i > 0)) {
+ i--;
delay(125);
}
if (i == 0) {
DPRINTF("%s: cs4215 didn't respond to CLB (0x%02x)\n",
device_xname(sc->sc_dev), sc->sc_mm.status);
- return (-1);
+ ret = -1;
+ goto fail;
}
#else
- while (((sc->sc_mm.status & 0xe4) != 0x20) && (bail < 10)) {
- DPRINTF("%s: tsleep %p\n", device_xname(sc->sc_dev), sc);
- tsleep(sc, PCATCH | PZERO, "dbrifxdt", hz);
+ while (((sc->sc_mm.status & 0xe4) != CS4215_ONE) && (bail < 10)) {
+ DPRINTF("%s: cv_wait_sig %p\n", device_xname(sc->sc_dev), sc);
+ error = cv_timedwait_sig(&sc->sc_cv, &sc->sc_intr_lock, hz);
+ if (error == EINTR) {
+ DPRINTF("%s: interrupted\n", device_xname(sc->sc_dev));
+ ret = -1;
+ mutex_spin_exit(&sc->sc_intr_lock);
+ goto fail;
+ }
bail++;
}
-#endif
if (bail >= 10) {
- DPRINTF("%s: switching to control mode timed out (%x %x)\n",
+ aprint_error("%s: switching to control mode timed out (%x %x)\n",
device_xname(sc->sc_dev), sc->sc_mm.status,
bus_space_read_4(iot, ioh, DBRI_REG2));
- return -1;
+ ret = -1;
+ goto fail;
}
+#endif
/* copy the version information before it becomes unreadable again */
sc->sc_version = sc->sc_mm.version;
+ sc->sc_whack_codec = 0;
+fail:
/* terminate cs4215 control mode */
sc->sc_mm.c.bcontrol[0] |= CS4215_CLB;
pipe_transmit_fixed(sc, 17, sc->sc_mm.c.lcontrol);
@@ -1331,8 +1369,6 @@
dd->callback = callback;
dd->callback_args = callback_args;
- mutex_spin_enter(&sc->sc_intr_lock);
-
/* the pipe shouldn't be active */
if (pipe_active(sc, pipe)) {
aprint_error("pipe active (CDP)\n");
@@ -1367,8 +1403,6 @@
DPRINTF("%s: starting DMA\n", __func__);
}
- mutex_spin_exit(&sc->sc_intr_lock);
-
return;
}
@@ -1428,8 +1462,6 @@
dd->callback = callback;
dd->callback_args = callback_args;
- mutex_spin_enter(&sc->sc_intr_lock);
-
/* the pipe shouldn't be active */
if (pipe_active(sc, pipe)) {
aprint_error("pipe active (CDP)\n");
@@ -1464,8 +1496,6 @@
DPRINTF("%s: starting DMA\n", __func__);
}
- mutex_spin_exit(&sc->sc_intr_lock);
-
return;
}
@@ -1994,6 +2024,7 @@
if (sc->sc_whack_codec == 0)
return 0;
+ mutex_spin_enter(&sc->sc_intr_lock);
ret = mmcodec_setcontrol(sc);
if (ret) {
DPRINTF("%s: control mode failed. Mutex %s PIL %x\n", __func__,
@@ -2002,6 +2033,7 @@
} else
DPRINTF("%s: control mode ok\n", __func__);
mmcodec_init_data(sc);
+ mutex_spin_exit(&sc->sc_intr_lock);
return 0;
}
@@ -2194,8 +2226,9 @@
DPRINTF("%s: %d\n", __func__, sc->sc_refcount);
- if (sc->sc_refcount == 0)
+ if (sc->sc_refcount == 0) {
dbri_bring_up(sc);
+ }
sc->sc_refcount++;
@@ -2224,7 +2257,9 @@
{
struct dbri_softc *sc = device_private(self);
Home |
Main Index |
Thread Index |
Old Index