git: d1dcb2b117a3 - main - snd_hdspe: Serialize rate and latency updates
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 02 Nov 2026 15:49:40 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=d1dcb2b117a3c128c8e8eda047f93739f06d6099
commit d1dcb2b117a3c128c8e8eda047f93739f06d6099
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-07-21 03:33:08 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-11-02 15:49:22 +0000
snd_hdspe: Serialize rate and latency updates
Protect running-state checks and register updates with the softc lock.
Drop the lock around sndbuf_resize(), which may sleep, and recheck the
running state after reacquiring it. Keep the resize ahead of the latency
register update so that a failed resize leaves the hardware unchanged.
Reviewed by: br
MFC after: 3 days
Sponsored by: BBOX.io
Differential Revision: https://reviews.freebsd.org/D58371
---
sys/dev/sound/pci/hdspe-pcm.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/sys/dev/sound/pci/hdspe-pcm.c b/sys/dev/sound/pci/hdspe-pcm.c
index 1f32909ce0d3..017142949d62 100644
--- a/sys/dev/sound/pci/hdspe-pcm.c
+++ b/sys/dev/sound/pci/hdspe-pcm.c
@@ -838,6 +838,8 @@ hdspechan_setspeed(kobj_t obj, void *data, uint32_t speed)
device_printf(scp->dev, "hdspechan_setspeed(%d)\n", speed);
#endif
+ mtx_lock(&sc->lock);
+
if (hdspe_running(sc) == 1)
goto end;
@@ -888,8 +890,10 @@ hdspechan_setspeed(kobj_t obj, void *data, uint32_t speed)
sc->speed = hr->speed;
end:
+ speed = sc->speed;
+ mtx_unlock(&sc->lock);
- return (sc->speed);
+ return (speed);
}
static uint32_t
@@ -911,6 +915,8 @@ hdspechan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
device_printf(scp->dev, "hdspechan_setblocksize(%d)\n", blocksize);
#endif
+ mtx_lock(&sc->lock);
+
if (hdspe_running(sc) == 1)
goto end;
@@ -941,12 +947,20 @@ hdspechan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
}
}
+ /* sndbuf_resize() may sleep. */
+ mtx_unlock(&sc->lock);
if (sndbuf_resize(ch->buffer,
(HDSPE_CHANBUF_SIZE * AFMT_CHANNEL(ch->format)) / (hl->period * 4),
(hl->period * 4)) != 0)
return (0);
mtx_lock(&sc->lock);
+ /* A channel may have started while the lock was dropped. */
+ if (hdspe_running(sc) == 1) {
+ mtx_unlock(&sc->lock);
+ return (0);
+ }
+
sc->ctrl_register &= ~HDSPE_LAT_MASK;
sc->ctrl_register |= hdspe_encode_latency(hl->n);
hdspe_write_4(sc, HDSPE_CONTROL_REG, sc->ctrl_register);
@@ -954,10 +968,12 @@ hdspechan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
mtx_unlock(&sc->lock);
#if 0
- device_printf(scp->dev, "New period=%d\n", sc->period);
+ device_printf(scp->dev, "New period=%d\n", hl->period);
#endif
+ return (ch->buffer->blksz);
end:
+ mtx_unlock(&sc->lock);
return (ch->buffer->blksz);
}