summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorpgoyette <pgoyette@NetBSD.org>2017-01-06 09:32:08 +0000
committerpgoyette <pgoyette@NetBSD.org>2017-01-06 09:32:08 +0000
commitbccce848e50e23364a2bd85bcf5c4e447ac1fc27 (patch)
tree32ff9dd9f043b0b8faa4150f1109c44147a35d8d /sys/dev
parent9dda8d65f690864a32d372f5c13a0ef115661ad1 (diff)
Implement a common spkr_detach() function and call it from the
attachment-specific detach functions. Returns EBUSY if the device instance is busy, based on whether or not a sc->sc_inbuf is allocated. The buffer is malloc()d at spkropen time, and is free()d in spkrclose(). Now we can actually implement the MODULE_CMD_FINI command and unload the driver at will. Addresses my PR kern/51785
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/isa/spkr_pcppi.c8
-rw-r--r--sys/dev/spkr.c44
-rw-r--r--sys/dev/spkr_audio.c9
-rw-r--r--sys/dev/spkrvar.h4
4 files changed, 47 insertions, 18 deletions
diff --git a/sys/dev/isa/spkr_pcppi.c b/sys/dev/isa/spkr_pcppi.c
index 27322f351bd..39e3c3ed8b3 100644
--- a/sys/dev/isa/spkr_pcppi.c
+++ b/sys/dev/isa/spkr_pcppi.c
@@ -1,4 +1,4 @@
-/* $NetBSD: spkr_pcppi.c,v 1.8 2016/12/15 06:48:14 pgoyette Exp $ */
+/* $NetBSD: spkr_pcppi.c,v 1.9 2017/01/06 09:32:08 pgoyette Exp $ */
/*
* Copyright (c) 1990 Eric S. Raymond (esr@snark.thyrsus.com)
@@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spkr_pcppi.c,v 1.8 2016/12/15 06:48:14 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spkr_pcppi.c,v 1.9 2017/01/06 09:32:08 pgoyette Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -129,6 +129,10 @@ static int
spkr_pcppi_detach(device_t self, int flags)
{
struct spkr_pcppi_softc *sc = device_private(self);
+ int error;
+
+ if ((error = spkr_detach(self, flags)) != 0)
+ return error;
sc->sc_pcppicookie = NULL;
pmf_device_deregister(self);
diff --git a/sys/dev/spkr.c b/sys/dev/spkr.c
index 5a1b7dc647c..bed93eaea0e 100644
--- a/sys/dev/spkr.c
+++ b/sys/dev/spkr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: spkr.c,v 1.5 2016/12/15 06:55:55 pgoyette Exp $ */
+/* $NetBSD: spkr.c,v 1.6 2017/01/06 09:32:08 pgoyette Exp $ */
/*
* Copyright (c) 1990 Eric S. Raymond (esr@snark.thyrsus.com)
@@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spkr.c,v 1.5 2016/12/15 06:55:55 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spkr.c,v 1.6 2017/01/06 09:32:08 pgoyette Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -358,6 +358,9 @@ spkr_attach(device_t self, void (*tone)(device_t, u_int, u_int),
{
struct spkr_softc *sc = device_private(self);
+#ifdef SPKRDEBUG
+ aprint_debug("%s: entering for unit %d\n", __func__, self->dv_unit);
+#endif /* SPKRDEBUG */
sc->sc_dev = self;
sc->sc_tone = tone;
sc->sc_rest = rest;
@@ -365,6 +368,22 @@ spkr_attach(device_t self, void (*tone)(device_t, u_int, u_int),
}
int
+spkr_detach(device_t self, int flags)
+{
+ struct spkr_softc *sc = device_private(self);
+
+#ifdef SPKRDEBUG
+ aprint_debug("%s: entering for unit %d\n", __func__, self->dv_unit);
+#endif /* SPKRDEBUG */
+ if (sc == NULL)
+ return ENXIO;
+ if (sc->sc_inbuf != NULL)
+ return EBUSY;
+
+ return 0;
+}
+
+int
spkropen(dev_t dev, int flags, int mode, struct lwp *l)
{
#ifdef SPKRDEBUG
@@ -374,7 +393,7 @@ spkropen(dev_t dev, int flags, int mode, struct lwp *l)
if (sc == NULL)
return ENXIO;
- if (sc->sc_inbuf)
+ if (sc->sc_inbuf != NULL)
return EBUSY;
sc->sc_inbuf = malloc(DEV_BSIZE, M_DEVBUF, M_WAITOK);
@@ -393,7 +412,7 @@ spkrwrite(dev_t dev, struct uio *uio, int flags)
if (sc == NULL)
return ENXIO;
- if (!sc->sc_inbuf)
+ if (sc->sc_inbuf == NULL)
return EINVAL;
size_t n = min(DEV_BSIZE, uio->uio_resid);
@@ -414,7 +433,7 @@ spkrclose(dev_t dev, int flags, int mode, struct lwp *l)
if (sc == NULL)
return ENXIO;
- if (!sc->sc_inbuf)
+ if (sc->sc_inbuf == NULL)
return EINVAL;
sc->sc_tone(sc->sc_dev, 0, 0);
@@ -448,7 +467,7 @@ spkrioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
if (sc == NULL)
return ENXIO;
- if (!sc->sc_inbuf)
+ if (sc->sc_inbuf == NULL)
return EINVAL;
switch (cmd) {
@@ -493,20 +512,21 @@ spkr_modcmd(modcmd_t cmd, void *arg)
break;
error = config_init_component(cfdriver_ioconf_spkr,
- cfattach_ioconf_spkr, cfdata_ioconf_spkr);
+ cfattach_ioconf_spkr, cfdata_ioconf_spkr);
if (error) {
devsw_detach(NULL, &spkr_cdevsw);
}
break;
case MODULE_CMD_FINI:
- return EBUSY;
-#ifdef notyet
- error = config_fini_component(cfdriver_ioconf_spkr,
- cfattach_ioconf_spkr, cfdata_ioconf_spkr);
devsw_detach(NULL, &spkr_cdevsw);
+ error = config_fini_component(cfdriver_ioconf_spkr,
+ cfattach_ioconf_spkr, cfdata_ioconf_spkr);
+ if (error)
+ devsw_attach(spkr_cd.cd_name, NULL, &bmajor,
+ &spkr_cdevsw, &cmajor);
break;
-#endif
+
default:
error = ENOTTY;
break;
diff --git a/sys/dev/spkr_audio.c b/sys/dev/spkr_audio.c
index 58b7c70ff7c..3266360bbc6 100644
--- a/sys/dev/spkr_audio.c
+++ b/sys/dev/spkr_audio.c
@@ -1,4 +1,4 @@
-/* $NetBSD: spkr_audio.c,v 1.2 2016/12/15 06:48:14 pgoyette Exp $ */
+/* $NetBSD: spkr_audio.c,v 1.3 2017/01/06 09:32:08 pgoyette Exp $ */
/*-
* Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spkr_audio.c,v 1.2 2016/12/15 06:48:14 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spkr_audio.c,v 1.3 2017/01/06 09:32:08 pgoyette Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -148,6 +148,10 @@ static int
spkr_audio_detach(device_t self, int flags)
{
struct spkr_audio_softc *sc = device_private(self);
+ int error;
+
+ if ((error = spkr_detach(self, flags)) != 0)
+ return error;
pmf_device_deregister(self);
@@ -161,7 +165,6 @@ spkr_audio_detach(device_t self, int flags)
cv_destroy(&sc->sc_bellcv);
mutex_destroy(&sc->sc_bellock);
-
return 0;
}
diff --git a/sys/dev/spkrvar.h b/sys/dev/spkrvar.h
index ae977a47772..7a20bab0cdf 100644
--- a/sys/dev/spkrvar.h
+++ b/sys/dev/spkrvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: spkrvar.h,v 1.5 2016/12/15 06:48:14 pgoyette Exp $ */
+/* $NetBSD: spkrvar.h,v 1.6 2017/01/06 09:32:08 pgoyette Exp $ */
#ifndef _SYS_DEV_SPKRVAR_H
#define _SYS_DEV_SPKRVAR_H
@@ -23,4 +23,6 @@ struct spkr_softc {
void spkr_attach(device_t,
void (*)(device_t, u_int, u_int), void (*)(device_t, int));
+int spkr_detach(device_t, int);
+
#endif /* _SYS_DEV_SPKRVAR_H */