From b5c63c69caa4c1169239d6d3fa6e8e2cc52dff7d Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 10 Jan 2020 16:13:16 +0530 Subject: [PATCH] Bluetooth: controller: split: Fix ull_disable hang Under race conditions it is possible that there is no call to k_sem_give to the waiting k_sem_take in the ull_disable function. ull_disable function checks for reference count before using a mayfly to schedule lll_disable, which in turn would close requested currently active role event leading to done event being propogated to ULL. Done event would then call the set disabled_cb callback when the reference count is zero, giving the semaphore to the waiting k_sem_give in the ull_disable. Under race conditions if the reference count reached zero after the reference count check and before the disabled_cb was assigned in the ull_disable function, then there are chances that a k_sem_give is not called while ull_disable proceeds to waiting using k_sem_take. Fixes #21586. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/ll_sw/ull.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index ccb2329b764..335c4667c85 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -1035,14 +1035,19 @@ int ull_disable(void *lll) u32_t ret; hdr = HDR_ULL(((struct lll_hdr *)lll)->parent); - if (!hdr || !hdr->ref) { + if (!hdr) { return ULL_STATUS_SUCCESS; } k_sem_init(&sem, 0, 1); + hdr->disabled_param = &sem; hdr->disabled_cb = disabled_cb; + if (!hdr->ref) { + return ULL_STATUS_SUCCESS; + } + mfy.param = lll; ret = mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_LLL, 0, &mfy);