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
This commit is contained in:
pgoyette 2017-01-06 09:32:08 +00:00
parent 88aac29387
commit d020b0ddde
4 changed files with 47 additions and 18 deletions

View File

@ -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);

View File

@ -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,12 +358,31 @@ 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;
sc->sc_inbuf = NULL;
}
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)
{
@ -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;

View File

@ -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;
}

View File

@ -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 */