summaryrefslogtreecommitdiff
path: root/sys/dev/pci/cmpci.c
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2013-05-15 08:29:27 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2013-05-15 08:29:27 +0000
commite4d6a0a80573196dfd09b1201d79c9b77536c745 (patch)
treee7cc60514c99640b6483947ee3bfb09d9b2d58bb /sys/dev/pci/cmpci.c
parent2af0efdd18ad07b832c93f5c98d654ace8e0524e (diff)
Introduce a global interrupt-aware mutex protecting data
structures (including sound-card registers) from concurent access by syscall and interrupt code-paths. Since critical sections remain the same, calls to splraise/spllower can be safely replaced by calls to mtx_enter/mtx_leave with two exceptions: (1) mutexes are not reentrant (the inner splraise is thus removed), and (2) we're not allowed to sleep with a mutex (either msleep is used or the mutex is released before sleeping). ok and help from kettenis, a lot of work from armani
Diffstat (limited to 'sys/dev/pci/cmpci.c')
-rw-r--r--sys/dev/pci/cmpci.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/sys/dev/pci/cmpci.c b/sys/dev/pci/cmpci.c
index 96a7cfb3d2b..6a14efd705a 100644
--- a/sys/dev/pci/cmpci.c
+++ b/sys/dev/pci/cmpci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmpci.c,v 1.33 2011/07/03 15:47:17 matthew Exp $ */
+/* $OpenBSD: cmpci.c,v 1.34 2013/05/15 08:29:24 ratchov Exp $ */
/* $NetBSD: cmpci.c,v 1.25 2004/10/26 06:32:20 xtraeme Exp $ */
/*
@@ -561,11 +561,14 @@ cmpci_intr(void *handle)
uint32_t intrstat;
uint16_t hwpos;
+ mtx_enter(&audio_lock);
intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
CMPCI_REG_INTR_STATUS);
- if (!(intrstat & CMPCI_REG_ANY_INTR))
+ if (!(intrstat & CMPCI_REG_ANY_INTR)) {
+ mtx_leave(&audio_lock);
return 0;
+ }
delay(10);
@@ -629,6 +632,7 @@ cmpci_intr(void *handle)
mpu_intr(sc->sc_mpudev);
#endif
+ mtx_leave(&audio_lock);
return 1;
}
@@ -994,9 +998,8 @@ cmpci_halt_output(void *handle)
{
struct cmpci_softc *sc = handle;
uint32_t reg_intr, reg_enable, reg_reset;
- int s;
- s = splaudio();
+ mtx_enter(&audio_lock);
if (sc->sc_play_channel == 1) {
sc->sc_ch1.intr = NULL;
reg_intr = CMPCI_REG_CH1_INTR_ENABLE;
@@ -1014,8 +1017,7 @@ cmpci_halt_output(void *handle)
cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, reg_reset);
delay(10);
cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_reset);
- splx(s);
-
+ mtx_leave(&audio_lock);
return 0;
}
@@ -1023,9 +1025,8 @@ int
cmpci_halt_input(void *handle)
{
struct cmpci_softc *sc = handle;
- int s;
- s = splaudio();
+ mtx_enter(&audio_lock);
sc->sc_ch1.intr = NULL;
cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
@@ -1033,8 +1034,7 @@ cmpci_halt_input(void *handle)
cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
delay(10);
cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
- splx(s);
-
+ mtx_leave(&audio_lock);
return 0;
}
@@ -2046,10 +2046,11 @@ cmpci_trigger_output(void *handle, void *start, void *end, int blksize,
delay(10);
/* start DMA */
+ mtx_enter(&audio_lock);
cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_dir); /* PLAY */
cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, reg_intr_enable);
cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, reg_enable);
-
+ mtx_leave(&audio_lock);
return 0;
}
@@ -2090,10 +2091,11 @@ cmpci_trigger_input(void *handle, void *start, void *end, int blksize,
delay(10);
/* start DMA */
+ mtx_enter(&audio_lock);
cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */
cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
-
+ mtx_leave(&audio_lock);
return 0;
}