Commit 30f260df authored by Vinayak Kariappa Chettimada's avatar Vinayak Kariappa Chettimada Committed by Carles Cufi
Browse files

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: default avatarVinayak Kariappa Chettimada <vich@nordicsemi.no>
parent 5e9d6d63
Loading
Loading
Loading
Loading
+67 −15
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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);
+8 −2
Original line number Diff line number Diff line
@@ -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;
+4 −4
Original line number Diff line number Diff line
@@ -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);
+8 −2
Original line number Diff line number Diff line
@@ -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;
Loading