The branch main has been updated by christos:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=7ad5f383fcb507482d5606c8eb7a324b3621a9db

commit 7ad5f383fcb507482d5606c8eb7a324b3621a9db
Author:     Christos Margiolis <chris...@freebsd.org>
AuthorDate: 2024-05-06 18:32:46 +0000
Commit:     Christos Margiolis <chris...@freebsd.org>
CommitDate: 2024-05-06 18:35:55 +0000

    sound: Move vchan-related code to pcm/vchan.*
    
    pcm/sound.* contains code that should be part of pcm/vchan.*.
    
    Changes:
    - pcm_setvchans() -> vchan_setnew()
    - pcm_setmaxautovchans() -> vchan_setmaxauto()
    - hw.snd.maxautovchans moved to pcm/vchan.c
    - snd_maxautovchans declaration moved to pcm/vchan.h and definition to
      pcm/vchan.c
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Reviewed by:    dev_submerge.ch, markj
    Differential Revision:  https://reviews.freebsd.org/D45015
---
 sys/dev/sound/pcm/feeder.c |   1 +
 sys/dev/sound/pcm/sound.c  | 176 +--------------------------------------------
 sys/dev/sound/pcm/sound.h  |   2 -
 sys/dev/sound/pcm/vchan.c  | 173 +++++++++++++++++++++++++++++++++++++++++++-
 sys/dev/sound/pcm/vchan.h  |   5 ++
 5 files changed, 180 insertions(+), 177 deletions(-)

diff --git a/sys/dev/sound/pcm/feeder.c b/sys/dev/sound/pcm/feeder.c
index 78443ad76140..0113299bd0d4 100644
--- a/sys/dev/sound/pcm/feeder.c
+++ b/sys/dev/sound/pcm/feeder.c
@@ -32,6 +32,7 @@
 #endif
 
 #include <dev/sound/pcm/sound.h>
+#include <dev/sound/pcm/vchan.h>
 
 #include "feeder_if.h"
 
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
index afa19f9f0624..971054261030 100644
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -56,8 +56,6 @@ static int snd_unit_auto = -1;
 SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RWTUN,
     &snd_unit_auto, 0, "assign default unit to a newly attached device");
 
-int snd_maxautovchans = 16;
-
 SYSCTL_NODE(_hw, OID_AUTO, snd, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
     "Sound driver");
 
@@ -111,126 +109,6 @@ snd_setup_intr(device_t dev, struct resource *res, int 
flags, driver_intr_t hand
        return bus_setup_intr(dev, res, flags, NULL, hand, param, cookiep);
 }
 
-int
-pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num)
-{
-       struct pcm_channel *c, *ch, *nch;
-       struct pcmchan_caps *caps;
-       int i, err, vcnt;
-
-       PCM_BUSYASSERT(d);
-
-       if ((direction == PCMDIR_PLAY && d->playcount < 1) ||
-           (direction == PCMDIR_REC && d->reccount < 1))
-               return (ENODEV);
-
-       if (!(d->flags & SD_F_AUTOVCHAN))
-               return (EINVAL);
-
-       if (newcnt < 0 || newcnt > SND_MAXVCHANS)
-               return (E2BIG);
-
-       if (direction == PCMDIR_PLAY)
-               vcnt = d->pvchancount;
-       else if (direction == PCMDIR_REC)
-               vcnt = d->rvchancount;
-       else
-               return (EINVAL);
-
-       if (newcnt > vcnt) {
-               KASSERT(num == -1 ||
-                   (num >= 0 && num < SND_MAXVCHANS && (newcnt - 1) == vcnt),
-                   ("bogus vchan_create() request num=%d newcnt=%d vcnt=%d",
-                   num, newcnt, vcnt));
-               /* add new vchans - find a parent channel first */
-               ch = NULL;
-               CHN_FOREACH(c, d, channels.pcm) {
-                       CHN_LOCK(c);
-                       if (c->direction == direction &&
-                           ((c->flags & CHN_F_HAS_VCHAN) || (vcnt == 0 &&
-                           c->refcount < 1 &&
-                           !(c->flags & (CHN_F_BUSY | CHN_F_VIRTUAL))))) {
-                               /* 
-                                * Reuse hw channel with vchans already
-                                * created.
-                                */
-                               if (c->flags & CHN_F_HAS_VCHAN) {
-                                       ch = c;
-                                       break;
-                               }
-                               /*
-                                * No vchans ever created, look for
-                                * channels with supported formats.
-                                */
-                               caps = chn_getcaps(c);
-                               if (caps == NULL) {
-                                       CHN_UNLOCK(c);
-                                       continue;
-                               }
-                               for (i = 0; caps->fmtlist[i] != 0; i++) {
-                                       if (caps->fmtlist[i] & AFMT_CONVERTIBLE)
-                                               break;
-                               }
-                               if (caps->fmtlist[i] != 0) {
-                                       ch = c;
-                                       break;
-                               }
-                       }
-                       CHN_UNLOCK(c);
-               }
-               if (ch == NULL)
-                       return (EBUSY);
-               ch->flags |= CHN_F_BUSY;
-               err = 0;
-               while (err == 0 && newcnt > vcnt) {
-                       err = vchan_create(ch, num);
-                       if (err == 0)
-                               vcnt++;
-                       else if (err == E2BIG && newcnt > vcnt)
-                               device_printf(d->dev,
-                                   "%s: err=%d Maximum channel reached.\n",
-                                   __func__, err);
-               }
-               if (vcnt == 0)
-                       ch->flags &= ~CHN_F_BUSY;
-               CHN_UNLOCK(ch);
-               if (err != 0)
-                       return (err);
-       } else if (newcnt < vcnt) {
-               KASSERT(num == -1,
-                   ("bogus vchan_destroy() request num=%d", num));
-               CHN_FOREACH(c, d, channels.pcm) {
-                       CHN_LOCK(c);
-                       if (c->direction != direction ||
-                           CHN_EMPTY(c, children) ||
-                           !(c->flags & CHN_F_HAS_VCHAN)) {
-                               CHN_UNLOCK(c);
-                               continue;
-                       }
-                       CHN_FOREACH_SAFE(ch, c, nch, children) {
-                               CHN_LOCK(ch);
-                               if (vcnt == 1 && c->refcount > 0) {
-                                       CHN_UNLOCK(ch);
-                                       break;
-                               }
-                               if (!(ch->flags & CHN_F_BUSY) &&
-                                   ch->refcount < 1) {
-                                       err = vchan_destroy(ch);
-                                       if (err == 0)
-                                               vcnt--;
-                               } else
-                                       CHN_UNLOCK(ch);
-                               if (vcnt == newcnt)
-                                       break;
-                       }
-                       CHN_UNLOCK(c);
-                       break;
-               }
-       }
-
-       return (0);
-}
-
 /* return error status and a locked channel */
 int
 pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
@@ -287,7 +165,7 @@ vchan_alloc:
        /* no channel available */
        if (!(vchancount > 0 && vchancount < snd_maxautovchans))
                return (err);
-       err = pcm_setvchans(d, direction, vchancount + 1, -1);
+       err = vchan_setnew(d, direction, vchancount + 1, -1);
        if (err == 0) {
                retry = true;
                goto retry_chnalloc;
@@ -296,25 +174,6 @@ vchan_alloc:
        return (err);
 }
 
-static void
-pcm_setmaxautovchans(struct snddev_info *d, int num)
-{
-       PCM_BUSYASSERT(d);
-
-       if (num < 0)
-               return;
-
-       if (num >= 0 && d->pvchancount > num)
-               (void)pcm_setvchans(d, PCMDIR_PLAY, num, -1);
-       else if (num > 0 && d->pvchancount == 0)
-               (void)pcm_setvchans(d, PCMDIR_PLAY, 1, -1);
-
-       if (num >= 0 && d->rvchancount > num)
-               (void)pcm_setvchans(d, PCMDIR_REC, num, -1);
-       else if (num > 0 && d->rvchancount == 0)
-               (void)pcm_setvchans(d, PCMDIR_REC, 1, -1);
-}
-
 static int
 sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS)
 {
@@ -338,37 +197,6 @@ SYSCTL_PROC(_hw_snd, OID_AUTO, default_unit,
     sizeof(int), sysctl_hw_snd_default_unit, "I",
     "default sound device");
 
-static int
-sysctl_hw_snd_maxautovchans(SYSCTL_HANDLER_ARGS)
-{
-       struct snddev_info *d;
-       int i, v, error;
-
-       v = snd_maxautovchans;
-       error = sysctl_handle_int(oidp, &v, 0, req);
-       if (error == 0 && req->newptr != NULL) {
-               if (v < 0)
-                       v = 0;
-               if (v > SND_MAXVCHANS)
-                       v = SND_MAXVCHANS;
-               snd_maxautovchans = v;
-               for (i = 0; pcm_devclass != NULL &&
-                   i < devclass_get_maxunit(pcm_devclass); i++) {
-                       d = devclass_get_softc(pcm_devclass, i);
-                       if (!PCM_REGISTERED(d))
-                               continue;
-                       PCM_ACQUIRE_QUICK(d);
-                       pcm_setmaxautovchans(d, v);
-                       PCM_RELEASE_QUICK(d);
-               }
-       }
-       return (error);
-}
-SYSCTL_PROC(_hw_snd, OID_AUTO, maxautovchans,
-    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int),
-    sysctl_hw_snd_maxautovchans, "I",
-    "maximum virtual channel");
-
 void
 pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch)
 {
@@ -549,7 +377,7 @@ pcm_setstatus(device_t dev, char *str)
        if (d->playcount > 0 || d->reccount > 0)
                d->flags |= SD_F_AUTOVCHAN;
 
-       pcm_setmaxautovchans(d, snd_maxautovchans);
+       vchan_setmaxauto(d, snd_maxautovchans);
 
        strlcpy(d->status, str, SND_STATUSLEN);
 
diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h
index 5a750440cbea..e4a3ba41ee7f 100644
--- a/sys/dev/sound/pcm/sound.h
+++ b/sys/dev/sound/pcm/sound.h
@@ -247,7 +247,6 @@ enum {
 
 extern int pcm_veto_load;
 extern int snd_unit;
-extern int snd_maxautovchans;
 extern int snd_verbose;
 extern devclass_t pcm_devclass;
 extern struct unrhdr *pcmsg_unrhdr;
@@ -265,7 +264,6 @@ extern struct unrhdr *pcmsg_unrhdr;
 
 SYSCTL_DECL(_hw_snd);
 
-int pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num);
 int pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
     pid_t pid, char *comm);
 
diff --git a/sys/dev/sound/pcm/vchan.c b/sys/dev/sound/pcm/vchan.c
index 1a21b7049b77..9df23298b742 100644
--- a/sys/dev/sound/pcm/vchan.c
+++ b/sys/dev/sound/pcm/vchan.c
@@ -57,6 +57,8 @@ struct vchan_info {
        int trigger;
 };
 
+int snd_maxautovchans = 16;
+
 static void *
 vchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
     struct pcm_channel *c, int dir)
@@ -337,7 +339,7 @@ sysctl_dev_pcm_vchans(SYSCTL_HANDLER_ARGS)
                        cnt = 0;
                if (cnt > SND_MAXVCHANS)
                        cnt = SND_MAXVCHANS;
-               err = pcm_setvchans(d, direction, cnt, -1);
+               err = vchan_setnew(d, direction, cnt, -1);
        }
 
        PCM_RELEASE_QUICK(d);
@@ -930,6 +932,175 @@ vchan_sync(struct pcm_channel *c)
        return (ret);
 }
 
+int
+vchan_setnew(struct snddev_info *d, int direction, int newcnt, int num)
+{
+       struct pcm_channel *c, *ch, *nch;
+       struct pcmchan_caps *caps;
+       int i, err, vcnt;
+
+       PCM_BUSYASSERT(d);
+
+       if ((direction == PCMDIR_PLAY && d->playcount < 1) ||
+           (direction == PCMDIR_REC && d->reccount < 1))
+               return (ENODEV);
+
+       if (!(d->flags & SD_F_AUTOVCHAN))
+               return (EINVAL);
+
+       if (newcnt < 0 || newcnt > SND_MAXVCHANS)
+               return (E2BIG);
+
+       if (direction == PCMDIR_PLAY)
+               vcnt = d->pvchancount;
+       else if (direction == PCMDIR_REC)
+               vcnt = d->rvchancount;
+       else
+               return (EINVAL);
+
+       if (newcnt > vcnt) {
+               KASSERT(num == -1 ||
+                   (num >= 0 && num < SND_MAXVCHANS && (newcnt - 1) == vcnt),
+                   ("bogus vchan_create() request num=%d newcnt=%d vcnt=%d",
+                   num, newcnt, vcnt));
+               /* add new vchans - find a parent channel first */
+               ch = NULL;
+               CHN_FOREACH(c, d, channels.pcm) {
+                       CHN_LOCK(c);
+                       if (c->direction == direction &&
+                           ((c->flags & CHN_F_HAS_VCHAN) || (vcnt == 0 &&
+                           c->refcount < 1 &&
+                           !(c->flags & (CHN_F_BUSY | CHN_F_VIRTUAL))))) {
+                               /*
+                                * Reuse hw channel with vchans already
+                                * created.
+                                */
+                               if (c->flags & CHN_F_HAS_VCHAN) {
+                                       ch = c;
+                                       break;
+                               }
+                               /*
+                                * No vchans ever created, look for
+                                * channels with supported formats.
+                                */
+                               caps = chn_getcaps(c);
+                               if (caps == NULL) {
+                                       CHN_UNLOCK(c);
+                                       continue;
+                               }
+                               for (i = 0; caps->fmtlist[i] != 0; i++) {
+                                       if (caps->fmtlist[i] & AFMT_CONVERTIBLE)
+                                               break;
+                               }
+                               if (caps->fmtlist[i] != 0) {
+                                       ch = c;
+                                       break;
+                               }
+                       }
+                       CHN_UNLOCK(c);
+               }
+               if (ch == NULL)
+                       return (EBUSY);
+               ch->flags |= CHN_F_BUSY;
+               err = 0;
+               while (err == 0 && newcnt > vcnt) {
+                       err = vchan_create(ch, num);
+                       if (err == 0)
+                               vcnt++;
+                       else if (err == E2BIG && newcnt > vcnt)
+                               device_printf(d->dev,
+                                   "%s: err=%d Maximum channel reached.\n",
+                                   __func__, err);
+               }
+               if (vcnt == 0)
+                       ch->flags &= ~CHN_F_BUSY;
+               CHN_UNLOCK(ch);
+               if (err != 0)
+                       return (err);
+       } else if (newcnt < vcnt) {
+               KASSERT(num == -1,
+                   ("bogus vchan_destroy() request num=%d", num));
+               CHN_FOREACH(c, d, channels.pcm) {
+                       CHN_LOCK(c);
+                       if (c->direction != direction ||
+                           CHN_EMPTY(c, children) ||
+                           !(c->flags & CHN_F_HAS_VCHAN)) {
+                               CHN_UNLOCK(c);
+                               continue;
+                       }
+                       CHN_FOREACH_SAFE(ch, c, nch, children) {
+                               CHN_LOCK(ch);
+                               if (vcnt == 1 && c->refcount > 0) {
+                                       CHN_UNLOCK(ch);
+                                       break;
+                               }
+                               if (!(ch->flags & CHN_F_BUSY) &&
+                                   ch->refcount < 1) {
+                                       err = vchan_destroy(ch);
+                                       if (err == 0)
+                                               vcnt--;
+                               } else
+                                       CHN_UNLOCK(ch);
+                               if (vcnt == newcnt)
+                                       break;
+                       }
+                       CHN_UNLOCK(c);
+                       break;
+               }
+       }
+
+       return (0);
+}
+
+void
+vchan_setmaxauto(struct snddev_info *d, int num)
+{
+       PCM_BUSYASSERT(d);
+
+       if (num < 0)
+               return;
+
+       if (num >= 0 && d->pvchancount > num)
+               (void)vchan_setnew(d, PCMDIR_PLAY, num, -1);
+       else if (num > 0 && d->pvchancount == 0)
+               (void)vchan_setnew(d, PCMDIR_PLAY, 1, -1);
+
+       if (num >= 0 && d->rvchancount > num)
+               (void)vchan_setnew(d, PCMDIR_REC, num, -1);
+       else if (num > 0 && d->rvchancount == 0)
+               (void)vchan_setnew(d, PCMDIR_REC, 1, -1);
+}
+
+static int
+sysctl_hw_snd_maxautovchans(SYSCTL_HANDLER_ARGS)
+{
+       struct snddev_info *d;
+       int i, v, error;
+
+       v = snd_maxautovchans;
+       error = sysctl_handle_int(oidp, &v, 0, req);
+       if (error == 0 && req->newptr != NULL) {
+               if (v < 0)
+                       v = 0;
+               if (v > SND_MAXVCHANS)
+                       v = SND_MAXVCHANS;
+               snd_maxautovchans = v;
+               for (i = 0; pcm_devclass != NULL &&
+                   i < devclass_get_maxunit(pcm_devclass); i++) {
+                       d = devclass_get_softc(pcm_devclass, i);
+                       if (!PCM_REGISTERED(d))
+                               continue;
+                       PCM_ACQUIRE_QUICK(d);
+                       vchan_setmaxauto(d, v);
+                       PCM_RELEASE_QUICK(d);
+               }
+       }
+       return (error);
+}
+SYSCTL_PROC(_hw_snd, OID_AUTO, maxautovchans,
+    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int),
+    sysctl_hw_snd_maxautovchans, "I", "maximum virtual channel");
+
 void
 vchan_initsys(device_t dev)
 {
diff --git a/sys/dev/sound/pcm/vchan.h b/sys/dev/sound/pcm/vchan.h
index e2dcc9761261..dcc1d6e9ff32 100644
--- a/sys/dev/sound/pcm/vchan.h
+++ b/sys/dev/sound/pcm/vchan.h
@@ -30,6 +30,8 @@
 #ifndef _SND_VCHAN_H_
 #define _SND_VCHAN_H_
 
+extern int snd_maxautovchans;
+
 int vchan_create(struct pcm_channel *, int);
 int vchan_destroy(struct pcm_channel *);
 
@@ -45,6 +47,9 @@ int vchan_sync(struct pcm_channel *);
        sndbuf_getfmt((c)->bufhard) != (c)->parentchannel->format ||    \
        sndbuf_getspd((c)->bufhard) != (c)->parentchannel->speed))
 
+int vchan_setnew(struct snddev_info *, int, int, int);
+void vchan_setmaxauto(struct snddev_info *, int);
+
 void vchan_initsys(device_t);
 
 /*

Reply via email to