Bluetooth: controller: Fix adv/scan context access post release
Fix advertiser and scanning context being accessed on done event when connection complete node rx that is processed earlier has release them. Relates to #30735. Fixes #35013. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
5e9d6d638c
commit
30f260dfaa
6 changed files with 90 additions and 26 deletions
|
@ -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_stop_conn_op_cb(uint32_t status, void *param);
|
||||||
static void ticker_start_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 inline void disable(uint16_t handle);
|
||||||
static void conn_cleanup(struct ll_conn *conn, uint8_t reason);
|
static void conn_cleanup(struct ll_conn *conn, uint8_t reason);
|
||||||
static void tx_ull_flush(struct ll_conn *conn);
|
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 */
|
#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 node_rx_ftr *ftr;
|
||||||
struct lll_conn *lll;
|
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);
|
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 +
|
lll = *((struct lll_conn **)((uint8_t *)ftr->param +
|
||||||
sizeof(struct lll_hdr)));
|
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)
|
/* Check for reference count and decide to setup connection
|
||||||
case 1:
|
* here or when done event arrives.
|
||||||
ull_slave_setup(link, rx, ftr, lll);
|
*/
|
||||||
break;
|
hdr = HDR_LLL2ULL(ftr->param);
|
||||||
#endif /* CONFIG_BT_PERIPHERAL */
|
if (ull_ref_get(hdr)) {
|
||||||
|
uint32_t ret;
|
||||||
|
|
||||||
default:
|
LL_ASSERT(!hdr->disabled_cb);
|
||||||
LL_ASSERT(0);
|
hdr->disabled_param = mfy.param;
|
||||||
break;
|
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);
|
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)
|
static inline void disable(uint16_t handle)
|
||||||
{
|
{
|
||||||
struct ll_conn *conn;
|
struct ll_conn *conn;
|
||||||
|
|
|
@ -20,7 +20,7 @@ uint8_t ull_conn_default_phy_tx_get(void);
|
||||||
uint8_t ull_conn_default_phy_rx_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,
|
bool ull_conn_peer_connected(uint8_t own_addr_type, uint8_t *own_addr,
|
||||||
uint8_t peer_addr_type, uint8_t *peer_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_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);
|
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);
|
void ull_conn_done(struct node_rx_event_done *done);
|
||||||
|
|
|
@ -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 */
|
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_CTLR_PHY_CODED */
|
||||||
}
|
}
|
||||||
|
|
||||||
void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx,
|
void ull_master_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr,
|
||||||
struct node_rx_ftr *ftr, struct lll_conn *lll)
|
struct lll_conn *lll)
|
||||||
{
|
{
|
||||||
uint32_t conn_offset_us, conn_interval_us;
|
uint32_t conn_offset_us, conn_interval_us;
|
||||||
uint8_t ticker_id_scan, ticker_id_conn;
|
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;
|
uint32_t ticker_status;
|
||||||
struct node_rx_cc *cc;
|
struct node_rx_cc *cc;
|
||||||
struct ll_conn *conn;
|
struct ll_conn *conn;
|
||||||
|
memq_link_t *link;
|
||||||
uint8_t chan_sel;
|
uint8_t chan_sel;
|
||||||
|
|
||||||
/* Get reference to Tx-ed CONNECT_IND PDU */
|
/* 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;
|
lll->tx_pwr_lvl = RADIO_TXP_DEFAULT;
|
||||||
#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
|
#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 */
|
/* Use Channel Selection Algorithm #2 if peer too supports it */
|
||||||
if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
|
if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
|
||||||
struct node_rx_pdu *rx_csa;
|
struct node_rx_pdu *rx_csa;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ull_master_cleanup(struct node_rx_hdr *rx_free);
|
void ull_master_cleanup(struct node_rx_hdr *rx_free);
|
||||||
void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx,
|
void ull_master_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr,
|
||||||
struct node_rx_ftr *ftr, struct lll_conn *lll);
|
struct lll_conn *lll);
|
||||||
void ull_master_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
|
void ull_master_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
|
||||||
uint8_t force, void *param);
|
uint16_t lazy, uint8_t force, void *param);
|
||||||
|
|
|
@ -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,
|
static void ticker_update_latency_cancel_op_cb(uint32_t ticker_status,
|
||||||
void *param);
|
void *param);
|
||||||
|
|
||||||
void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx,
|
void ull_slave_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr,
|
||||||
struct node_rx_ftr *ftr, struct lll_conn *lll)
|
struct lll_conn *lll)
|
||||||
{
|
{
|
||||||
uint32_t conn_offset_us, conn_interval_us;
|
uint32_t conn_offset_us, conn_interval_us;
|
||||||
uint8_t ticker_id_adv, ticker_id_conn;
|
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 node_rx_cc *cc;
|
||||||
struct ll_conn *conn;
|
struct ll_conn *conn;
|
||||||
uint16_t win_offset;
|
uint16_t win_offset;
|
||||||
|
memq_link_t *link;
|
||||||
uint16_t timeout;
|
uint16_t timeout;
|
||||||
uint8_t chan_sel;
|
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);
|
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)
|
#if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_CONN)
|
||||||
uint8_t own_addr_type = pdu_adv->rx_addr;
|
uint8_t own_addr_type = pdu_adv->rx_addr;
|
||||||
uint8_t *own_addr = adv->own_addr;
|
uint8_t *own_addr = adv->own_addr;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx,
|
void ull_slave_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr,
|
||||||
struct node_rx_ftr *ftr, struct lll_conn *lll);
|
struct lll_conn *lll);
|
||||||
void ull_slave_latency_cancel(struct ll_conn *conn, uint16_t handle);
|
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,
|
void ull_slave_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
|
||||||
uint16_t lazy, uint8_t force, void *param);
|
uint16_t lazy, uint8_t force, void *param);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue