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
175177uint8_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
15261538void 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
19572040static 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