*/
        int mss = icsk->icsk_ack.rcv_mss;
        int free_space = tcp_space(sk);
-       int full_space = min_t(int, tp->window_clamp, tcp_full_space(sk));
+       int allowed_space = tcp_full_space(sk);
+       int full_space = min_t(int, tp->window_clamp, allowed_space);
        int window;
 
        if (mss > full_space)
                        tp->rcv_ssthresh = min(tp->rcv_ssthresh,
                                               4U * tp->advmss);
 
-               if (free_space < mss)
+               /* free_space might become our new window, make sure we don't
+                * increase it due to wscale.
+                */
+               free_space = round_down(free_space, 1 << tp->rx_opt.rcv_wscale);
+
+               /* if free space is less than mss estimate, or is below 1/16th
+                * of the maximum allowed, try to move to zero-window, else
+                * tcp_clamp_window() will grow rcv buf up to tcp_rmem[2], and
+                * new incoming data is dropped due to memory limits.
+                * With large window, mss test triggers way too late in order
+                * to announce zero window in time before rmem limit kicks in.
+                */
+               if (free_space < (allowed_space >> 4) || free_space < mss)
                        return 0;
        }