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: Wolfgang Puffitsch <wopu@demant.com>
This commit is contained in:
parent
0392127997
commit
5ce5dc055e
8 changed files with 34 additions and 6 deletions
|
@ -46,6 +46,7 @@ struct lll_conn {
|
||||||
uint8_t data_chan_count:6;
|
uint8_t data_chan_count:6;
|
||||||
uint8_t data_chan_sel:1;
|
uint8_t data_chan_sel:1;
|
||||||
uint8_t role:1;
|
uint8_t role:1;
|
||||||
|
uint8_t initiated:1;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
|
@ -59,6 +60,7 @@ struct lll_conn {
|
||||||
#if defined(CONFIG_BT_PERIPHERAL)
|
#if defined(CONFIG_BT_PERIPHERAL)
|
||||||
struct {
|
struct {
|
||||||
uint8_t latency_enabled:1;
|
uint8_t latency_enabled:1;
|
||||||
|
|
||||||
uint32_t window_widening_periodic_us;
|
uint32_t window_widening_periodic_us;
|
||||||
uint32_t window_widening_max_us;
|
uint32_t window_widening_max_us;
|
||||||
uint32_t window_widening_prepare_us;
|
uint32_t window_widening_prepare_us;
|
||||||
|
|
|
@ -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,
|
lll_adv_connect_ind_check(lll, pdu_rx, tx_addr, addr,
|
||||||
rx_addr, tgt_addr,
|
rx_addr, tgt_addr,
|
||||||
devmatch_ok, &rl_idx) &&
|
devmatch_ok, &rl_idx) &&
|
||||||
lll->conn) {
|
lll->conn &&
|
||||||
|
!lll->conn->initiated) {
|
||||||
struct node_rx_ftr *ftr;
|
struct node_rx_ftr *ftr;
|
||||||
struct node_rx_pdu *rx;
|
struct node_rx_pdu *rx;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1366,6 +1367,8 @@ static inline int isr_rx_pdu(struct lll_adv *lll,
|
||||||
ret = lll_stop(lll);
|
ret = lll_stop(lll);
|
||||||
LL_ASSERT(!ret);
|
LL_ASSERT(!ret);
|
||||||
|
|
||||||
|
lll->conn->initiated = 1;
|
||||||
|
|
||||||
rx = ull_pdu_rx_alloc();
|
rx = ull_pdu_rx_alloc();
|
||||||
|
|
||||||
rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "lll_vendor.h"
|
#include "lll_vendor.h"
|
||||||
#include "lll_clock.h"
|
#include "lll_clock.h"
|
||||||
#include "lll_chan.h"
|
#include "lll_chan.h"
|
||||||
|
#include "lll_conn.h"
|
||||||
#include "lll_adv_types.h"
|
#include "lll_adv_types.h"
|
||||||
#include "lll_adv.h"
|
#include "lll_adv.h"
|
||||||
#include "lll_adv_pdu.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 devmatch_ok, uint8_t devmatch_id,
|
||||||
uint8_t irkmatch_ok, uint8_t irkmatch_id,
|
uint8_t irkmatch_ok, uint8_t irkmatch_id,
|
||||||
uint8_t rssi_ready);
|
uint8_t rssi_ready);
|
||||||
|
#if defined(CONFIG_BT_PERIPHERAL)
|
||||||
static void isr_tx_connect_rsp(void *param);
|
static void isr_tx_connect_rsp(void *param);
|
||||||
|
#endif /* CONFIG_BT_PERIPHERAL */
|
||||||
|
|
||||||
static struct pdu_adv *init_connect_rsp_pdu(void)
|
static struct pdu_adv *init_connect_rsp_pdu(void)
|
||||||
{
|
{
|
||||||
|
@ -103,6 +106,7 @@ static struct pdu_adv *init_connect_rsp_pdu(void)
|
||||||
return pdu;
|
return pdu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_PERIPHERAL)
|
||||||
static struct pdu_adv *update_connect_rsp_pdu(struct pdu_adv *pdu_ci)
|
static struct pdu_adv *update_connect_rsp_pdu(struct pdu_adv *pdu_ci)
|
||||||
{
|
{
|
||||||
struct pdu_adv_com_ext_adv *cr_com_hdr;
|
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;
|
return pdu_cr;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_BT_PERIPHERAL */
|
||||||
|
|
||||||
int lll_adv_aux_init(void)
|
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_adv;
|
||||||
struct pdu_adv *pdu_aux;
|
struct pdu_adv *pdu_aux;
|
||||||
struct pdu_adv *pdu_rx;
|
struct pdu_adv *pdu_rx;
|
||||||
struct pdu_adv *pdu_tx;
|
|
||||||
struct lll_adv *lll;
|
struct lll_adv *lll;
|
||||||
uint8_t *tgt_addr;
|
uint8_t *tgt_addr;
|
||||||
uint8_t tx_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);
|
CONFIG_BT_CTLR_GPIO_PA_OFFSET);
|
||||||
#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
|
#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_PERIPHERAL)
|
||||||
} else if ((pdu_rx->type == PDU_ADV_TYPE_AUX_CONNECT_REQ) &&
|
} else if ((pdu_rx->type == PDU_ADV_TYPE_AUX_CONNECT_REQ) &&
|
||||||
(pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) &&
|
(pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) &&
|
||||||
lll_adv_connect_ind_check(lll, pdu_rx, tx_addr, addr,
|
lll_adv_connect_ind_check(lll, pdu_rx, tx_addr, addr,
|
||||||
rx_addr, tgt_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_ftr *ftr;
|
||||||
struct node_rx_pdu *rx;
|
struct node_rx_pdu *rx;
|
||||||
|
struct pdu_adv *pdu_tx;
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
|
if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
|
||||||
rx = ull_pdu_rx_alloc_peek(4);
|
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;
|
return 0;
|
||||||
|
#endif /* CONFIG_BT_PERIPHERAL */
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_PERIPHERAL)
|
||||||
static void isr_tx_connect_rsp(void *param)
|
static void isr_tx_connect_rsp(void *param)
|
||||||
{
|
{
|
||||||
struct node_rx_ftr *ftr;
|
struct node_rx_ftr *ftr;
|
||||||
|
@ -678,9 +689,12 @@ static void isr_tx_connect_rsp(void *param)
|
||||||
/* Stop further LLL radio events */
|
/* Stop further LLL radio events */
|
||||||
ret = lll_stop(lll);
|
ret = lll_stop(lll);
|
||||||
LL_ASSERT(!ret);
|
LL_ASSERT(!ret);
|
||||||
|
|
||||||
|
lll->conn->initiated = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear radio status and events */
|
/* Clear radio status and events */
|
||||||
lll_isr_status_reset();
|
lll_isr_status_reset();
|
||||||
lll_isr_cleanup(lll);
|
lll_isr_cleanup(lll);
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_BT_PERIPHERAL */
|
||||||
|
|
|
@ -768,7 +768,7 @@ static inline int isr_rx_pdu(struct lll_scan *lll, struct pdu_adv *pdu_adv_rx,
|
||||||
if (0) {
|
if (0) {
|
||||||
#if defined(CONFIG_BT_CENTRAL)
|
#if defined(CONFIG_BT_CENTRAL)
|
||||||
/* Initiator */
|
/* Initiator */
|
||||||
} else if ((lll->conn) &&
|
} else if (lll->conn && !lll->conn->initiated &&
|
||||||
isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) {
|
isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) {
|
||||||
struct lll_conn *lll_conn;
|
struct lll_conn *lll_conn;
|
||||||
struct node_rx_ftr *ftr;
|
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);
|
ret = lll_stop(lll);
|
||||||
LL_ASSERT(!ret);
|
LL_ASSERT(!ret);
|
||||||
|
|
||||||
|
lll->conn->initiated = 1;
|
||||||
|
|
||||||
rx = ull_pdu_rx_alloc();
|
rx = ull_pdu_rx_alloc();
|
||||||
|
|
||||||
rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
||||||
|
|
|
@ -896,7 +896,8 @@ static inline int isr_rx_pdu(struct lll_adv *lll,
|
||||||
(pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) &&
|
(pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) &&
|
||||||
isr_rx_ci_check(lll, pdu_adv, pdu_rx, devmatch_ok,
|
isr_rx_ci_check(lll, pdu_adv, pdu_rx, devmatch_ok,
|
||||||
&rl_idx) &&
|
&rl_idx) &&
|
||||||
lll->conn) {
|
lll->conn &&
|
||||||
|
!lll->conn->initiated) {
|
||||||
struct node_rx_ftr *ftr;
|
struct node_rx_ftr *ftr;
|
||||||
struct node_rx_pdu *rx;
|
struct node_rx_pdu *rx;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -930,6 +931,8 @@ static inline int isr_rx_pdu(struct lll_adv *lll,
|
||||||
ret = lll_stop(lll);
|
ret = lll_stop(lll);
|
||||||
LL_ASSERT(!ret);
|
LL_ASSERT(!ret);
|
||||||
|
|
||||||
|
lll->conn->initiated = 1;
|
||||||
|
|
||||||
rx = ull_pdu_rx_alloc();
|
rx = ull_pdu_rx_alloc();
|
||||||
|
|
||||||
rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
||||||
|
|
|
@ -672,7 +672,7 @@ static inline uint32_t isr_rx_pdu(struct lll_scan *lll, uint8_t devmatch_ok,
|
||||||
if (0) {
|
if (0) {
|
||||||
#if defined(CONFIG_BT_CENTRAL)
|
#if defined(CONFIG_BT_CENTRAL)
|
||||||
/* Initiator */
|
/* Initiator */
|
||||||
} else if ((lll->conn) &&
|
} else if (lll->conn && !lll->conn->initiated &&
|
||||||
isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) {
|
isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) {
|
||||||
struct lll_conn *lll_conn;
|
struct lll_conn *lll_conn;
|
||||||
struct node_rx_ftr *ftr;
|
struct node_rx_ftr *ftr;
|
||||||
|
@ -829,6 +829,8 @@ static inline uint32_t isr_rx_pdu(struct lll_scan *lll, uint8_t devmatch_ok,
|
||||||
ret = lll_stop(lll);
|
ret = lll_stop(lll);
|
||||||
LL_ASSERT(!ret);
|
LL_ASSERT(!ret);
|
||||||
|
|
||||||
|
lll->conn->initiated = 1;
|
||||||
|
|
||||||
rx = ull_pdu_rx_alloc();
|
rx = ull_pdu_rx_alloc();
|
||||||
|
|
||||||
rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
||||||
|
|
|
@ -872,6 +872,7 @@ uint8_t ll_adv_enable(uint8_t enable)
|
||||||
|
|
||||||
/* FIXME: BEGIN: Move to ULL? */
|
/* FIXME: BEGIN: Move to ULL? */
|
||||||
conn_lll->role = 1;
|
conn_lll->role = 1;
|
||||||
|
conn_lll->initiated = 0;
|
||||||
conn_lll->data_chan_sel = 0;
|
conn_lll->data_chan_sel = 0;
|
||||||
conn_lll->data_chan_use = 0;
|
conn_lll->data_chan_use = 0;
|
||||||
conn_lll->event_counter = 0;
|
conn_lll->event_counter = 0;
|
||||||
|
|
|
@ -213,6 +213,7 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
|
||||||
conn_lll->data_chan_sel = 0;
|
conn_lll->data_chan_sel = 0;
|
||||||
conn_lll->data_chan_use = 0;
|
conn_lll->data_chan_use = 0;
|
||||||
conn_lll->role = 0;
|
conn_lll->role = 0;
|
||||||
|
conn_lll->initiated = 0;
|
||||||
/* FIXME: END: Move to ULL? */
|
/* FIXME: END: Move to ULL? */
|
||||||
#if defined(CONFIG_BT_CTLR_CONN_META)
|
#if defined(CONFIG_BT_CTLR_CONN_META)
|
||||||
memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta));
|
memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue