Bluetooth: Controller: Fix LLL events pending check from ULL Low
ULL reference count is checked in ULL_LOW context to decide if LLL events are pending, but the reference count can be decremented by the ULL HIGH execution context which can prevent the set `disabled_cb` function not being called due to no pending event to produce the done events. Fixed by checking the reference count in the ULL HIGH execution context using a mayfly to schedule the check. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
d2be89d725
commit
f06ac2be2c
3 changed files with 126 additions and 92 deletions
|
@ -84,6 +84,7 @@ static void conn_cleanup(struct ll_conn *conn, uint8_t reason);
|
|||
static void conn_cleanup_finalize(struct ll_conn *conn);
|
||||
static void tx_ull_flush(struct ll_conn *conn);
|
||||
static void ticker_stop_op_cb(uint32_t status, void *param);
|
||||
static void conn_disable(void *param);
|
||||
static void disabled_cb(void *param);
|
||||
static void tx_lll_flush(void *param);
|
||||
|
||||
|
@ -2039,39 +2040,47 @@ static void tx_ull_flush(struct ll_conn *conn)
|
|||
static void ticker_stop_op_cb(uint32_t status, void *param)
|
||||
{
|
||||
static memq_link_t link;
|
||||
static struct mayfly mfy = {0, 0, &link, NULL, NULL};
|
||||
struct ll_conn *conn;
|
||||
struct ull_hdr *hdr;
|
||||
static struct mayfly mfy = {0, 0, &link, NULL, conn_disable};
|
||||
uint32_t ret;
|
||||
|
||||
LL_ASSERT(status == TICKER_STATUS_SUCCESS);
|
||||
|
||||
/* NOTE: We are in ULL_LOW which can be pre-empted by ULL_HIGH.
|
||||
* As we are in the callback after successful stop of the
|
||||
* ticker, the ULL reference count will not be modified
|
||||
* further hence it is safe to check and act on either the need
|
||||
* to call lll_disable or not.
|
||||
*/
|
||||
/* Check if any pending LLL events that need to be aborted */
|
||||
mfy.param = param;
|
||||
ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW,
|
||||
TICKER_USER_ID_ULL_HIGH, 0, &mfy);
|
||||
LL_ASSERT(!ret);
|
||||
}
|
||||
|
||||
static void conn_disable(void *param)
|
||||
{
|
||||
struct ll_conn *conn;
|
||||
struct ull_hdr *hdr;
|
||||
|
||||
/* Check ref count to determine if any pending LLL events in pipeline */
|
||||
conn = param;
|
||||
hdr = &conn->ull;
|
||||
mfy.param = &conn->lll;
|
||||
if (ull_ref_get(hdr)) {
|
||||
static memq_link_t link;
|
||||
static struct mayfly mfy = {0, 0, &link, NULL, lll_disable};
|
||||
uint32_t ret;
|
||||
|
||||
mfy.param = &conn->lll;
|
||||
|
||||
/* Setup disabled callback to be called when ref count
|
||||
* returns to zero.
|
||||
*/
|
||||
LL_ASSERT(!hdr->disabled_cb);
|
||||
hdr->disabled_param = mfy.param;
|
||||
hdr->disabled_cb = disabled_cb;
|
||||
|
||||
mfy.fp = lll_disable;
|
||||
ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW,
|
||||
/* Trigger LLL disable */
|
||||
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
|
||||
TICKER_USER_ID_LLL, 0, &mfy);
|
||||
LL_ASSERT(!ret);
|
||||
} else {
|
||||
uint32_t ret;
|
||||
|
||||
mfy.fp = disabled_cb;
|
||||
ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW,
|
||||
TICKER_USER_ID_ULL_HIGH, 0, &mfy);
|
||||
LL_ASSERT(!ret);
|
||||
/* No pending LLL events */
|
||||
disabled_cb(&conn->lll);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue