@@ -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
121121static 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
139139K_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
254254static 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
323324static 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
441442end :
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
11501166static 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