18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* Management of Tx window, Tx resend, ACKs and out-of-sequence reception 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/circ_buf.h> 128c2ecf20Sopenharmony_ci#include <linux/net.h> 138c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/udp.h> 168c2ecf20Sopenharmony_ci#include <net/sock.h> 178c2ecf20Sopenharmony_ci#include <net/af_rxrpc.h> 188c2ecf20Sopenharmony_ci#include "ar-internal.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* 218c2ecf20Sopenharmony_ci * Propose a PING ACK be sent. 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_cistatic void rxrpc_propose_ping(struct rxrpc_call *call, 248c2ecf20Sopenharmony_ci bool immediate, bool background) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci if (immediate) { 278c2ecf20Sopenharmony_ci if (background && 288c2ecf20Sopenharmony_ci !test_and_set_bit(RXRPC_CALL_EV_PING, &call->events)) 298c2ecf20Sopenharmony_ci rxrpc_queue_call(call); 308c2ecf20Sopenharmony_ci } else { 318c2ecf20Sopenharmony_ci unsigned long now = jiffies; 328c2ecf20Sopenharmony_ci unsigned long ping_at = now + rxrpc_idle_ack_delay; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci if (time_before(ping_at, call->ping_at)) { 358c2ecf20Sopenharmony_ci WRITE_ONCE(call->ping_at, ping_at); 368c2ecf20Sopenharmony_ci rxrpc_reduce_call_timer(call, ping_at, now, 378c2ecf20Sopenharmony_ci rxrpc_timer_set_for_ping); 388c2ecf20Sopenharmony_ci } 398c2ecf20Sopenharmony_ci } 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* 438c2ecf20Sopenharmony_ci * propose an ACK be sent 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_cistatic void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, 468c2ecf20Sopenharmony_ci u32 serial, bool immediate, bool background, 478c2ecf20Sopenharmony_ci enum rxrpc_propose_ack_trace why) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci enum rxrpc_propose_ack_outcome outcome = rxrpc_propose_ack_use; 508c2ecf20Sopenharmony_ci unsigned long expiry = rxrpc_soft_ack_delay; 518c2ecf20Sopenharmony_ci s8 prior = rxrpc_ack_priority[ack_reason]; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /* Pings are handled specially because we don't want to accidentally 548c2ecf20Sopenharmony_ci * lose a ping response by subsuming it into a ping. 558c2ecf20Sopenharmony_ci */ 568c2ecf20Sopenharmony_ci if (ack_reason == RXRPC_ACK_PING) { 578c2ecf20Sopenharmony_ci rxrpc_propose_ping(call, immediate, background); 588c2ecf20Sopenharmony_ci goto trace; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci /* Update DELAY, IDLE, REQUESTED and PING_RESPONSE ACK serial 628c2ecf20Sopenharmony_ci * numbers, but we don't alter the timeout. 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_ci _debug("prior %u %u vs %u %u", 658c2ecf20Sopenharmony_ci ack_reason, prior, 668c2ecf20Sopenharmony_ci call->ackr_reason, rxrpc_ack_priority[call->ackr_reason]); 678c2ecf20Sopenharmony_ci if (ack_reason == call->ackr_reason) { 688c2ecf20Sopenharmony_ci if (RXRPC_ACK_UPDATEABLE & (1 << ack_reason)) { 698c2ecf20Sopenharmony_ci outcome = rxrpc_propose_ack_update; 708c2ecf20Sopenharmony_ci call->ackr_serial = serial; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci if (!immediate) 738c2ecf20Sopenharmony_ci goto trace; 748c2ecf20Sopenharmony_ci } else if (prior > rxrpc_ack_priority[call->ackr_reason]) { 758c2ecf20Sopenharmony_ci call->ackr_reason = ack_reason; 768c2ecf20Sopenharmony_ci call->ackr_serial = serial; 778c2ecf20Sopenharmony_ci } else { 788c2ecf20Sopenharmony_ci outcome = rxrpc_propose_ack_subsume; 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci switch (ack_reason) { 828c2ecf20Sopenharmony_ci case RXRPC_ACK_REQUESTED: 838c2ecf20Sopenharmony_ci if (rxrpc_requested_ack_delay < expiry) 848c2ecf20Sopenharmony_ci expiry = rxrpc_requested_ack_delay; 858c2ecf20Sopenharmony_ci if (serial == 1) 868c2ecf20Sopenharmony_ci immediate = false; 878c2ecf20Sopenharmony_ci break; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci case RXRPC_ACK_DELAY: 908c2ecf20Sopenharmony_ci if (rxrpc_soft_ack_delay < expiry) 918c2ecf20Sopenharmony_ci expiry = rxrpc_soft_ack_delay; 928c2ecf20Sopenharmony_ci break; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci case RXRPC_ACK_IDLE: 958c2ecf20Sopenharmony_ci if (rxrpc_idle_ack_delay < expiry) 968c2ecf20Sopenharmony_ci expiry = rxrpc_idle_ack_delay; 978c2ecf20Sopenharmony_ci break; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci default: 1008c2ecf20Sopenharmony_ci immediate = true; 1018c2ecf20Sopenharmony_ci break; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (test_bit(RXRPC_CALL_EV_ACK, &call->events)) { 1058c2ecf20Sopenharmony_ci _debug("already scheduled"); 1068c2ecf20Sopenharmony_ci } else if (immediate || expiry == 0) { 1078c2ecf20Sopenharmony_ci _debug("immediate ACK %lx", call->events); 1088c2ecf20Sopenharmony_ci if (!test_and_set_bit(RXRPC_CALL_EV_ACK, &call->events) && 1098c2ecf20Sopenharmony_ci background) 1108c2ecf20Sopenharmony_ci rxrpc_queue_call(call); 1118c2ecf20Sopenharmony_ci } else { 1128c2ecf20Sopenharmony_ci unsigned long now = jiffies, ack_at; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (call->peer->srtt_us != 0) 1158c2ecf20Sopenharmony_ci ack_at = usecs_to_jiffies(call->peer->srtt_us >> 3); 1168c2ecf20Sopenharmony_ci else 1178c2ecf20Sopenharmony_ci ack_at = expiry; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci ack_at += READ_ONCE(call->tx_backoff); 1208c2ecf20Sopenharmony_ci ack_at += now; 1218c2ecf20Sopenharmony_ci if (time_before(ack_at, call->ack_at)) { 1228c2ecf20Sopenharmony_ci WRITE_ONCE(call->ack_at, ack_at); 1238c2ecf20Sopenharmony_ci rxrpc_reduce_call_timer(call, ack_at, now, 1248c2ecf20Sopenharmony_ci rxrpc_timer_set_for_ack); 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_citrace: 1298c2ecf20Sopenharmony_ci trace_rxrpc_propose_ack(call, why, ack_reason, serial, immediate, 1308c2ecf20Sopenharmony_ci background, outcome); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* 1348c2ecf20Sopenharmony_ci * propose an ACK be sent, locking the call structure 1358c2ecf20Sopenharmony_ci */ 1368c2ecf20Sopenharmony_civoid rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, 1378c2ecf20Sopenharmony_ci u32 serial, bool immediate, bool background, 1388c2ecf20Sopenharmony_ci enum rxrpc_propose_ack_trace why) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci spin_lock_bh(&call->lock); 1418c2ecf20Sopenharmony_ci __rxrpc_propose_ACK(call, ack_reason, serial, 1428c2ecf20Sopenharmony_ci immediate, background, why); 1438c2ecf20Sopenharmony_ci spin_unlock_bh(&call->lock); 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci/* 1478c2ecf20Sopenharmony_ci * Handle congestion being detected by the retransmit timeout. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_cistatic void rxrpc_congestion_timeout(struct rxrpc_call *call) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci set_bit(RXRPC_CALL_RETRANS_TIMEOUT, &call->flags); 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci/* 1558c2ecf20Sopenharmony_ci * Perform retransmission of NAK'd and unack'd packets. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_cistatic void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci struct sk_buff *skb; 1608c2ecf20Sopenharmony_ci unsigned long resend_at; 1618c2ecf20Sopenharmony_ci rxrpc_seq_t cursor, seq, top; 1628c2ecf20Sopenharmony_ci ktime_t now, max_age, oldest, ack_ts; 1638c2ecf20Sopenharmony_ci int ix; 1648c2ecf20Sopenharmony_ci u8 annotation, anno_type, retrans = 0, unacked = 0; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci _enter("{%d,%d}", call->tx_hard_ack, call->tx_top); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci now = ktime_get_real(); 1698c2ecf20Sopenharmony_ci max_age = ktime_sub_us(now, jiffies_to_usecs(call->peer->rto_j)); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci spin_lock_bh(&call->lock); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci cursor = call->tx_hard_ack; 1748c2ecf20Sopenharmony_ci top = call->tx_top; 1758c2ecf20Sopenharmony_ci ASSERT(before_eq(cursor, top)); 1768c2ecf20Sopenharmony_ci if (cursor == top) 1778c2ecf20Sopenharmony_ci goto out_unlock; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* Scan the packet list without dropping the lock and decide which of 1808c2ecf20Sopenharmony_ci * the packets in the Tx buffer we're going to resend and what the new 1818c2ecf20Sopenharmony_ci * resend timeout will be. 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_ci trace_rxrpc_resend(call, (cursor + 1) & RXRPC_RXTX_BUFF_MASK); 1848c2ecf20Sopenharmony_ci oldest = now; 1858c2ecf20Sopenharmony_ci for (seq = cursor + 1; before_eq(seq, top); seq++) { 1868c2ecf20Sopenharmony_ci ix = seq & RXRPC_RXTX_BUFF_MASK; 1878c2ecf20Sopenharmony_ci annotation = call->rxtx_annotations[ix]; 1888c2ecf20Sopenharmony_ci anno_type = annotation & RXRPC_TX_ANNO_MASK; 1898c2ecf20Sopenharmony_ci annotation &= ~RXRPC_TX_ANNO_MASK; 1908c2ecf20Sopenharmony_ci if (anno_type == RXRPC_TX_ANNO_ACK) 1918c2ecf20Sopenharmony_ci continue; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci skb = call->rxtx_buffer[ix]; 1948c2ecf20Sopenharmony_ci rxrpc_see_skb(skb, rxrpc_skb_seen); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci if (anno_type == RXRPC_TX_ANNO_UNACK) { 1978c2ecf20Sopenharmony_ci if (ktime_after(skb->tstamp, max_age)) { 1988c2ecf20Sopenharmony_ci if (ktime_before(skb->tstamp, oldest)) 1998c2ecf20Sopenharmony_ci oldest = skb->tstamp; 2008c2ecf20Sopenharmony_ci continue; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci if (!(annotation & RXRPC_TX_ANNO_RESENT)) 2038c2ecf20Sopenharmony_ci unacked++; 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci /* Okay, we need to retransmit a packet. */ 2078c2ecf20Sopenharmony_ci call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS | annotation; 2088c2ecf20Sopenharmony_ci retrans++; 2098c2ecf20Sopenharmony_ci trace_rxrpc_retransmit(call, seq, annotation | anno_type, 2108c2ecf20Sopenharmony_ci ktime_to_ns(ktime_sub(skb->tstamp, max_age))); 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci resend_at = nsecs_to_jiffies(ktime_to_ns(ktime_sub(now, oldest))); 2148c2ecf20Sopenharmony_ci resend_at += jiffies + rxrpc_get_rto_backoff(call->peer, retrans); 2158c2ecf20Sopenharmony_ci WRITE_ONCE(call->resend_at, resend_at); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (unacked) 2188c2ecf20Sopenharmony_ci rxrpc_congestion_timeout(call); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /* If there was nothing that needed retransmission then it's likely 2218c2ecf20Sopenharmony_ci * that an ACK got lost somewhere. Send a ping to find out instead of 2228c2ecf20Sopenharmony_ci * retransmitting data. 2238c2ecf20Sopenharmony_ci */ 2248c2ecf20Sopenharmony_ci if (!retrans) { 2258c2ecf20Sopenharmony_ci rxrpc_reduce_call_timer(call, resend_at, now_j, 2268c2ecf20Sopenharmony_ci rxrpc_timer_set_for_resend); 2278c2ecf20Sopenharmony_ci spin_unlock_bh(&call->lock); 2288c2ecf20Sopenharmony_ci ack_ts = ktime_sub(now, call->acks_latest_ts); 2298c2ecf20Sopenharmony_ci if (ktime_to_us(ack_ts) < (call->peer->srtt_us >> 3)) 2308c2ecf20Sopenharmony_ci goto out; 2318c2ecf20Sopenharmony_ci rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false, 2328c2ecf20Sopenharmony_ci rxrpc_propose_ack_ping_for_lost_ack); 2338c2ecf20Sopenharmony_ci rxrpc_send_ack_packet(call, true, NULL); 2348c2ecf20Sopenharmony_ci goto out; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci /* Now go through the Tx window and perform the retransmissions. We 2388c2ecf20Sopenharmony_ci * have to drop the lock for each send. If an ACK comes in whilst the 2398c2ecf20Sopenharmony_ci * lock is dropped, it may clear some of the retransmission markers for 2408c2ecf20Sopenharmony_ci * packets that it soft-ACKs. 2418c2ecf20Sopenharmony_ci */ 2428c2ecf20Sopenharmony_ci for (seq = cursor + 1; before_eq(seq, top); seq++) { 2438c2ecf20Sopenharmony_ci ix = seq & RXRPC_RXTX_BUFF_MASK; 2448c2ecf20Sopenharmony_ci annotation = call->rxtx_annotations[ix]; 2458c2ecf20Sopenharmony_ci anno_type = annotation & RXRPC_TX_ANNO_MASK; 2468c2ecf20Sopenharmony_ci if (anno_type != RXRPC_TX_ANNO_RETRANS) 2478c2ecf20Sopenharmony_ci continue; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* We need to reset the retransmission state, but we need to do 2508c2ecf20Sopenharmony_ci * so before we drop the lock as a new ACK/NAK may come in and 2518c2ecf20Sopenharmony_ci * confuse things 2528c2ecf20Sopenharmony_ci */ 2538c2ecf20Sopenharmony_ci annotation &= ~RXRPC_TX_ANNO_MASK; 2548c2ecf20Sopenharmony_ci annotation |= RXRPC_TX_ANNO_UNACK | RXRPC_TX_ANNO_RESENT; 2558c2ecf20Sopenharmony_ci call->rxtx_annotations[ix] = annotation; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci skb = call->rxtx_buffer[ix]; 2588c2ecf20Sopenharmony_ci if (!skb) 2598c2ecf20Sopenharmony_ci continue; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci rxrpc_get_skb(skb, rxrpc_skb_got); 2628c2ecf20Sopenharmony_ci spin_unlock_bh(&call->lock); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci if (rxrpc_send_data_packet(call, skb, true) < 0) { 2658c2ecf20Sopenharmony_ci rxrpc_free_skb(skb, rxrpc_skb_freed); 2668c2ecf20Sopenharmony_ci return; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci if (rxrpc_is_client_call(call)) 2708c2ecf20Sopenharmony_ci rxrpc_expose_client_call(call); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci rxrpc_free_skb(skb, rxrpc_skb_freed); 2738c2ecf20Sopenharmony_ci spin_lock_bh(&call->lock); 2748c2ecf20Sopenharmony_ci if (after(call->tx_hard_ack, seq)) 2758c2ecf20Sopenharmony_ci seq = call->tx_hard_ack; 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ciout_unlock: 2798c2ecf20Sopenharmony_ci spin_unlock_bh(&call->lock); 2808c2ecf20Sopenharmony_ciout: 2818c2ecf20Sopenharmony_ci _leave(""); 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci/* 2858c2ecf20Sopenharmony_ci * Handle retransmission and deferred ACK/abort generation. 2868c2ecf20Sopenharmony_ci */ 2878c2ecf20Sopenharmony_civoid rxrpc_process_call(struct work_struct *work) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci struct rxrpc_call *call = 2908c2ecf20Sopenharmony_ci container_of(work, struct rxrpc_call, processor); 2918c2ecf20Sopenharmony_ci rxrpc_serial_t *send_ack; 2928c2ecf20Sopenharmony_ci unsigned long now, next, t; 2938c2ecf20Sopenharmony_ci unsigned int iterations = 0; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci rxrpc_see_call(call); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci //printk("\n--------------------\n"); 2988c2ecf20Sopenharmony_ci _enter("{%d,%s,%lx}", 2998c2ecf20Sopenharmony_ci call->debug_id, rxrpc_call_states[call->state], call->events); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cirecheck_state: 3028c2ecf20Sopenharmony_ci /* Limit the number of times we do this before returning to the manager */ 3038c2ecf20Sopenharmony_ci iterations++; 3048c2ecf20Sopenharmony_ci if (iterations > 5) 3058c2ecf20Sopenharmony_ci goto requeue; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci if (test_and_clear_bit(RXRPC_CALL_EV_ABORT, &call->events)) { 3088c2ecf20Sopenharmony_ci rxrpc_send_abort_packet(call); 3098c2ecf20Sopenharmony_ci goto recheck_state; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if (call->state == RXRPC_CALL_COMPLETE) { 3138c2ecf20Sopenharmony_ci rxrpc_delete_call_timer(call); 3148c2ecf20Sopenharmony_ci goto out_put; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci /* Work out if any timeouts tripped */ 3188c2ecf20Sopenharmony_ci now = jiffies; 3198c2ecf20Sopenharmony_ci t = READ_ONCE(call->expect_rx_by); 3208c2ecf20Sopenharmony_ci if (time_after_eq(now, t)) { 3218c2ecf20Sopenharmony_ci trace_rxrpc_timer(call, rxrpc_timer_exp_normal, now); 3228c2ecf20Sopenharmony_ci set_bit(RXRPC_CALL_EV_EXPIRED, &call->events); 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci t = READ_ONCE(call->expect_req_by); 3268c2ecf20Sopenharmony_ci if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST && 3278c2ecf20Sopenharmony_ci time_after_eq(now, t)) { 3288c2ecf20Sopenharmony_ci trace_rxrpc_timer(call, rxrpc_timer_exp_idle, now); 3298c2ecf20Sopenharmony_ci set_bit(RXRPC_CALL_EV_EXPIRED, &call->events); 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci t = READ_ONCE(call->expect_term_by); 3338c2ecf20Sopenharmony_ci if (time_after_eq(now, t)) { 3348c2ecf20Sopenharmony_ci trace_rxrpc_timer(call, rxrpc_timer_exp_hard, now); 3358c2ecf20Sopenharmony_ci set_bit(RXRPC_CALL_EV_EXPIRED, &call->events); 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci t = READ_ONCE(call->ack_at); 3398c2ecf20Sopenharmony_ci if (time_after_eq(now, t)) { 3408c2ecf20Sopenharmony_ci trace_rxrpc_timer(call, rxrpc_timer_exp_ack, now); 3418c2ecf20Sopenharmony_ci cmpxchg(&call->ack_at, t, now + MAX_JIFFY_OFFSET); 3428c2ecf20Sopenharmony_ci set_bit(RXRPC_CALL_EV_ACK, &call->events); 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci t = READ_ONCE(call->ack_lost_at); 3468c2ecf20Sopenharmony_ci if (time_after_eq(now, t)) { 3478c2ecf20Sopenharmony_ci trace_rxrpc_timer(call, rxrpc_timer_exp_lost_ack, now); 3488c2ecf20Sopenharmony_ci cmpxchg(&call->ack_lost_at, t, now + MAX_JIFFY_OFFSET); 3498c2ecf20Sopenharmony_ci set_bit(RXRPC_CALL_EV_ACK_LOST, &call->events); 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci t = READ_ONCE(call->keepalive_at); 3538c2ecf20Sopenharmony_ci if (time_after_eq(now, t)) { 3548c2ecf20Sopenharmony_ci trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now); 3558c2ecf20Sopenharmony_ci cmpxchg(&call->keepalive_at, t, now + MAX_JIFFY_OFFSET); 3568c2ecf20Sopenharmony_ci rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, true, 3578c2ecf20Sopenharmony_ci rxrpc_propose_ack_ping_for_keepalive); 3588c2ecf20Sopenharmony_ci set_bit(RXRPC_CALL_EV_PING, &call->events); 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci t = READ_ONCE(call->ping_at); 3628c2ecf20Sopenharmony_ci if (time_after_eq(now, t)) { 3638c2ecf20Sopenharmony_ci trace_rxrpc_timer(call, rxrpc_timer_exp_ping, now); 3648c2ecf20Sopenharmony_ci cmpxchg(&call->ping_at, t, now + MAX_JIFFY_OFFSET); 3658c2ecf20Sopenharmony_ci set_bit(RXRPC_CALL_EV_PING, &call->events); 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci t = READ_ONCE(call->resend_at); 3698c2ecf20Sopenharmony_ci if (time_after_eq(now, t)) { 3708c2ecf20Sopenharmony_ci trace_rxrpc_timer(call, rxrpc_timer_exp_resend, now); 3718c2ecf20Sopenharmony_ci cmpxchg(&call->resend_at, t, now + MAX_JIFFY_OFFSET); 3728c2ecf20Sopenharmony_ci set_bit(RXRPC_CALL_EV_RESEND, &call->events); 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci /* Process events */ 3768c2ecf20Sopenharmony_ci if (test_and_clear_bit(RXRPC_CALL_EV_EXPIRED, &call->events)) { 3778c2ecf20Sopenharmony_ci if (test_bit(RXRPC_CALL_RX_HEARD, &call->flags) && 3788c2ecf20Sopenharmony_ci (int)call->conn->hi_serial - (int)call->rx_serial > 0) { 3798c2ecf20Sopenharmony_ci trace_rxrpc_call_reset(call); 3808c2ecf20Sopenharmony_ci rxrpc_abort_call("EXP", call, 0, RX_CALL_DEAD, -ECONNRESET); 3818c2ecf20Sopenharmony_ci } else { 3828c2ecf20Sopenharmony_ci rxrpc_abort_call("EXP", call, 0, RX_CALL_TIMEOUT, -ETIME); 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci set_bit(RXRPC_CALL_EV_ABORT, &call->events); 3858c2ecf20Sopenharmony_ci goto recheck_state; 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci send_ack = NULL; 3898c2ecf20Sopenharmony_ci if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events)) { 3908c2ecf20Sopenharmony_ci call->acks_lost_top = call->tx_top; 3918c2ecf20Sopenharmony_ci rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false, 3928c2ecf20Sopenharmony_ci rxrpc_propose_ack_ping_for_lost_ack); 3938c2ecf20Sopenharmony_ci send_ack = &call->acks_lost_ping; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci if (test_and_clear_bit(RXRPC_CALL_EV_ACK, &call->events) || 3978c2ecf20Sopenharmony_ci send_ack) { 3988c2ecf20Sopenharmony_ci if (call->ackr_reason) { 3998c2ecf20Sopenharmony_ci rxrpc_send_ack_packet(call, false, send_ack); 4008c2ecf20Sopenharmony_ci goto recheck_state; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci if (test_and_clear_bit(RXRPC_CALL_EV_PING, &call->events)) { 4058c2ecf20Sopenharmony_ci rxrpc_send_ack_packet(call, true, NULL); 4068c2ecf20Sopenharmony_ci goto recheck_state; 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci if (test_and_clear_bit(RXRPC_CALL_EV_RESEND, &call->events) && 4108c2ecf20Sopenharmony_ci call->state != RXRPC_CALL_CLIENT_RECV_REPLY) { 4118c2ecf20Sopenharmony_ci rxrpc_resend(call, now); 4128c2ecf20Sopenharmony_ci goto recheck_state; 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci /* Make sure the timer is restarted */ 4168c2ecf20Sopenharmony_ci next = call->expect_rx_by; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci#define set(T) { t = READ_ONCE(T); if (time_before(t, next)) next = t; } 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci set(call->expect_req_by); 4218c2ecf20Sopenharmony_ci set(call->expect_term_by); 4228c2ecf20Sopenharmony_ci set(call->ack_at); 4238c2ecf20Sopenharmony_ci set(call->ack_lost_at); 4248c2ecf20Sopenharmony_ci set(call->resend_at); 4258c2ecf20Sopenharmony_ci set(call->keepalive_at); 4268c2ecf20Sopenharmony_ci set(call->ping_at); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci now = jiffies; 4298c2ecf20Sopenharmony_ci if (time_after_eq(now, next)) 4308c2ecf20Sopenharmony_ci goto recheck_state; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci rxrpc_reduce_call_timer(call, next, now, rxrpc_timer_restart); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci /* other events may have been raised since we started checking */ 4358c2ecf20Sopenharmony_ci if (call->events && call->state < RXRPC_CALL_COMPLETE) 4368c2ecf20Sopenharmony_ci goto requeue; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ciout_put: 4398c2ecf20Sopenharmony_ci rxrpc_put_call(call, rxrpc_call_put); 4408c2ecf20Sopenharmony_ciout: 4418c2ecf20Sopenharmony_ci _leave(""); 4428c2ecf20Sopenharmony_ci return; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_cirequeue: 4458c2ecf20Sopenharmony_ci __rxrpc_queue_call(call); 4468c2ecf20Sopenharmony_ci goto out; 4478c2ecf20Sopenharmony_ci} 448