git: a25ad366d51d - main - snd_hdsp: Serialize rate and latency updates
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 02 Nov 2026 15:55:27 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=a25ad366d51d52ef30b8bc4e2a7dd377255a409b
commit a25ad366d51d52ef30b8bc4e2a7dd377255a409b
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-11-02 15:54:35 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-11-02 15:55:04 +0000
snd_hdsp: Serialize rate and latency updates
Protect running-state checks and register updates with the softc lock.
Keep the pointer reset and the HDSP 9632 frequency rewrite in the same
critical section as the latency update.
Drop the lock around sndbuf_resize(), which may sleep, and recheck the
running state after reacquiring it. Preserve resize error handling so
that a failed resize leaves the hardware unchanged.
This mirrors the locking in snd_hdspe.
MFC after: 3 days
Sponsored by: BBOX.io
---
sys/dev/sound/pci/hdsp-pcm.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/sys/dev/sound/pci/hdsp-pcm.c b/sys/dev/sound/pci/hdsp-pcm.c
index 27ab21fd6d74..24969f0e22b0 100644
--- a/sys/dev/sound/pci/hdsp-pcm.c
+++ b/sys/dev/sound/pci/hdsp-pcm.c
@@ -851,6 +851,8 @@ hdspchan_setspeed(kobj_t obj, void *data, uint32_t speed)
device_printf(scp->dev, "hdspchan_setspeed(%d)\n", speed);
#endif
+ mtx_lock(&sc->lock);
+
if (hdsp_running(sc) == 1)
goto end;
@@ -890,8 +892,10 @@ hdspchan_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
@@ -913,6 +917,8 @@ hdspchan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
device_printf(scp->dev, "hdspchan_setblocksize(%d)\n", blocksize);
#endif
+ mtx_lock(&sc->lock);
+
if (hdsp_running(sc) == 1)
goto end;
@@ -943,16 +949,23 @@ hdspchan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
}
}
+ /* sndbuf_resize() may sleep. */
+ mtx_unlock(&sc->lock);
if (sndbuf_resize(ch->buffer, 2,
(hl->period * AFMT_CHANNEL(ch->format) * sizeof(uint32_t))) != 0)
return (0);
mtx_lock(&sc->lock);
+ /* A channel may have started while the lock was dropped. */
+ if (hdsp_running(sc) == 1) {
+ mtx_unlock(&sc->lock);
+ return (0);
+ }
+
sc->ctrl_register &= ~HDSP_LAT_MASK;
sc->ctrl_register |= hdsp_encode_latency(hl->n);
hdsp_write_4(sc, HDSP_CONTROL_REG, sc->ctrl_register);
sc->period = hl->period;
- mtx_unlock(&sc->lock);
#if 0
device_printf(scp->dev, "New period=%d\n", sc->period);
@@ -963,6 +976,7 @@ hdspchan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
if (sc->type == HDSP_9632)
hdsp_write_4(sc, HDSP_FREQ_REG, hdsp_freq_reg_value(sc->speed));
end:
+ mtx_unlock(&sc->lock);
return (ch->buffer->blksz);
}