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,12 +24,26 @@ void mayfly_enable_cb(uint8_t caller_id, uint8_t callee_id, uint8_t enable)
|
||||||
{
|
{
|
||||||
(void)caller_id;
|
(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) {
|
case MAYFLY_CALL_ID_JOB:
|
||||||
irq_enable(HAL_SWI_JOB_IRQ);
|
if (enable) {
|
||||||
} else {
|
irq_enable(HAL_SWI_JOB_IRQ);
|
||||||
irq_disable(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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t mayfly_is_running(void)
|
||||||
|
{
|
||||||
|
return k_is_in_isr();
|
||||||
|
}
|
||||||
|
|
|
@ -29,12 +29,26 @@ void mayfly_enable_cb(uint8_t caller_id, uint8_t callee_id, uint8_t enable)
|
||||||
{
|
{
|
||||||
(void)caller_id;
|
(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) {
|
case MAYFLY_CALL_ID_JOB:
|
||||||
irq_enable(HAL_SWI_JOB_IRQ);
|
if (enable) {
|
||||||
} else {
|
irq_enable(HAL_SWI_JOB_IRQ);
|
||||||
irq_disable(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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t mayfly_is_running(void)
|
||||||
|
{
|
||||||
|
return k_is_in_isr();
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "util/mem.h"
|
#include "util/mem.h"
|
||||||
#include "util/memq.h"
|
#include "util/memq.h"
|
||||||
|
#include "util/mayfly.h"
|
||||||
#include "util/dbuf.h"
|
#include "util/dbuf.h"
|
||||||
|
|
||||||
#include "pdu.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_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
|
* 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)
|
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);
|
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)
|
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;
|
struct proc_ctx *ctx;
|
||||||
|
|
||||||
|
bool key = shared_data_access_lock();
|
||||||
|
|
||||||
ctx = (struct proc_ctx *)sys_slist_get(&conn->llcp.local.pend_proc_list);
|
ctx = (struct proc_ctx *)sys_slist_get(&conn->llcp.local.pend_proc_list);
|
||||||
|
|
||||||
|
shared_data_access_unlock(key);
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct proc_ctx *llcp_lr_peek(struct ll_conn *conn)
|
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;
|
struct proc_ctx *ctx;
|
||||||
|
|
||||||
|
bool key = shared_data_access_lock();
|
||||||
|
|
||||||
ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.local.pend_proc_list);
|
ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.local.pend_proc_list);
|
||||||
|
|
||||||
|
shared_data_access_unlock(key);
|
||||||
|
|
||||||
return ctx;
|
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_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 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 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)
|
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