#define REXMIT_LOST    1 /* retransmit packets marked lost */
 #define REXMIT_NEW     2 /* FRTO-style transmit of unsent/new packets */
 
+static void tcp_gro_dev_warn(struct sock *sk, const struct sk_buff *skb)
+{
+       static bool __once __read_mostly;
+
+       if (!__once) {
+               struct net_device *dev;
+
+               __once = true;
+
+               rcu_read_lock();
+               dev = dev_get_by_index_rcu(sock_net(sk), skb->skb_iif);
+               pr_warn("%s: Driver has suspect GRO implementation, TCP performance may be compromised.\n",
+                       dev ? dev->name : "Unknown driver");
+               rcu_read_unlock();
+       }
+}
+
 /* Adapt the MSS value used to make delayed ack decision to the
  * real world.
  */
         */
        len = skb_shinfo(skb)->gso_size ? : skb->len;
        if (len >= icsk->icsk_ack.rcv_mss) {
-               icsk->icsk_ack.rcv_mss = len;
+               icsk->icsk_ack.rcv_mss = min_t(unsigned int, len,
+                                              tcp_sk(sk)->advmss);
+               if (unlikely(icsk->icsk_ack.rcv_mss != len))
+                       tcp_gro_dev_warn(sk, skb);
        } else {
                /* Otherwise, we make more careful check taking into account,
                 * that SACKs block is variable.