Bluetooth: Controller: Properly terminate per adv HCI on failed rx

If one of AUX_CHAIN_IND is not received properly we need to send an
extra report over HCI to indicate that data are incomplete.

Signed-off-by: Andrzej Kaczmarek <andrzej.kaczmarek@codecoup.pl>
This commit is contained in:
Andrzej Kaczmarek 2021-08-27 17:42:33 +02:00 committed by Christopher Friedt
parent f83dc928f6
commit defda27969
4 changed files with 57 additions and 4 deletions

View File

@ -5545,6 +5545,21 @@ static void le_per_adv_sync_report(struct pdu_data *pdu_data,
return;
}
if (node_rx->hdr.rx_ftr.aux_failed) {
sep = meta_evt(buf,
BT_HCI_EVT_LE_PER_ADVERTISING_REPORT,
sizeof(*sep));
sep->handle = sys_cpu_to_le16(node_rx->hdr.handle);
sep->tx_power = BT_HCI_LE_ADV_TX_POWER_NO_PREF;
sep->rssi = BT_HCI_LE_RSSI_NOT_AVAILABLE;
sep->cte_type = BT_HCI_LE_NO_CTE;
sep->data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE;
sep->length = 0;
return;
}
/* The Link Layer currently returns RSSI as an absolute value */
rssi = -(node_rx->hdr.rx_ftr.rssi);

View File

@ -283,6 +283,7 @@ struct node_rx_ftr {
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_OBSERVER)
uint8_t aux_lll_sched:1;
uint8_t aux_w4next:1;
uint8_t aux_failed:1;
uint8_t phy_flags:1;
uint8_t scan_req:1;

View File

@ -492,6 +492,7 @@ static int isr_rx(struct lll_sync *lll, uint8_t node_type, uint8_t *crc_ok)
ftr = &(node_rx->hdr.rx_ftr);
ftr->param = lll;
ftr->aux_failed = 0U;
ftr->rssi = (rssi_ready) ? radio_rssi_get() :
BT_HCI_LE_RSSI_NOT_AVAILABLE;
ftr->ticks_anchor = radio_tmr_start_get();
@ -582,6 +583,21 @@ static void isr_rx_aux_chain(void *param)
return;
}
if (!trx_cnt || !crc_ok) {
struct node_rx_pdu *node_rx;
node_rx = ull_pdu_rx_alloc();
LL_ASSERT(node_rx);
node_rx->hdr.type = NODE_RX_TYPE_EXT_AUX_RELEASE;
node_rx->hdr.rx_ftr.param = lll;
node_rx->hdr.rx_ftr.aux_failed = 1U;
ull_rx_put(node_rx->hdr.link, node_rx);
ull_rx_sched();
}
isr_rx_aux_chain_done:
isr_rx_done_cleanup(lll, 1U);
}

View File

@ -636,9 +636,15 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx)
if (ull_scan_is_valid_get(param_ull)) {
struct lll_scan *lll;
/* Mark for buffer for release */
rx->type = NODE_RX_TYPE_RELEASE;
lll = rx->rx_ftr.param;
lll_aux = lll->lll_aux;
} else if (ull_scan_aux_is_valid_get(param_ull)) {
/* Mark for buffer for release */
rx->type = NODE_RX_TYPE_RELEASE;
lll_aux = rx->rx_ftr.param;
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
} else if (ull_sync_is_valid_get(param_ull)) {
@ -646,6 +652,12 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx)
lll = rx->rx_ftr.param;
lll_aux = lll->lll_aux;
/* Change node type so HCI can dispatch report for truncated
* data properly.
*/
rx->type = NODE_RX_TYPE_SYNC_REPORT;
rx->handle = ull_sync_handle_get(HDR_LLL2ULL(lll));
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
} else {
LL_ASSERT(0);
@ -654,13 +666,22 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx)
if (lll_aux) {
struct ll_scan_aux_set *aux;
struct ull_hdr *hdr;
aux = HDR_LLL2ULL(lll_aux);
flush(aux);
}
hdr = &aux->ull;
/* Mark for buffer for release */
rx->type = NODE_RX_TYPE_RELEASE;
LL_ASSERT(ull_ref_get(hdr) < 2);
/* Flush from here of from done event, if one is pending */
if (ull_ref_get(hdr) == 0) {
flush(aux);
} else {
LL_ASSERT(!hdr->disabled_cb);
hdr->disabled_param = aux;
hdr->disabled_cb = last_disabled_cb;
}
}
ll_rx_put(link, rx);
ll_rx_sched();