diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -1185,14 +1185,21 @@ PCM_LOCKASSERT(d); switch (dir) { - case PCMDIR_PLAY: + case PCMDIR_PLAY: /* FALLTHROUGH */ + d->playcount++; case PCMDIR_PLAY_VIRTUAL: + /* Do not increase vchancount in case of fallthrough. */ + if (dir == PCMDIR_PLAY_VIRTUAL) + d->pvchancount++; direction = PCMDIR_PLAY; vchanrate = &d->pvchanrate; vchanformat = &d->pvchanformat; break; - case PCMDIR_REC: + case PCMDIR_REC: /* FALLTHROUGH */ + d->reccount++; case PCMDIR_REC_VIRTUAL: + if (dir == PCMDIR_REC_VIRTUAL) + d->rvchancount++; direction = PCMDIR_REC; vchanrate = &d->rvchanrate; vchanformat = &d->rvchanformat; @@ -1307,40 +1314,10 @@ *vchanformat = sndbuf_getfmt(c->bufsoft); } - switch (c->type) { - case PCMDIR_PLAY: - d->playcount++; - break; - case PCMDIR_PLAY_VIRTUAL: - d->pvchancount++; - break; - case PCMDIR_REC: - d->reccount++; - break; - case PCMDIR_REC_VIRTUAL: - d->rvchancount++; - break; - default: - __assert_unreachable(); - } - return (c); fail: - free_unr(chn_getunr(d, c->type), c->unit); - feeder_remove(c); - if (c->devinfo && CHANNEL_FREE(c->methods, c->devinfo)) - sndbuf_free(b); - if (bs) - sndbuf_destroy(bs); - if (b) - sndbuf_destroy(b); - CHN_LOCK(c); - chn_lockdestroy(c); - - kobj_delete(c->methods, M_DEVBUF); - free(c, M_DEVBUF); - + chn_kill(c); PCM_LOCK(d); return (NULL); @@ -1383,12 +1360,14 @@ chn_trigger(c, PCMTRIG_ABORT); CHN_UNLOCK(c); } - free_unr(chn_getunr(c->parentsnddev, c->type), c->unit); + free_unr(chn_getunr(d, c->type), c->unit); feeder_remove(c); - if (CHANNEL_FREE(c->methods, c->devinfo)) + if (c->devinfo && CHANNEL_FREE(c->methods, c->devinfo)) sndbuf_free(b); - sndbuf_destroy(bs); - sndbuf_destroy(b); + if (bs) + sndbuf_destroy(bs); + if (b) + sndbuf_destroy(b); CHN_LOCK(c); c->flags |= CHN_F_DEAD; chn_lockdestroy(c);