Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150431907
D43545.id133873.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D43545.id133873.diff
View Options
diff --git a/share/man/man4/snd_uaudio.4 b/share/man/man4/snd_uaudio.4
--- a/share/man/man4/snd_uaudio.4
+++ b/share/man/man4/snd_uaudio.4
@@ -86,16 +86,6 @@
by
.An Hiten Pandya Aq Mt hmp@FreeBSD.org .
.Sh BUGS
-The
-.Tn PCM
-framework in
-.Fx
-only supports synchronous device detach.
-That means all mixer and DSP character devices belonging to a given
-USB audio device must be closed when receiving an error on a DSP read,
-a DSP write or a DSP IOCTL request.
-Else the USB audio driver will wait for this to happen, preventing
-enumeration of new devices on the parenting USB controller.
.Pp
Some USB audio devices might refuse to work properly unless the sample
rate is configured the same for both recording and playback, even if
diff --git a/sys/dev/sound/clone.c b/sys/dev/sound/clone.c
--- a/sys/dev/sound/clone.c
+++ b/sys/dev/sound/clone.c
@@ -37,10 +37,7 @@
#include "opt_snd.h"
#endif
-#if defined(SND_DIAGNOSTIC) || defined(SND_DEBUG)
#include <dev/sound/pcm/sound.h>
-#endif
-
#include <dev/sound/clone.h>
/*
@@ -354,23 +351,36 @@
return (pruned);
}
+static void
+snd_clone_gone_cb(void *arg)
+{
+ struct snd_clone *c;
+ struct snd_clone_entry *ce = arg;
+
+ SND_CLONE_ASSERT(ce != NULL, ("NULL snd_clone_entry"));
+ c = ce->parent;
+ SND_CLONE_ASSERT(c != NULL, ("NULL parent"));
+
+ TAILQ_REMOVE(&c->head, ce, link);
+ free(ce, M_DEVBUF);
+ c->refcount--;
+ c->size--;
+
+ /* All clones have been unref'd, free the manager as well. */
+ if (c->refcount == 0)
+ free(c, M_DEVBUF);
+}
+
void
snd_clone_destroy(struct snd_clone *c)
{
- struct snd_clone_entry *ce, *tmp;
+ struct snd_clone_entry *ce;
SND_CLONE_ASSERT(c != NULL, ("NULL snd_clone"));
- ce = TAILQ_FIRST(&c->head);
- while (ce != NULL) {
- tmp = TAILQ_NEXT(ce, link);
- if (ce->devt != NULL)
- destroy_dev(ce->devt);
- free(ce, M_DEVBUF);
- ce = tmp;
+ TAILQ_FOREACH(ce, &c->head, link) {
+ destroy_dev_sched_cb(ce->devt, snd_clone_gone_cb, ce);
}
-
- free(c, M_DEVBUF);
}
/*
diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c
--- a/sys/dev/sound/pcm/mixer.c
+++ b/sys/dev/sound/pcm/mixer.c
@@ -799,6 +799,20 @@
return (0);
}
+static void
+mixer_gone_cb(void *arg)
+{
+ struct snd_mixer *m = arg;
+
+ KASSERT(m != NULL, ("NULL snd_mixer"));
+ KASSERT(m->type == MIXER_TYPE_PRIMARY,
+ ("%s(): illegal mixer type=%d", __func__, m->type));
+
+ snd_mtxfree(m->lock);
+ kobj_delete((kobj_t)m, M_MIXER);
+ --mixer_count;
+}
+
int
mixer_uninit(device_t dev)
{
@@ -817,20 +831,7 @@
KASSERT(m->type == MIXER_TYPE_PRIMARY,
("%s(): illegal mixer type=%d", __func__, m->type));
- snd_mtxlock(m->lock);
-
- if (m->busy) {
- snd_mtxunlock(m->lock);
- return EBUSY;
- }
-
- /* destroy dev can sleep --hps */
-
- snd_mtxunlock(m->lock);
-
pdev->si_drv1 = NULL;
- destroy_dev(pdev);
-
snd_mtxlock(m->lock);
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
@@ -844,13 +845,9 @@
MIXER_UNINIT(m);
- snd_mtxfree(m->lock);
- kobj_delete((kobj_t)m, M_MIXER);
-
+ destroy_dev_sched_cb(pdev, mixer_gone_cb, m);
d->mixer_dev = NULL;
- --mixer_count;
-
return 0;
}
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -1176,39 +1176,28 @@
CHN_FOREACH(ch, d, channels.pcm) {
CHN_LOCK(ch);
- if (ch->refcount > 0) {
- device_printf(dev,
- "unregister: channel %s busy (pid %d)\n",
- ch->name, ch->pid);
- CHN_UNLOCK(ch);
- PCM_RELEASE_QUICK(d);
- return (EBUSY);
+ if (ch->flags & CHN_F_SLEEPING) {
+ /*
+ * We are detaching, so do not wait for the timeout in
+ * chn_read()/chn_write(). Wake up the thread and kill
+ * the channel immediately.
+ */
+ CHN_BROADCAST(&ch->intr_cv);
+ ch->flags |= CHN_F_DEAD;
}
+ chn_abort(ch);
CHN_UNLOCK(ch);
}
if (d->clones != NULL) {
- if (snd_clone_busy(d->clones) != 0) {
- device_printf(dev, "unregister: clone busy\n");
- PCM_RELEASE_QUICK(d);
- return (EBUSY);
- } else {
- PCM_LOCK(d);
- (void)snd_clone_disable(d->clones);
- PCM_UNLOCK(d);
- }
- }
-
- if (mixer_uninit(dev) == EBUSY) {
- device_printf(dev, "unregister: mixer busy\n");
PCM_LOCK(d);
- if (d->clones != NULL)
- (void)snd_clone_enable(d->clones);
- PCM_RELEASE(d);
+ (void)snd_clone_disable(d->clones);
PCM_UNLOCK(d);
- return (EBUSY);
+ snd_clone_destroy(d->clones);
}
+ (void)mixer_uninit(dev);
+
/* remove /dev/sndstat entry first */
sndstat_unregister(dev);
@@ -1217,15 +1206,6 @@
d->flags &= ~SD_F_REGISTERED;
PCM_UNLOCK(d);
- /*
- * No lock being held, so this thing can be flushed without
- * stucking into devdrn oblivion.
- */
- if (d->clones != NULL) {
- snd_clone_destroy(d->clones);
- d->clones = NULL;
- }
-
if (d->play_sysctl_tree != NULL) {
sysctl_ctx_free(&d->play_sysctl_ctx);
d->play_sysctl_tree = NULL;
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -1250,20 +1250,12 @@
unsigned i = uaudio_get_child_index_by_dev(sc, dev);
int error = 0;
-repeat:
- if (sc->sc_child[i].pcm_registered) {
+ if (sc->sc_child[i].pcm_registered)
error = pcm_unregister(dev);
- } else {
- if (sc->sc_child[i].mixer_init)
- error = mixer_uninit(dev);
- }
+ else if (sc->sc_child[i].mixer_init)
+ error = mixer_uninit(dev);
- if (error) {
- device_printf(dev, "Waiting for sound application to exit!\n");
- usb_pause_mtx(NULL, 2 * hz);
- goto repeat; /* try again */
- }
- return (0); /* success */
+ return (error);
}
static int
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Apr 2, 4:50 AM (9 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30704483
Default Alt Text
D43545.id133873.diff (5 KB)
Attached To
Mode
D43545: sound: Implement asynchronous device detach
Attached
Detach File
Event Timeline
Log In to Comment