void x25_kick(struct sock *sk) { struct sk_buff *skb, *skbn; unsigned short start, end; int modulus; struct x25_sock *x25 = x25_sk(sk); if (x25->state != X25_STATE_3) return; if (skb_peek(&x25->interrupt_out_queue) != NULL && !test_and_set_bit(X25_INTERRUPT_FLAG, &x25->flags)) { skb = skb_dequeue(&x25->interrupt_out_queue); x25_transmit_link(skb, x25->neighbour); } if (x25->condition & X25_COND_PEER_RX_BUSY) return; if (!skb_peek(&sk->sk_write_queue)) return; modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS; start = skb_peek(&x25->ack_queue) ? x25->vs : x25->va; end = (x25->va + x25->facilities.winsize_out) % modulus; if (start == end) return; x25->vs = start; skb = skb_dequeue(&sk->sk_write_queue); do { if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { skb_queue_head(&sk->sk_write_queue, skb); break; } skb_set_owner_w(skbn, sk); x25_send_iframe(sk, skbn); x25->vs = (x25->vs + 1) % modulus; skb_queue_tail(&x25->ack_queue, skb); } while (x25->vs != end && (skb = skb_dequeue(&sk->sk_write_queue)) != NULL); x25->vl = x25->vr; x25->condition &= ~X25_COND_ACK_PENDING; x25_stop_timer(sk); }
void x25_kick(struct sock *sk) { struct sk_buff *skb, *skbn; unsigned short start, end; int modulus; struct x25_opt *x25 = x25_sk(sk); if (x25->state != X25_STATE_3) return; /* * Transmit interrupt data. */ if (!x25->intflag && skb_peek(&x25->interrupt_out_queue) != NULL) { x25->intflag = 1; skb = skb_dequeue(&x25->interrupt_out_queue); x25_transmit_link(skb, x25->neighbour); } if (x25->condition & X25_COND_PEER_RX_BUSY) return; if (!skb_peek(&sk->sk_write_queue)) return; modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS; start = skb_peek(&x25->ack_queue) ? x25->vs : x25->va; end = (x25->va + x25->facilities.winsize_out) % modulus; if (start == end) return; x25->vs = start; /* * Transmit data until either we're out of data to send or * the window is full. */ skb = skb_dequeue(&sk->sk_write_queue); do { if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { skb_queue_head(&sk->sk_write_queue, skb); break; } skb_set_owner_w(skbn, sk); /* * Transmit the frame copy. */ x25_send_iframe(sk, skbn); x25->vs = (x25->vs + 1) % modulus; /* * Requeue the original data frame. */ skb_queue_tail(&x25->ack_queue, skb); } while (x25->vs != end && (skb = skb_dequeue(&sk->sk_write_queue)) != NULL); x25->vl = x25->vr; x25->condition &= ~X25_COND_ACK_PENDING; x25_stop_timer(sk); }