Commit 5ce5dc05 authored by Wolfgang Puffitsch's avatar Wolfgang Puffitsch Committed by Anas Nashif
Browse files

Bluetooth: controller: Avoid race between ULL and LLL when initiating conn



Use an "initiated" flag in the lll_conn struct to guard the processing
of PDUs related to connection initiation (CONNECT_IND,
AUX_CONNECT_RSP). This avoids races between ULL and LLL when creating
a connection.

Signed-off-by: default avatarWolfgang Puffitsch <wopu@demant.com>
parent 03921279
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ struct lll_conn {
	uint8_t data_chan_count:6;
	uint8_t data_chan_sel:1;
	uint8_t role:1;
	uint8_t initiated:1;

	union {
		struct {
@@ -59,6 +60,7 @@ struct lll_conn {
#if defined(CONFIG_BT_PERIPHERAL)
	struct {
		uint8_t  latency_enabled:1;

		uint32_t window_widening_periodic_us;
		uint32_t window_widening_max_us;
		uint32_t window_widening_prepare_us;
+4 −1
Original line number Diff line number Diff line
@@ -1331,7 +1331,8 @@ static inline int isr_rx_pdu(struct lll_adv *lll,
		   lll_adv_connect_ind_check(lll, pdu_rx, tx_addr, addr,
					     rx_addr, tgt_addr,
					     devmatch_ok, &rl_idx) &&
		   lll->conn) {
		   lll->conn &&
		   !lll->conn->initiated) {
		struct node_rx_ftr *ftr;
		struct node_rx_pdu *rx;
		int ret;
@@ -1366,6 +1367,8 @@ static inline int isr_rx_pdu(struct lll_adv *lll,
		ret = lll_stop(lll);
		LL_ASSERT(!ret);

		lll->conn->initiated = 1;

		rx = ull_pdu_rx_alloc();

		rx->hdr.type = NODE_RX_TYPE_CONNECTION;
+16 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "lll_vendor.h"
#include "lll_clock.h"
#include "lll_chan.h"
#include "lll_conn.h"
#include "lll_adv_types.h"
#include "lll_adv.h"
#include "lll_adv_pdu.h"
@@ -56,7 +57,9 @@ static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux,
			     uint8_t devmatch_ok, uint8_t devmatch_id,
			     uint8_t irkmatch_ok, uint8_t irkmatch_id,
			     uint8_t rssi_ready);
#if defined(CONFIG_BT_PERIPHERAL)
static void isr_tx_connect_rsp(void *param);
#endif /* CONFIG_BT_PERIPHERAL */

static struct pdu_adv *init_connect_rsp_pdu(void)
{
@@ -103,6 +106,7 @@ static struct pdu_adv *init_connect_rsp_pdu(void)
	return pdu;
}

#if defined(CONFIG_BT_PERIPHERAL)
static struct pdu_adv *update_connect_rsp_pdu(struct pdu_adv *pdu_ci)
{
	struct pdu_adv_com_ext_adv *cr_com_hdr;
@@ -127,6 +131,7 @@ static struct pdu_adv *update_connect_rsp_pdu(struct pdu_adv *pdu_ci)

	return pdu_cr;
}
#endif /* CONFIG_BT_PERIPHERAL */

int lll_adv_aux_init(void)
{
@@ -487,7 +492,6 @@ static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux,
	struct pdu_adv *pdu_adv;
	struct pdu_adv *pdu_aux;
	struct pdu_adv *pdu_rx;
	struct pdu_adv *pdu_tx;
	struct lll_adv *lll;
	uint8_t *tgt_addr;
	uint8_t tx_addr;
@@ -566,13 +570,18 @@ static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux,
					 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
		return 0;

#if defined(CONFIG_BT_PERIPHERAL)
	} else if ((pdu_rx->type == PDU_ADV_TYPE_AUX_CONNECT_REQ) &&
		   (pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) &&
		   lll_adv_connect_ind_check(lll, pdu_rx, tx_addr, addr,
					     rx_addr, tgt_addr,
					     devmatch_ok, &rl_idx)) {
					     devmatch_ok, &rl_idx) &&
		   lll->conn &&
		   !lll->conn->initiated) {
		struct node_rx_ftr *ftr;
		struct node_rx_pdu *rx;
		struct pdu_adv *pdu_tx;

		if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
			rx = ull_pdu_rx_alloc_peek(4);
@@ -637,11 +646,13 @@ static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux,
		}

		return 0;
#endif /* CONFIG_BT_PERIPHERAL */
	}

	return -EINVAL;
}

#if defined(CONFIG_BT_PERIPHERAL)
static void isr_tx_connect_rsp(void *param)
{
	struct node_rx_ftr *ftr;
@@ -678,9 +689,12 @@ static void isr_tx_connect_rsp(void *param)
		/* Stop further LLL radio events */
		ret = lll_stop(lll);
		LL_ASSERT(!ret);

		lll->conn->initiated = 1;
	}

	/* Clear radio status and events */
	lll_isr_status_reset();
	lll_isr_cleanup(lll);
}
#endif /* CONFIG_BT_PERIPHERAL */
+3 −1
Original line number Diff line number Diff line
@@ -768,7 +768,7 @@ static inline int isr_rx_pdu(struct lll_scan *lll, struct pdu_adv *pdu_adv_rx,
	if (0) {
#if defined(CONFIG_BT_CENTRAL)
	/* Initiator */
	} else if ((lll->conn) &&
	} else if (lll->conn && !lll->conn->initiated &&
		   isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) {
		struct lll_conn *lll_conn;
		struct node_rx_ftr *ftr;
@@ -925,6 +925,8 @@ static inline int isr_rx_pdu(struct lll_scan *lll, struct pdu_adv *pdu_adv_rx,
		ret = lll_stop(lll);
		LL_ASSERT(!ret);

		lll->conn->initiated = 1;

		rx = ull_pdu_rx_alloc();

		rx->hdr.type = NODE_RX_TYPE_CONNECTION;
+4 −1
Original line number Diff line number Diff line
@@ -896,7 +896,8 @@ static inline int isr_rx_pdu(struct lll_adv *lll,
		   (pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) &&
		   isr_rx_ci_check(lll, pdu_adv, pdu_rx, devmatch_ok,
				   &rl_idx) &&
		   lll->conn) {
		   lll->conn &&
		   !lll->conn->initiated) {
		struct node_rx_ftr *ftr;
		struct node_rx_pdu *rx;
		int ret;
@@ -930,6 +931,8 @@ static inline int isr_rx_pdu(struct lll_adv *lll,
		ret = lll_stop(lll);
		LL_ASSERT(!ret);

		lll->conn->initiated = 1;

		rx = ull_pdu_rx_alloc();

		rx->hdr.type = NODE_RX_TYPE_CONNECTION;
Loading