diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index b2d8e8dc18f..2c5619c7cab 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -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); diff --git a/subsys/bluetooth/controller/ll_sw/lll.h b/subsys/bluetooth/controller/ll_sw/lll.h index 03951ba76e5..079db2ad064 100644 --- a/subsys/bluetooth/controller/ll_sw/lll.h +++ b/subsys/bluetooth/controller/ll_sw/lll.h @@ -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; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index 94748d486d7..feaba2e3fd7 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -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); } diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c index 9f683ed13c4..7e55d00d825 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c @@ -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();