Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bluetooth: Mesh: Allow to suspend mesh from bt_mesh_send_cb callbacks #68735

Merged
merged 4 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions include/zephyr/bluetooth/mesh/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -607,10 +607,6 @@ void bt_mesh_reset(void);
* If at all possible, the Friendship feature should be used instead, to
* make the node into a Low Power Node.
*
* @note Should not be called from work queue due to undefined behavior.
* This is due to k_work_flush_delayable() being used in disabling of the
* extended advertising.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_suspend(void);
Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/mesh/adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ int bt_mesh_scan_disable(void);

int bt_mesh_adv_enable(void);

/* Should not be called from work queue due to undefined behavior */
int bt_mesh_adv_disable(void);

void bt_mesh_adv_local_ready(void);
Expand Down
23 changes: 22 additions & 1 deletion subsys/bluetooth/mesh/adv_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ enum {
*/
ADV_FLAG_UPDATE_PARAMS,

/** The advertiser is suspending. */
ADV_FLAG_SUSPENDING,

/* Number of adv flags. */
ADV_FLAGS_NUM
};
Expand Down Expand Up @@ -248,6 +251,11 @@ static void send_pending_adv(struct k_work *work)

ext_adv = CONTAINER_OF(work, struct bt_mesh_ext_adv, work);

if (atomic_test_bit(ext_adv->flags, ADV_FLAG_SUSPENDING)) {
LOG_DBG("Advertiser is suspending");
return;
}

if (atomic_test_and_clear_bit(ext_adv->flags, ADV_FLAG_SENT)) {
LOG_DBG("Advertising stopped after %u ms for %s",
k_uptime_get_32() - ext_adv->timestamp,
Expand Down Expand Up @@ -292,6 +300,11 @@ static void send_pending_adv(struct k_work *work)
}
}

if (ext_adv->instance == NULL) {
LOG_DBG("Advertiser is suspended or deleted");
return;
}

if (IS_ENABLED(CONFIG_BT_MESH_PROXY_SOLICITATION) &&
!bt_mesh_sol_send()) {
return;
Expand Down Expand Up @@ -496,7 +509,12 @@ int bt_mesh_adv_disable(void)
struct k_work_sync sync;

for (int i = 0; i < ARRAY_SIZE(advs); i++) {
k_work_flush(&advs[i].work, &sync);
atomic_set_bit(advs[i].flags, ADV_FLAG_SUSPENDING);

if (k_current_get() != &k_sys_work_q.thread ||
(k_work_busy_get(&advs[i].work) & K_WORK_RUNNING) == 0) {
k_work_flush(&advs[i].work, &sync);
}

err = bt_le_ext_adv_stop(advs[i].instance);
if (err) {
Expand All @@ -514,7 +532,10 @@ int bt_mesh_adv_disable(void)
LOG_ERR("Failed to delete adv %d", err);
return err;
}

advs[i].instance = NULL;

atomic_clear_bit(advs[i].flags, ADV_FLAG_SUSPENDING);
}

return 0;
Expand Down
12 changes: 9 additions & 3 deletions subsys/bluetooth/mesh/adv_legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ static int bt_data_send(uint8_t num_events, uint16_t adv_int,
bt_mesh_adv_send_start(duration, err, ctx);
}

k_sleep(K_MSEC(duration));
if (enabled) {
k_sleep(K_MSEC(duration));
}

err = bt_le_adv_stop();
if (err) {
Expand Down Expand Up @@ -239,9 +241,13 @@ int bt_mesh_adv_enable(void)

int bt_mesh_adv_disable(void)
{
int err;

enabled = false;
k_thread_join(&adv_thread_data, K_FOREVER);
LOG_DBG("Advertising disabled");

err = k_thread_join(&adv_thread_data, K_FOREVER);
LOG_DBG("Advertising disabled: %d", err);

return 0;
}

Expand Down
9 changes: 1 addition & 8 deletions tests/bsim/bluetooth/mesh/src/test_advertiser.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,13 +598,6 @@ static void adv_resume(void)
ASSERT_OK_MSG(bt_mesh_adv_enable(), "Failed to enable advertiser");
}

static void adv_disable_work_handler(struct k_work *work)
{
adv_suspend();
}

static K_WORK_DEFINE(adv_disable_work, adv_disable_work_handler);

struct adv_suspend_ctx {
bool suspend;
int instance_idx;
Expand Down Expand Up @@ -644,7 +637,7 @@ static void adv_send_start(uint16_t duration, int err, void *cb_data)
if (adv_data->suspend) {
if (adv_data->instance_idx == 0) {
ASSERT_EQUAL(err, 0);
k_work_submit(&adv_disable_work);
adv_suspend();
} else {
/* For the advs that were pushed to the mesh advertiser by calling
* `bt_mesh_adv_send` function but not sent to the host, the start callback
Expand Down
12 changes: 3 additions & 9 deletions tests/bsim/bluetooth/mesh/src/test_provision.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,20 +147,15 @@ static const struct bt_mesh_comp rpr_cli_srv_comp = {
.elem_count = 1,
};

/* Delayed work to suspend device to allow publication to finish. */
static struct k_work_delayable suspend_work;
static void delayed_suspend(struct k_work *work)
static int mock_pdu_send(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Device becomes unresponsive and doesn't communicate with other nodes anymore */
k_sleep(K_MSEC(10));
bt_mesh_suspend();

k_sem_give(&pdu_send_sem);
}

static int mock_pdu_send(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
k_work_schedule(&suspend_work, K_MSEC(100));
return 0;
}

Expand Down Expand Up @@ -1272,7 +1267,6 @@ static void test_device_pb_remote_server_unproved(void)
*/
static void test_device_pb_remote_server_unproved_unresponsive(void)
{
k_work_init_delayable(&suspend_work, delayed_suspend);
device_pb_remote_server_setup_unproved(&rpr_srv_comp_unresponsive, NULL);

k_sem_init(&pdu_send_sem, 0, 1);
Expand Down
Loading