Skip to content

Commit bb7a67d

Browse files
ppryga-nordiccarlescufi
authored andcommitted
Bluetooth: Controller: Fix per sync cancel and sync establ synchronize
Current implementation of ll_sync_create_cancel does not allow to stop synchronization after ull_sync_setup is called. When that is done, sync->timeout_reload is not zero and the ll_sync_create_cancel will return BT_HCI_ERR_CMD_DISALLOWED. That means the Controller is able to cancel periodic advertising synchronization only in period between call to ll_sync_create and reception of AUX_ADV_IND that has SyncInfo field. The Controller should be able to cancell synchronization until first AUX_SYNC_IND PDU is received and host notified about synchronization established. Complete information about synchronization status is provdied by two ll_sync_set members: node_rx_sync_established and timeout_reload. These two members of the structure were used in ll_sync_create_cancel function to do a proper cancel and cleanup. The node_rx_sync_established member was not cleared when sync was established or expired. That was required to get a proper information about synchronization state. Besides that, to avoid race condition between ll_sync_create_cancel and ull_sync_established_report, the latter function was extended to check if cancel operation or sync lost has happened. Signed-off-by: Piotr Pryga <[email protected]>
1 parent 80b2d77 commit bb7a67d

File tree

2 files changed

+69
-9
lines changed

2 files changed

+69
-9
lines changed

subsys/bluetooth/controller/ll_sw/ull_sync.c

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,14 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
182182

183183
/* Initialize sync context */
184184
node_rx->link = link_sync_estab;
185-
sync->node_rx_sync_estab = node_rx;
186185
sync->node_rx_lost.hdr.link = link_sync_lost;
187186

187+
/* Make sure that the node_rx_sync_establ hasn't got anything assigned. It is used to
188+
* mark when sync establishment is in progress.
189+
*/
190+
LL_ASSERT(!sync->node_rx_sync_estab);
191+
sync->node_rx_sync_estab = node_rx;
192+
188193
/* Reporting initially enabled/disabled */
189194
sync->rx_enable =
190195
!(options & BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_REPORTS_DISABLED);
@@ -301,16 +306,43 @@ uint8_t ll_sync_create_cancel(void **rx)
301306
}
302307
cpu_dmb();
303308
sync = scan->periodic.sync;
304-
if (!sync || sync->timeout_reload) {
305-
/* FIXME: sync establishment in progress looking for first
306-
* AUX_SYNC_IND. Cleanup by stopping ticker and disabling
307-
* LLL events.
308-
*/
309+
if (!sync) {
309310
return BT_HCI_ERR_CMD_DISALLOWED;
310311
}
311312

313+
/* node_rx_sync_estab is assigned when Host calls create sync and cleared when sync is
314+
* established. timeout_reload is set when sync is found and setup. It is non-zero until
315+
* sync is terminated. Together they give information about current sync state:
316+
* - node_rx_sync_estab == NULL && timeout_reload != 0 => sync is established
317+
* - node_rx_sync_estab == NULL && timeout_reload == 0 => sync is terminated
318+
* - node_rx_sync_estab != NULL && timeout_reload == 0 => sync is created
319+
* - node_rx_sync_estab != NULL && timeout_reload != 0 => sync is waiting to be established
320+
*/
321+
if (!sync->node_rx_sync_estab) {
322+
/* There is no sync to be cancelled */
323+
return BT_HCI_ERR_CMD_DISALLOWED;
324+
}
325+
326+
sync->is_stop = 1U;
327+
cpu_dmb();
328+
329+
if (sync->timeout_reload != 0) {
330+
uint16_t sync_handle = ull_sync_handle_get(sync);
331+
332+
LL_ASSERT(sync_handle <= UINT8_MAX);
333+
334+
/* Sync is not established yet, so stop sync ticker */
335+
int err = ull_ticker_stop_with_mark(
336+
TICKER_ID_SCAN_SYNC_BASE + (uint8_t)sync_handle, sync, &sync->lll);
337+
338+
LL_ASSERT(err == 0 || err == -EALREADY);
339+
if (err != 0 && err != -EALREADY) {
340+
return BT_HCI_ERR_CMD_DISALLOWED;
341+
}
342+
} /* else: sync was created but not yet setup, there is no sync ticker yet. */
343+
312344
/* It is safe to remove association with scanner as cancelled flag is
313-
* set and sync has not been established.
345+
* set, sync is_stop flag was set and sync has not been established.
314346
*/
315347
ull_sync_setup_reset(scan);
316348

@@ -327,6 +359,11 @@ uint8_t ll_sync_create_cancel(void **rx)
327359
ll_rx_link_release(link_sync_estab);
328360
ll_rx_release(node_rx);
329361

362+
/* Clear the node after release to mark the sync establish as being completed.
363+
* In this case the completion reason is sync cancelled by Host.
364+
*/
365+
sync->node_rx_sync_estab = NULL;
366+
330367
node_rx = (void *)&sync->node_rx_lost;
331368
node_rx->hdr.type = NODE_RX_TYPE_SYNC;
332369
node_rx->hdr.handle = LLL_HANDLE_INVALID;
@@ -792,6 +829,11 @@ void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx)
792829
lll = ftr->param;
793830
sync = HDR_LLL2ULL(lll);
794831

832+
/* Do nothing if sync is cancelled or lost. */
833+
if (unlikely(sync->is_stop || !sync->timeout_reload)) {
834+
return;
835+
}
836+
795837
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING)
796838
enum sync_status sync_status;
797839

@@ -832,6 +874,11 @@ void ull_sync_established_report(memq_link_t *link, struct node_rx_hdr *rx)
832874
rx_establ->hdr.type = NODE_RX_TYPE_SYNC;
833875
rx_establ->hdr.handle = ull_sync_handle_get(sync);
834876
se = (void *)rx_establ->pdu;
877+
/* Clear the node to mark the sync establish as being completed.
878+
* In this case the completion reason is sync being established.
879+
*/
880+
sync->node_rx_sync_estab = NULL;
881+
835882
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING)
836883
se->status = (ftr->sync_status == SYNC_STAT_TERM) ?
837884
BT_HCI_ERR_UNSUPP_REMOTE_FEATURE :
@@ -1242,6 +1289,11 @@ static void sync_expire(void *param)
12421289
rx->hdr.type = NODE_RX_TYPE_SYNC;
12431290
rx->hdr.handle = LLL_HANDLE_INVALID;
12441291

1292+
/* Clear the node to mark the sync establish as being completed.
1293+
* In this case the completion reason is sync expire.
1294+
*/
1295+
sync->node_rx_sync_estab = NULL;
1296+
12451297
/* NOTE: struct node_rx_sync_estab has uint8_t member following the
12461298
* struct node_rx_hdr to store the reason.
12471299
*/

subsys/bluetooth/controller/ll_sw/ull_sync_types.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ struct ll_sync_set {
1818

1919
uint16_t skip;
2020
uint16_t timeout;
21-
uint16_t volatile timeout_reload; /* Non-zero when sync established */
21+
/* Non-zero when sync is setup. It can be in two sub-stated:
22+
* - Waiting for first AUX_SYNC_IND, before sync established was notified to Host.
23+
* If sync establishment is in progress node_rx_sync_estab is not NULL.
24+
* - sync is already established, node_rx_sync_estab is NULL.
25+
*/
26+
uint16_t volatile timeout_reload;
2227
uint16_t timeout_expire;
2328

2429
/* Member to store periodic advertising sync prepare.
@@ -49,7 +54,7 @@ struct ll_sync_set {
4954
uint8_t is_term:1;
5055
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING && !CONFIG_BT_CTLR_CTEINLINE_SUPPORT */
5156

52-
uint8_t is_stop:1; /* sync terminate requested */
57+
uint8_t is_stop:1; /* sync terminate or cancel requested */
5358
uint8_t sync_expire:3; /* countdown of 6 before fail to establish */
5459

5560
#if defined(CONFIG_BT_CTLR_CHECK_SAME_PEER_SYNC)
@@ -68,6 +73,9 @@ struct ll_sync_set {
6873
};
6974
} node_rx_lost;
7075

76+
/* Not-Null when sync was setup and Controller is waiting for first AUX_SYNC_IND PDU.
77+
* It means the sync was not estalished yet.
78+
*/
7179
struct node_rx_hdr *node_rx_sync_estab;
7280

7381
#if defined(CONFIG_BT_CTLR_SYNC_ISO)

0 commit comments

Comments
 (0)