summaryrefslogtreecommitdiffstats
path: root/net/x25/x25_out.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-12-16 05:34:03 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-12-16 05:34:03 +0000
commit967c65a99059fd459b956c1588ce0ba227912c4e (patch)
tree8224d013ff5d255420713d05610c7efebd204d2a /net/x25/x25_out.c
parente20c1cc1656a66a2773bca4591a895cbc12696ff (diff)
Merge with Linux 2.1.72, part 1.
Diffstat (limited to 'net/x25/x25_out.c')
-rw-r--r--net/x25/x25_out.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c
index aa8fc2c1b..5283092a1 100644
--- a/net/x25/x25_out.c
+++ b/net/x25/x25_out.c
@@ -126,8 +126,8 @@ static void x25_send_iframe(struct sock *sk, struct sk_buff *skb)
void x25_kick(struct sock *sk)
{
- struct sk_buff *skb;
- unsigned short end;
+ struct sk_buff *skb, *skbn;
+ unsigned short start, end;
int modulus;
if (sk->protinfo.x25->state != X25_STATE_3)
@@ -149,11 +149,15 @@ void x25_kick(struct sock *sk)
return;
modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS;
+
+ start = (skb_peek(&sk->protinfo.x25->ack_queue) == NULL) ? sk->protinfo.x25->va : sk->protinfo.x25->vs;
end = (sk->protinfo.x25->va + sk->protinfo.x25->facilities.winsize_out) % modulus;
- if (sk->protinfo.x25->vs == end)
+ if (start == end)
return;
+ sk->protinfo.x25->vs = start;
+
/*
* Transmit data until either we're out of data to send or
* the window is full.
@@ -162,13 +166,25 @@ void x25_kick(struct sock *sk)
skb = skb_dequeue(&sk->write_queue);
do {
+ if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
+ skb_queue_head(&sk->write_queue, skb);
+ break;
+ }
+
+ skb_set_owner_w(skbn, sk);
+
/*
- * Transmit the frame.
+ * Transmit the frame copy.
*/
- x25_send_iframe(sk, skb);
+ x25_send_iframe(sk, skbn);
sk->protinfo.x25->vs = (sk->protinfo.x25->vs + 1) % modulus;
+ /*
+ * Requeue the original data frame.
+ */
+ skb_queue_tail(&sk->protinfo.x25->ack_queue, skb);
+
} while (sk->protinfo.x25->vs != end && (skb = skb_dequeue(&sk->write_queue)) != NULL);
sk->protinfo.x25->vl = sk->protinfo.x25->vr;
@@ -195,15 +211,4 @@ void x25_enquiry_response(struct sock *sk)
x25_stop_timer(sk);
}
-void x25_check_iframes_acked(struct sock *sk, unsigned short nr)
-{
- if (sk->protinfo.x25->vs == nr) {
- sk->protinfo.x25->va = nr;
- } else {
- if (sk->protinfo.x25->va != nr) {
- sk->protinfo.x25->va = nr;
- }
- }
-}
-
#endif