convert a lockless + spltty() combo to a IPL_VM mutex and cv.

hopefully this will avoid the beep-didn't-stop problem i had recently
that i was able to fix by calling wakeup() on pcppi's softc from ddb.
This commit is contained in:
mrg 2011-05-03 04:27:13 +00:00
parent 5517207853
commit dad44dc109
2 changed files with 32 additions and 23 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pcppi.c,v 1.35 2009/04/17 20:46:37 dyoung Exp $ */
/* $NetBSD: pcppi.c,v 1.36 2011/05/03 04:27:13 mrg Exp $ */
/*
* Copyright (c) 1996 Carnegie-Mellon University.
@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pcppi.c,v 1.35 2009/04/17 20:46:37 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: pcppi.c,v 1.36 2011/05/03 04:27:13 mrg Exp $");
#include "attimer.h"
@ -39,8 +39,9 @@ __KERNEL_RCSID(0, "$NetBSD: pcppi.c,v 1.35 2009/04/17 20:46:37 dyoung Exp $");
#include <sys/proc.h>
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/bus.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <dev/ic/attimervar.h>
@ -199,6 +200,10 @@ pcppi_detach(device_t self, int flags)
callout_stop(&sc->sc_bell_ch);
callout_destroy(&sc->sc_bell_ch);
bus_space_unmap(sc->sc_iot, sc->sc_ppi_ioh, sc->sc_size);
mutex_destroy(&sc->sc_lock);
cv_destroy(&sc->sc_stop_cv);
return 0;
}
@ -212,6 +217,9 @@ pcppi_attach(struct pcppi_softc *sc)
sc->sc_bellactive = sc->sc_bellpitch = sc->sc_slp = 0;
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
cv_init(&sc->sc_stop_cv, "bell");
#if NPCKBD > 0
/* Provide a beeper for the PC Keyboard, if there isn't one already. */
pckbd_hookup_bell(pcppi_pckbd_bell, sc);
@ -266,21 +274,20 @@ void
pcppi_bell(pcppi_tag_t self, int pitch, int period, int slp)
{
struct pcppi_softc *sc = self;
int s;
s = spltty(); /* ??? */
mutex_enter(&sc->sc_lock);
if (sc->sc_bellactive) {
if (sc->sc_timeout) {
sc->sc_timeout = 0;
callout_stop(&sc->sc_bell_ch);
}
if (sc->sc_slp)
wakeup(pcppi_bell_stop);
cv_broadcast(&sc->sc_stop_cv);
}
if (pitch == 0 || period == 0) {
pcppi_bell_stop(sc);
sc->sc_bellpitch = 0;
splx(s);
mutex_exit(&sc->sc_lock);
return;
}
if (!sc->sc_bellactive || sc->sc_bellpitch != pitch) {
@ -304,20 +311,19 @@ pcppi_bell(pcppi_tag_t self, int pitch, int period, int slp)
callout_reset(&sc->sc_bell_ch, period, pcppi_bell_stop, sc);
if (slp & PCPPI_BELL_SLEEP) {
sc->sc_slp = 1;
tsleep(pcppi_bell_stop, PCPPIPRI | PCATCH, "bell", 0);
cv_wait_sig(&sc->sc_stop_cv, &sc->sc_lock);
sc->sc_slp = 0;
}
}
splx(s);
mutex_exit(&sc->sc_lock);
}
static void
pcppi_bell_stop(void *arg)
{
struct pcppi_softc *sc = arg;
int s;
s = spltty(); /* ??? */
mutex_enter(&sc->sc_lock);
sc->sc_timeout = 0;
/* disable bell */
@ -326,8 +332,8 @@ pcppi_bell_stop(void *arg)
& ~PIT_SPKR);
sc->sc_bellactive = 0;
if (sc->sc_slp)
wakeup(pcppi_bell_stop);
splx(s);
cv_broadcast(&sc->sc_stop_cv);
mutex_exit(&sc->sc_lock);
}
#if NPCKBD > 0

View File

@ -1,4 +1,4 @@
/* $NetBSD: pcppivar.h,v 1.9 2008/03/04 16:35:19 cube Exp $ */
/* $NetBSD: pcppivar.h,v 1.10 2011/05/03 04:27:13 mrg Exp $ */
/*
* Copyright (c) 1996 Carnegie-Mellon University.
@ -37,18 +37,21 @@ struct pcppi_attach_args {
};
struct pcppi_softc {
device_t sc_dv;
device_t sc_dv;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ppi_ioh;
bus_size_t sc_size;
device_t sc_timer;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ppi_ioh;
bus_size_t sc_size;
device_t sc_timer;
struct callout sc_bell_ch;
struct callout sc_bell_ch;
int sc_bellactive, sc_bellpitch;
int sc_slp;
int sc_timeout;
int sc_bellactive, sc_bellpitch;
int sc_slp;
int sc_timeout;
kmutex_t sc_lock;
kcondvar_t sc_stop_cv;
};
void pcppi_attach(struct pcppi_softc *);