Skip to content

Commit 9dc6b71

Browse files
LingaoMBalaklaka
authored andcommitted
[nrf fromtree] Bluetooth: Mesh: Introduce separate workq for ADV EXT
this PR is to make the host always send packets. Signed-off-by: Lingao Meng <[email protected]> (cherry picked from commit b9fbfc9) Signed-off-by: Ingar Kulbrandstad <[email protected]>
1 parent 4f3ef0a commit 9dc6b71

File tree

19 files changed

+197
-8
lines changed

19 files changed

+197
-8
lines changed

doc/releases/release-notes-4.0.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ Bluetooth
107107

108108
* HCI Drivers
109109

110+
* Mesh
111+
112+
* Introduced a mesh-specific workqueue to increase reliability of the mesh messages
113+
transmission. To get the old behavior enable :kconfig:option:`CONFIG_BT_MESH_WORKQ_SYS`.
114+
110115
Boards & SoC Support
111116
********************
112117

subsys/bluetooth/mesh/Kconfig

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,64 @@ menuconfig BT_MESH_ADV_EXT
107107

108108
if BT_MESH_ADV_EXT
109109

110+
choice BT_MESH_WORKQ_CONTEXT
111+
prompt "Advertising thread selection"
112+
default BT_MESH_WORKQ_MESH
113+
help
114+
Defines a context for mesh messages transmission.
115+
116+
config BT_MESH_WORKQ_MESH
117+
bool "Mesh-specific workqueue"
118+
help
119+
When this option is selected, the mesh sends messages from the
120+
mesh-specific workqueue. This will ensure that messages are always sent.
121+
The application needs to ensure the mesh-specific workqueue size is large
122+
enough. Refer to BT_MESH_ADV_STACK_SIZE for the recommended minimum.
123+
124+
config BT_MESH_WORKQ_SYS
125+
bool "System workqueue"
126+
help
127+
When this option is selected, the mesh sends messages from
128+
the system work queue. The application needs to ensure the system
129+
workqueue stack size (SYSTEM_WORKQUEUE_STACK_SIZE) is large enough,
130+
refer to BT_MESH_ADV_STACK_SIZE for the recommended minimum.
131+
132+
When this option is enabled and the mesh tries to send a message,
133+
and the host ran out the HCI command buffers controlled by
134+
CONFIG_BT_BUF_CMD_TX_COUNT, the host returns -ENOBUFS immediately
135+
and the mesh drops the message transmission. To mitigate this
136+
issue, make sure to have sufficient number of HCI command buffers.
137+
When this option is enabled, the latency of sending mesh messages
138+
will be affected by other users on the system work queue, resulting in
139+
reduced reliability for sending mesh messages.
140+
141+
endchoice
142+
143+
if BT_MESH_WORKQ_MESH
144+
145+
config BT_MESH_ADV_STACK_SIZE
146+
int "Mesh extended advertiser thread stack size"
147+
default 1536 if BT_MESH_PROXY
148+
default 1024 if BT_HOST_CRYPTO
149+
default 776 if BT_MESH_PRIV_BEACONS
150+
default 768
151+
help
152+
Size of bt mesh adv thread stack.
153+
154+
NOTE: This is an advanced setting and should not be changed unless
155+
absolutely necessary
156+
157+
config BT_MESH_ADV_PRIO
158+
int "Mesh advertiser thread priority"
159+
default 7
160+
help
161+
Priority of bt mesh adv thread.
162+
163+
NOTE: This is an advanced setting and should not be changed unless
164+
absolutely necessary
165+
166+
endif # BT_MESH_WORKQ_MESH
167+
110168
config BT_MESH_RELAY_ADV_SETS
111169
int "Maximum of simultaneous relay message support"
112170
default 0

subsys/bluetooth/mesh/adv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,6 @@ int bt_mesh_scan_active_set(bool active);
123123
int bt_mesh_adv_bt_data_send(uint8_t num_events, uint16_t adv_interval,
124124
const struct bt_data *ad, size_t ad_len);
125125

126+
int bt_mesh_wq_submit(struct k_work *work);
127+
126128
#endif /* ZEPHYR_SUBSYS_BLUETOOTH_MESH_ADV_H_ */

subsys/bluetooth/mesh/adv_ext.c

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ LOG_MODULE_REGISTER(bt_mesh_adv_ext);
3636
#define CONFIG_BT_MESH_RELAY_ADV_SETS 0
3737
#endif
3838

39+
#ifdef CONFIG_BT_MESH_ADV_STACK_SIZE
40+
#define MESH_WORKQ_PRIORITY CONFIG_BT_MESH_ADV_PRIO
41+
#define MESH_WORKQ_STACK_SIZE CONFIG_BT_MESH_ADV_STACK_SIZE
42+
#else
43+
#define MESH_WORKQ_PRIORITY 0
44+
#define MESH_WORKQ_STACK_SIZE 0
45+
#endif
46+
3947
enum {
4048
/** Controller is currently advertising */
4149
ADV_FLAG_ACTIVE,
@@ -72,6 +80,15 @@ struct bt_mesh_ext_adv {
7280
static void send_pending_adv(struct k_work *work);
7381
static bool schedule_send(struct bt_mesh_ext_adv *ext_adv);
7482

83+
static struct k_work_q bt_mesh_workq;
84+
static K_KERNEL_STACK_DEFINE(thread_stack, MESH_WORKQ_STACK_SIZE);
85+
86+
#if defined(CONFIG_BT_MESH_WORKQ_MESH)
87+
#define MESH_WORKQ &bt_mesh_workq
88+
#else /* CONFIG_BT_MESH_WORKQ_SYS */
89+
#define MESH_WORKQ &k_sys_work_q
90+
#endif /* CONFIG_BT_MESH_WORKQ_MESH */
91+
7592
static struct bt_mesh_ext_adv advs[] = {
7693
[0] = {
7794
.tags = (
@@ -283,7 +300,7 @@ static bool schedule_send_with_mask(struct bt_mesh_ext_adv *ext_adv, int ignore_
283300
}
284301

285302
atomic_clear_bit(ext_adv->flags, ADV_FLAG_SCHEDULE_PENDING);
286-
k_work_submit(&ext_adv->work);
303+
bt_mesh_wq_submit(&ext_adv->work);
287304

288305
return true;
289306
}
@@ -432,7 +449,7 @@ int bt_mesh_adv_terminate(struct bt_mesh_adv *adv)
432449

433450
atomic_set_bit(ext_adv->flags, ADV_FLAG_SENT);
434451

435-
k_work_submit(&ext_adv->work);
452+
bt_mesh_wq_submit(&ext_adv->work);
436453

437454
return 0;
438455
}
@@ -455,6 +472,13 @@ void bt_mesh_adv_init(void)
455472
(void)memcpy(&advs[i].adv_param, &adv_param, sizeof(adv_param));
456473
}
457474

475+
if (IS_ENABLED(CONFIG_BT_MESH_WORKQ_MESH)) {
476+
k_work_queue_init(&bt_mesh_workq);
477+
k_work_queue_start(&bt_mesh_workq, thread_stack, MESH_WORKQ_STACK_SIZE,
478+
K_PRIO_COOP(MESH_WORKQ_PRIORITY), NULL);
479+
k_thread_name_set(&bt_mesh_workq.thread, "BT MESH WQ");
480+
}
481+
458482
#if defined(CONFIG_BT_LL_SOFTDEVICE)
459483
const sdc_hci_cmd_vs_scan_accept_ext_adv_packets_set_t cmd_params = {
460484
.accept_ext_adv_packets = IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_ACCEPT_EXT_ADV_PACKETS),
@@ -495,7 +519,7 @@ static void adv_sent(struct bt_le_ext_adv *instance,
495519

496520
atomic_set_bit(ext_adv->flags, ADV_FLAG_SENT);
497521

498-
k_work_submit(&ext_adv->work);
522+
bt_mesh_wq_submit(&ext_adv->work);
499523
}
500524

501525
#if defined(CONFIG_BT_MESH_GATT_SERVER)
@@ -549,13 +573,13 @@ int bt_mesh_adv_enable(void)
549573

550574
int bt_mesh_adv_disable(void)
551575
{
552-
int err;
553576
struct k_work_sync sync;
577+
int err;
554578

555579
for (int i = 0; i < ARRAY_SIZE(advs); i++) {
556580
atomic_set_bit(advs[i].flags, ADV_FLAG_SUSPENDING);
557581

558-
if (k_current_get() != &k_sys_work_q.thread ||
582+
if (k_current_get() != k_work_queue_thread_get(MESH_WORKQ) ||
559583
(k_work_busy_get(&advs[i].work) & K_WORK_RUNNING) == 0) {
560584
k_work_flush(&advs[i].work, &sync);
561585
}
@@ -608,3 +632,8 @@ int bt_mesh_adv_bt_data_send(uint8_t num_events, uint16_t adv_interval,
608632
{
609633
return bt_data_send(advs, num_events, adv_interval, ad, ad_len);
610634
}
635+
636+
int bt_mesh_wq_submit(struct k_work *work)
637+
{
638+
return k_work_submit_to_queue(MESH_WORKQ, work);
639+
}

subsys/bluetooth/mesh/adv_legacy.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,8 @@ int bt_mesh_adv_gatt_start(const struct bt_le_adv_param *param, int32_t duration
258258
adv_timeout = duration;
259259
return bt_le_adv_start(param, ad, ad_len, sd, sd_len);
260260
}
261+
262+
int bt_mesh_wq_submit(struct k_work *work)
263+
{
264+
return k_work_submit(work);
265+
}

subsys/bluetooth/mesh/proxy_msg.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ static void proxy_sar_timeout(struct k_work *work)
6464
LOG_WRN("Proxy SAR timeout");
6565

6666
role = CONTAINER_OF(dwork, struct bt_mesh_proxy_role, sar_timer);
67+
68+
while (!k_fifo_is_empty(&role->pending)) {
69+
struct bt_mesh_adv *adv = k_fifo_get(&role->pending, K_NO_WAIT);
70+
71+
__ASSERT_NO_MSG(adv);
72+
73+
bt_mesh_adv_unref(adv);
74+
}
75+
6776
if (role->conn) {
6877
bt_conn_disconnect(role->conn,
6978
BT_HCI_ERR_REMOTE_USER_TERM_CONN);
@@ -200,7 +209,7 @@ static void buf_send_end(struct bt_conn *conn, void *user_data)
200209
bt_mesh_adv_unref(adv);
201210
}
202211

203-
int bt_mesh_proxy_relay_send(struct bt_conn *conn, struct bt_mesh_adv *adv)
212+
static int proxy_relay_send(struct bt_conn *conn, struct bt_mesh_adv *adv)
204213
{
205214
int err;
206215

@@ -230,6 +239,41 @@ int bt_mesh_proxy_relay_send(struct bt_conn *conn, struct bt_mesh_adv *adv)
230239
return err;
231240
}
232241

242+
int bt_mesh_proxy_relay_send(struct bt_conn *conn, struct bt_mesh_adv *adv)
243+
{
244+
struct bt_mesh_proxy_role *role = &roles[bt_conn_index(conn)];
245+
246+
k_fifo_put(&role->pending, bt_mesh_adv_ref(adv));
247+
248+
bt_mesh_wq_submit(&role->work);
249+
250+
return 0;
251+
}
252+
253+
static void proxy_msg_send_pending(struct k_work *work)
254+
{
255+
struct bt_mesh_proxy_role *role;
256+
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
257+
struct bt_mesh_adv *adv;
258+
259+
role = CONTAINER_OF(dwork, struct bt_mesh_proxy_role, sar_timer);
260+
if (!role->conn) {
261+
return;
262+
}
263+
264+
adv = k_fifo_get(&role->pending, K_NO_WAIT);
265+
if (!adv) {
266+
return;
267+
}
268+
269+
(void)proxy_relay_send(role->conn, adv);
270+
bt_mesh_adv_unref(adv);
271+
272+
if (!k_fifo_is_empty(&role->pending)) {
273+
bt_mesh_wq_submit(&role->work);
274+
}
275+
}
276+
233277
static void proxy_msg_init(struct bt_mesh_proxy_role *role)
234278
{
235279
/* Check if buf has been allocated, in this way, we no longer need
@@ -247,6 +291,9 @@ static void proxy_msg_init(struct bt_mesh_proxy_role *role)
247291

248292
net_buf_simple_reset(&role->buf);
249293

294+
k_fifo_init(&role->pending);
295+
k_work_init(&role->work, proxy_msg_send_pending);
296+
250297
k_work_init_delayable(&role->sar_timer, proxy_sar_timeout);
251298
}
252299

subsys/bluetooth/mesh/proxy_msg.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ struct bt_mesh_proxy_role {
3737
struct bt_conn *conn;
3838
uint8_t msg_type;
3939

40+
struct k_fifo pending;
41+
struct k_work work;
42+
4043
struct {
4144
proxy_send_cb_t send;
4245
proxy_recv_cb_t recv;

subsys/bluetooth/mesh/proxy_srv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ static ssize_t proxy_ccc_write(struct bt_conn *conn,
917917
client = find_client(conn);
918918
if (client->filter_type == NONE) {
919919
client->filter_type = ACCEPT;
920-
k_work_submit(&client->send_beacons);
920+
bt_mesh_wq_submit(&client->send_beacons);
921921
}
922922

923923
return sizeof(value);

tests/bsim/bluetooth/mesh/compile.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@ app=tests/bsim/bluetooth/mesh conf_overlay=overlay_pst.conf compile
1515
app=tests/bsim/bluetooth/mesh conf_overlay=overlay_gatt.conf compile
1616
app=tests/bsim/bluetooth/mesh conf_overlay=overlay_low_lat.conf compile
1717
app=tests/bsim/bluetooth/mesh conf_overlay=overlay_psa.conf compile
18+
app=tests/bsim/bluetooth/mesh conf_overlay=overlay_workq_sys.conf compile
1819
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_pst.conf;overlay_psa.conf" compile
1920
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_gatt.conf;overlay_psa.conf" compile
21+
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_gatt.conf;overlay_workq_sys.conf" compile
2022
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_low_lat.conf;overlay_psa.conf" compile
2123
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_gatt.conf;overlay_low_lat.conf" compile
2224
app=tests/bsim/bluetooth/mesh conf_overlay="overlay_pst.conf;overlay_gatt.conf" compile
2325
app=tests/bsim/bluetooth/mesh \
2426
conf_overlay="overlay_pst.conf;overlay_gatt.conf;overlay_psa.conf" compile
25-
27+
app=tests/bsim/bluetooth/mesh \
28+
conf_overlay="overlay_pst.conf;overlay_gatt.conf;overlay_workq_sys.conf" compile
2629
wait_for_background_jobs
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CONFIG_BT_MESH_WORKQ_SYS=y

0 commit comments

Comments
 (0)