Bluetooth: Mesh: Fix unable send mesh message when proxy adv pending

When Proxy advertising or PB-GATT Advertising Enabled and use a same
advertising sets.

As `adv_start` will call multi HCI Command will cause syswork_q yield.
At same time, if another thread(BT RX) all `schedule_send` will cause
unable send mesh message, because `ADV_FLAG_ACTIVE` was be set, but
`ADV_FLAG_PROXY` not set currentlly.

Add `ADV_FLAG_SCHEDULE_PENDING` indicate mesh buf has been pendings
but not scheduled, so when proxy advertising enable, let's take again,
as we can't break or terminated `adv_start`, so we must waiting proxy
advertising enabled.

Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
This commit is contained in:
Lingao Meng 2022-02-28 10:32:52 +08:00 committed by Marti Bolivar
commit 8c3b244fe3

View file

@ -33,6 +33,8 @@ enum {
ADV_FLAG_PROXY,
/** The send-call has been scheduled. */
ADV_FLAG_SCHEDULED,
/** The send-call has been pending. */
ADV_FLAG_SCHEDULE_PENDING,
/** Custom adv params have been set, we need to update the parameters on
* the next send.
*/
@ -53,6 +55,7 @@ struct bt_mesh_ext_adv {
};
static void send_pending_adv(struct k_work *work);
static bool schedule_send(struct bt_mesh_ext_adv *adv);
static STRUCT_SECTION_ITERABLE(bt_mesh_ext_adv, adv_main) = {
.tag = (BT_MESH_LOCAL_ADV |
@ -220,12 +223,19 @@ static void send_pending_adv(struct k_work *work)
}
}
if (IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER) &&
(adv->tag & BT_MESH_PROXY_ADV) &&
!bt_mesh_adv_gatt_send()) {
atomic_set_bit(adv->flags, ADV_FLAG_PROXY);
if (!IS_ENABLED(CONFIG_BT_MESH_GATT_SERVER) ||
!(adv->tag & BT_MESH_PROXY_ADV)) {
return;
}
if (!bt_mesh_adv_gatt_send()) {
atomic_set_bit(adv->flags, ADV_FLAG_PROXY);
}
if (atomic_test_and_clear_bit(adv->flags, ADV_FLAG_SCHEDULE_PENDING)) {
schedule_send(adv);
}
}
static bool schedule_send(struct bt_mesh_ext_adv *adv)
@ -244,11 +254,15 @@ static bool schedule_send(struct bt_mesh_ext_adv *adv)
atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
}
if (atomic_test_bit(adv->flags, ADV_FLAG_ACTIVE) ||
atomic_test_and_set_bit(adv->flags, ADV_FLAG_SCHEDULED)) {
if (atomic_test_bit(adv->flags, ADV_FLAG_ACTIVE)) {
atomic_set_bit(adv->flags, ADV_FLAG_SCHEDULE_PENDING);
return false;
} else if (atomic_test_and_set_bit(adv->flags, ADV_FLAG_SCHEDULED)) {
return false;
}
atomic_clear_bit(adv->flags, ADV_FLAG_SCHEDULE_PENDING);
/* The controller will send the next advertisement immediately.
* Introduce a delay here to avoid sending the next mesh packet closer
* to the previous packet than what's permitted by the specification.