Merge tag 'v3.10.108' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / ipv4 / tcp_input.c
index 094515e751d01c323f6600356cf072d0a723d457..41ef73a7cb66102f1923f44aa6a104da87eeaac0 100644 (file)
@@ -112,6 +112,7 @@ int sysctl_tcp_default_init_rwnd __read_mostly = TCP_DEFAULT_INIT_RCVWND;
 #define FLAG_ORIG_SACK_ACKED   0x200 /* Never retransmitted data are (s)acked  */
 #define FLAG_SND_UNA_ADVANCED  0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */
 #define FLAG_DSACKING_ACK      0x800 /* SACK blocks contained D-SACK info */
+#define FLAG_SET_XMIT_TIMER    0x1000 /* Set TLP or RTO timer */
 #define FLAG_SACK_RENEGING     0x2000 /* snd_una advanced to a sacked seq */
 #define FLAG_UPDATE_TS_RECENT  0x4000 /* tcp_replace_ts_recent() */
 
@@ -2588,8 +2589,8 @@ static inline void tcp_end_cwnd_reduction(struct sock *sk)
        struct tcp_sock *tp = tcp_sk(sk);
 
        /* Reset cwnd to ssthresh in CWR or Recovery (unless it's undone) */
-       if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR ||
-           (tp->undo_marker && tp->snd_ssthresh < TCP_INFINITE_SSTHRESH)) {
+       if (tp->snd_ssthresh < TCP_INFINITE_SSTHRESH &&
+           (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR || tp->undo_marker)) {
                tp->snd_cwnd = tp->snd_ssthresh;
                tp->snd_cwnd_stamp = tcp_time_stamp;
        }
@@ -3007,14 +3008,11 @@ void tcp_rearm_rto(struct sock *sk)
                /* Offset the time elapsed after installing regular RTO */
                if (icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
                    icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
-                       struct sk_buff *skb = tcp_write_queue_head(sk);
-                       const u32 rto_time_stamp = TCP_SKB_CB(skb)->when + rto;
-                       s32 delta = (s32)(rto_time_stamp - tcp_time_stamp);
+                       s32 delta = tcp_rto_delta(sk);
                        /* delta may not be positive if the socket is locked
                         * when the retrans timer fires and is rescheduled.
                         */
-                       if (delta > 0)
-                               rto = delta;
+                       rto = max_t(int, delta, 1);
                }
                inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto,
                                          sysctl_tcp_rto_max);
@@ -3039,6 +3037,13 @@ void tcp_resume_early_retransmit(struct sock *sk)
        tcp_xmit_retransmit_queue(sk);
 }
 
+/* Try to schedule a loss probe; if that doesn't work, then schedule an RTO. */
+static void tcp_set_xmit_timer(struct sock *sk)
+{
+       if (!tcp_schedule_loss_probe(sk))
+               tcp_rearm_rto(sk);
+}
+
 /* If we get here, the whole TSO packet has not been acked. */
 static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb)
 {
@@ -3169,7 +3174,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
                }
 
                tcp_ack_update_rtt(sk, flag, seq_rtt);
-               tcp_rearm_rto(sk);
+               flag |= FLAG_SET_XMIT_TIMER;  /* set TLP or RTO timer */
 
                if (tcp_is_reno(tp)) {
                        tcp_remove_reno_sacks(sk, pkts_acked);
@@ -3429,10 +3434,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
        if (after(ack, tp->snd_nxt))
                goto invalid_ack;
 
-       if (icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
-           icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)
-               tcp_rearm_rto(sk);
-
        if (after(ack, prior_snd_una))
                flag |= FLAG_SND_UNA_ADVANCED;
 
@@ -3489,6 +3490,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 
        pkts_acked = previous_packets_out - tp->packets_out;
 
+       if (tp->tlp_high_seq)
+               tcp_process_tlp_ack(sk, ack, flag);
+       /* If needed, reset TLP/RTO timer; RACK may later override this. */
+       if (flag & FLAG_SET_XMIT_TIMER)
+               tcp_set_xmit_timer(sk);
+
        if (tcp_ack_is_dubious(sk, flag)) {
                /* Advance CWND, if state allows this. */
                if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(sk, flag))
@@ -3501,17 +3508,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
                        tcp_cong_avoid(sk, ack, prior_in_flight);
        }
 
-       if (tp->tlp_high_seq)
-               tcp_process_tlp_ack(sk, ack, flag);
-
        if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) {
                struct dst_entry *dst = __sk_dst_get(sk);
                if (dst)
                        dst_confirm(dst);
        }
 
-       if (icsk->icsk_pending == ICSK_TIME_RETRANS)
-               tcp_schedule_loss_probe(sk);
        if (tp->srtt != prior_rtt || tp->snd_cwnd != prior_cwnd)
                tcp_update_pacing_rate(sk);
        return 1;