Commit f192fccf authored by Thomas Ebert Hansen's avatar Thomas Ebert Hansen Committed by Carles Cufi
Browse files

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: default avatarThomas Ebert Hansen <thoh@oticon.com>
parent 83c380bf
Loading
Loading
Loading
Loading
+24 −5
Original line number Diff line number Diff line
@@ -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();
}
+24 −5
Original line number Diff line number Diff line
@@ -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();
}
+56 −0
Original line number Diff line number Diff line
@@ -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;
}

+1 −0
Original line number Diff line number Diff line
@@ -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);
+5 −0
Original line number Diff line number Diff line
@@ -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;
}