Merge tag 'dmaengine-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw...
[cascardo/linux.git] / net / ipv4 / tcp.c
index 4874a0e..8ee43ae 100644 (file)
@@ -386,7 +386,7 @@ void tcp_init_sock(struct sock *sk)
        INIT_LIST_HEAD(&tp->tsq_node);
 
        icsk->icsk_rto = TCP_TIMEOUT_INIT;
-       tp->mdev = TCP_TIMEOUT_INIT;
+       tp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT);
 
        /* So many TCP implementations out there (incorrectly) count the
         * initial SYN frame in their delayed-ACK and congestion control
@@ -425,6 +425,17 @@ void tcp_init_sock(struct sock *sk)
 }
 EXPORT_SYMBOL(tcp_init_sock);
 
+static void tcp_tx_timestamp(struct sock *sk, struct sk_buff *skb)
+{
+       if (sk->sk_tsflags) {
+               struct skb_shared_info *shinfo = skb_shinfo(skb);
+
+               sock_tx_timestamp(sk, &shinfo->tx_flags);
+               if (shinfo->tx_flags & SKBTX_ANY_TSTAMP)
+                       shinfo->tskey = TCP_SKB_CB(skb)->seq + skb->len - 1;
+       }
+}
+
 /*
  *     Wait for a TCP event.
  *
@@ -522,7 +533,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
        }
        /* This barrier is coupled with smp_wmb() in tcp_reset() */
        smp_rmb();
-       if (sk->sk_err)
+       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
                mask |= POLLERR;
 
        return mask;
@@ -958,8 +969,10 @@ new_segment:
 
                copied += copy;
                offset += copy;
-               if (!(size -= copy))
+               if (!(size -= copy)) {
+                       tcp_tx_timestamp(sk, skb);
                        goto out;
+               }
 
                if (skb->len < size_goal || (flags & MSG_OOB))
                        continue;
@@ -1107,7 +1120,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        if (unlikely(tp->repair)) {
                if (tp->repair_queue == TCP_RECV_QUEUE) {
                        copied = tcp_send_rcvq(sk, msg, size);
-                       goto out;
+                       goto out_nopush;
                }
 
                err = -EINVAL;
@@ -1173,13 +1186,6 @@ new_segment:
                                if (!skb)
                                        goto wait_for_memory;
 
-                               /*
-                                * All packets are restored as if they have
-                                * already been sent.
-                                */
-                               if (tp->repair)
-                                       TCP_SKB_CB(skb)->when = tcp_time_stamp;
-
                                /*
                                 * Check whether we can use HW checksum.
                                 */
@@ -1189,6 +1195,13 @@ new_segment:
                                skb_entail(sk, skb);
                                copy = size_goal;
                                max = size_goal;
+
+                               /* All packets are restored as if they have
+                                * already been sent. skb_mstamp isn't set to
+                                * avoid wrong rtt estimation.
+                                */
+                               if (tp->repair)
+                                       TCP_SKB_CB(skb)->sacked |= TCPCB_REPAIRED;
                        }
 
                        /* Try to append data to the end of skb. */
@@ -1251,8 +1264,10 @@ new_segment:
 
                        from += copy;
                        copied += copy;
-                       if ((seglen -= copy) == 0 && iovlen == 0)
+                       if ((seglen -= copy) == 0 && iovlen == 0) {
+                               tcp_tx_timestamp(sk, skb);
                                goto out;
+                       }
 
                        if (skb->len < max || (flags & MSG_OOB) || unlikely(tp->repair))
                                continue;
@@ -1281,6 +1296,7 @@ wait_for_memory:
 out:
        if (copied)
                tcp_push(sk, flags, mss_now, tp->nonagle, size_goal);
+out_nopush:
        release_sock(sk);
        return copied + copied_syn;
 
@@ -1581,6 +1597,9 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        struct sk_buff *skb;
        u32 urg_hole = 0;
 
+       if (unlikely(flags & MSG_ERRQUEUE))
+               return ip_recv_error(sk, msg, len, addr_len);
+
        if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue) &&
            (sk->sk_state == TCP_ESTABLISHED))
                sk_busy_loop(sk, nonblock);
@@ -2222,7 +2241,7 @@ int tcp_disconnect(struct sock *sk, int flags)
 
        sk->sk_shutdown = 0;
        sock_reset_flag(sk, SOCK_DONE);
-       tp->srtt = 0;
+       tp->srtt_us = 0;
        if ((tp->write_seq += tp->max_window + 2) == 0)
                tp->write_seq = 1;
        icsk->icsk_backoff = 0;
@@ -2666,8 +2685,8 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info)
 
        info->tcpi_pmtu = icsk->icsk_pmtu_cookie;
        info->tcpi_rcv_ssthresh = tp->rcv_ssthresh;
-       info->tcpi_rtt = jiffies_to_usecs(tp->srtt)>>3;
-       info->tcpi_rttvar = jiffies_to_usecs(tp->mdev)>>2;
+       info->tcpi_rtt = tp->srtt_us >> 3;
+       info->tcpi_rttvar = tp->mdev_us >> 2;
        info->tcpi_snd_ssthresh = tp->snd_ssthresh;
        info->tcpi_snd_cwnd = tp->snd_cwnd;
        info->tcpi_advmss = tp->advmss;
@@ -2677,6 +2696,11 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info)
        info->tcpi_rcv_space = tp->rcvq_space.space;
 
        info->tcpi_total_retrans = tp->total_retrans;
+
+       info->tcpi_pacing_rate = sk->sk_pacing_rate != ~0U ?
+                                       sk->sk_pacing_rate : ~0ULL;
+       info->tcpi_max_pacing_rate = sk->sk_max_pacing_rate != ~0U ?
+                                       sk->sk_max_pacing_rate : ~0ULL;
 }
 EXPORT_SYMBOL_GPL(tcp_get_info);
 
@@ -2792,6 +2816,14 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
        case TCP_USER_TIMEOUT:
                val = jiffies_to_msecs(icsk->icsk_user_timeout);
                break;
+
+       case TCP_FASTOPEN:
+               if (icsk->icsk_accept_queue.fastopenq != NULL)
+                       val = icsk->icsk_accept_queue.fastopenq->max_qlen;
+               else
+                       val = 0;
+               break;
+
        case TCP_TIMESTAMP:
                val = tcp_time_stamp + tp->tsoffset;
                break;