Bluetooth: controller: Implement disabling the other PHY initiator
When connection is initiated in one of either 1M or Coded PHY initiating scan instance then the other scanning instance's scheduling and memory allocation needs to be cleaned up. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
9eb5f85870
commit
a6b8eba7c5
@ -24,9 +24,7 @@ struct lll_scan {
|
||||
uint8_t filter_policy:2;
|
||||
uint8_t type:1;
|
||||
uint8_t init_addr_type:1;
|
||||
#if defined(CONFIG_BT_CENTRAL)
|
||||
uint8_t adv_addr_type:1;
|
||||
#endif /* CONFIG_BT_CENTRAL */
|
||||
uint8_t is_stop:1;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
uint16_t duration_reload;
|
||||
@ -35,6 +33,10 @@ struct lll_scan {
|
||||
uint8_t is_adv_ind:1;
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||
|
||||
#if defined(CONFIG_BT_CENTRAL)
|
||||
uint8_t adv_addr_type:1;
|
||||
#endif /* CONFIG_BT_CENTRAL */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
||||
uint8_t rpa_gen:1;
|
||||
/* initiator only */
|
||||
|
||||
@ -217,9 +217,10 @@ static int prepare_cb(struct lll_prepare_param *p)
|
||||
/* Check if stopped (on connection establishment race between LLL and
|
||||
* ULL.
|
||||
*/
|
||||
if (unlikely(lll->conn &&
|
||||
(lll->conn->master.initiated ||
|
||||
lll->conn->master.cancelled))) {
|
||||
if (unlikely(lll->is_stop ||
|
||||
(lll->conn &&
|
||||
(lll->conn->master.initiated ||
|
||||
lll->conn->master.cancelled)))) {
|
||||
radio_isr_set(lll_isr_early_abort, lll);
|
||||
radio_disable();
|
||||
|
||||
@ -960,8 +961,14 @@ static inline int isr_rx_pdu(struct lll_scan *lll, struct pdu_adv *pdu_adv_rx,
|
||||
* radio_status_reset();
|
||||
*/
|
||||
|
||||
/* Stop further LLL radio events */
|
||||
lll->conn->master.initiated = 1;
|
||||
/* Stop further connection initiation */
|
||||
/* FIXME: for extended connection initiation, handle reset on
|
||||
* event aborted before connect_rsp is received.
|
||||
*/
|
||||
lll->conn->master.initiated = 1U;
|
||||
|
||||
/* Stop further initiating events */
|
||||
lll->is_stop = 1U;
|
||||
|
||||
rx = ull_pdu_rx_alloc();
|
||||
|
||||
|
||||
@ -124,17 +124,32 @@ static int prepare_cb(struct lll_prepare_param *p)
|
||||
|
||||
DEBUG_RADIO_START_O(1);
|
||||
|
||||
lll = p->param;
|
||||
aux_set = HDR_LLL2ULL(lll);
|
||||
scan_set = HDR_LLL2ULL(aux_set->rx_head->rx_ftr.param);
|
||||
lll_scan = &scan_set->lll;
|
||||
|
||||
#if defined(CONFIG_BT_CENTRAL)
|
||||
/* Check if stopped (on connection establishment race between LLL and
|
||||
* ULL.
|
||||
*/
|
||||
if (unlikely(lll_scan->is_stop ||
|
||||
(lll_scan->conn &&
|
||||
(lll_scan->conn->master.initiated ||
|
||||
lll_scan->conn->master.cancelled)))) {
|
||||
radio_isr_set(lll_isr_early_abort, lll);
|
||||
radio_disable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_CENTRAL */
|
||||
|
||||
/* Start setting up Radio h/w */
|
||||
radio_reset();
|
||||
|
||||
/* Reset Tx/rx count */
|
||||
trx_cnt = 0U;
|
||||
|
||||
lll = p->param;
|
||||
aux_set = HDR_LLL2ULL(lll);
|
||||
scan_set = HDR_LLL2ULL(aux_set->rx_head->rx_ftr.param);
|
||||
lll_scan = &scan_set->lll;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
|
||||
radio_tx_power_set(lll->tx_pwr_lvl);
|
||||
#else
|
||||
@ -371,7 +386,7 @@ static int isr_rx_pdu(struct lll_scan_aux *lll, uint8_t devmatch_ok,
|
||||
if (0) {
|
||||
#if defined(CONFIG_BT_CENTRAL)
|
||||
/* Initiator */
|
||||
} else if (lll_scan->conn &&
|
||||
} else if (lll_scan->conn && !lll_scan->conn->master.cancelled &&
|
||||
(pdu->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_CONN) &&
|
||||
isr_scan_init_check(lll_scan, pdu, rl_idx)) {
|
||||
struct node_rx_ftr *ftr;
|
||||
@ -493,6 +508,12 @@ static int isr_rx_pdu(struct lll_scan_aux *lll, uint8_t devmatch_ok,
|
||||
* radio_status_reset();
|
||||
*/
|
||||
|
||||
/* Stop further connection initiation */
|
||||
lll_scan->conn->master.initiated = 1U;
|
||||
|
||||
/* Stop further initiating events */
|
||||
lll_scan->is_stop = 1U;
|
||||
|
||||
rx = ull_pdu_rx_alloc();
|
||||
|
||||
rx->hdr.type = NODE_RX_TYPE_CONNECTION;
|
||||
@ -657,6 +678,12 @@ static void isr_rx_connect_rsp(void *param)
|
||||
if (!trx_done) {
|
||||
struct node_rx_ftr *ftr;
|
||||
|
||||
/* Try again with connection initiation */
|
||||
lll->conn->master.initiated = 0U;
|
||||
|
||||
/* Dont stop initiating events on primary channels */
|
||||
lll->is_stop = 0U;
|
||||
|
||||
ftr = &(rx->hdr.rx_ftr);
|
||||
|
||||
rx->hdr.type = NODE_RX_TYPE_RELEASE;
|
||||
@ -667,9 +694,6 @@ static void isr_rx_connect_rsp(void *param)
|
||||
goto isr_rx_do_close;
|
||||
}
|
||||
|
||||
/* Stop further LLL radio events */
|
||||
lll->conn->master.initiated = 1;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
lll->conn->phy_tx = lll_aux->phy;
|
||||
lll->conn->phy_tx_time = lll_aux->phy;
|
||||
|
||||
@ -961,12 +961,32 @@ void ll_rx_dequeue(void)
|
||||
ARG_UNUSED(cc);
|
||||
#endif /* !CONFIG_BT_PERIPHERAL */
|
||||
|
||||
} else if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
|
||||
#if defined(CONFIG_BT_CENTRAL)
|
||||
} else {
|
||||
struct ll_scan_set *scan = HDR_LLL2ULL(ftr->param);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_CTLR_PHY_CODED)
|
||||
struct ll_scan_set *scan_other =
|
||||
ull_scan_is_enabled_get(SCAN_HANDLE_PHY_CODED);
|
||||
|
||||
if (scan_other) {
|
||||
if (scan_other == scan) {
|
||||
scan_other = ull_scan_is_enabled_get(SCAN_HANDLE_1M);
|
||||
}
|
||||
|
||||
if (scan_other) {
|
||||
scan_other->lll.conn = NULL;
|
||||
scan_other->is_enabled = 0U;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_CTLR_PHY_CODED */
|
||||
|
||||
scan->lll.conn = NULL;
|
||||
scan->is_enabled = 0U;
|
||||
#else /* !CONFIG_BT_CENTRAL */
|
||||
} else {
|
||||
LL_ASSERT(0);
|
||||
#endif /* !CONFIG_BT_CENTRAL */
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY)) {
|
||||
|
||||
@ -55,6 +55,9 @@
|
||||
#include "hal/debug.h"
|
||||
|
||||
static void ticker_op_stop_scan_cb(uint32_t status, void *param);
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_CTLR_PHY_CODED)
|
||||
static void ticker_op_stop_scan_other_cb(uint32_t status, void *param);
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_CTLR_PHY_CODED */
|
||||
static void ticker_op_cb(uint32_t status, void *param);
|
||||
static inline void conn_release(struct ll_scan_set *scan);
|
||||
|
||||
@ -669,28 +672,28 @@ void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx,
|
||||
uint8_t ticker_id_scan, ticker_id_conn;
|
||||
uint8_t peer_addr[BDADDR_SIZE];
|
||||
uint32_t ticks_slot_overhead;
|
||||
struct ll_scan_set *scan;
|
||||
uint32_t ticks_slot_offset;
|
||||
struct ll_scan_set *scan;
|
||||
struct pdu_adv *pdu_tx;
|
||||
struct node_rx_cc *cc;
|
||||
struct ll_conn *conn;
|
||||
uint8_t peer_addr_type;
|
||||
uint32_t ticker_status;
|
||||
struct node_rx_cc *cc;
|
||||
struct ll_conn *conn;
|
||||
uint8_t chan_sel;
|
||||
|
||||
((struct lll_scan *)ftr->param)->conn = NULL;
|
||||
|
||||
scan = ((struct lll_scan *)ftr->param)->hdr.parent;
|
||||
conn = lll->hdr.parent;
|
||||
|
||||
/* Get reference to Tx-ed CONNECT_IND PDU */
|
||||
pdu_tx = (void *)((struct node_rx_pdu *)rx)->pdu;
|
||||
|
||||
/* Backup peer addr and type, as we reuse the Tx-ed PDU to generate
|
||||
* event towards LL
|
||||
*/
|
||||
peer_addr_type = pdu_tx->rx_addr;
|
||||
memcpy(peer_addr, &pdu_tx->connect_ind.adv_addr[0], BDADDR_SIZE);
|
||||
|
||||
/* This is the chan sel bit from the received adv pdu */
|
||||
chan_sel = pdu_tx->chan_sel;
|
||||
|
||||
/* Populate the fields required for connection complete event */
|
||||
cc = (void *)pdu_tx;
|
||||
cc->status = 0U;
|
||||
cc->role = 0U;
|
||||
@ -723,11 +726,14 @@ void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx,
|
||||
memcpy(cc->peer_addr, &peer_addr[0], BDADDR_SIZE);
|
||||
}
|
||||
|
||||
scan = HDR_LLL2ULL(ftr->param);
|
||||
|
||||
cc->interval = lll->interval;
|
||||
cc->latency = lll->latency;
|
||||
cc->timeout = scan->lll.conn_timeout;
|
||||
cc->sca = lll_clock_sca_local_get();
|
||||
|
||||
conn = lll->hdr.parent;
|
||||
lll->handle = ll_conn_handle_get(conn);
|
||||
rx->handle = lll->handle;
|
||||
|
||||
@ -804,8 +810,34 @@ void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx,
|
||||
ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR,
|
||||
TICKER_USER_ID_ULL_HIGH,
|
||||
ticker_id_scan, ticker_op_stop_scan_cb,
|
||||
(void *)(uint32_t)ticker_id_scan);
|
||||
ticker_op_stop_scan_cb(ticker_status, (void *)(uint32_t)ticker_id_scan);
|
||||
scan);
|
||||
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
|
||||
(ticker_status == TICKER_STATUS_BUSY));
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_CTLR_PHY_CODED)
|
||||
/* Determine if coded PHY was also enabled, if so, reset the assigned
|
||||
* connection context.
|
||||
*/
|
||||
struct ll_scan_set *scan_other =
|
||||
ull_scan_is_enabled_get(SCAN_HANDLE_PHY_CODED);
|
||||
if (scan_other) {
|
||||
if (scan_other == scan) {
|
||||
scan_other = ull_scan_is_enabled_get(SCAN_HANDLE_1M);
|
||||
}
|
||||
|
||||
if (scan_other) {
|
||||
ticker_id_scan = TICKER_ID_SCAN_BASE +
|
||||
ull_scan_handle_get(scan_other);
|
||||
ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR,
|
||||
TICKER_USER_ID_ULL_HIGH,
|
||||
ticker_id_scan,
|
||||
ticker_op_stop_scan_other_cb,
|
||||
scan_other);
|
||||
LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
|
||||
(ticker_status == TICKER_STATUS_BUSY));
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_CTLR_PHY_CODED */
|
||||
|
||||
/* Scanner stop can expire while here in this ISR.
|
||||
* Deferred attempt to stop can fail as it would have
|
||||
@ -912,9 +944,45 @@ void ull_master_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t
|
||||
|
||||
static void ticker_op_stop_scan_cb(uint32_t status, void *param)
|
||||
{
|
||||
/* TODO: */
|
||||
/* NOTE: Nothing to do here, present here to add debug code if required
|
||||
*/
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_CTLR_PHY_CODED)
|
||||
static void ticker_op_stop_scan_other_cb(uint32_t status, void *param)
|
||||
{
|
||||
static memq_link_t link;
|
||||
static struct mayfly mfy = {0, 0, &link, NULL, NULL};
|
||||
struct ll_scan_set *scan;
|
||||
struct ull_hdr *hdr;
|
||||
|
||||
/* Ignore if race between thread and ULL */
|
||||
if (status != TICKER_STATUS_SUCCESS) {
|
||||
/* TODO: detect race */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* NOTE: We are in ULL_LOW which can be pre-empted by ULL_HIGH.
|
||||
* As we are in the callback after successful stop of the
|
||||
* ticker, the ULL reference count will not be modified
|
||||
* further hence it is safe to check and act on either the need
|
||||
* to call lll_disable or not.
|
||||
*/
|
||||
scan = param;
|
||||
hdr = &scan->ull;
|
||||
mfy.param = &scan->lll;
|
||||
if (ull_ref_get(hdr)) {
|
||||
uint32_t ret;
|
||||
|
||||
mfy.fp = lll_disable;
|
||||
ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW,
|
||||
TICKER_USER_ID_LLL, 0, &mfy);
|
||||
LL_ASSERT(!ret);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_CTLR_PHY_CODED */
|
||||
|
||||
static void ticker_op_cb(uint32_t status, void *param)
|
||||
{
|
||||
ARG_UNUSED(param);
|
||||
|
||||
@ -358,9 +358,10 @@ uint8_t ull_scan_enable(struct ll_scan_set *scan)
|
||||
uint32_t ticks_anchor;
|
||||
uint32_t ret;
|
||||
|
||||
lll->chan = 0;
|
||||
lll->init_addr_type = scan->own_addr_type;
|
||||
ll_addr_get(lll->init_addr_type, lll->init_addr);
|
||||
lll->chan = 0U;
|
||||
lll->is_stop = 0U;
|
||||
|
||||
ull_hdr_init(&scan->ull);
|
||||
lll_hdr_init(lll, scan);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user