Module Name: src
Committed By: snj
Date: Fri Apr 10 18:12:53 UTC 2009
Modified Files:
src/sys/dev/ir [netbsd-5]: irframe_tty.c
Log Message:
Pull up following revision(s) (requested by mlelstv in ticket #684):
sys/dev/ir/irframe_tty.c: revision 1.56
Avoid crash under LOCKDEBUG by destroying a mutex correctly.
Also: move mutex init/destroy into attach/detach functions and
handle case where line discipline is closed before the irframe
device. Fixes PR kern/40271.
To generate a diff of this commit:
cvs rdiff -u -r1.54 -r1.54.8.1 src/sys/dev/ir/irframe_tty.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/ir/irframe_tty.c
diff -u src/sys/dev/ir/irframe_tty.c:1.54 src/sys/dev/ir/irframe_tty.c:1.54.8.1
--- src/sys/dev/ir/irframe_tty.c:1.54 Sun May 25 19:22:21 2008
+++ src/sys/dev/ir/irframe_tty.c Fri Apr 10 18:12:53 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: irframe_tty.c,v 1.54 2008/05/25 19:22:21 ad Exp $ */
+/* $NetBSD: irframe_tty.c,v 1.54.8.1 2009/04/10 18:12:53 snj Exp $ */
/*
* TODO
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: irframe_tty.c,v 1.54 2008/05/25 19:22:21 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: irframe_tty.c,v 1.54.8.1 2009/04/10 18:12:53 snj Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@@ -148,6 +148,7 @@
static void irt_setspeed(struct tty *, u_int);
static void irt_setline(struct tty *, u_int);
static void irt_delay(struct tty *, u_int);
+static void irt_buffer(struct irframet_softc *, u_int);
static const struct irframe_methods irframet_methods = {
irframet_open, irframet_close, irframet_read, irframet_write,
@@ -218,9 +219,16 @@
static void
irframet_attach(device_t parent, device_t self, void *aux)
{
+ struct irframet_softc *sc = device_private(self);
/* pseudo-device attachment does not print name */
aprint_normal("%s", device_xname(self));
+
+ callout_init(&sc->sc_timeout, 0);
+ mutex_init(&sc->sc_wr_lk, MUTEX_DEFAULT, IPL_NONE);
+ selinit(&sc->sc_rsel);
+ selinit(&sc->sc_wsel);
+
#if 0 /* XXX can't do it yet because pseudo-devices don't get aux */
struct ir_attach_args ia;
@@ -234,8 +242,19 @@
static int
irframet_detach(struct device *dev, int flags)
{
+ struct irframet_softc *sc = device_private(dev);
+ int rc;
+
+ callout_stop(&sc->sc_timeout);
+
+ rc = irframe_detach(dev, flags);
- return (irframe_detach(dev, flags));
+ callout_destroy(&sc->sc_timeout);
+ mutex_destroy(&sc->sc_wr_lk);
+ seldestroy(&sc->sc_wsel);
+ seldestroy(&sc->sc_rsel);
+
+ return rc;
}
/*
@@ -326,8 +345,8 @@
ttyflush(tp, FREAD | FWRITE);
mutex_spin_exit(&tty_lock); /* XXX */
ttyldisc_release(tp->t_linesw);
- tp->t_linesw = ttyldisc_default();
- if (sc != NULL) {
+ tp->t_linesw = ttyldisc_default(); if (sc != NULL) {
+ irt_buffer(sc, 0);
tp->t_sc = NULL;
aprint_normal("%s detached from tty%02d\n",
device_xname(sc->sc_irp.sc_dev), minor(tp->t_dev));
@@ -402,6 +421,35 @@
return (0);
}
+static void
+irt_buffer(struct irframet_softc *sc, u_int maxsize)
+{
+ int i;
+
+ DPRINTF(("%s: sc=%p, maxsize=%u\n", __func__, sc, maxsize));
+
+ if (sc->sc_params.maxsize != maxsize) {
+ sc->sc_params.maxsize = maxsize;
+ if (sc->sc_inbuf != NULL)
+ free(sc->sc_inbuf, M_DEVBUF);
+ for (i = 0; i < MAXFRAMES; i++)
+ if (sc->sc_frames[i].buf != NULL)
+ free(sc->sc_frames[i].buf, M_DEVBUF);
+ if (sc->sc_params.maxsize != 0) {
+ sc->sc_inbuf = malloc(sc->sc_params.maxsize+2,
+ M_DEVBUF, M_WAITOK);
+ for (i = 0; i < MAXFRAMES; i++)
+ sc->sc_frames[i].buf =
+ malloc(sc->sc_params.maxsize,
+ M_DEVBUF, M_WAITOK);
+ } else {
+ sc->sc_inbuf = NULL;
+ for (i = 0; i < MAXFRAMES; i++)
+ sc->sc_frames[i].buf = NULL;
+ }
+ }
+}
+
void
irt_frame(struct irframet_softc *sc, u_char *tbuf, u_int len)
{
@@ -529,7 +577,6 @@
{
struct tty *tp = h;
struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
- static bool again;
DPRINTF(("%s: tp=%p\n", __func__, tp));
@@ -541,15 +588,6 @@
sc->sc_framei = 0;
sc->sc_frameo = 0;
- /* XXX */
- if (!again) {
- again = true;
- callout_init(&sc->sc_timeout, 0);
- mutex_init(&sc->sc_wr_lk, MUTEX_DEFAULT, IPL_NONE);
- selinit(&sc->sc_rsel);
- selinit(&sc->sc_wsel);
- }
-
return (0);
}
@@ -559,22 +597,17 @@
{
struct tty *tp = h;
struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
- int i, s;
+ int s;
DPRINTF(("%s: tp=%p\n", __func__, tp));
+ /* line discipline was closed */
+ if (sc == NULL)
+ return (0);
+
callout_stop(&sc->sc_timeout);
s = splir();
- if (sc->sc_inbuf != NULL) {
- free(sc->sc_inbuf, M_DEVBUF);
- sc->sc_inbuf = NULL;
- }
- for (i = 0; i < MAXFRAMES; i++) {
- if (sc->sc_frames[i].buf != NULL) {
- free(sc->sc_frames[i].buf, M_DEVBUF);
- sc->sc_frames[i].buf = NULL;
- }
- }
+ irt_buffer(sc, 0);
splx(s);
return (0);
@@ -830,7 +863,6 @@
{
struct tty *tp = h;
struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
- int i;
DPRINTF(("%s: tp=%p speed=%d ebofs=%d maxsize=%d\n",
__func__, tp, p->speed, p->ebofs, p->maxsize));
@@ -845,27 +877,7 @@
/* Max size checked in irframe.c */
sc->sc_params.ebofs = p->ebofs;
- /* Max size checked in irframe.c */
- if (sc->sc_params.maxsize != p->maxsize) {
- sc->sc_params.maxsize = p->maxsize;
- if (sc->sc_inbuf != NULL)
- free(sc->sc_inbuf, M_DEVBUF);
- for (i = 0; i < MAXFRAMES; i++)
- if (sc->sc_frames[i].buf != NULL)
- free(sc->sc_frames[i].buf, M_DEVBUF);
- if (sc->sc_params.maxsize != 0) {
- sc->sc_inbuf = malloc(sc->sc_params.maxsize+2,
- M_DEVBUF, M_WAITOK);
- for (i = 0; i < MAXFRAMES; i++)
- sc->sc_frames[i].buf =
- malloc(sc->sc_params.maxsize,
- M_DEVBUF, M_WAITOK);
- } else {
- sc->sc_inbuf = NULL;
- for (i = 0; i < MAXFRAMES; i++)
- sc->sc_frames[i].buf = NULL;
- }
- }
+ irt_buffer(sc, p->maxsize);
sc->sc_framestate = FRAME_OUTSIDE;
return (0);