From b34e3b8c68604d748d9837d3feb09e1bc96e40e3 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 30 Sep 2025 15:09:48 -0700 Subject: [PATCH] i2s: i2s_nrfx: Lock irqs when supplying buffers in i2s_nrfx_write() It seems to be possible for a race between data_handler() and the latter part of i2s_nrfx_write() to cause supply_next_buffers() to be called after nrfx_i2s_uninit() has run, causing ASSERTION FAIL [p_cb->state == NRFX_DRV_STATE_POWERED_ON] @ WEST_TOPDIR/build/external-code/modules/hal/nordic/nrfx/drivers/src/nrfx_i2s.c:445 [00:00:25.492,095] os: r0/a1: 0x00000004 r1/a2: 0x000001bd r2/a3: 0x00000003 [00:00:25.492,095] os: r3/a4: 0x00000004 r12/ip: 0x00000014 r14/lr: 0x000418a1 [00:00:25.492,126] os: xpsr: 0x01000000 [00:00:25.492,126] os: s[ 0]: 0x20002460 s[ 1]: 0x00026c87 s[ 2]: 0x00000000 s[ 3]: 0x2000ec28 [00:00:25.492,126] os: s[ 4]: 0x20002480 s[ 5]: 0x000531d3 s[ 6]: 0x00000000 s[ 7]: 0x00000000 [00:00:25.492,156] os: s[ 8]: 0x0005f854 s[ 9]: 0x2000249c s[10]: 0x20002488 s[11]: 0x000524a5 [00:00:25.492,187] os: s[12]: 0x36388f32 s[13]: 0x2000249c s[14]: 0x200024a8 s[15]: 0x00041897 [00:00:25.492,187] os: fpscr: 0x0005f854 [00:00:25.492,187] os: Faulting instruction address (r15/pc): 0x0005248c [00:00:25.492,248] os: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0 [00:00:25.492,279] os: Current thread: 0x20001f88 (unknown) [00:00:25.962,005] os: Halting system assert to happen. A burte force solution for this is to lock irqs to prevent this race from happening. Signed-off-by: Andrey Smirnov --- drivers/i2s/i2s_nrfx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/i2s/i2s_nrfx.c b/drivers/i2s/i2s_nrfx.c index 8c52fb42da30d..d43b1b6c79ead 100644 --- a/drivers/i2s/i2s_nrfx.c +++ b/drivers/i2s/i2s_nrfx.c @@ -660,6 +660,8 @@ static int i2s_nrfx_write(const struct device *dev, * opens the possibility for a race condition between this function and * data_handler() that is called in interrupt context. */ + + unsigned int key = irq_lock(); if (drv_data->state == I2S_STATE_RUNNING && drv_data->next_tx_buffer_needed) { nrfx_i2s_buffers_t next = { 0 }; @@ -670,6 +672,7 @@ static int i2s_nrfx_write(const struct device *dev, * responsible for releasing the buffer. */ LOG_ERR("Cannot reacquire queued buffer"); + irq_unlock(key); return 0; } @@ -678,10 +681,12 @@ static int i2s_nrfx_write(const struct device *dev, LOG_DBG("Next TX %p", next.p_tx_buffer); if (!supply_next_buffers(drv_data, &next)) { + irq_unlock(key); return -EIO; } } + irq_unlock(key); return 0; }