Bluetooth: controller: Add lock around LLCP data

Add mayfly locking around the access to the local pending procedure list
as it is accessed by both thread and mayfly.

Fixes #45427

Signed-off-by: Thomas Ebert Hansen <thoh@oticon.com>
This commit is contained in:
Thomas Ebert Hansen 2022-11-15 09:59:49 +01:00 committed by Carles Cufí
commit f192fccf3a
5 changed files with 110 additions and 10 deletions

View file

@ -24,12 +24,26 @@ void mayfly_enable_cb(uint8_t caller_id, uint8_t callee_id, uint8_t enable)
{
(void)caller_id;
LL_ASSERT(callee_id == MAYFLY_CALL_ID_JOB);
switch (callee_id) {
case MAYFLY_CALL_ID_WORKER:
if (enable) {
irq_enable(HAL_SWI_WORKER_IRQ);
} else {
irq_disable(HAL_SWI_WORKER_IRQ);
}
break;
if (enable) {
irq_enable(HAL_SWI_JOB_IRQ);
} else {
irq_disable(HAL_SWI_JOB_IRQ);
case MAYFLY_CALL_ID_JOB:
if (enable) {
irq_enable(HAL_SWI_JOB_IRQ);
} else {
irq_disable(HAL_SWI_JOB_IRQ);
}
break;
default:
LL_ASSERT(0);
break;
}
}
@ -101,3 +115,8 @@ void mayfly_pend(uint8_t caller_id, uint8_t callee_id)
break;
}
}
uint32_t mayfly_is_running(void)
{
return k_is_in_isr();
}

View file

@ -29,12 +29,26 @@ void mayfly_enable_cb(uint8_t caller_id, uint8_t callee_id, uint8_t enable)
{
(void)caller_id;
LL_ASSERT(callee_id == MAYFLY_CALL_ID_JOB);
switch (callee_id) {
case MAYFLY_CALL_ID_WORKER:
if (enable) {
irq_enable(HAL_SWI_WORKER_IRQ);
} else {
irq_disable(HAL_SWI_WORKER_IRQ);
}
break;
if (enable) {
irq_enable(HAL_SWI_JOB_IRQ);
} else {
irq_disable(HAL_SWI_JOB_IRQ);
case MAYFLY_CALL_ID_JOB:
if (enable) {
irq_enable(HAL_SWI_JOB_IRQ);
} else {
irq_disable(HAL_SWI_JOB_IRQ);
}
break;
default:
LL_ASSERT(0);
break;
}
}
@ -112,3 +126,8 @@ void mayfly_pend(uint8_t caller_id, uint8_t callee_id)
break;
}
}
uint32_t mayfly_is_running(void)
{
return k_is_in_isr();
}

View file

@ -16,6 +16,7 @@
#include "util/util.h"
#include "util/mem.h"
#include "util/memq.h"
#include "util/mayfly.h"
#include "util/dbuf.h"
#include "pdu.h"
@ -81,6 +82,35 @@ static void lr_check_done(struct ll_conn *conn, struct proc_ctx *ctx)
llcp_proc_ctx_release(ctx);
}
}
/*
* LLCP Local Request Shared Data Locking
*/
static ALWAYS_INLINE uint32_t shared_data_access_lock(void)
{
bool enabled;
if (mayfly_is_running()) {
/* We are in Mayfly context, nothing to be done */
return false;
}
/* We are in thread context and have to disable TICKER_USER_ID_ULL_HIGH */
enabled = mayfly_is_enabled(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH) != 0U;
mayfly_enable(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH, 0U);
return enabled;
}
static ALWAYS_INLINE void shared_data_access_unlock(bool key)
{
if (key) {
/* We are in thread context and have to reenable TICKER_USER_ID_ULL_HIGH */
mayfly_enable(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH, 1U);
}
}
/*
* LLCP Local Request FSM
*/
@ -92,22 +122,48 @@ static void lr_set_state(struct ll_conn *conn, enum lr_state state)
void llcp_lr_enqueue(struct ll_conn *conn, struct proc_ctx *ctx)
{
/* This function is called from both Thread and Mayfly (ISR),
* make sure only a single context have access at a time.
*/
bool key = shared_data_access_lock();
sys_slist_append(&conn->llcp.local.pend_proc_list, &ctx->node);
shared_data_access_unlock(key);
}
static struct proc_ctx *lr_dequeue(struct ll_conn *conn)
{
/* This function is called from both Thread and Mayfly (ISR),
* make sure only a single context have access at a time.
*/
struct proc_ctx *ctx;
bool key = shared_data_access_lock();
ctx = (struct proc_ctx *)sys_slist_get(&conn->llcp.local.pend_proc_list);
shared_data_access_unlock(key);
return ctx;
}
struct proc_ctx *llcp_lr_peek(struct ll_conn *conn)
{
/* This function is called from both Thread and Mayfly (ISR),
* make sure only a single context have access at a time.
*/
struct proc_ctx *ctx;
bool key = shared_data_access_lock();
ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.local.pend_proc_list);
shared_data_access_unlock(key);
return ctx;
}

View file

@ -30,3 +30,4 @@ extern void mayfly_enable_cb(uint8_t caller_id, uint8_t callee_id, uint8_t enabl
extern uint32_t mayfly_is_enabled(uint8_t caller_id, uint8_t callee_id);
extern uint32_t mayfly_prio_is_equal(uint8_t caller_id, uint8_t callee_id);
extern void mayfly_pend(uint8_t caller_id, uint8_t callee_id);
extern uint32_t mayfly_is_running(void);

View file

@ -31,3 +31,8 @@ uint32_t mayfly_enqueue(uint8_t caller_id, uint8_t callee_id, uint8_t chain, str
void mayfly_run(uint8_t callee_id)
{
}
uint32_t mayfly_is_running(void)
{
return 0U;
}