git: 858504a1d89f - stable/14 - sound: Call chn_kill() in chn_init() failure

From: Christos Margiolis <christos_at_FreeBSD.org>
Date: Tue, 04 Mar 2025 15:47:09 UTC
The branch stable/14 has been updated by christos:

URL: https://cgit.FreeBSD.org/src/commit/?id=858504a1d89f3e1cb89f6126b3b59e80716fb3df

commit 858504a1d89f3e1cb89f6126b3b59e80716fb3df
Author:     Christos Margiolis <christos@FreeBSD.org>
AuthorDate: 2025-02-25 11:44:37 +0000
Commit:     Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2025-03-04 15:46:06 +0000

    sound: Call chn_kill() in chn_init() failure
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D48966
    
    (cherry picked from commit bc7e65e950154572d8c9a04dc033075bf37aae40)
---
 sys/dev/sound/pcm/channel.c | 50 ++++++++++++++-------------------------------
 1 file changed, 15 insertions(+), 35 deletions(-)

diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
index c3ee50d51c4b..0a0059411399 100644
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -1179,11 +1179,19 @@ chn_init(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls,
 
 	switch (dir) {
 	case PCMDIR_PLAY:
+		d->playcount++;
+		/* FALLTHROUGH */
 	case PCMDIR_PLAY_VIRTUAL:
+		if (dir == PCMDIR_PLAY_VIRTUAL)
+			d->pvchancount++;
 		direction = PCMDIR_PLAY;
 		break;
 	case PCMDIR_REC:
+		d->reccount++;
+		/* FALLTHROUGH */
 	case PCMDIR_REC_VIRTUAL:
+		if (dir == PCMDIR_REC_VIRTUAL)
+			d->rvchancount++;
 		direction = PCMDIR_REC;
 		break;
 	default:
@@ -1292,40 +1300,10 @@ chn_init(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls,
 	if ((c->flags & CHN_F_VIRTUAL) == 0)
 		CHN_INSERT_SORT_ASCEND(d, c, channels.pcm.primary);
 
-	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);
@@ -1368,12 +1346,14 @@ chn_kill(struct pcm_channel *c)
 		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);