Skip to content

Commit 84220f2

Browse files
committed
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]>
1 parent 185432c commit 84220f2

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
@@ -132,6 +132,11 @@ Bluetooth
132132

133133
* HCI Drivers
134134

135+
* Mesh
136+
137+
* Introduced a mesh-specific workqueue to increase reliability of the mesh messages
138+
transmission. To get the old behavior enable :kconfig:option:`CONFIG_BT_MESH_WORKQ_SYS`.
139+
135140
Boards & SoC Support
136141
********************
137142

subsys/bluetooth/mesh/Kconfig

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

104104
if BT_MESH_ADV_EXT
105105

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

36+
#ifdef CONFIG_BT_MESH_ADV_STACK_SIZE
37+
#define MESH_WORKQ_PRIORITY CONFIG_BT_MESH_ADV_PRIO
38+
#define MESH_WORKQ_STACK_SIZE CONFIG_BT_MESH_ADV_STACK_SIZE
39+
#else
40+
#define MESH_WORKQ_PRIORITY 0
41+
#define MESH_WORKQ_STACK_SIZE 0
42+
#endif
43+
3644
enum {
3745
/** Controller is currently advertising */
3846
ADV_FLAG_ACTIVE,
@@ -69,6 +77,15 @@ struct bt_mesh_ext_adv {
6977
static void send_pending_adv(struct k_work *work);
7078
static bool schedule_send(struct bt_mesh_ext_adv *ext_adv);
7179

80+
static struct k_work_q bt_mesh_workq;
81+
static K_KERNEL_STACK_DEFINE(thread_stack, MESH_WORKQ_STACK_SIZE);
82+
83+
#if defined(CONFIG_BT_MESH_WORKQ_MESH)
84+
#define MESH_WORKQ &bt_mesh_workq
85+
#else /* CONFIG_BT_MESH_WORKQ_SYS */
86+
#define MESH_WORKQ &k_sys_work_q
87+
#endif /* CONFIG_BT_MESH_WORKQ_MESH */
88+
7289
static struct bt_mesh_ext_adv advs[] = {
7390
[0] = {
7491
.tags = (
@@ -258,7 +275,7 @@ static bool schedule_send_with_mask(struct bt_mesh_ext_adv *ext_adv, int ignore_
258275
}
259276

260277
atomic_clear_bit(ext_adv->flags, ADV_FLAG_SCHEDULE_PENDING);
261-
k_work_submit(&ext_adv->work);
278+
bt_mesh_wq_submit(&ext_adv->work);
262279

263280
return true;
264281
}
@@ -407,7 +424,7 @@ int bt_mesh_adv_terminate(struct bt_mesh_adv *adv)
407424

408425
atomic_set_bit(ext_adv->flags, ADV_FLAG_SENT);
409426

410-
k_work_submit(&ext_adv->work);
427+
bt_mesh_wq_submit(&ext_adv->work);
411428

412429
return 0;
413430
}
@@ -429,6 +446,13 @@ void bt_mesh_adv_init(void)
429446
for (int i = 0; i < ARRAY_SIZE(advs); i++) {
430447
(void)memcpy(&advs[i].adv_param, &adv_param, sizeof(adv_param));
431448
}
449+
450+
if (IS_ENABLED(CONFIG_BT_MESH_WORKQ_MESH)) {
451+
k_work_queue_init(&bt_mesh_workq);
452+
k_work_queue_start(&bt_mesh_workq, thread_stack, MESH_WORKQ_STACK_SIZE,
453+
K_PRIO_COOP(MESH_WORKQ_PRIORITY), NULL);
454+
k_thread_name_set(&bt_mesh_workq.thread, "BT MESH WQ");
455+
}
432456
}
433457

434458
static struct bt_mesh_ext_adv *adv_instance_find(struct bt_le_ext_adv *instance)
@@ -458,7 +482,7 @@ static void adv_sent(struct bt_le_ext_adv *instance,
458482

459483
atomic_set_bit(ext_adv->flags, ADV_FLAG_SENT);
460484

461-
k_work_submit(&ext_adv->work);
485+
bt_mesh_wq_submit(&ext_adv->work);
462486
}
463487

464488
#if defined(CONFIG_BT_MESH_GATT_SERVER)
@@ -503,13 +527,13 @@ int bt_mesh_adv_enable(void)
503527

504528
int bt_mesh_adv_disable(void)
505529
{
506-
int err;
507530
struct k_work_sync sync;
531+
int err;
508532

509533
for (int i = 0; i < ARRAY_SIZE(advs); i++) {
510534
atomic_set_bit(advs[i].flags, ADV_FLAG_SUSPENDING);
511535

512-
if (k_current_get() != &k_sys_work_q.thread ||
536+
if (k_current_get() != k_work_queue_thread_get(MESH_WORKQ) ||
513537
(k_work_busy_get(&advs[i].work) & K_WORK_RUNNING) == 0) {
514538
k_work_flush(&advs[i].work, &sync);
515539
}
@@ -562,3 +586,8 @@ int bt_mesh_adv_bt_data_send(uint8_t num_events, uint16_t adv_interval,
562586
{
563587
return bt_data_send(advs, num_events, adv_interval, ad, ad_len);
564588
}
589+
590+
int bt_mesh_wq_submit(struct k_work *work)
591+
{
592+
return k_work_submit_to_queue(MESH_WORKQ, work);
593+
}

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
@@ -916,7 +916,7 @@ static ssize_t proxy_ccc_write(struct bt_conn *conn,
916916
client = find_client(conn);
917917
if (client->filter_type == NONE) {
918918
client->filter_type = ACCEPT;
919-
k_work_submit(&client->send_beacons);
919+
bt_mesh_wq_submit(&client->send_beacons);
920920
}
921921

922922
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)