This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 0cce6d327e1 drivers/i3c/master.c: Fix IBI completion semaphore handling
0cce6d327e1 is described below
commit 0cce6d327e1d3d58c97ba1bac2e26a7cd5cfbec8
Author: boyangcao <[email protected]>
AuthorDate: Tue Oct 20 17:13:12 2026 +0800
drivers/i3c/master.c: Fix IBI completion semaphore handling
- Use nxsem_post() and nxsem_wait_uninterruptible() for IBI completion
synchronization.
- Initialize all_ibis_handled with a zero count and wait until all pending
IBIs are handled.
- Keep the completion semaphore alive across IBI disable operations.
- Destroy the semaphore when IBI resources are freed or IBI allocation
fails.
- Use atomic_fetch_sub to safely check and decrement pending IBI count
Assisted-by: Codex
Signed-off-by: boyangcao <[email protected]>
---
drivers/i3c/master.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 9859de035ed..9e5ff324ea6 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1187,10 +1187,9 @@ static void i3c_master_handle_ibi(FAR void *arg)
}
master->ops->recycle_ibi_slot(dev, slot);
- atomic_sub(&dev->ibi->pending_ibis, 1);
- if (!atomic_read(&dev->ibi->pending_ibis))
+ if (atomic_sub(&dev->ibi->pending_ibis, 1) == 1)
{
- sem_post(&dev->ibi->all_ibis_handled);
+ nxsem_post(&dev->ibi->all_ibis_handled);
}
}
@@ -2035,13 +2034,21 @@ int i3c_dev_disable_ibi_locked(FAR struct i3c_dev_desc
*dev)
return ret;
}
- if (atomic_read(&dev->ibi->pending_ibis))
+ /* Pair the pending check with the worker's completion notification so
+ * that the IBI state cannot be freed before the final post finishes.
+ * Recheck after each wait because earlier IBIs may have left a token.
+ */
+
+ while (atomic_read(&dev->ibi->pending_ibis))
{
- sem_wait(&dev->ibi->all_ibis_handled);
+ ret = nxsem_wait_uninterruptible(&dev->ibi->all_ibis_handled);
+ if (ret < 0)
+ {
+ return ret;
+ }
}
dev->ibi->enabled = false;
- sem_destroy(&dev->ibi->all_ibis_handled);
return 0;
}
@@ -2089,7 +2096,7 @@ int i3c_dev_request_ibi_locked(FAR struct i3c_dev_desc
*dev,
}
atomic_set(&ibi->pending_ibis, 0);
- sem_init(&ibi->all_ibis_handled, 0, 1);
+ nxsem_init(&ibi->all_ibis_handled, 0, 0);
ibi->handler = req->handler;
ibi->max_payload_len = req->max_payload_len;
ibi->num_slots = req->num_slots;
@@ -2098,6 +2105,7 @@ int i3c_dev_request_ibi_locked(FAR struct i3c_dev_desc
*dev,
ret = master->ops->request_ibi(dev, req);
if (ret)
{
+ nxsem_destroy(&ibi->all_ibis_handled);
kmm_free(ibi);
dev->ibi = NULL;
}
@@ -2115,6 +2123,7 @@ void i3c_dev_free_ibi_locked(FAR struct i3c_dev_desc *dev)
}
master->ops->free_ibi(dev);
+ nxsem_destroy(&dev->ibi->all_ibis_handled);
kmm_free(dev->ibi);
dev->ibi = NULL;
}