From 8c3b244fe3c5ae6405f37cd345a4af9e2ae0ac1c Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Mon, 28 Feb 2022 10:32:52 +0800 Subject: [PATCH] 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 --- subsys/bluetooth/mesh/adv_ext.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/subsys/bluetooth/mesh/adv_ext.c b/subsys/bluetooth/mesh/adv_ext.c index 78eaf6a91ae..e779b39a5dd 100644 --- a/subsys/bluetooth/mesh/adv_ext.c +++ b/subsys/bluetooth/mesh/adv_ext.c @@ -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.