Bluetooth: Mesh: Fix adv_send call before enabled.
Since the default syswork thread priority = `-1`. `adv_send` will call when controller report advertising sending completed, due to this process by BT RX task, will maybe process this before `buf_send`, since, sysworkq will be used by other place and defer by any place. Note: secure beacon will be 40ms, and friend and lpn will be 20ms. This problem is very easy to reproduce, especially in native posix. Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
This commit is contained in:
parent
58a501d6cd
commit
b76d74cd64
1 changed files with 30 additions and 15 deletions
|
@ -33,6 +33,8 @@
|
|||
enum {
|
||||
/** Controller is currently advertising */
|
||||
ADV_FLAG_ACTIVE,
|
||||
/** Advertising sending completed */
|
||||
ADV_FLAG_SENT,
|
||||
/** Currently performing proxy advertising */
|
||||
ADV_FLAG_PROXY,
|
||||
/** The send-call has been scheduled. */
|
||||
|
@ -208,6 +210,29 @@ static void send_pending_adv(struct k_work *work)
|
|||
int err;
|
||||
|
||||
adv = CONTAINER_OF(work, struct bt_mesh_ext_adv, work.work);
|
||||
|
||||
if (atomic_test_and_clear_bit(adv->flags, ADV_FLAG_SENT)) {
|
||||
/* Calling k_uptime_delta on a timestamp moves it to the current time.
|
||||
* This is essential here, as schedule_send() uses the end of the event
|
||||
* as a reference to avoid sending the next advertisement too soon.
|
||||
*/
|
||||
int64_t duration = k_uptime_delta(&adv->timestamp);
|
||||
|
||||
BT_DBG("Advertising stopped after %u ms", (uint32_t)duration);
|
||||
|
||||
atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
|
||||
atomic_clear_bit(adv->flags, ADV_FLAG_PROXY);
|
||||
|
||||
if (adv->buf) {
|
||||
net_buf_unref(adv->buf);
|
||||
adv->buf = NULL;
|
||||
}
|
||||
|
||||
(void)schedule_send(adv);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
atomic_clear_bit(adv->flags, ADV_FLAG_SCHEDULED);
|
||||
|
||||
while ((buf = bt_mesh_adv_buf_get_by_tag(adv->tag, K_NO_WAIT))) {
|
||||
|
@ -334,23 +359,13 @@ static void adv_sent(struct bt_le_ext_adv *instance,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Calling k_uptime_delta on a timestamp moves it to the current time.
|
||||
* This is essential here, as schedule_send() uses the end of the event
|
||||
* as a reference to avoid sending the next advertisement too soon.
|
||||
*/
|
||||
int64_t duration = k_uptime_delta(&adv->timestamp);
|
||||
|
||||
BT_DBG("Advertising stopped after %u ms", (uint32_t)duration);
|
||||
|
||||
atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
|
||||
atomic_clear_bit(adv->flags, ADV_FLAG_PROXY);
|
||||
|
||||
if (adv->buf) {
|
||||
net_buf_unref(adv->buf);
|
||||
adv->buf = NULL;
|
||||
if (!atomic_test_bit(adv->flags, ADV_FLAG_ACTIVE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)schedule_send(adv);
|
||||
atomic_set_bit(adv->flags, ADV_FLAG_SENT);
|
||||
|
||||
k_work_submit(&adv->work.work);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_MESH_GATT_SERVER)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue