Skip to content

Commit 4e6cb11

Browse files
pabigotjhedberg
authored andcommitted
Bluetooth: Mesh: transport: update delayable work
Switch to the new API. Adds early exits for the ack and retransmit timers, and replaces a remaining_time() + submit() call with schedule(). Signed-off-by: Peter Bigot <[email protected]> Signed-off-by: Trond Einar Snekvik <[email protected]>
1 parent 1577fec commit 4e6cb11

File tree

1 file changed

+39
-21
lines changed

1 file changed

+39
-21
lines changed

subsys/bluetooth/mesh/transport.c

+39-21
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ static struct seg_tx {
115115
friend_cred:1; /* Using Friend credentials */
116116
const struct bt_mesh_send_cb *cb;
117117
void *cb_data;
118-
struct k_delayed_work retransmit; /* Retransmit timer */
118+
struct k_work_delayable retransmit; /* Retransmit timer */
119119
} seg_tx[CONFIG_BT_MESH_TX_SEG_MSG_COUNT];
120120

121121
static struct seg_rx {
@@ -133,7 +133,7 @@ static struct seg_rx {
133133
uint8_t ttl;
134134
uint32_t block;
135135
uint32_t last;
136-
struct k_delayed_work ack;
136+
struct k_work_delayable ack;
137137
} seg_rx[CONFIG_BT_MESH_RX_SEG_MSG_COUNT];
138138

139139
K_MEM_SLAB_DEFINE(segs, BT_MESH_APP_SEG_SDU_MAX, CONFIG_BT_MESH_SEG_BUFS, 4);
@@ -247,15 +247,16 @@ static void seg_tx_unblock_check(struct seg_tx *tx)
247247
BT_DBG("Unblocked 0x%04x",
248248
(uint16_t)(blocked->seq_auth & TRANS_SEQ_ZERO_MASK));
249249
blocked->blocked = false;
250-
k_delayed_work_submit(&blocked->retransmit, K_NO_WAIT);
250+
k_work_reschedule(&blocked->retransmit, K_NO_WAIT);
251251
}
252252
}
253253

254254
static void seg_tx_reset(struct seg_tx *tx)
255255
{
256256
int i;
257257

258-
k_delayed_work_cancel(&tx->retransmit);
258+
/* If this call fails, the handler will exit early, as nack_count is 0. */
259+
(void)k_work_cancel_delayable(&tx->retransmit);
259260

260261
tx->cb = NULL;
261262
tx->cb_data = NULL;
@@ -315,9 +316,9 @@ static void schedule_retransmit(struct seg_tx *tx)
315316
* called this from inside bt_mesh_net_send), we should continue the
316317
* retransmit immediately, as we just freed up a tx buffer.
317318
*/
318-
k_delayed_work_submit(&tx->retransmit,
319-
tx->seg_o ? K_NO_WAIT :
320-
K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx)));
319+
k_work_reschedule(&tx->retransmit,
320+
tx->seg_o ? K_NO_WAIT :
321+
K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx)));
321322
}
322323

323324
static void seg_send_start(uint16_t duration, int err, void *user_data)
@@ -440,8 +441,8 @@ static void seg_tx_send_unacked(struct seg_tx *tx)
440441

441442
end:
442443
if (!tx->seg_pending) {
443-
k_delayed_work_submit(&tx->retransmit,
444-
K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx)));
444+
k_work_reschedule(&tx->retransmit,
445+
K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx)));
445446
}
446447

447448
tx->sending = 0U;
@@ -859,8 +860,6 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
859860
return -EINVAL;
860861
}
861862

862-
k_delayed_work_cancel(&tx->retransmit);
863-
864863
while ((bit = find_lsb_set(ack))) {
865864
if (tx->seg[bit - 1]) {
866865
BT_DBG("seg %u/%u acked", bit - 1, tx->seg_n);
@@ -871,7 +870,11 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
871870
}
872871

873872
if (tx->nack_count) {
874-
seg_tx_send_unacked(tx);
873+
/* According to the Bluetooth Mesh Profile specification,
874+
* section 3.5.3.3, we should reset the retransmit timer and
875+
* retransmit immediately when receiving a valid ack message:
876+
*/
877+
k_work_reschedule(&tx->retransmit, K_NO_WAIT);
875878
} else {
876879
BT_DBG("SDU TX complete");
877880
seg_tx_complete(tx, 0);
@@ -1090,7 +1093,10 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
10901093

10911094
BT_DBG("rx %p", rx);
10921095

1093-
k_delayed_work_cancel(&rx->ack);
1096+
/* If this fails, the handler will exit early on the next execution, as
1097+
* it checks rx->in_use.
1098+
*/
1099+
(void)k_work_cancel_delayable(&rx->ack);
10941100

10951101
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->obo &&
10961102
rx->block != BLOCK_COMPLETE(rx->seg_n)) {
@@ -1127,6 +1133,16 @@ static void seg_ack(struct k_work *work)
11271133
struct seg_rx *rx = CONTAINER_OF(work, struct seg_rx, ack);
11281134
int32_t timeout;
11291135

1136+
if (!rx->in_use || rx->block == BLOCK_COMPLETE(rx->seg_n)) {
1137+
/* Cancellation of this timer may have failed. If it fails as
1138+
* part of seg_reset, in_use will be false.
1139+
* If it fails as part of the processing of a fully received
1140+
* SDU, the ack is already being sent from the receive handler,
1141+
* and the timer based ack sending can be ignored.
1142+
*/
1143+
return;
1144+
}
1145+
11301146
BT_DBG("rx %p", rx);
11311147

11321148
if (k_uptime_get_32() - rx->last > (60 * MSEC_PER_SEC)) {
@@ -1144,7 +1160,7 @@ static void seg_ack(struct k_work *work)
11441160
rx->block, rx->obo);
11451161

11461162
timeout = ack_timeout(rx);
1147-
k_delayed_work_submit(&rx->ack, K_MSEC(timeout));
1163+
k_work_schedule(&rx->ack, K_MSEC(timeout));
11481164
}
11491165

11501166
static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n)
@@ -1447,11 +1463,10 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
14471463
/* Reset the Incomplete Timer */
14481464
rx->last = k_uptime_get_32();
14491465

1450-
if (!k_delayed_work_remaining_get(&rx->ack) &&
1451-
!bt_mesh_lpn_established()) {
1466+
if (!bt_mesh_lpn_established()) {
14521467
int32_t timeout = ack_timeout(rx);
1453-
1454-
k_delayed_work_submit(&rx->ack, K_MSEC(timeout));
1468+
/* Should only start ack timer if it isn't running already: */
1469+
k_work_schedule(&rx->ack, K_MSEC(timeout));
14551470
}
14561471

14571472
/* Allocated segment here */
@@ -1487,7 +1502,10 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
14871502

14881503
*pdu_type = BT_MESH_FRIEND_PDU_COMPLETE;
14891504

1490-
k_delayed_work_cancel(&rx->ack);
1505+
/* If this fails, the work handler will either exit early because the
1506+
* block is fully received, or rx->in_use is false.
1507+
*/
1508+
(void)k_work_cancel_delayable(&rx->ack);
14911509
send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
14921510
net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo);
14931511

@@ -1643,11 +1661,11 @@ void bt_mesh_trans_init(void)
16431661
int i;
16441662

16451663
for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
1646-
k_delayed_work_init(&seg_tx[i].retransmit, seg_retransmit);
1664+
k_work_init_delayable(&seg_tx[i].retransmit, seg_retransmit);
16471665
}
16481666

16491667
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
1650-
k_delayed_work_init(&seg_rx[i].ack, seg_ack);
1668+
k_work_init_delayable(&seg_rx[i].ack, seg_ack);
16511669
}
16521670
}
16531671

0 commit comments

Comments
 (0)