--- channel.c.old Wed Nov 12 02:42:43 2003 +++ channel.c Wed Nov 12 03:59:31 2003 @@ -41,6 +41,10 @@ #define DEB(x) x */ +static int chn_fragsps = 0; +SYSCTL_INT(_hw_snd, OID_AUTO, fragsps, CTLFLAG_RW, + &chn_fragsps, 1, "max fragments per second, 0 to disable"); + static int chn_targetirqrate = 32; TUNABLE_INT("hw.snd.targetirqrate", &chn_targetirqrate); @@ -59,7 +63,7 @@ return err; } SYSCTL_PROC(_hw_snd, OID_AUTO, targetirqrate, CTLTYPE_INT | CTLFLAG_RW, - 0, sizeof(int), sysctl_hw_snd_targetirqrate, "I", ""); + 0, sizeof(int), sysctl_hw_snd_targetirqrate, "I", "default fragment targets this IRQ rate"); static int report_soft_formats = 1; SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW, &report_soft_formats, 1, "report software-emulated formats"); @@ -113,10 +117,17 @@ chn_wakeup(struct pcm_channel *c) { struct snd_dbuf *bs = c->bufsoft; + struct pcmchan_children *pce; - CHN_LOCKASSERT(c); - if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c)) - selwakeup(sndbuf_getsel(bs)); +// CHN_LOCKASSERT(c); + if (SLIST_EMPTY(&c->children)) { + if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c)) + selwakeup(sndbuf_getsel(bs)); + } else { + SLIST_FOREACH(pce, &c->children, link) { + chn_wakeup(pce->channel); + } + } wakeup(bs); } @@ -931,7 +942,7 @@ { struct snd_dbuf *b = c->bufhard; struct snd_dbuf *bs = c->bufsoft; - int bufsz, irqhz, tmp, ret; + int irqhz, tmp, ret; CHN_LOCKASSERT(c); if (!CANCHANGE(c) || (c->flags & CHN_F_MAPPED)) @@ -960,14 +971,23 @@ DEB(printf("%s: updating (%d, %d)\n", __func__, blkcnt, blksz)); } } else { + if ( chn_fragsps != 0 && + sndbuf_getbps(bs) * sndbuf_getspd(bs) / blksz > chn_fragsps) + { + blksz = sndbuf_getbps(bs) * sndbuf_getspd(bs) / chn_fragsps; + tmp = 32; + while (tmp < blksz) + tmp <<= 1; + blksz = tmp; + if (blksz * blkcnt > CHN_2NDBUFMAXSIZE) + blkcnt = CHN_2NDBUFMAXSIZE / blksz; + } ret = EINVAL; if ((blksz < 16) || (blkcnt < 2) || (blkcnt * blksz > CHN_2NDBUFMAXSIZE)) goto out; ret = 0; c->flags |= CHN_F_HAS_SIZE; } - - bufsz = blkcnt * blksz; ret = sndbuf_remalloc(bs, blkcnt, blksz); if (ret)