Module Name:    src
Committed By:   nakayama
Date:           Sun Sep 23 21:18:30 UTC 2018

Modified Files:
        src/sys/dev/pad: pad.c

Log Message:
pad(4) mixer has only 1 channel, so return EINVAL in the case other than 1.

This fixes the following strange output of mixerctl(1):

        outputs.master=255,0
        inputs.dac=255,0


To generate a diff of this commit:
cvs rdiff -u -r1.53 -r1.54 src/sys/dev/pad/pad.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/pad/pad.c
diff -u src/sys/dev/pad/pad.c:1.53 src/sys/dev/pad/pad.c:1.54
--- src/sys/dev/pad/pad.c:1.53	Mon Sep  3 16:29:32 2018
+++ src/sys/dev/pad/pad.c	Sun Sep 23 21:18:30 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: pad.c,v 1.53 2018/09/03 16:29:32 riastradh Exp $ */
+/* $NetBSD: pad.c,v 1.54 2018/09/23 21:18:30 nakayama Exp $ */
 
 /*-
  * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca>
@@ -27,23 +27,18 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.53 2018/09/03 16:29:32 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.54 2018/09/23 21:18:30 nakayama Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/conf.h>
 #include <sys/buf.h>
-#include <sys/file.h>
-#include <sys/filedesc.h>
-#include <sys/vnode.h>
-#include <sys/kauth.h>
 #include <sys/kmem.h>
 #include <sys/kernel.h>
 #include <sys/device.h>
 #include <sys/proc.h>
 #include <sys/condvar.h>
 #include <sys/select.h>
-#include <sys/stat.h>
 #include <sys/audioio.h>
 #include <sys/vnode.h>
 #include <sys/module.h>
@@ -57,17 +52,9 @@ __KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.53
 
 #include <dev/pad/padvar.h>
 
-#define MAXDEVS		128
-#define PADCLONER	254
 #define PADUNIT(x)	minor(x)
 
-#define PADFREQ		44100
-#define PADCHAN		2
-#define PADPREC		16
-#define PADENC		AUDIO_ENCODING_SLINEAR_LE
-
 extern struct cfdriver pad_cd;
-kmutex_t padconfig;
 
 typedef struct pad_block {
 	uint8_t		*pb_ptr;
@@ -112,18 +99,7 @@ static stream_filter_t *pad_swvol_filter
     const audio_params_t *, const audio_params_t *);
 static void	pad_swvol_dtor(stream_filter_t *);
 
-static int pad_close(struct pad_softc *);
-static int pad_read(struct pad_softc *, off_t *, struct uio *, kauth_cred_t, int);
-
-static int fops_pad_close(struct file *);
-static int fops_pad_read(struct file *, off_t *, struct uio *, kauth_cred_t, int);
-static int pad_write(struct file *, off_t *, struct uio *, kauth_cred_t, int);
-static int pad_ioctl(struct file *, u_long, void *);
-static int pad_kqfilter(struct file *, struct knote *);
-static int pad_poll(struct file *, int);
-static int pad_stat(struct file *, struct stat *);
-static int pad_mmap(struct file *, off_t *, size_t, int, int *, int *,
-			   struct uvm_object **, int *);
+static bool	pad_is_attached;	/* Do we have an audio* child? */
 
 static const struct audio_hw_if pad_hw_if = {
 	.open = pad_audio_open,
@@ -144,8 +120,8 @@ static const struct audio_hw_if pad_hw_i
 
 #define PAD_NFORMATS	1
 static const struct audio_format pad_formats[PAD_NFORMATS] = {
-	{ NULL, AUMODE_PLAY|AUMODE_RECORD, PADENC, PADPREC, PADPREC,
-	  PADCHAN, AUFMT_STEREO, 1, { PADFREQ } },
+	{ NULL, AUMODE_PLAY|AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
+	  2, AUFMT_STEREO, 1, { 44100 } },
 };
 
 extern void	padattach(int);
@@ -154,13 +130,13 @@ static int	pad_add_block(pad_softc_t *, 
 static int	pad_get_block(pad_softc_t *, pad_block_t *, int);
 
 dev_type_open(pad_open);
-dev_type_close(cdev_pad_close);
-dev_type_read(cdev_pad_read);
+dev_type_close(pad_close);
+dev_type_read(pad_read);
 
 const struct cdevsw pad_cdevsw = {
 	.d_open = pad_open,
-	.d_close = cdev_pad_close,
-	.d_read = cdev_pad_read,
+	.d_close = pad_close,
+	.d_read = pad_read,
 	.d_write = nowrite,
 	.d_ioctl = noioctl,
 	.d_stop = nostop,
@@ -172,36 +148,34 @@ const struct cdevsw pad_cdevsw = {
 	.d_flag = D_OTHER | D_MPSAFE,
 };
 
-const struct fileops pad_fileops = {
-	.fo_name = "pad",
-	.fo_read = fops_pad_read,
-	.fo_write = pad_write,
-	.fo_ioctl = pad_ioctl,
-	.fo_fcntl = fnullop_fcntl,
-	.fo_stat = pad_stat,
-	.fo_poll = pad_poll,
-	.fo_close = fops_pad_close,
-	.fo_mmap = pad_mmap,
-	.fo_kqfilter = pad_kqfilter,
-	.fo_restart = fnullop_restart
-};
-
 CFATTACH_DECL2_NEW(pad, sizeof(pad_softc_t), pad_match, pad_attach, pad_detach,
     NULL, NULL, pad_childdet);
 
 void
 padattach(int n)
 {
-	int error;
+	int i, err;
+	cfdata_t cf;
 
-	error = config_cfattach_attach(pad_cd.cd_name, &pad_ca);
-	if (error) {
+	aprint_debug("pad: requested %d units\n", n);
+
+	err = config_cfattach_attach(pad_cd.cd_name, &pad_ca);
+	if (err) {
 		aprint_error("%s: couldn't register cfattach: %d\n",
-		    pad_cd.cd_name, error);
+		    pad_cd.cd_name, err);
 		config_cfdriver_detach(&pad_cd);
 		return;
 	}
-	mutex_init(&padconfig, MUTEX_DEFAULT, IPL_NONE);
+
+	for (i = 0; i < n; i++) {
+		cf = kmem_alloc(sizeof(struct cfdata), KM_SLEEP);
+		cf->cf_name = pad_cd.cd_name;
+		cf->cf_atname = pad_cd.cd_name;
+		cf->cf_unit = i;
+		cf->cf_fstate = FSTATE_STAR;
+
+		(void)config_attach_pseudo(cf);
+	}
 
 	return;
 }
@@ -244,7 +218,7 @@ pad_get_block(pad_softc_t *sc, pad_block
 	KASSERT(mutex_owned(&sc->sc_lock));
 	KASSERT(pb != NULL);
 
-	if (sc->sc_buflen < (uint)blksize)
+	if (sc->sc_buflen < blksize)
 		return ERESTART;
 
 	pb->pb_ptr = (sc->sc_audiobuf + sc->sc_rpos);
@@ -279,149 +253,51 @@ pad_childdet(device_t self, device_t chi
 static void
 pad_attach(device_t parent, device_t self, void *opaque)
 {
-	aprint_normal_dev(self, "outputs: 44100Hz, 16-bit, stereo\n");
-
-	return;
-}
-
-static int
-pad_detach(device_t self, int flags)
-{
-	pad_softc_t *sc;
-	int cmaj, mn;
-
-	sc = device_private(self);
-	cmaj = cdevsw_lookup_major(&pad_cdevsw);
-	mn = device_unit(sc->sc_dev);
-	if (!sc->sc_dying)
-		vdevgone(cmaj, mn, mn, VCHR);
-
-	return 0;
-}
-
-int
-pad_open(dev_t dev, int flags, int fmt, struct lwp *l)
-{
-	pad_softc_t *sc;
-	struct file *fp;
-	device_t paddev;
-	cfdata_t cf;
-	int error, fd, i;
-
-	error = 0;
-
-	mutex_enter(&padconfig);
-	if (PADUNIT(dev) == PADCLONER) {
-		for (i = 0; i < MAXDEVS; i++) {
-			if (device_lookup(&pad_cd, i) == NULL)
-				break;
-		}
-		if (i == MAXDEVS)
-			goto bad;
-	} else {
-		if (PADUNIT(dev) >= MAXDEVS)
-			goto bad;
-		i = PADUNIT(dev);
-	}
-
-	cf = kmem_alloc(sizeof(struct cfdata), KM_SLEEP);
-	cf->cf_name = pad_cd.cd_name;
-	cf->cf_atname = pad_cd.cd_name;
-	cf->cf_unit = i;
-	cf->cf_fstate = FSTATE_STAR;
-
-	bool existing = false;
-	paddev = device_lookup(&pad_cd, minor(dev));
-	if (paddev == NULL)
-		paddev = config_attach_pseudo(cf);
-	else
-		existing = true;
-	if (paddev == NULL)
-		goto bad;
-
-	sc = device_private(paddev);
-	if (sc == NULL)
-		goto bad;
-
-	if (sc->sc_open == 1) {
-		mutex_exit(&padconfig);
-		return EBUSY;
-	}
-
-	sc->sc_dev = paddev;
-	sc->sc_dying = false;
+	pad_softc_t *sc = device_private(self);
 
-	if (PADUNIT(dev) == PADCLONER) {
-		error = fd_allocfile(&fp, &fd);
-		if (error) {
-			if (existing == false)
-				config_detach(sc->sc_dev, 0);
-			mutex_exit(&padconfig);
-			return error;
-		}
-	}
+	aprint_normal_dev(self, "outputs: 44100Hz, 16-bit, stereo\n");
 
+	sc->sc_dev = self;
+	sc->sc_open = 0;
 	if (auconv_create_encodings(pad_formats, PAD_NFORMATS,
 	    &sc->sc_encodings) != 0) {
-		aprint_error_dev(sc->sc_dev, "couldn't create encodings\n");
-		if (existing == false)
-			config_detach(sc->sc_dev, 0);
-		mutex_exit(&padconfig);
-		return EINVAL;
+		aprint_error_dev(self, "couldn't create encodings\n");
+		return;
 	}
 
-	cv_init(&sc->sc_condvar, device_xname(sc->sc_dev));
+	cv_init(&sc->sc_condvar, device_xname(self));
 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_NONE);
 
 	sc->sc_swvol = 255;
 	sc->sc_buflen = 0;
 	sc->sc_rpos = sc->sc_wpos = 0;
-	sc->sc_audiodev = audio_attach_mi(&pad_hw_if, sc, sc->sc_dev);
+	sc->sc_audiodev = (void *)audio_attach_mi(&pad_hw_if, sc, sc->sc_dev);
 
-	if (!pmf_device_register(sc->sc_dev, NULL, NULL))
-		aprint_error_dev(sc->sc_dev, "couldn't establish power handler\n");
+	if (!pmf_device_register(self, NULL, NULL))
+		aprint_error_dev(self, "couldn't establish power handler\n");
 
-	if (PADUNIT(dev) == PADCLONER) {
-		error = fd_clone(fp, fd, flags, &pad_fileops, sc);
-		KASSERT(error == EMOVEFD);
-	}	
-	sc->sc_open = 1;
-	mutex_exit(&padconfig);
-
-	return error;
-bad:
-	mutex_exit(&padconfig);
-	return ENXIO;
+	pad_is_attached = true;
+	return;
 }
 
 static int
-pad_close(struct pad_softc *sc)
+pad_detach(device_t self, int flags)
 {
-	int rc;
+	pad_softc_t *sc = device_private(self);
+	int cmaj, mn, rc;
 
-	if (sc == NULL)
+	if (!pad_is_attached)
 		return ENXIO;
 
-	mutex_enter(&padconfig);
-	config_deactivate(sc->sc_audiodev);
-	
-	/* Start draining existing accessors of the device. */
-	if ((rc = config_detach_children(sc->sc_dev,
-	    DETACH_SHUTDOWN|DETACH_FORCE)) != 0) {
-		mutex_exit(&padconfig);
-		return rc;
-	}
-
-	mutex_enter(&sc->sc_lock);
-	sc->sc_dying = true;
-	cv_broadcast(&sc->sc_condvar);
-	mutex_exit(&sc->sc_lock);
+	cmaj = cdevsw_lookup_major(&pad_cdevsw);
+	mn = device_unit(self);
+	vdevgone(cmaj, mn, mn, VCHR);
 
-	KASSERT(sc->sc_open > 0);
-	sc->sc_open = 0;
+	if ((rc = config_detach_children(self, flags)) != 0)
+		return rc;
 
-	pmf_device_deregister(sc->sc_dev);
+	pmf_device_deregister(self);
 
 	mutex_destroy(&sc->sc_lock);
 	mutex_destroy(&sc->sc_intr_lock);
@@ -429,138 +305,64 @@ pad_close(struct pad_softc *sc)
 
 	auconv_delete_encodings(sc->sc_encodings);
 
-	rc = config_detach(sc->sc_dev, 0);
-	mutex_exit(&padconfig);
-
-	return rc;
-}
-
-static int
-fops_pad_close(struct file *fp)
-{
-	pad_softc_t *sc;
-	int error;
-
-	sc = fp->f_pad;
-
-	error = pad_close(sc);
-
-	if (error == 0)
-		fp->f_pad = NULL;
-
-	return error;
+	pad_is_attached = false;
+	return 0;
 }
 
 int
-cdev_pad_close(dev_t dev, int flags, int ifmt, struct lwp *l)
+pad_open(dev_t dev, int flags, int fmt, struct lwp *l)
 {
 	pad_softc_t *sc;
-	sc = device_private(device_lookup(&pad_cd, PADUNIT(dev)));
-
-	return pad_close(sc);
-}
 
-static int
-pad_poll(struct file *fp, int events)
-{
-	return ENODEV;
-}
-
-static int
-pad_kqfilter(struct file *fp, struct knote *kn)
-{
-	struct pad_softc *sc;
-	dev_t dev;
-	
-	sc = fp->f_pad;
+	sc = device_lookup_private(&pad_cd, PADUNIT(dev));
 	if (sc == NULL)
-		return EIO;
-
-	dev = makedev(cdevsw_lookup_major(&pad_cdevsw), device_unit(sc->sc_dev));
-
-	return seltrue_kqfilter(dev, kn);
-}
-
-static int
-pad_ioctl(struct file *fp, u_long cmd, void *data)
-{
-	return ENODEV;
-}
+		return ENXIO;
 
-static int
-pad_stat(struct file *fp, struct stat *st)
-{
-	struct pad_softc *sc;
+	if (atomic_swap_uint(&sc->sc_open, 1) != 0) {
+		return EBUSY;
+	}
 	
-	sc = fp->f_pad;
-	if (sc == NULL)
-		return EIO;
-
-	memset(st, 0, sizeof(*st));
-
-	st->st_dev = makedev(cdevsw_lookup_major(&pad_cdevsw), device_unit(sc->sc_dev));
-
-	st->st_uid = kauth_cred_geteuid(fp->f_cred);
-	st->st_gid = kauth_cred_getegid(fp->f_cred);
-	st->st_mode = S_IFCHR;
-
 	return 0;
 }
 
-static int
-pad_mmap(struct file *fp, off_t *offp, size_t len, int prot, int *flagsp,
-	     int *advicep, struct uvm_object **uobjp, int *maxprotp)
-{
-	return 1;
-}
-
-#define PAD_BYTES_PER_SEC   (PADFREQ * PADPREC / NBBY * PADCHAN)
-#define BYTESTOSLEEP	    (int64_t)(PAD_BLKSIZE)
-#define TIMENEXTREAD	    (int64_t)(BYTESTOSLEEP * 1000000 / PAD_BYTES_PER_SEC)
-
 int
-cdev_pad_read(dev_t dev, struct uio *uio, int ioflag)
+pad_close(dev_t dev, int flags, int fmt, struct lwp *l)
 {
 	pad_softc_t *sc;
-	sc = device_private(device_lookup(&pad_cd, PADUNIT(dev)));
-	if (sc == NULL)
-		return ENXIO;
-
-	return pad_read(sc, NULL, uio, NULL, ioflag);
-}
 
-static int
-fops_pad_read(struct file *fp, off_t *offp, struct uio *uio, kauth_cred_t cred,
-	  int ioflag)
-{
-	pad_softc_t *sc;
-
-	sc = fp->f_pad;
+	sc = device_lookup_private(&pad_cd, PADUNIT(dev));
 	if (sc == NULL)
 		return ENXIO;
 
-	return pad_read(sc, offp, uio, cred, ioflag);
+	KASSERT(sc->sc_open > 0);
+	sc->sc_open = 0;
+
+	return 0;
 }
 
-static int
-pad_read(struct pad_softc *sc, off_t *offp, struct uio *uio, kauth_cred_t cred,
-	  int ioflag)
+#define PAD_BYTES_PER_SEC   (44100 * sizeof(int16_t) * 2)
+#define BYTESTOSLEEP 	    (int64_t)(PAD_BLKSIZE)
+#define TIMENEXTREAD	    (int64_t)(BYTESTOSLEEP * 1000000 / PAD_BYTES_PER_SEC)
+
+int
+pad_read(dev_t dev, struct uio *uio, int flags)
 {
 	struct timeval now;
 	uint64_t nowusec, lastusec;
+	pad_softc_t *sc;
 	pad_block_t pb;
 	void (*intr)(void *);
 	void *intrarg;
 	int err, wait_ticks;
 
+	sc = device_lookup_private(&pad_cd, PADUNIT(dev));
+	if (sc == NULL)
+		return ENXIO;
+
 	err = 0;
 
 	while (uio->uio_resid > 0 && !err) {
 		mutex_enter(&sc->sc_lock);
-		if (sc->sc_dying == true) {
-			mutex_exit(&sc->sc_lock);
-			return EIO;
-		}
 		intr = sc->sc_intr;
 		intrarg = sc->sc_intrarg;
 
@@ -577,19 +379,15 @@ pad_read(struct pad_softc *sc, off_t *of
 			wait_ticks = (hz * sc->sc_remainder) / 1000000;
 			if (wait_ticks > 0) {
 				sc->sc_remainder -= wait_ticks * 1000000 / hz;
-				err = kpause("padwait", TRUE, wait_ticks,
+				kpause("padwait", TRUE, wait_ticks,
 				    &sc->sc_lock);
-				if (err != EWOULDBLOCK) {
-					mutex_exit(&sc->sc_lock);
-					continue;
-				}
 			}
 		}
 
 		if (sc->sc_bytes_count >= BYTESTOSLEEP)
 			sc->sc_bytes_count -= BYTESTOSLEEP;
 
-		err = pad_get_block(sc, &pb, uimin(uio->uio_resid, PAD_BLKSIZE));
+		err = pad_get_block(sc, &pb, min(uio->uio_resid, PAD_BLKSIZE));
 		if (!err) {
 			getmicrotime(&sc->sc_last);
 			sc->sc_bytes_count += pb.pb_len;
@@ -623,13 +421,6 @@ pad_read(struct pad_softc *sc, off_t *of
 }
 
 static int
-pad_write(struct file *fp, off_t *offp, struct uio *uio, kauth_cred_t cred,
-	  int ioflag)
-{
-	return EOPNOTSUPP;
-}
-
-static int
 pad_audio_open(void *opaque, int flags)
 {
 	pad_softc_t *sc;
@@ -781,6 +572,8 @@ pad_set_port(void *opaque, mixer_ctrl_t 
 	switch (mc->dev) {
 	case PAD_OUTPUT_MASTER_VOLUME:
 	case PAD_INPUT_DAC_VOLUME:
+		if (mc->un.value.num_channels != 1)
+			return EINVAL;
 		sc->sc_swvol = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
 		return 0;
 	}
@@ -800,6 +593,8 @@ pad_get_port(void *opaque, mixer_ctrl_t 
 	switch (mc->dev) {
 	case PAD_OUTPUT_MASTER_VOLUME:
 	case PAD_INPUT_DAC_VOLUME:
+		if (mc->un.value.num_channels != 1)
+			return EINVAL;
 		mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_swvol;
 		return 0;
 	}
@@ -932,66 +727,95 @@ MODULE(MODULE_CLASS_DRIVER, pad, "audio"
 
 #ifdef _MODULE
 
-#include "ioconf.c"
-
-devmajor_t cmajor = NODEVMAJOR, bmajor = NODEVMAJOR;
-
-/*
- * We need our own version of cfattach since config(1)'s ioconf does not
- * generate what we need
- */
-
-static struct cfattach *pad_cfattachinit[] = { &pad_ca, NULL };
+static const struct cfiattrdata audiobuscf_iattrdata = {
+	"audiobus", 0, { { NULL, NULL, 0 }, }
+};
+static const struct cfiattrdata * const pad_attrs[] = {
+	&audiobuscf_iattrdata, NULL
+};
 
-static struct cfattachinit pad_cfattach[] = {
-	{ "pad", pad_cfattachinit },
-	{ NULL, NULL }
+CFDRIVER_DECL(pad, DV_DULL, pad_attrs);
+extern struct cfattach pad_ca;
+static int padloc[] = { -1, -1 };
+
+static struct cfdata pad_cfdata[] = {
+	{
+		.cf_name = "pad",
+		.cf_atname = "pad",
+		.cf_unit = 0,
+		.cf_fstate = FSTATE_STAR,
+		.cf_loc = padloc,
+		.cf_flags = 0,
+		.cf_pspec = NULL,
+	},
+	{ NULL, NULL, 0, 0, NULL, 0, NULL }
 };
 #endif
 
 static int
 pad_modcmd(modcmd_t cmd, void *arg)
 {
+#ifdef _MODULE
+	devmajor_t cmajor = NODEVMAJOR, bmajor = NODEVMAJOR;
+#endif
 	int error = 0;
 
 	switch (cmd) {
 	case MODULE_CMD_INIT:
 #ifdef _MODULE
-		pad_cfattach[1] = cfattach_ioconf_pad[0];
-		error = config_init_component(cfdriver_ioconf_pad,
-		    pad_cfattach, cfdata_ioconf_pad);
-		if (error)
+		error = config_cfdriver_attach(&pad_cd);
+		if (error) {
 			break;
+		}
+
+		error = config_cfattach_attach(pad_cd.cd_name, &pad_ca);
+		if (error) {
+			config_cfdriver_detach(&pad_cd);
+			aprint_error("%s: unable to register cfattach\n",
+				pad_cd.cd_name);
+
+			break;
+		}
+
+		error = config_cfdata_attach(pad_cfdata, 1);
+		if (error) {
+			config_cfattach_detach(pad_cd.cd_name, &pad_ca);
+			config_cfdriver_detach(&pad_cd);
+			aprint_error("%s: unable to register cfdata\n",
+				pad_cd.cd_name);
+
+			break;
+		}
 
 		error = devsw_attach(pad_cd.cd_name, NULL, &bmajor,
-			    &pad_cdevsw, &cmajor);
+		    &pad_cdevsw, &cmajor);
 		if (error) {
-			config_fini_component(cfdriver_ioconf_pad,
-			    pad_cfattach, cfdata_ioconf_pad);
+			config_cfdata_detach(pad_cfdata);
+			config_cfattach_detach(pad_cd.cd_name, &pad_ca);
+			config_cfdriver_detach(&pad_cd);
+			aprint_error("%s: unable to register devsw\n",
+				pad_cd.cd_name);
+
 			break;
 		}
-		mutex_init(&padconfig, MUTEX_DEFAULT, IPL_NONE);
 
+		(void)config_attach_pseudo(pad_cfdata);
 #endif
-		break;
 
+		break;
 	case MODULE_CMD_FINI:
 #ifdef _MODULE
-		error = devsw_detach(NULL, &pad_cdevsw);
-		if (error)
-			break;
-
-		error = config_fini_component(cfdriver_ioconf_pad,
-		    pad_cfattach, cfdata_ioconf_pad);
+		error = config_cfdata_detach(pad_cfdata);
 		if (error) {
-			devsw_attach(pad_cd.cd_name, NULL, &bmajor,
-			    &pad_cdevsw, &cmajor);
 			break;
 		}
-		mutex_destroy(&padconfig);
+
+		config_cfattach_detach(pad_cd.cd_name, &pad_ca);
+		config_cfdriver_detach(&pad_cd);
+		devsw_detach(NULL, &pad_cdevsw);
 #endif
-		break;
 
+		break;
 	default:
 		error = ENOTTY;
 	}

Reply via email to