Skip to content

Commit febc615

Browse files
committed
Bluetooth: Controller: Fix ISO Tx ack data flow for context-safety
Fix ISO Tx ack data flow design for context-safety. Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent 79ed38d commit febc615

File tree

1 file changed

+113
-27
lines changed

1 file changed

+113
-27
lines changed

subsys/bluetooth/controller/ll_sw/ull_iso.c

Lines changed: 113 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#include "ull_sync_iso_internal.h"
6161
#include "ull_conn_iso_internal.h"
6262

63+
#include "ll.h"
6364
#include "ll_feat.h"
6465

6566
#include "hal/debug.h"
@@ -150,9 +151,6 @@ static void iso_rx_demux(void *param);
150151
#define ISO_TEST_PACKET_COUNTER_SIZE 4U
151152

152153
#if defined(CONFIG_BT_CTLR_ADV_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)
153-
void ll_iso_link_tx_release(void *link);
154-
void ll_iso_tx_mem_release(void *node_tx);
155-
156154
#define NODE_TX_BUFFER_SIZE MROUND(offsetof(struct node_tx_iso, pdu) + \
157155
offsetof(struct pdu_iso, payload) + \
158156
MAX(LL_BIS_OCTETS_TX_MAX, \
@@ -170,6 +168,10 @@ static struct {
170168
uint8_t pool[sizeof(memq_link_t) * BT_CTLR_ISO_TX_PDU_BUFFERS];
171169
} mem_link_iso_tx;
172170

171+
/* MFIFO for ISO TX acknowledgments from LLL to ULL */
172+
static MFIFO_DEFINE(iso_ack, sizeof(struct lll_tx), BT_CTLR_ISO_TX_PDU_BUFFERS);
173+
174+
static void ull_iso_tx_ack_sched(void);
173175
#endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
174176

175177
uint8_t ll_read_iso_tx_sync(uint16_t handle, uint16_t *seq,
@@ -1477,21 +1479,18 @@ void ull_iso_lll_ack_enqueue(uint16_t handle, struct node_tx_iso *node_tx)
14771479

14781480
if (dp) {
14791481
isoal_tx_pdu_release(dp->source_hdl, node_tx);
1480-
} else {
1482+
return;
1483+
}
1484+
14811485
#if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH)
1482-
/* Possible race with Data Path remove - handle release in vendor
1483-
* function.
1484-
*/
1485-
ll_data_path_tx_pdu_release(handle, node_tx);
1486+
/* Possible race with Data Path remove - handle release in vendor
1487+
* function.
1488+
*/
1489+
ll_data_path_tx_pdu_release(handle, node_tx);
1490+
return;
14861491
#else
1487-
/* FIXME: ll_tx_ack_put is not LLL callable as it is
1488-
* used by ACL connections in ULL context to dispatch
1489-
* ack.
1490-
*/
1491-
ll_tx_ack_put(handle, (void *)node_tx);
1492-
ll_rx_sched();
1492+
/* No datapath and no vendor datapath - fall through to MFIFO */
14931493
#endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */
1494-
}
14951494
} else if (IS_ENABLED(CONFIG_BT_CTLR_ADV_ISO) && IS_ADV_ISO_HANDLE(handle)) {
14961495
struct lll_adv_iso_stream *stream;
14971496
struct ll_iso_datapath *dp;
@@ -1502,25 +1501,38 @@ void ull_iso_lll_ack_enqueue(uint16_t handle, struct node_tx_iso *node_tx)
15021501
dp = stream->dp;
15031502

15041503
if (dp) {
1504+
/* Unified: Use ISOAL like CIS */
15051505
isoal_tx_pdu_release(dp->source_hdl, node_tx);
1506-
} else {
1506+
return;
1507+
}
1508+
15071509
#if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH)
1508-
/* Possible race with Data Path remove - handle release in vendor
1509-
* function.
1510-
*/
1511-
ll_data_path_tx_pdu_release(handle, node_tx);
1510+
ll_data_path_tx_pdu_release(handle, node_tx);
1511+
return;
15121512
#else
1513-
/* FIXME: ll_tx_ack_put is not LLL callable as it is
1514-
* used by ACL connections in ULL context to dispatch
1515-
* ack.
1516-
*/
1517-
ll_tx_ack_put(handle, (void *)node_tx);
1518-
ll_rx_sched();
1513+
/* No datapath and no vendor datapath - fall through to MFIFO */
15191514
#endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */
1520-
}
15211515
} else {
15221516
LL_ASSERT_DBG(0);
1517+
return;
15231518
}
1519+
1520+
/* Context-safe fallback: Enqueue to iso_ack MFIFO when no datapath.
1521+
* This handles CIS/BIS without datapath and without vendor data path support.
1522+
*/
1523+
struct lll_tx *lll_tx;
1524+
uint8_t idx;
1525+
1526+
idx = MFIFO_ENQUEUE_GET(iso_ack, (void **)&lll_tx);
1527+
LL_ASSERT_ERR(lll_tx);
1528+
1529+
lll_tx->handle = handle;
1530+
lll_tx->node = (struct node_tx *)node_tx;
1531+
1532+
MFIFO_ENQUEUE(iso_ack, idx);
1533+
1534+
/* Schedule independent ISO TX ack processing (not serialized with RX) */
1535+
ull_iso_tx_ack_sched();
15241536
}
15251537

15261538
void ull_iso_lll_event_prepare(uint16_t handle, uint64_t event_count)
@@ -1952,6 +1964,77 @@ static isoal_status_t ll_iso_pdu_release(struct node_tx_iso *node_tx,
19521964
return ISOAL_STATUS_OK;
19531965
}
19541966
#endif /* CONFIG_BT_CTLR_CONN_ISO */
1967+
1968+
/**
1969+
* @brief Peek at next ISO TX ack without dequeuing
1970+
*/
1971+
static memq_link_t *ull_iso_ack_peek(uint8_t *ack_last, uint16_t *handle,
1972+
struct node_tx_iso **tx)
1973+
{
1974+
struct lll_tx *lll_tx;
1975+
1976+
lll_tx = MFIFO_DEQUEUE_GET(iso_ack);
1977+
if (!lll_tx) {
1978+
return NULL;
1979+
}
1980+
1981+
if (ack_last) {
1982+
*ack_last = mfifo_fifo_iso_ack.l;
1983+
}
1984+
*handle = lll_tx->handle;
1985+
*tx = (struct node_tx_iso *)lll_tx->node;
1986+
1987+
return (*tx)->link;
1988+
}
1989+
1990+
/**
1991+
* @brief Dequeue ISO TX ack from MFIFO
1992+
*/
1993+
static void *ull_iso_ack_dequeue(void)
1994+
{
1995+
return MFIFO_DEQUEUE(iso_ack);
1996+
}
1997+
1998+
/**
1999+
* @brief Process ISO TX acknowledgments independently
2000+
* @details Processes iso_ack MFIFO without serialization with RX
2001+
*/
2002+
static void iso_tx_ack_demux(void *param)
2003+
{
2004+
struct node_tx_iso *node_tx;
2005+
memq_link_t *link;
2006+
uint16_t handle;
2007+
2008+
/* Process all pending ISO TX acks */
2009+
do {
2010+
link = ull_iso_ack_peek(NULL, &handle, &node_tx);
2011+
if (link) {
2012+
/* Dequeue from iso_ack MFIFO */
2013+
ull_iso_ack_dequeue();
2014+
2015+
/* Now safely call ll_tx_ack_put in ULL context */
2016+
ll_tx_ack_put(handle, (struct node_tx *)node_tx);
2017+
2018+
/* Release link mem */
2019+
ll_iso_link_tx_release(link);
2020+
}
2021+
} while (link);
2022+
2023+
/* Trigger thread to call ll_rx_get() */
2024+
ll_rx_sched();
2025+
}
2026+
2027+
/**
2028+
* @brief Schedule ISO TX ack processing
2029+
*/
2030+
static void ull_iso_tx_ack_sched(void)
2031+
{
2032+
static memq_link_t link;
2033+
static struct mayfly mfy = {0, 0, &link, NULL, iso_tx_ack_demux};
2034+
2035+
/* Kick the ULL (using the mayfly, tailchain it) */
2036+
mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_HIGH, 1, &mfy);
2037+
}
19552038
#endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
19562039

19572040
static int init_reset(void)
@@ -1988,6 +2071,9 @@ static int init_reset(void)
19882071
/* Initialize tx link pool. */
19892072
mem_init(mem_link_iso_tx.pool, sizeof(memq_link_t), BT_CTLR_ISO_TX_PDU_BUFFERS,
19902073
&mem_link_iso_tx.free);
2074+
2075+
/* Initialize iso_ack MFIFO */
2076+
MFIFO_INIT(iso_ack);
19912077
#endif /* CONFIG_BT_CTLR_ADV_ISO || CONFIG_BT_CTLR_CONN_ISO */
19922078

19932079
#if BT_CTLR_ISO_STREAMS

0 commit comments

Comments
 (0)