]> git.ipfire.org Git - people/ms/linux.git/blobdiff - net/rxrpc/output.c
rxrpc: Fix decision on when to generate an IDLE ACK
[people/ms/linux.git] / net / rxrpc / output.c
index 46aae9b7006fad7bb4909120ff88dbfc816b8224..9683617db7049c1e0db8dbd29d6d51b18fada2ad 100644 (file)
@@ -74,11 +74,18 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn,
                                 u8 reason)
 {
        rxrpc_serial_t serial;
+       unsigned int tmp;
        rxrpc_seq_t hard_ack, top, seq;
        int ix;
        u32 mtu, jmax;
        u8 *ackp = pkt->acks;
 
+       tmp = atomic_xchg(&call->ackr_nr_unacked, 0);
+       tmp |= atomic_xchg(&call->ackr_nr_consumed, 0);
+       if (!tmp && (reason == RXRPC_ACK_DELAY ||
+                    reason == RXRPC_ACK_IDLE))
+               return 0;
+
        /* Barrier against rxrpc_input_data(). */
        serial = call->ackr_serial;
        hard_ack = READ_ONCE(call->rx_hard_ack);
@@ -223,6 +230,10 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
        n = rxrpc_fill_out_ack(conn, call, pkt, &hard_ack, &top, reason);
 
        spin_unlock_bh(&call->lock);
+       if (n == 0) {
+               kfree(pkt);
+               return 0;
+       }
 
        iov[0].iov_base = pkt;
        iov[0].iov_len  = sizeof(pkt->whdr) + sizeof(pkt->ack) + n;
@@ -259,13 +270,6 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
                                          ntohl(pkt->ack.serial),
                                          false, true,
                                          rxrpc_propose_ack_retry_tx);
-               } else {
-                       spin_lock_bh(&call->lock);
-                       if (after(hard_ack, call->ackr_consumed))
-                               call->ackr_consumed = hard_ack;
-                       if (after(top, call->ackr_seen))
-                               call->ackr_seen = top;
-                       spin_unlock_bh(&call->lock);
                }
 
                rxrpc_set_keepalive(call);