@@ -115,7 +115,7 @@ static struct seg_tx {
115
115
friend_cred :1 ; /* Using Friend credentials */
116
116
const struct bt_mesh_send_cb * cb ;
117
117
void * cb_data ;
118
- struct k_delayed_work retransmit ; /* Retransmit timer */
118
+ struct k_work_delayable retransmit ; /* Retransmit timer */
119
119
} seg_tx [CONFIG_BT_MESH_TX_SEG_MSG_COUNT ];
120
120
121
121
static struct seg_rx {
@@ -133,7 +133,7 @@ static struct seg_rx {
133
133
uint8_t ttl ;
134
134
uint32_t block ;
135
135
uint32_t last ;
136
- struct k_delayed_work ack ;
136
+ struct k_work_delayable ack ;
137
137
} seg_rx [CONFIG_BT_MESH_RX_SEG_MSG_COUNT ];
138
138
139
139
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)
247
247
BT_DBG ("Unblocked 0x%04x" ,
248
248
(uint16_t )(blocked -> seq_auth & TRANS_SEQ_ZERO_MASK ));
249
249
blocked -> blocked = false;
250
- k_delayed_work_submit (& blocked -> retransmit , K_NO_WAIT );
250
+ k_work_reschedule (& blocked -> retransmit , K_NO_WAIT );
251
251
}
252
252
}
253
253
254
254
static void seg_tx_reset (struct seg_tx * tx )
255
255
{
256
256
int i ;
257
257
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 );
259
260
260
261
tx -> cb = NULL ;
261
262
tx -> cb_data = NULL ;
@@ -315,9 +316,9 @@ static void schedule_retransmit(struct seg_tx *tx)
315
316
* called this from inside bt_mesh_net_send), we should continue the
316
317
* retransmit immediately, as we just freed up a tx buffer.
317
318
*/
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 )));
321
322
}
322
323
323
324
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)
440
441
441
442
end :
442
443
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 )));
445
446
}
446
447
447
448
tx -> sending = 0U ;
@@ -859,8 +860,6 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
859
860
return - EINVAL ;
860
861
}
861
862
862
- k_delayed_work_cancel (& tx -> retransmit );
863
-
864
863
while ((bit = find_lsb_set (ack ))) {
865
864
if (tx -> seg [bit - 1 ]) {
866
865
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,
871
870
}
872
871
873
872
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 );
875
878
} else {
876
879
BT_DBG ("SDU TX complete" );
877
880
seg_tx_complete (tx , 0 );
@@ -1090,7 +1093,10 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
1090
1093
1091
1094
BT_DBG ("rx %p" , rx );
1092
1095
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 );
1094
1100
1095
1101
if (IS_ENABLED (CONFIG_BT_MESH_FRIEND ) && rx -> obo &&
1096
1102
rx -> block != BLOCK_COMPLETE (rx -> seg_n )) {
@@ -1127,6 +1133,16 @@ static void seg_ack(struct k_work *work)
1127
1133
struct seg_rx * rx = CONTAINER_OF (work , struct seg_rx , ack );
1128
1134
int32_t timeout ;
1129
1135
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
+
1130
1146
BT_DBG ("rx %p" , rx );
1131
1147
1132
1148
if (k_uptime_get_32 () - rx -> last > (60 * MSEC_PER_SEC )) {
@@ -1144,7 +1160,7 @@ static void seg_ack(struct k_work *work)
1144
1160
rx -> block , rx -> obo );
1145
1161
1146
1162
timeout = ack_timeout (rx );
1147
- k_delayed_work_submit (& rx -> ack , K_MSEC (timeout ));
1163
+ k_work_schedule (& rx -> ack , K_MSEC (timeout ));
1148
1164
}
1149
1165
1150
1166
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,
1447
1463
/* Reset the Incomplete Timer */
1448
1464
rx -> last = k_uptime_get_32 ();
1449
1465
1450
- if (!k_delayed_work_remaining_get (& rx -> ack ) &&
1451
- !bt_mesh_lpn_established ()) {
1466
+ if (!bt_mesh_lpn_established ()) {
1452
1467
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 ));
1455
1470
}
1456
1471
1457
1472
/* Allocated segment here */
@@ -1487,7 +1502,10 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
1487
1502
1488
1503
* pdu_type = BT_MESH_FRIEND_PDU_COMPLETE ;
1489
1504
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 );
1491
1509
send_ack (net_rx -> sub , net_rx -> ctx .recv_dst , net_rx -> ctx .addr ,
1492
1510
net_rx -> ctx .send_ttl , seq_auth , rx -> block , rx -> obo );
1493
1511
@@ -1643,11 +1661,11 @@ void bt_mesh_trans_init(void)
1643
1661
int i ;
1644
1662
1645
1663
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 );
1647
1665
}
1648
1666
1649
1667
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 );
1651
1669
}
1652
1670
}
1653
1671
0 commit comments