mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
sound: Prefer idle primary channels when allocating
dsp_chn_alloc() stopped at the first primary channel that was either idle or already had vchans. Since the list is walked in order, the first channel matched both conditions once it had been used, so every client after the first was stacked onto it as a vchan and the remaining primary channels were never allocated at all. This is invisible on devices with a single primary channel, but not on those which provide several. snd_emu10kx(4), for instance, registers four primary channels for its front device, each able to run with its own rate. Look for an idle primary channel first, and only fall back to sharing one that already has vchans when there is none left. Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D59084
This commit is contained in:
1 parent
949029692f
commit
5e02679f03
1 file changed
+17
-7
+17
-7
@@ -186,18 +186,28 @@ dsp_chn_alloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
|
||||
(direction == PCMDIR_REC && d->flags & SD_F_RVCHANS);
|
||||
|
||||
*ch = NULL;
|
||||
|
||||
/*
|
||||
* Prefer an idle primary channel, so that devices which provide more
|
||||
* than one of them use them all, instead of stacking every client on
|
||||
* the first one.
|
||||
*/
|
||||
CHN_FOREACH(c, d, channels.pcm.primary) {
|
||||
CHN_LOCK(c);
|
||||
if (c->direction != direction) {
|
||||
CHN_UNLOCK(c);
|
||||
continue;
|
||||
}
|
||||
/* Find an available primary channel to use. */
|
||||
if ((c->flags & CHN_F_BUSY) == 0 ||
|
||||
(vdir_enabled && (c->flags & CHN_F_HAS_VCHAN)))
|
||||
if (c->direction == direction && (c->flags & CHN_F_BUSY) == 0)
|
||||
break;
|
||||
CHN_UNLOCK(c);
|
||||
}
|
||||
/* Fall back to sharing a primary channel that already has vchans. */
|
||||
if (c == NULL && vdir_enabled) {
|
||||
CHN_FOREACH(c, d, channels.pcm.primary) {
|
||||
CHN_LOCK(c);
|
||||
if (c->direction == direction &&
|
||||
(c->flags & CHN_F_HAS_VCHAN))
|
||||
break;
|
||||
CHN_UNLOCK(c);
|
||||
}
|
||||
}
|
||||
if (c == NULL)
|
||||
return (EBUSY);
|
||||
|
||||
|
||||
Reference in new issue
Block a user