Page MenuHomeFreeBSD

D45015.diff
No OneTemporary

D45015.diff

diff --git a/sys/dev/sound/pcm/feeder.c b/sys/dev/sound/pcm/feeder.c
--- 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.h b/sys/dev/sound/pcm/sound.h
--- a/sys/dev/sound/pcm/sound.h
+++ b/sys/dev/sound/pcm/sound.h
@@ -247,7 +247,6 @@
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 @@
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/sound.c b/sys/dev/sound/pcm/sound.c
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -56,8 +56,6 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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/vchan.h b/sys/dev/sound/pcm/vchan.h
--- 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 @@
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);
/*
diff --git a/sys/dev/sound/pcm/vchan.c b/sys/dev/sound/pcm/vchan.c
--- a/sys/dev/sound/pcm/vchan.c
+++ b/sys/dev/sound/pcm/vchan.c
@@ -57,6 +57,8 @@
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 @@
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 @@
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)
{

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 20, 5:40 PM (21 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14743869
Default Alt Text
D45015.diff (11 KB)

Event Timeline