diff options
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r-- | net/ipv4/tcp_output.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 10435b3b9d0f..3be16727f058 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -698,7 +698,8 @@ static void tcp_tsq_handler(struct sock *sk) | |||
698 | if ((1 << sk->sk_state) & | 698 | if ((1 << sk->sk_state) & |
699 | (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_CLOSING | | 699 | (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_CLOSING | |
700 | TCPF_CLOSE_WAIT | TCPF_LAST_ACK)) | 700 | TCPF_CLOSE_WAIT | TCPF_LAST_ACK)) |
701 | tcp_write_xmit(sk, tcp_current_mss(sk), 0, 0, GFP_ATOMIC); | 701 | tcp_write_xmit(sk, tcp_current_mss(sk), tcp_sk(sk)->nonagle, |
702 | 0, GFP_ATOMIC); | ||
702 | } | 703 | } |
703 | /* | 704 | /* |
704 | * One tasklet per cpu tries to send more skbs. | 705 | * One tasklet per cpu tries to send more skbs. |
@@ -1904,7 +1905,15 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
1904 | 1905 | ||
1905 | if (atomic_read(&sk->sk_wmem_alloc) > limit) { | 1906 | if (atomic_read(&sk->sk_wmem_alloc) > limit) { |
1906 | set_bit(TSQ_THROTTLED, &tp->tsq_flags); | 1907 | set_bit(TSQ_THROTTLED, &tp->tsq_flags); |
1907 | break; | 1908 | /* It is possible TX completion already happened |
1909 | * before we set TSQ_THROTTLED, so we must | ||
1910 | * test again the condition. | ||
1911 | * We abuse smp_mb__after_clear_bit() because | ||
1912 | * there is no smp_mb__after_set_bit() yet | ||
1913 | */ | ||
1914 | smp_mb__after_clear_bit(); | ||
1915 | if (atomic_read(&sk->sk_wmem_alloc) > limit) | ||
1916 | break; | ||
1908 | } | 1917 | } |
1909 | 1918 | ||
1910 | limit = mss_now; | 1919 | limit = mss_now; |