git: 7944824ae357 - releng/14.4 - sound: Check for errors from sndbuf_resize()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 14 Oct 2026 16:03:53 UTC
The branch releng/14.4 has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=7944824ae3577c93670b7f707d0838121fe6edc3
commit 7944824ae3577c93670b7f707d0838121fe6edc3
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-10-13 15:53:39 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-10-13 16:54:40 +0000
sound: Check for errors from sndbuf_resize()
Most implementations of CHANNEL_SETBLOCKSIZE and CHANNEL_SETFRAGMENTS
were not checking this. This is probably not a big problem: it's
unlikely for sndbuf_resize() to fail due to the refcount check in this
case since it's operating on the hardware buffer, which doesn't get
mmaped. But, I will add more reasons for it to fail in the next patch,
so let's be more careful.
This change modifies various CHANNEL_SETBLOCKSIZE implementations to
check for errors. In some cases I reordered things to avoid updating
driver state until after sndbuf_resize() succeeds.
Return 0 from CHANNEL_SETBLOCKSIZE to indicate an error, as it otherwise
returns the new block size. We could change the interface to return
both an error number and a block size, but that would break at least one
out-of-tree driver and I wish to avoid that here. Make sure that errors
from CHANNEL_SETFRAGMENTS are returned to userspace.
Approved by: so
Security: FreeBSD-SA-26:71.sound
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D60553
---
sys/arm/freescale/imx/imx6_ssi.c | 3 ++-
sys/arm/freescale/vybrid/vf_sai.c | 3 ++-
sys/dev/sound/pci/als4000.c | 3 ++-
sys/dev/sound/pci/atiixp.c | 8 ++++++--
sys/dev/sound/pci/cmi.c | 3 ++-
sys/dev/sound/pci/cs4281.c | 10 ++++++----
sys/dev/sound/pci/envy24.c | 16 +++++++++-------
sys/dev/sound/pci/envy24ht.c | 16 +++++++++-------
sys/dev/sound/pci/es137x.c | 12 ++++++++----
sys/dev/sound/pci/hda/hdaa.c | 9 +++++++--
sys/dev/sound/pci/hdspe-pcm.c | 8 +++++---
sys/dev/sound/pci/ich.c | 21 ++++++++++++---------
sys/dev/sound/pci/t4dwave.c | 7 ++++---
sys/dev/sound/pci/via8233.c | 8 ++++++--
sys/dev/sound/pci/via82c686.c | 3 ++-
sys/dev/sound/pci/vibes.c | 3 ++-
sys/dev/sound/pcm/channel.c | 37 ++++++++++++++++++++++++++++---------
sys/dev/sound/usb/uaudio.c | 14 +++++---------
sys/dev/sound/usb/uaudio.h | 2 --
sys/dev/sound/usb/uaudio_pcm.c | 7 -------
20 files changed, 117 insertions(+), 76 deletions(-)
diff --git a/sys/arm/freescale/imx/imx6_ssi.c b/sys/arm/freescale/imx/imx6_ssi.c
index 6b23334a4e97..39395ff3f330 100644
--- a/sys/arm/freescale/imx/imx6_ssi.c
+++ b/sys/arm/freescale/imx/imx6_ssi.c
@@ -395,7 +395,8 @@ ssichan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
struct sc_pcminfo *scp = ch->parent;
struct sc_info *sc = scp->sc;
- sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize);
+ if (sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize) != 0)
+ return (0);
setup_dma(scp);
diff --git a/sys/arm/freescale/vybrid/vf_sai.c b/sys/arm/freescale/vybrid/vf_sai.c
index 3b3a120df4e1..cdb1ab0dda37 100644
--- a/sys/arm/freescale/vybrid/vf_sai.c
+++ b/sys/arm/freescale/vybrid/vf_sai.c
@@ -368,7 +368,8 @@ saichan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
struct sc_pcminfo *scp = ch->parent;
struct sc_info *sc = scp->sc;
- sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize);
+ if (sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize) != 0)
+ return (0);
sc->period = sndbuf_getblksz(ch->buffer);
return (sc->period);
diff --git a/sys/dev/sound/pci/als4000.c b/sys/dev/sound/pci/als4000.c
index b1376d2b6e5a..9c1724c5facb 100644
--- a/sys/dev/sound/pci/als4000.c
+++ b/sys/dev/sound/pci/als4000.c
@@ -267,7 +267,8 @@ alschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
if (blocksize > sc->bufsz / 2) {
blocksize = sc->bufsz / 2;
}
- sndbuf_resize(ch->buffer, 2, blocksize);
+ if (sndbuf_resize(ch->buffer, 2, blocksize) != 0)
+ return 0;
return blocksize;
}
diff --git a/sys/dev/sound/pci/atiixp.c b/sys/dev/sound/pci/atiixp.c
index eeb28bb08276..2fbb5d3af157 100644
--- a/sys/dev/sound/pci/atiixp.c
+++ b/sys/dev/sound/pci/atiixp.c
@@ -532,6 +532,7 @@ atiixp_chan_setfragments(kobj_t obj, void *data,
{
struct atiixp_chinfo *ch = data;
struct atiixp_info *sc = ch->parent;
+ int error;
blksz &= ATI_IXP_BLK_ALIGN;
@@ -555,9 +556,11 @@ atiixp_chan_setfragments(kobj_t obj, void *data,
if ((sndbuf_getblksz(ch->buffer) != blksz ||
sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
- sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
+ (error = sndbuf_resize(ch->buffer, blkcnt, blksz)) != 0) {
device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
__func__, blksz, blkcnt);
+ return (error);
+ }
ch->blksz = sndbuf_getblksz(ch->buffer);
ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
@@ -571,7 +574,8 @@ atiixp_chan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
struct atiixp_chinfo *ch = data;
struct atiixp_info *sc = ch->parent;
- atiixp_chan_setfragments(obj, data, blksz, sc->blkcnt);
+ if (atiixp_chan_setfragments(obj, data, blksz, sc->blkcnt) != 0)
+ return (0);
return (ch->blksz);
}
diff --git a/sys/dev/sound/pci/cmi.c b/sys/dev/sound/pci/cmi.c
index 9a92066c51a4..cf273886789d 100644
--- a/sys/dev/sound/pci/cmi.c
+++ b/sys/dev/sound/pci/cmi.c
@@ -470,7 +470,8 @@ cmichan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
if (blocksize > sc->bufsz / CMI_INTR_PER_BUFFER) {
blocksize = sc->bufsz / CMI_INTR_PER_BUFFER;
}
- sndbuf_resize(ch->buffer, CMI_INTR_PER_BUFFER, blocksize);
+ if (sndbuf_resize(ch->buffer, CMI_INTR_PER_BUFFER, blocksize) != 0)
+ return 0;
return blocksize;
}
diff --git a/sys/dev/sound/pci/cs4281.c b/sys/dev/sound/pci/cs4281.c
index 972b83efff8f..7a0a7fbf9409 100644
--- a/sys/dev/sound/pci/cs4281.c
+++ b/sys/dev/sound/pci/cs4281.c
@@ -346,12 +346,14 @@ cs4281chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
struct sc_info *sc = ch->parent;
u_int32_t go;
- go = adcdac_go(ch, 0);
-
/* 2 interrupts are possible and used in buffer (half-empty,empty),
* hence factor of 2. */
- ch->blksz = MIN(blocksize, sc->bufsz / 2);
- sndbuf_resize(ch->buffer, 2, ch->blksz);
+ blocksize = MIN(blocksize, sc->bufsz / 2);
+ if (sndbuf_resize(ch->buffer, 2, blocksize) != 0)
+ return 0;
+ ch->blksz = blocksize;
+
+ go = adcdac_go(ch, 0);
ch->dma_setup = 0;
adcdac_prog(ch);
adcdac_go(ch, go);
diff --git a/sys/dev/sound/pci/envy24.c b/sys/dev/sound/pci/envy24.c
index f7cc7ff5724d..ea9820b30b6f 100644
--- a/sys/dev/sound/pci/envy24.c
+++ b/sys/dev/sound/pci/envy24.c
@@ -1716,7 +1716,7 @@ envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
struct sc_chinfo *ch = data;
/* struct sc_info *sc = ch->parent; */
- u_int32_t size, prev;
+ uint32_t blk, size, prev;
unsigned int bcnt, bsize;
#if(0)
@@ -1731,20 +1731,22 @@ envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
break;
}
- ch->blk = prev / ch->unit;
+ blk = prev / ch->unit;
if (ch->dir == PCMDIR_PLAY)
- ch->blk *= ENVY24_PLAY_BUFUNIT / 4;
+ blk *= ENVY24_PLAY_BUFUNIT / 4;
else
- ch->blk *= ENVY24_REC_BUFUNIT / 4;
+ blk *= ENVY24_REC_BUFUNIT / 4;
/* set channel buffer information */
/* ch->size = ch->unit * ENVY24_SAMPLE_NUM; */
if (ch->dir == PCMDIR_PLAY)
- bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
+ bsize = blk * 4 / ENVY24_PLAY_BUFUNIT;
else
- bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
+ bsize = blk * 4 / ENVY24_REC_BUFUNIT;
bsize *= ch->unit;
bcnt = ch->size / bsize;
- sndbuf_resize(ch->buffer, bcnt, bsize);
+ if (sndbuf_resize(ch->buffer, bcnt, bsize) != 0)
+ return 0;
+ ch->blk = blk;
/* snd_mtxunlock(sc->lock); */
#if(0)
diff --git a/sys/dev/sound/pci/envy24ht.c b/sys/dev/sound/pci/envy24ht.c
index 65c67b84ce53..1448b232f206 100644
--- a/sys/dev/sound/pci/envy24ht.c
+++ b/sys/dev/sound/pci/envy24ht.c
@@ -1627,7 +1627,7 @@ envy24htchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
struct sc_chinfo *ch = data;
/* struct sc_info *sc = ch->parent; */
- u_int32_t size, prev;
+ uint32_t blk, size, prev;
unsigned int bcnt, bsize;
#if(0)
@@ -1642,20 +1642,22 @@ envy24htchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
break;
}
- ch->blk = prev / ch->unit;
+ blk = prev / ch->unit;
if (ch->dir == PCMDIR_PLAY)
- ch->blk *= ENVY24HT_PLAY_BUFUNIT / 4;
+ blk *= ENVY24HT_PLAY_BUFUNIT / 4;
else
- ch->blk *= ENVY24HT_REC_BUFUNIT / 4;
+ blk *= ENVY24HT_REC_BUFUNIT / 4;
/* set channel buffer information */
/* ch->size = ch->unit * ENVY24HT_SAMPLE_NUM; */
if (ch->dir == PCMDIR_PLAY)
- bsize = ch->blk * 4 / ENVY24HT_PLAY_BUFUNIT;
+ bsize = blk * 4 / ENVY24HT_PLAY_BUFUNIT;
else
- bsize = ch->blk * 4 / ENVY24HT_REC_BUFUNIT;
+ bsize = blk * 4 / ENVY24HT_REC_BUFUNIT;
bsize *= ch->unit;
bcnt = ch->size / bsize;
- sndbuf_resize(ch->buffer, bcnt, bsize);
+ if (sndbuf_resize(ch->buffer, bcnt, bsize) != 0)
+ return 0;
+ ch->blk = blk;
/* snd_mtxunlock(sc->lock); */
#if(0)
diff --git a/sys/dev/sound/pci/es137x.c b/sys/dev/sound/pci/es137x.c
index 8f832d899dd3..0b6c83e911c8 100644
--- a/sys/dev/sound/pci/es137x.c
+++ b/sys/dev/sound/pci/es137x.c
@@ -632,8 +632,9 @@ eschan1371_setspeed(kobj_t obj, void *data, uint32_t speed)
static int
eschan_setfragments(kobj_t obj, void *data, uint32_t blksz, uint32_t blkcnt)
{
- struct es_chinfo *ch = data;
- struct es_info *es = ch->parent;
+ struct es_chinfo *ch = data;
+ struct es_info *es = ch->parent;
+ int error;
blksz &= ES_BLK_ALIGN;
@@ -657,9 +658,11 @@ eschan_setfragments(kobj_t obj, void *data, uint32_t blksz, uint32_t blkcnt)
if ((sndbuf_getblksz(ch->buffer) != blksz ||
sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
- sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
+ (error = sndbuf_resize(ch->buffer, blkcnt, blksz)) != 0) {
device_printf(es->dev, "%s: failed blksz=%u blkcnt=%u\n",
__func__, blksz, blkcnt);
+ return (error);
+ }
ch->bufsz = sndbuf_getsize(ch->buffer);
ch->blksz = sndbuf_getblksz(ch->buffer);
@@ -674,7 +677,8 @@ eschan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
struct es_chinfo *ch = data;
struct es_info *es = ch->parent;
- eschan_setfragments(obj, data, blksz, es->blkcnt);
+ if (eschan_setfragments(obj, data, blksz, es->blkcnt) != 0)
+ return (0);
return (ch->blksz);
}
diff --git a/sys/dev/sound/pci/hda/hdaa.c b/sys/dev/sound/pci/hda/hdaa.c
index 14306526a4e7..12234eaffeab 100644
--- a/sys/dev/sound/pci/hda/hdaa.c
+++ b/sys/dev/sound/pci/hda/hdaa.c
@@ -2053,6 +2053,7 @@ hdaa_channel_setfragments(kobj_t obj, void *data,
uint32_t blksz, uint32_t blkcnt)
{
struct hdaa_chan *ch = data;
+ int error;
blksz -= blksz % lcm(HDA_DMA_ALIGNMENT, sndbuf_getalign(ch->b));
@@ -2076,9 +2077,11 @@ hdaa_channel_setfragments(kobj_t obj, void *data,
if ((sndbuf_getblksz(ch->b) != blksz ||
sndbuf_getblkcnt(ch->b) != blkcnt) &&
- sndbuf_resize(ch->b, blkcnt, blksz) != 0)
+ (error = sndbuf_resize(ch->b, blkcnt, blksz)) != 0) {
device_printf(ch->devinfo->dev, "%s: failed blksz=%u blkcnt=%u\n",
__func__, blksz, blkcnt);
+ return (error);
+ }
ch->blksz = sndbuf_getblksz(ch->b);
ch->blkcnt = sndbuf_getblkcnt(ch->b);
@@ -2091,7 +2094,9 @@ hdaa_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz)
{
struct hdaa_chan *ch = data;
- hdaa_channel_setfragments(obj, data, blksz, ch->pdevinfo->chan_blkcnt);
+ if (hdaa_channel_setfragments(obj, data, blksz,
+ ch->pdevinfo->chan_blkcnt) != 0)
+ return (0);
return (ch->blksz);
}
diff --git a/sys/dev/sound/pci/hdspe-pcm.c b/sys/dev/sound/pci/hdspe-pcm.c
index 4bea6c65e087..082deb98a23f 100644
--- a/sys/dev/sound/pci/hdspe-pcm.c
+++ b/sys/dev/sound/pci/hdspe-pcm.c
@@ -907,6 +907,11 @@ hdspechan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
}
}
+ if (sndbuf_resize(ch->buffer,
+ (HDSPE_CHANBUF_SIZE * AFMT_CHANNEL(ch->format)) / (hl->period * 4),
+ (hl->period * 4)) != 0)
+ return (0);
+
snd_mtxlock(sc->lock);
sc->ctrl_register &= ~HDSPE_LAT_MASK;
sc->ctrl_register |= hdspe_encode_latency(hl->n);
@@ -918,9 +923,6 @@ hdspechan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
device_printf(scp->dev, "New period=%d\n", sc->period);
#endif
- sndbuf_resize(ch->buffer,
- (HDSPE_CHANBUF_SIZE * AFMT_CHANNEL(ch->format)) / (sc->period * 4),
- (sc->period * 4));
end:
return (sndbuf_getblksz(ch->buffer));
diff --git a/sys/dev/sound/pci/ich.c b/sys/dev/sound/pci/ich.c
index 910a371c6653..3966da1c6693 100644
--- a/sys/dev/sound/pci/ich.c
+++ b/sys/dev/sound/pci/ich.c
@@ -294,21 +294,23 @@ AC97_DECLARE(ich_ac97);
/* -------------------------------------------------------------------- */
/* common routines */
-static void
-ich_filldtbl(struct sc_chinfo *ch)
+static int
+ich_filldtbl(struct sc_chinfo *ch, uint32_t blksz)
{
struct sc_info *sc = ch->parent;
uint32_t base;
- int i;
+ int error, i;
base = sndbuf_getbufaddr(ch->buffer);
- if ((ch->blksz * ch->blkcnt) > sndbuf_getmaxsize(ch->buffer))
- ch->blksz = sndbuf_getmaxsize(ch->buffer) / ch->blkcnt;
- if ((sndbuf_getblksz(ch->buffer) != ch->blksz ||
+ if ((blksz * ch->blkcnt) > sndbuf_getmaxsize(ch->buffer))
+ blksz = sndbuf_getmaxsize(ch->buffer) / ch->blkcnt;
+ if ((sndbuf_getblksz(ch->buffer) != blksz ||
sndbuf_getblkcnt(ch->buffer) != ch->blkcnt) &&
- sndbuf_resize(ch->buffer, ch->blkcnt, ch->blksz) != 0)
+ (error = sndbuf_resize(ch->buffer, ch->blkcnt, blksz)) != 0) {
device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
__func__, ch->blksz, ch->blkcnt);
+ return (error);
+ }
ch->blksz = sndbuf_getblksz(ch->buffer);
for (i = 0; i < ICH_DTBL_LENGTH; i++) {
@@ -316,6 +318,7 @@ ich_filldtbl(struct sc_chinfo *ch)
ch->dtbl[i].length = ICH_BDC_IOC
| (ch->blksz / ch->parent->sample_size);
}
+ return (0);
}
static int
@@ -496,8 +499,8 @@ ichchan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
if (blocksize < ICH_MIN_BLKSZ)
blocksize = ICH_MIN_BLKSZ;
blocksize &= ~(ICH_MIN_BLKSZ - 1);
- ch->blksz = blocksize;
- ich_filldtbl(ch);
+ if (ich_filldtbl(ch, blocksize) != 0)
+ return (0);
ICH_LOCK(sc);
ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ch->blkcnt - 1, 1);
ICH_UNLOCK(sc);
diff --git a/sys/dev/sound/pci/t4dwave.c b/sys/dev/sound/pci/t4dwave.c
index 653e610febbe..caa54a4a83dd 100644
--- a/sys/dev/sound/pci/t4dwave.c
+++ b/sys/dev/sound/pci/t4dwave.c
@@ -538,7 +538,8 @@ trpchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
struct tr_chinfo *ch = data;
- sndbuf_resize(ch->buffer, 2, blocksize);
+ if (sndbuf_resize(ch->buffer, 2, blocksize) != 0)
+ return 0;
return blocksize;
}
@@ -659,8 +660,8 @@ trrchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
struct tr_rchinfo *ch = data;
- sndbuf_resize(ch->buffer, 2, blocksize);
-
+ if (sndbuf_resize(ch->buffer, 2, blocksize) != 0)
+ return 0;
return blocksize;
}
diff --git a/sys/dev/sound/pci/via8233.c b/sys/dev/sound/pci/via8233.c
index 9f3b312e4365..a0df7aef5c3e 100644
--- a/sys/dev/sound/pci/via8233.c
+++ b/sys/dev/sound/pci/via8233.c
@@ -565,6 +565,7 @@ via8233chan_setfragments(kobj_t obj, void *data,
{
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
+ int error;
blksz &= VIA_BLK_ALIGN;
@@ -588,9 +589,11 @@ via8233chan_setfragments(kobj_t obj, void *data,
if ((sndbuf_getblksz(ch->buffer) != blksz ||
sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
- sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
+ (error = sndbuf_resize(ch->buffer, blkcnt, blksz)) != 0) {
device_printf(via->dev, "%s: failed blksz=%u blkcnt=%u\n",
__func__, blksz, blkcnt);
+ return (error);
+ }
ch->blksz = sndbuf_getblksz(ch->buffer);
ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
@@ -604,7 +607,8 @@ via8233chan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
- via8233chan_setfragments(obj, data, blksz, via->blkcnt);
+ if (via8233chan_setfragments(obj, data, blksz, via->blkcnt) != 0)
+ return (0);
return (ch->blksz);
}
diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c
index 44f846b684d7..f869f2c26dc5 100644
--- a/sys/dev/sound/pci/via82c686.c
+++ b/sys/dev/sound/pci/via82c686.c
@@ -328,8 +328,9 @@ viachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
struct via_chinfo *ch = data;
+ if (sndbuf_resize(ch->buffer, SEGS_PER_CHAN, blocksize) != 0)
+ return 0;
ch->blksz = blocksize;
- sndbuf_resize(ch->buffer, SEGS_PER_CHAN, ch->blksz);
return ch->blksz;
}
diff --git a/sys/dev/sound/pci/vibes.c b/sys/dev/sound/pci/vibes.c
index e587f0113b5d..79bfb0d08887 100644
--- a/sys/dev/sound/pci/vibes.c
+++ b/sys/dev/sound/pci/vibes.c
@@ -224,7 +224,8 @@ svchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
/* user has requested interrupts every blocksize bytes */
RANGE(blocksize, SV_MIN_BLKSZ, sc->bufsz / SV_INTR_PER_BUFFER);
- sndbuf_resize(ch->buffer, SV_INTR_PER_BUFFER, blocksize);
+ if (sndbuf_resize(ch->buffer, SV_INTR_PER_BUFFER, blocksize) != 0)
+ return 0;
DEB(printf("svchan_setblocksize: %d\n", blocksize));
return blocksize;
}
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
index 4d13f20a5262..5264bad15516 100644
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -1870,7 +1870,6 @@ chn_resizebuf(struct pcm_channel *c, int latency,
{
struct snd_dbuf *b, *bs, *pb;
int sblksz, sblkcnt, hblksz, hblkcnt, limit = 0, nsblksz, nsblkcnt;
- int ret;
CHN_LOCKASSERT(c);
@@ -1940,6 +1939,8 @@ chn_resizebuf(struct pcm_channel *c, int latency,
sndbuf_xbytes(sndbuf_getblksz(pb), pb, bs) * 2 : 0;
}
} else {
+ int error;
+
hblkcnt = 2;
if (c->flags & CHN_F_HAS_SIZE) {
hblksz = round_blksz(sndbuf_xbytes(sblksz, bs, b),
@@ -1965,11 +1966,27 @@ chn_resizebuf(struct pcm_channel *c, int latency,
hblksz -= hblksz % sndbuf_getalign(b);
CHN_UNLOCK(c);
- if (chn_usefrags == 0 ||
- CHANNEL_SETFRAGMENTS(c->methods, c->devinfo,
- hblksz, hblkcnt) != 0)
- sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods,
- c->devinfo, hblksz));
+ error = ENOTSUP;
+ if (chn_usefrags) {
+ error = CHANNEL_SETFRAGMENTS(c->methods, c->devinfo,
+ hblksz, hblkcnt);
+ /* The default implementation returns ENOTSUP. */
+ if (error != 0 && error != ENOTSUP) {
+ CHN_LOCK(c);
+ return error;
+ }
+ }
+ if (error == ENOTSUP) {
+ uint32_t nblksz;
+
+ nblksz = CHANNEL_SETBLOCKSIZE(c->methods, c->devinfo,
+ hblksz);
+ if (nblksz == 0) {
+ CHN_LOCK(c);
+ return EINVAL;
+ }
+ sndbuf_setblksz(b, nblksz);
+ }
CHN_LOCK(c);
if (!CHN_EMPTY(c, children)) {
@@ -2008,11 +2025,13 @@ chn_resizebuf(struct pcm_channel *c, int latency,
if (sndbuf_getblkcnt(bs) != sblkcnt || sndbuf_getblksz(bs) != sblksz ||
sndbuf_getsize(bs) != (sblkcnt * sblksz)) {
- ret = sndbuf_remalloc(bs, sblkcnt, sblksz);
- if (ret != 0) {
+ int error;
+
+ error = sndbuf_remalloc(bs, sblkcnt, sblksz);
+ if (error != 0) {
device_printf(c->dev, "%s(): Failed: %d %d\n",
__func__, sblkcnt, sblksz);
- return ret;
+ return error;
}
}
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index 8238629a2a51..9f0486521d48 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -2724,16 +2724,12 @@ uaudio_chan_free(struct uaudio_chan *ch)
int
uaudio_chan_set_param_blocksize(struct uaudio_chan *ch, uint32_t blocksize)
{
- uint32_t temp = 2 * uaudio_get_buffer_size(ch, ch->set_alt);
- sndbuf_setup(ch->pcm_buf, ch->buf, temp);
- return (temp / 2);
-}
+ uint32_t temp;
-int
-uaudio_chan_set_param_fragments(struct uaudio_chan *ch, uint32_t blocksize,
- uint32_t blockcount)
-{
- return (1);
+ temp = 2 * uaudio_get_buffer_size(ch, ch->set_alt);
+ if (sndbuf_setup(ch->pcm_buf, ch->buf, temp) != 0)
+ return (0);
+ return (temp / 2);
}
int
diff --git a/sys/dev/sound/usb/uaudio.h b/sys/dev/sound/usb/uaudio.h
index 54b31a4e7bd2..406afa5d42eb 100644
--- a/sys/dev/sound/usb/uaudio.h
+++ b/sys/dev/sound/usb/uaudio.h
@@ -45,8 +45,6 @@ extern void *uaudio_chan_init(struct uaudio_chan *ch, struct snd_dbuf *b,
extern int uaudio_chan_free(struct uaudio_chan *ch);
extern int uaudio_chan_set_param_blocksize(struct uaudio_chan *ch,
uint32_t blocksize);
-extern int uaudio_chan_set_param_fragments(struct uaudio_chan *ch,
- uint32_t blocksize, uint32_t blockcount);
extern int uaudio_chan_set_param_speed(struct uaudio_chan *ch,
uint32_t speed);
extern int uaudio_chan_getptr(struct uaudio_chan *ch);
diff --git a/sys/dev/sound/usb/uaudio_pcm.c b/sys/dev/sound/usb/uaudio_pcm.c
index 0b3da9b20440..ad94a225edd7 100644
--- a/sys/dev/sound/usb/uaudio_pcm.c
+++ b/sys/dev/sound/usb/uaudio_pcm.c
@@ -71,12 +71,6 @@ ua_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
return (uaudio_chan_set_param_blocksize(data, blocksize));
}
-static int
-ua_chan_setfragments(kobj_t obj, void *data, uint32_t blocksize, uint32_t blockcount)
-{
- return (uaudio_chan_set_param_fragments(data, blocksize, blockcount));
-}
-
static int
ua_chan_trigger(kobj_t obj, void *data, int go)
{
@@ -114,7 +108,6 @@ static kobj_method_t ua_chan_methods[] = {
KOBJMETHOD(channel_setformat, ua_chan_setformat),
KOBJMETHOD(channel_setspeed, ua_chan_setspeed),
KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize),
- KOBJMETHOD(channel_setfragments, ua_chan_setfragments),
KOBJMETHOD(channel_trigger, ua_chan_trigger),
KOBJMETHOD(channel_getptr, ua_chan_getptr),
KOBJMETHOD(channel_getcaps, ua_chan_getcaps),