|
@@ -216,10 +216,11 @@ static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb,
|
|
|
/*
|
|
|
* Apply a hard ACK by advancing the Tx window.
|
|
|
*/
|
|
|
-static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
|
|
|
+static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
|
|
|
struct rxrpc_ack_summary *summary)
|
|
|
{
|
|
|
struct sk_buff *skb, *list = NULL;
|
|
|
+ bool rot_last = false;
|
|
|
int ix;
|
|
|
u8 annotation;
|
|
|
|
|
@@ -243,15 +244,17 @@ static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
|
|
|
skb->next = list;
|
|
|
list = skb;
|
|
|
|
|
|
- if (annotation & RXRPC_TX_ANNO_LAST)
|
|
|
+ if (annotation & RXRPC_TX_ANNO_LAST) {
|
|
|
set_bit(RXRPC_CALL_TX_LAST, &call->flags);
|
|
|
+ rot_last = true;
|
|
|
+ }
|
|
|
if ((annotation & RXRPC_TX_ANNO_MASK) != RXRPC_TX_ANNO_ACK)
|
|
|
summary->nr_rot_new_acks++;
|
|
|
}
|
|
|
|
|
|
spin_unlock(&call->lock);
|
|
|
|
|
|
- trace_rxrpc_transmit(call, (test_bit(RXRPC_CALL_TX_LAST, &call->flags) ?
|
|
|
+ trace_rxrpc_transmit(call, (rot_last ?
|
|
|
rxrpc_transmit_rotate_last :
|
|
|
rxrpc_transmit_rotate));
|
|
|
wake_up(&call->waitq);
|
|
@@ -262,6 +265,8 @@ static void rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
|
|
|
skb->next = NULL;
|
|
|
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
|
|
|
}
|
|
|
+
|
|
|
+ return rot_last;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -332,11 +337,11 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
|
|
|
trace_rxrpc_timer(call, rxrpc_timer_init_for_reply, now);
|
|
|
}
|
|
|
|
|
|
- if (!test_bit(RXRPC_CALL_TX_LAST, &call->flags))
|
|
|
- rxrpc_rotate_tx_window(call, top, &summary);
|
|
|
if (!test_bit(RXRPC_CALL_TX_LAST, &call->flags)) {
|
|
|
- rxrpc_proto_abort("TXL", call, top);
|
|
|
- return false;
|
|
|
+ if (!rxrpc_rotate_tx_window(call, top, &summary)) {
|
|
|
+ rxrpc_proto_abort("TXL", call, top);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
if (!rxrpc_end_tx_phase(call, true, "ETD"))
|
|
|
return false;
|
|
@@ -897,8 +902,12 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
|
|
|
if (nr_acks > call->tx_top - hard_ack)
|
|
|
return rxrpc_proto_abort("AKN", call, 0);
|
|
|
|
|
|
- if (after(hard_ack, call->tx_hard_ack))
|
|
|
- rxrpc_rotate_tx_window(call, hard_ack, &summary);
|
|
|
+ if (after(hard_ack, call->tx_hard_ack)) {
|
|
|
+ if (rxrpc_rotate_tx_window(call, hard_ack, &summary)) {
|
|
|
+ rxrpc_end_tx_phase(call, false, "ETA");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
if (nr_acks > 0) {
|
|
|
if (skb_copy_bits(skb, offset, buf.acks, nr_acks) < 0)
|
|
@@ -907,11 +916,6 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
|
|
|
&summary);
|
|
|
}
|
|
|
|
|
|
- if (test_bit(RXRPC_CALL_TX_LAST, &call->flags)) {
|
|
|
- rxrpc_end_tx_phase(call, false, "ETA");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
if (call->rxtx_annotations[call->tx_top & RXRPC_RXTX_BUFF_MASK] &
|
|
|
RXRPC_TX_ANNO_LAST &&
|
|
|
summary.nr_acks == call->tx_top - hard_ack &&
|
|
@@ -933,8 +937,7 @@ static void rxrpc_input_ackall(struct rxrpc_call *call, struct sk_buff *skb)
|
|
|
|
|
|
_proto("Rx ACKALL %%%u", sp->hdr.serial);
|
|
|
|
|
|
- rxrpc_rotate_tx_window(call, call->tx_top, &summary);
|
|
|
- if (test_bit(RXRPC_CALL_TX_LAST, &call->flags))
|
|
|
+ if (rxrpc_rotate_tx_window(call, call->tx_top, &summary))
|
|
|
rxrpc_end_tx_phase(call, false, "ETL");
|
|
|
}
|
|
|
|