drivers: i2s: honour the configured timeout in i2s_buf_write() - #115727
Merged
nashif merged 2 commits intoAug 22, 2026
Conversation
zephyrbot
requested review from
Peterson-Brett,
TomasBarakNXP,
anangl and
mariopaja
August 9, 2026 00:22
Contributor
|
Please check |
sylvioalves
reviewed
Aug 10, 2026
| */ | ||
| ret = k_mem_slab_alloc(tx_cfg->mem_slab, &mem_block, | ||
| tx_cfg->timeout == SYS_FOREVER_MS ? K_FOREVER | ||
| : K_MSEC(tx_cfg->timeout)); |
Contributor
There was a problem hiding this comment.
Suggested change
| : K_MSEC(tx_cfg->timeout)); | |
| : SYS_TIMEOUT_MS(tx_cfg->timeout)); |
Member
Author
There was a problem hiding this comment.
Took it, and a bit further: SYS_TIMEOUT_MS maps SYS_FOREVER_MS itself, so the whole ternary goes.
sylvioalves
reviewed
Aug 10, 2026
Contributor
|
Would you also add an entry in the migration-guide file that |
thc1006
force-pushed
the
fix/i2s-buf-write-honor-timeout
branch
from
August 11, 2026 02:39
d227b81 to
6cf7404
Compare
Member
Author
|
Good catch on the verifier. It had the same |
zephyrbot
requested review from
henrikbrixandersen,
kartben,
nashif and
teburd
August 11, 2026 02:41
i2s_buf_write() acquires its memory block with K_FOREVER, so on a multithreaded build the two error codes it documents for that step can never be produced: -ENOMEM because K_FOREVER does not return it, which also makes the error branch below the call dead code, and -EAGAIN because nothing ever times out. An application that exhausts the slab blocks forever instead of being told. Without CONFIG_MULTITHREADING the slab treats every timeout as no-wait, so only -EAGAIN is unreachable. The userspace path has its own copy. z_vrfy_i2s_buf_write() allocates the same way and then flattens whatever it gets to -ENOMEM, which was harmless only because that branch was equally unreachable. Both copies now use SYS_TIMEOUT_MS(), which already maps SYS_FOREVER_MS itself, and both return the slab's errno unchanged, so the two paths agree. k_mem_slab_alloc() produces exactly the two documented codes: -ENOMEM when told not to wait, which is what a configured timeout of 0 becomes, and -EAGAIN when the wait expires. One consequence is worth stating rather than leaving to be discovered: drivers already apply the same configured timeout when enqueueing the block, so this call can now spend it twice, once acquiring and once enqueueing. Making it a single end-to-end deadline would need a way to pass the remaining time into i2s_write(), which the API has no room for today, so it is documented as a per-stage bound instead. The in-tree suites are unaffected: the loopback test prefills exactly NUM_TX_BLOCKS blocks into a slab of NUM_TX_BLOCKS, so every acquisition succeeds without waiting. Fixes zephyrproject-rtos#113333 Signed-off-by: Hsiu-Chi Tsai <hctsai@linux.com>
thc1006
force-pushed
the
fix/i2s-buf-write-honor-timeout
branch
from
August 12, 2026 10:27
6cf7404 to
b8a7fa7
Compare
sylvioalves
reviewed
Aug 12, 2026
The acquisition now reports an exhausted slab instead of waiting on it, and nothing covered either code it can return. Queue NUM_TX_BLOCKS blocks without starting the stream, which leaves them all owned by the driver, then check that the next call reports -ENOMEM with a timeout of 0 and -EAGAIN with a finite one. Both cases fail before the driver's write(), so no loopback fixture is involved. Draining the slab through i2s_buf_write() rather than the slab API keeps this usable from a user thread, so the same helper can cover the supervisor and userspace copies of the allocation. Signed-off-by: Hsiu-Chi Tsai <hctsai@linux.com>
thc1006
force-pushed
the
fix/i2s-buf-write-honor-timeout
branch
from
August 12, 2026 11:52
b8a7fa7 to
23c35e8
Compare
sylvioalves
approved these changes
Aug 12, 2026
|
dkalowsk
approved these changes
Aug 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



i2s_buf_write()acquires its memory block withK_FOREVER, so on a multithreaded build neither error code it documents for that step can be produced:-ENOMEMbecauseK_FOREVERdoes not return it, which also leaves theif (ret < 0)below the call as dead code, and-EAGAINbecause nothing ever times out. An application that exhausts the TX slab blocks forever instead of being told. WithoutCONFIG_MULTITHREADINGthe slab treats every timeout as no-wait, so only-EAGAINis unreachable there.Passing the configured timeout through fixes both, and
k_mem_slab_alloc()already returns exactly the two documented codes, so the errno goes back unchanged rather than being flattened to-ENOMEM.Fixes #113333
Two stages, not one deadline
Drivers already apply the same configured timeout when enqueueing the block, so after this change the call can spend it twice, once acquiring and once enqueueing. Making it a single end-to-end deadline would need a way to pass the remaining time into
i2s_write(), and the API has no room for that today, so I documented it as a per-stage bound rather than quietly leave the impression it is one.That also means no single
timeoutvalue reproduces the old combination of an unbounded acquisition and a bounded enqueue, which is what the migration note now says.A related problem I am deliberately keeping out of this PR
Several drivers pass
i2s_config.timeoutstraight intoK_MSEC().Z_TIMEOUT_MS()isMAX(t, 0), soSYS_FOREVER_MSbecomesK_NO_WAITthere, and the field documentsSYS_FOREVER_MSas a valid value. Four drivers do this; the twenty other call sites in the subsystem already convert withSYS_TIMEOUT_MS(). It predates this change and is a driver fix rather than an API one, so I filed it separately as #116030.Testing
The two new tests queue
NUM_TX_BLOCKSblocks without starting the stream, which leaves every one of them owned by the driver, then check that the next call reports-ENOMEMwith a timeout of 0 and-EAGAINwith a finite one. Both fail before the driver'swrite(), so no loopback fixture is involved. Draining throughi2s_buf_write()rather than the slab API keeps this usable from a user thread, sincek_mem_slab_alloc()is not a syscall, so one helper covers the supervisor and userspace copies of the allocation.Built for
esp32s3_devkitc/esp32s3/procpu. I have not run the suite on hardware; it needs the loopback fixture.