Bluetooth: Controller: Fix sync reports post terminate and rx disable
Fix generating periodic advertising reports post sync terminate under race condition when disabling reporting or terminating the sync or while performing HCI reset. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
a602a18660
commit
6fb38eb24f
|
@ -6643,6 +6643,7 @@ static void le_per_adv_sync_report(struct pdu_data *pdu_data,
|
|||
struct pdu_adv_aux_ptr *aux_ptr = NULL;
|
||||
const struct pdu_adv_adi *adi = NULL;
|
||||
uint8_t cte_type = BT_HCI_LE_NO_CTE;
|
||||
const struct ll_sync_set *sync;
|
||||
struct pdu_adv_com_ext_adv *p;
|
||||
struct pdu_adv_ext_hdr *h;
|
||||
uint16_t data_len_total;
|
||||
|
@ -6664,6 +6665,22 @@ static void le_per_adv_sync_report(struct pdu_data *pdu_data,
|
|||
return;
|
||||
}
|
||||
|
||||
/* NOTE: The timeout_reload field in the sync context is checked under
|
||||
* race condition between HCI Tx and Rx thread wherein a sync
|
||||
* terminate was performed which resets the timeout_reload field
|
||||
* before releasing the sync context back into its memory pool.
|
||||
* It is important that timeout_reload field is at safe offset
|
||||
* inside the sync context such that it is not corrupt while being
|
||||
* in the memory pool.
|
||||
*
|
||||
* This check ensures reports are not sent out after sync
|
||||
* terminate.
|
||||
*/
|
||||
sync = HDR_LLL2ULL(ftr->param);
|
||||
if (unlikely(!sync->timeout_reload)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((le_event_mask & BT_EVT_MASK_LE_PER_ADVERTISING_REPORT) &&
|
||||
node_rx->hdr.rx_ftr.aux_failed) {
|
||||
struct bt_hci_evt_le_per_advertising_report *sep;
|
||||
|
@ -6787,14 +6804,13 @@ no_ext_hdr:
|
|||
defined(CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT)
|
||||
} else if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT) &&
|
||||
adi) {
|
||||
const struct ll_sync_set *sync = HDR_LLL2ULL(ftr->param);
|
||||
uint8_t data_status;
|
||||
|
||||
data_status = (aux_ptr) ?
|
||||
BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL :
|
||||
BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE;
|
||||
|
||||
accept = ftr->sync_rx_enabled &&
|
||||
accept = sync->rx_enable && ftr->sync_rx_enabled &&
|
||||
(!sync->nodups ||
|
||||
!dup_found(PDU_ADV_TYPE_EXT_IND,
|
||||
sync->peer_id_addr_type,
|
||||
|
@ -6806,7 +6822,7 @@ no_ext_hdr:
|
|||
*/
|
||||
|
||||
} else {
|
||||
accept = ftr->sync_rx_enabled;
|
||||
accept = sync->rx_enable && ftr->sync_rx_enabled;
|
||||
}
|
||||
|
||||
data_len_max = CONFIG_BT_BUF_EVT_RX_SIZE -
|
||||
|
|
|
@ -52,6 +52,14 @@
|
|||
#include <soc.h>
|
||||
#include "hal/debug.h"
|
||||
|
||||
/* Check that timeout_reload member is at safe offset when ll_sync_set is
|
||||
* allocated using mem interface. timeout_reload being non-zero is used to
|
||||
* indicate that a sync is established. And is used to check for sync being
|
||||
* terminated under race conditions between HCI Tx and Rx thread when
|
||||
* Periodic Advertising Reports are generated.
|
||||
*/
|
||||
MEM_FREE_MEMBER_ACCESS_BUILD_ASSERT(struct ll_sync_set, timeout_reload);
|
||||
|
||||
static int init_reset(void);
|
||||
static inline struct ll_sync_set *sync_acquire(void);
|
||||
static void sync_ticker_cleanup(struct ll_sync_set *sync, ticker_op_func stop_op_cb);
|
||||
|
|
Loading…
Reference in a new issue