diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -2086,7 +2086,15 @@ return; found: d = devclass_get_softc(pcm_devclass, snd_unit); - if (!PCM_REGISTERED(d)) + /* + * If we only have a single soundcard attached and we detach it right + * before entering dsp_clone(), there is a chance pcm_unregister() will + * have returned already, meaning it will have set snd_unit to -1, and + * thus devclass_get_softc() will return NULL here. + */ + if (d == NULL) + return; + if (!PCM_REGISTERED(d) || d->dsp_dev == NULL) return; *dev = d->dsp_dev; dev_ref(*dev); 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 @@ -1378,6 +1378,9 @@ return; if (strcmp(name, "mixer") == 0) { d = devclass_get_softc(pcm_devclass, snd_unit); + /* See related comment in dsp_clone(). */ + if (d == NULL) + return; if (PCM_REGISTERED(d) && d->mixer_dev != NULL) { *dev = d->mixer_dev; dev_ref(*dev); 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 @@ -1013,10 +1013,6 @@ CHN_UNLOCK(ch); } - dsp_destroy_dev(dev); - - (void)mixer_uninit(dev); - /* remove /dev/sndstat entry first */ sndstat_unregister(dev); @@ -1034,6 +1030,9 @@ d->rec_sysctl_tree = NULL; } + dsp_destroy_dev(dev); + (void)mixer_uninit(dev); + while (!CHN_EMPTY(d, channels.pcm)) pcm_killchan(dev);