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:
parent
83c380bfcd
commit
f192fccf3a
5 changed files with 110 additions and 10 deletions
|
@ -24,13 +24,27 @@ 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mayfly_is_enabled(uint8_t caller_id, uint8_t callee_id)
|
||||
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -29,13 +29,27 @@ 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mayfly_is_enabled(uint8_t caller_id, uint8_t callee_id)
|
||||
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue