diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 41843ec0f49..de0a097da61 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -77,6 +77,7 @@ static void ticker_update_conn_op_cb(uint32_t status, void *param); static void ticker_stop_conn_op_cb(uint32_t status, void *param); 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 tx_ull_flush(struct ll_conn *conn); @@ -817,10 +818,21 @@ bool ull_conn_peer_connected(uint8_t own_addr_type, uint8_t *own_addr, } #endif /* CONFIG_BT_CTLR_CHECK_SAME_PEER_CONN */ -void ull_conn_setup(memq_link_t *link, struct node_rx_hdr *rx) +void ull_conn_setup(memq_link_t *rx_link, struct node_rx_hdr *rx) { + static memq_link_t link; + static struct mayfly mfy = {0, 0, &link, NULL, NULL}; struct node_rx_ftr *ftr; struct lll_conn *lll; + struct ull_hdr *hdr; + + /* Pass the node rx as mayfly function parameter */ + mfy.param = rx; + + /* Store the link in the node rx so that when done event is + * processed it can be used to enqueue node rx towards LL context + */ + rx->link = rx_link; ftr = &(rx->rx_ftr); @@ -829,22 +841,29 @@ void ull_conn_setup(memq_link_t *link, struct node_rx_hdr *rx) */ lll = *((struct lll_conn **)((uint8_t *)ftr->param + sizeof(struct lll_hdr))); - switch (lll->role) { -#if defined(CONFIG_BT_CENTRAL) - case 0: - ull_master_setup(link, rx, ftr, lll); - break; -#endif /* CONFIG_BT_CENTRAL */ -#if defined(CONFIG_BT_PERIPHERAL) - case 1: - ull_slave_setup(link, rx, ftr, lll); - break; -#endif /* CONFIG_BT_PERIPHERAL */ + /* Check for reference count and decide to setup connection + * here or when done event arrives. + */ + hdr = HDR_LLL2ULL(ftr->param); + if (ull_ref_get(hdr)) { + uint32_t ret; - default: - LL_ASSERT(0); - break; + LL_ASSERT(!hdr->disabled_cb); + hdr->disabled_param = mfy.param; + hdr->disabled_cb = conn_setup_adv_scan_disabled_cb; + + mfy.fp = lll_disable; + ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, + TICKER_USER_ID_LLL, 0, &mfy); + LL_ASSERT(!ret); + } else { + uint32_t ret; + + mfy.fp = conn_setup_adv_scan_disabled_cb; + ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, + TICKER_USER_ID_ULL_HIGH, 0, &mfy); + LL_ASSERT(!ret); } } @@ -1873,6 +1892,39 @@ static void ticker_start_conn_op_cb(uint32_t status, void *param) LL_ASSERT(p == param); } +static void conn_setup_adv_scan_disabled_cb(void *param) +{ + struct node_rx_ftr *ftr; + struct node_rx_hdr *rx; + struct lll_conn *lll; + + rx = param; + ftr = &(rx->rx_ftr); + + /* NOTE: LLL conn context SHALL be after lll_hdr in + * struct lll_adv and struct lll_scan. + */ + lll = *((struct lll_conn **)((uint8_t *)ftr->param + + sizeof(struct lll_hdr))); + switch (lll->role) { +#if defined(CONFIG_BT_CENTRAL) + case 0: + ull_master_setup(rx, ftr, lll); + break; +#endif /* CONFIG_BT_CENTRAL */ + +#if defined(CONFIG_BT_PERIPHERAL) + case 1: + ull_slave_setup(rx, ftr, lll); + break; +#endif /* CONFIG_BT_PERIPHERAL */ + + default: + LL_ASSERT(0); + break; + } +} + static inline void disable(uint16_t handle) { struct ll_conn *conn; diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h index b06dd548555..1009cbe6fbd 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h @@ -20,7 +20,7 @@ uint8_t ull_conn_default_phy_tx_get(void); uint8_t ull_conn_default_phy_rx_get(void); bool ull_conn_peer_connected(uint8_t own_addr_type, uint8_t *own_addr, uint8_t peer_addr_type, uint8_t *peer_addr); -void ull_conn_setup(memq_link_t *link, struct node_rx_hdr *rx); +void ull_conn_setup(memq_link_t *rx_link, struct node_rx_hdr *rx); int ull_conn_rx(memq_link_t *link, struct node_rx_pdu **rx); int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy); void ull_conn_done(struct node_rx_event_done *done); diff --git a/subsys/bluetooth/controller/ll_sw/ull_master.c b/subsys/bluetooth/controller/ll_sw/ull_master.c index e77264ea469..26911ce3361 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_master.c +++ b/subsys/bluetooth/controller/ll_sw/ull_master.c @@ -665,8 +665,8 @@ void ull_master_cleanup(struct node_rx_hdr *rx_free) #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_CTLR_PHY_CODED */ } -void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx, - struct node_rx_ftr *ftr, struct lll_conn *lll) +void ull_master_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr, + struct lll_conn *lll) { uint32_t conn_offset_us, conn_interval_us; uint8_t ticker_id_scan, ticker_id_conn; @@ -679,6 +679,7 @@ void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx, uint32_t ticker_status; struct node_rx_cc *cc; struct ll_conn *conn; + memq_link_t *link; uint8_t chan_sel; /* Get reference to Tx-ed CONNECT_IND PDU */ @@ -741,6 +742,11 @@ void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx, lll->tx_pwr_lvl = RADIO_TXP_DEFAULT; #endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + /* Use the link stored in the node rx to enqueue connection + * complete node rx towards LL context. + */ + link = rx->link; + /* Use Channel Selection Algorithm #2 if peer too supports it */ if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) { struct node_rx_pdu *rx_csa; diff --git a/subsys/bluetooth/controller/ll_sw/ull_master_internal.h b/subsys/bluetooth/controller/ll_sw/ull_master_internal.h index 6909c2ccc3d..d653c8066e2 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_master_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_master_internal.h @@ -5,7 +5,7 @@ */ void ull_master_cleanup(struct node_rx_hdr *rx_free); -void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx, - struct node_rx_ftr *ftr, struct lll_conn *lll); -void ull_master_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy, - uint8_t force, void *param); +void ull_master_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr, + struct lll_conn *lll); +void ull_master_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, + uint16_t lazy, uint8_t force, void *param); diff --git a/subsys/bluetooth/controller/ll_sw/ull_slave.c b/subsys/bluetooth/controller/ll_sw/ull_slave.c index 6ff44120166..e0602c6d729 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_slave.c +++ b/subsys/bluetooth/controller/ll_sw/ull_slave.c @@ -54,8 +54,8 @@ static void ticker_op_cb(uint32_t status, void *param); static void ticker_update_latency_cancel_op_cb(uint32_t ticker_status, void *param); -void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx, - struct node_rx_ftr *ftr, struct lll_conn *lll) +void ull_slave_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr, + struct lll_conn *lll) { uint32_t conn_offset_us, conn_interval_us; uint8_t ticker_id_adv, ticker_id_conn; @@ -72,6 +72,7 @@ void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx, struct node_rx_cc *cc; struct ll_conn *conn; uint16_t win_offset; + memq_link_t *link; uint16_t timeout; uint8_t chan_sel; @@ -99,6 +100,11 @@ void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx, memcpy(peer_id_addr, peer_addr, BDADDR_SIZE); } + /* Use the link stored in the node rx to enqueue connection + * complete node rx towards LL context. + */ + link = rx->link; + #if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_CONN) uint8_t own_addr_type = pdu_adv->rx_addr; uint8_t *own_addr = adv->own_addr; diff --git a/subsys/bluetooth/controller/ll_sw/ull_slave_internal.h b/subsys/bluetooth/controller/ll_sw/ull_slave_internal.h index 2414b4360f3..067631a78e9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_slave_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_slave_internal.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx, - struct node_rx_ftr *ftr, struct lll_conn *lll); +void ull_slave_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr, + struct lll_conn *lll); void ull_slave_latency_cancel(struct ll_conn *conn, uint16_t handle); void ull_slave_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy, uint8_t force, void *param);