git: 4a556c2277fd - main - Revert "sound: Create a dsp_close() helper function"

From: Christos Margiolis <christos_at_FreeBSD.org>
Date: Fri, 25 Apr 2025 22:03:56 UTC
The branch main has been updated by christos:

URL: https://cgit.FreeBSD.org/src/commit/?id=4a556c2277fd63d83820099d72e953275a03a814

commit 4a556c2277fd63d83820099d72e953275a03a814
Author:     Christos Margiolis <christos@FreeBSD.org>
AuthorDate: 2025-04-25 22:02:08 +0000
Commit:     Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2025-04-25 22:02:08 +0000

    Revert "sound: Create a dsp_close() helper function"
    
    Committed by accident.
    
    This reverts commit 532b45fe103c623855bf1004d5de2fd41e2885e4.
---
 sys/dev/sound/pcm/dsp.c | 129 +++++++++++++++++++++++++++---------------------
 1 file changed, 74 insertions(+), 55 deletions(-)

diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index 0f7cf0d456cf..bc64b50b4510 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -97,7 +97,6 @@ struct cdevsw dsp_cdevsw = {
 
 static eventhandler_tag dsp_ehtag = NULL;
 
-static void dsp_close_chan(struct pcm_channel *c);
 static int dsp_oss_syncgroup(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_syncgroup *group);
 static int dsp_oss_syncstart(int sg_id);
 static int dsp_oss_policy(struct pcm_channel *wrch, struct pcm_channel *rdch, int policy);
@@ -242,19 +241,20 @@ dsp_chn_alloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
 }
 
 static void
-dsp_close_chan(struct pcm_channel *c)
+dsp_close(void *data)
 {
+	struct dsp_cdevpriv *priv = data;
+	struct pcm_channel *rdch, *wrch, *parent;
 	struct snddev_info *d;
-	struct pcm_channel *parent;
 	int sg_ids;
 
-	if (c == NULL)
+	if (priv == NULL)
 		return;
 
-	d = c->parentsnddev;
+	d = priv->sc;
 	/* At this point pcm_unregister() will destroy all channels anyway. */
 	if (!DSP_REGISTERED(d))
-		return;
+		goto skip;
 
 	PCM_GIANT_ENTER(d);
 
@@ -262,63 +262,82 @@ dsp_close_chan(struct pcm_channel *c)
 	PCM_WAIT(d);
 	PCM_ACQUIRE(d);
 
-	CHN_REMOVE(d, c, channels.pcm.opened);
-
-	PCM_UNLOCK(d);
+	rdch = priv->rdch;
+	wrch = priv->wrch;
 
-	/*
-	 * The channel itself need not be locked because:
-	 *   a)  Adding a channel to a syncgroup happens only in dsp_ioctl(),
-	 *       which cannot run concurrently to dsp_close_chan().
-	 *   b)  The syncmember pointer (sm) is protected by the global
-	 *       syncgroup list lock.
-	 *   c)  A channel can't just disappear, invalidating pointers, unless
-	 *       it's closed/dereferenced first.
-	 */
-	PCM_SG_LOCK();
-	sg_ids = chn_syncdestroy(c);
-	PCM_SG_UNLOCK();
-	if (sg_ids != 0)
-		free_unr(pcmsg_unrhdr, sg_ids);
+	if (rdch != NULL)
+		CHN_REMOVE(d, rdch, channels.pcm.opened);
+	if (wrch != NULL)
+		CHN_REMOVE(d, wrch, channels.pcm.opened);
 
-	if (c->flags & CHN_F_VIRTUAL) {
-		parent = c->parentchannel;
-		CHN_LOCK(parent);
-		CHN_LOCK(c);
-		vchan_destroy(c);
-		CHN_UNLOCK(parent);
-	} else {
-		CHN_LOCK(c);
-		if (c->direction == PCMDIR_REC)
-			chn_abort(c); /* won't sleep */
-		else
-			chn_flush(c); /* may sleep */
-		c->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP | CHN_F_DEAD |
-		    CHN_F_EXCLUSIVE);
-		chn_reset(c, 0, 0);
-		chn_release(c);
+	if (rdch != NULL || wrch != NULL) {
+		PCM_UNLOCK(d);
+		if (rdch != NULL) {
+			/*
+			 * The channel itself need not be locked because:
+			 *   a)  Adding a channel to a syncgroup happens only
+			 *       in dsp_ioctl(), which cannot run concurrently
+			 *       to dsp_close().
+			 *   b)  The syncmember pointer (sm) is protected by
+			 *       the global syncgroup list lock.
+			 *   c)  A channel can't just disappear, invalidating
+			 *       pointers, unless it's closed/dereferenced
+			 *       first.
+			 */
+			PCM_SG_LOCK();
+			sg_ids = chn_syncdestroy(rdch);
+			PCM_SG_UNLOCK();
+			if (sg_ids != 0)
+				free_unr(pcmsg_unrhdr, sg_ids);
+
+			if (rdch->flags & CHN_F_VIRTUAL) {
+				parent = rdch->parentchannel;
+				CHN_LOCK(parent);
+				CHN_LOCK(rdch);
+				vchan_destroy(rdch);
+				CHN_UNLOCK(parent);
+			} else {
+				CHN_LOCK(rdch);
+				chn_abort(rdch); /* won't sleep */
+				rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP |
+				    CHN_F_DEAD | CHN_F_EXCLUSIVE);
+				chn_reset(rdch, 0, 0);
+				chn_release(rdch);
+			}
+		}
+		if (wrch != NULL) {
+			/*
+			 * Please see block above.
+			 */
+			PCM_SG_LOCK();
+			sg_ids = chn_syncdestroy(wrch);
+			PCM_SG_UNLOCK();
+			if (sg_ids != 0)
+				free_unr(pcmsg_unrhdr, sg_ids);
+
+			if (wrch->flags & CHN_F_VIRTUAL) {
+				parent = wrch->parentchannel;
+				CHN_LOCK(parent);
+				CHN_LOCK(wrch);
+				vchan_destroy(wrch);
+				CHN_UNLOCK(parent);
+			} else {
+				CHN_LOCK(wrch);
+				chn_flush(wrch); /* may sleep */
+				wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP |
+				    CHN_F_DEAD | CHN_F_EXCLUSIVE);
+				chn_reset(wrch, 0, 0);
+				chn_release(wrch);
+			}
+		}
+		PCM_LOCK(d);
 	}
 
-	PCM_LOCK(d);
-
 	PCM_RELEASE(d);
 	PCM_UNLOCK(d);
 
 	PCM_GIANT_LEAVE(d);
-}
-
-
-static void
-dsp_close(void *data)
-{
-	struct dsp_cdevpriv *priv = data;
-
-	if (priv == NULL)
-		return;
-
-	dsp_close_chan(priv->rdch);
-	dsp_close_chan(priv->wrch);
-
+skip:
 	free(priv, M_DEVBUF);
 	priv = NULL;
 }