Bluetooth: Controller: fix per sync hang if wrong cte and list filter
In case of use of filtering based on: periodic advertising list and CTE type, the synchronization can hang. That is possible if a periodic advertiser uses wrong CTE type. In such situation the sync is not released in ull_sync_done call. What more the sync->timeout_reload is not cleared and Host is not able to cancel the synchronization. The periodic advertising is in a semi-sync-established state. There are no reports send to Host. Host can't use the sync set to synchronize with other device. It is only able to terminate the sync (call to ll_sync_terminate). To fix the issue following changes should be applied: - isr_rx_adv_sync_estab should call isr_rx_done_cleanup with sync_term parameter in case the sync_ok isn't SYNC_STAT_ALLOWED. In any case the CTE type is wrong, no matter is the periodic advertising list filtering is enabled or not. - ull_sync_established_report should set sync->is_term to true in case the CTE type is not allowed. That change is required for devices that do not support Direction Finding Extension. For those devices CTE type based filtering is done in ULL by ull_sync_established_report function. The sync->is_term should be set unconditionally, hence is moved up in the function. With these two changes done, ull_sync_done function will execute sync_ticker_release in case the CTE has wrong type. ULL, depending on notifications prepared by ull_sync_established_report, will follow up on sync termination if required. Signed-off-by: Piotr Pryga <piotr.pryga@nordicsemi.no>
This commit is contained in:
parent
154b5a1319
commit
3715241bde
|
@ -814,7 +814,7 @@ static void isr_rx_adv_sync_estab(void *param)
|
|||
isr_rx_done:
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING) && \
|
||||
defined(CONFIG_BT_CTLR_CTEINLINE_SUPPORT)
|
||||
isr_rx_done_cleanup(lll, crc_ok, sync_ok == SYNC_STAT_TERM);
|
||||
isr_rx_done_cleanup(lll, crc_ok, sync_ok != SYNC_STAT_ALLOWED);
|
||||
#else
|
||||
isr_rx_done_cleanup(lll, crc_ok, false);
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING && CONFIG_BT_CTLR_CTEINLINE_SUPPORT */
|
||||
|
|
|
@ -808,6 +808,14 @@ void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx)
|
|||
sync_status = lll_sync_cte_is_allowed(lll->cte_type, lll->filter_policy, 0,
|
||||
BT_HCI_LE_NO_CTE);
|
||||
}
|
||||
|
||||
/* If there is no CTEInline support, notify done event handler to terminate periodic
|
||||
* advertising sync in case the CTE is not allowed.
|
||||
* If the periodic filtering list is not used then terminate synchronization and notify
|
||||
* host. If the periodic filtering list is used then stop synchronization with this
|
||||
* particular periodic advertised but continue to search for other one.
|
||||
*/
|
||||
sync->is_term = (sync_status != SYNC_STAT_ALLOWED);
|
||||
#endif /* CONFIG_BT_CTLR_CTEINLINE_SUPPORT */
|
||||
|
||||
/* Send periodic advertisement sync established report when sync has correct CTE type
|
||||
|
@ -824,16 +832,10 @@ void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx)
|
|||
rx_establ->hdr.type = NODE_RX_TYPE_SYNC;
|
||||
rx_establ->hdr.handle = ull_sync_handle_get(sync);
|
||||
se = (void *)rx_establ->pdu;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING)
|
||||
se->status = (ftr->sync_status == SYNC_STAT_TERM) ?
|
||||
BT_HCI_ERR_UNSUPP_REMOTE_FEATURE :
|
||||
BT_HCI_ERR_SUCCESS;
|
||||
|
||||
#if !defined(CONFIG_BT_CTLR_CTEINLINE_SUPPORT)
|
||||
/* Notify done event handler to terminate sync scan if required. */
|
||||
sync->is_term = (sync_status == SYNC_STAT_TERM);
|
||||
#endif /* !CONFIG_BT_CTLR_CTEINLINE_SUPPORT */
|
||||
#else
|
||||
se->status = BT_HCI_ERR_SUCCESS;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING */
|
||||
|
@ -851,7 +853,7 @@ void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx)
|
|||
* the sync was found or was established in the past. The report is not send if
|
||||
* scanning is terminated due to wrong CTE type.
|
||||
*/
|
||||
if (sync_status != SYNC_STAT_TERM) {
|
||||
if (sync_status == SYNC_STAT_ALLOWED) {
|
||||
#else /* !CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING */
|
||||
|
||||
if (1) {
|
||||
|
@ -896,7 +898,16 @@ void ull_sync_done(struct node_rx_event_done *done)
|
|||
#else
|
||||
if (sync->is_term) {
|
||||
#endif /* CONFIG_BT_CTLR_CTEINLINE_SUPPORT */
|
||||
/* Stop periodic advertising scan ticker */
|
||||
/* In case the periodic advertising list filtering is not used the synchronization
|
||||
* must be terminated and host notification must be send.
|
||||
* In case the periodic advertising list filtering is used the synchronization with
|
||||
* this particular periodic advertiser but search for other one from the list.
|
||||
*
|
||||
* Stop periodic advertising sync ticker and clear variables informing the
|
||||
* sync is pending. That is a step to completely terminate the synchronization.
|
||||
* In case search for another periodic advertiser it allows to setup new ticker for
|
||||
* that.
|
||||
*/
|
||||
sync_ticker_cleanup(sync, NULL);
|
||||
} else
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING */
|
||||
|
|
Loading…
Reference in a new issue