Bluetooth: controller: CIS/CIG teardown at ACL disconnect
When an ACL connection with active CISes terminates, inject CIS/CIG teardown to ensure CIS is stopped before ACL disconnection completes. This includes stopping CIG ticker when last CIS has stopped. Signed-off-by: Morten Priess <mtpr@oticon.com>
This commit is contained in:
parent
01e7dd853f
commit
d1f71e93a0
8 changed files with 282 additions and 30 deletions
|
@ -34,12 +34,14 @@
|
|||
#include "ull_conn_types.h"
|
||||
#include "ull_conn_iso_types.h"
|
||||
#include "ull_internal.h"
|
||||
#include "ull_iso_internal.h"
|
||||
#include "ull_sched_internal.h"
|
||||
#include "ull_chan_internal.h"
|
||||
#include "ull_conn_internal.h"
|
||||
#include "ull_slave_internal.h"
|
||||
#include "ull_master_internal.h"
|
||||
|
||||
#include "ull_iso_internal.h"
|
||||
#include "ull_conn_iso_internal.h"
|
||||
#include "ull_peripheral_iso_internal.h"
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_USER_EXT)
|
||||
|
@ -80,6 +82,7 @@ static void ticker_start_conn_op_cb(uint32_t status, void *param);
|
|||
static void conn_setup_adv_scan_disabled_cb(void *param);
|
||||
static inline void disable(uint16_t handle);
|
||||
static void conn_cleanup(struct ll_conn *conn, uint8_t reason);
|
||||
static void conn_cleanup_finalize(struct ll_conn *conn);
|
||||
static void tx_ull_flush(struct ll_conn *conn);
|
||||
static void ticker_op_stop_cb(uint32_t status, void *param);
|
||||
static void disabled_cb(void *param);
|
||||
|
@ -1923,28 +1926,28 @@ static inline void disable(uint16_t handle)
|
|||
conn->lll.link_tx_free = NULL;
|
||||
}
|
||||
|
||||
static void conn_cleanup(struct ll_conn *conn, uint8_t reason)
|
||||
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) || defined(CONFIG_BT_CTLR_CENTRAL_ISO)
|
||||
static void conn_cleanup_iso_cis_released_cb(struct ll_conn *conn)
|
||||
{
|
||||
struct ll_conn_iso_stream *cis;
|
||||
|
||||
cis = ll_conn_iso_stream_get_by_acl(conn, NULL);
|
||||
if (cis) {
|
||||
/* More associated CISes - stop next */
|
||||
ull_conn_iso_cis_stop(cis, conn_cleanup_iso_cis_released_cb);
|
||||
} else {
|
||||
/* No more CISes associated with conn - finalize */
|
||||
conn_cleanup_finalize(conn);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO || CONFIG_BT_CTLR_CENTRAL_ISO */
|
||||
|
||||
static void conn_cleanup_finalize(struct ll_conn *conn)
|
||||
{
|
||||
struct lll_conn *lll = &conn->lll;
|
||||
struct node_rx_pdu *rx;
|
||||
uint32_t ticker_status;
|
||||
|
||||
/* reset mutex */
|
||||
if (conn == conn_upd_curr) {
|
||||
ull_conn_upd_curr_reset();
|
||||
}
|
||||
|
||||
/* Only termination structure is populated here in ULL context
|
||||
* but the actual enqueue happens in the LLL context in
|
||||
* tx_lll_flush. The reason being to avoid passing the reason
|
||||
* value and handle through the mayfly scheduling of the
|
||||
* tx_lll_flush.
|
||||
*/
|
||||
rx = (void *)&conn->llcp_terminate.node_rx;
|
||||
rx->hdr.handle = conn->lll.handle;
|
||||
rx->hdr.type = NODE_RX_TYPE_TERMINATE;
|
||||
*((uint8_t *)rx->pdu) = reason;
|
||||
|
||||
/* release any llcp reserved rx node */
|
||||
rx = conn->llcp_rx;
|
||||
while (rx) {
|
||||
|
@ -1979,6 +1982,42 @@ static void conn_cleanup(struct ll_conn *conn, uint8_t reason)
|
|||
ull_conn_tx_demux(UINT8_MAX);
|
||||
}
|
||||
|
||||
static void conn_cleanup(struct ll_conn *conn, uint8_t reason)
|
||||
{
|
||||
struct node_rx_pdu *rx;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) || defined(CONFIG_BT_CTLR_CENTRAL_ISO)
|
||||
struct ll_conn_iso_stream *cis;
|
||||
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO || CONFIG_BT_CTLR_CENTRAL_ISO */
|
||||
|
||||
/* Reset mutex */
|
||||
if (conn == conn_upd_curr) {
|
||||
ull_conn_upd_curr_reset();
|
||||
}
|
||||
|
||||
/* Only termination structure is populated here in ULL context
|
||||
* but the actual enqueue happens in the LLL context in
|
||||
* tx_lll_flush. The reason being to avoid passing the reason
|
||||
* value and handle through the mayfly scheduling of the
|
||||
* tx_lll_flush.
|
||||
*/
|
||||
rx = (void *)&conn->llcp_terminate.node_rx;
|
||||
rx->hdr.handle = conn->lll.handle;
|
||||
rx->hdr.type = NODE_RX_TYPE_TERMINATE;
|
||||
*((uint8_t *)rx->pdu) = reason;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO) || defined(CONFIG_BT_CTLR_CENTRAL_ISO)
|
||||
cis = ll_conn_iso_stream_get_by_acl(conn, NULL);
|
||||
if (cis) {
|
||||
/* Stop CIS and defer cleanup to after teardown. */
|
||||
ull_conn_iso_cis_stop(cis, conn_cleanup_iso_cis_released_cb);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO || CONFIG_BT_CTLR_CENTRAL_ISO */
|
||||
|
||||
conn_cleanup_finalize(conn);
|
||||
}
|
||||
|
||||
static void tx_ull_flush(struct ll_conn *conn)
|
||||
{
|
||||
while (conn->tx_head) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue