aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
authorChris Leech <christopher.leech@intel.com>2006-05-23 21:05:53 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-18 00:25:56 -0400
commit1a2449a87bb7606113b1aa1a9d3c3e78ef189a1c (patch)
tree86e833a8694f201de138697646e7e8469e9c8ef6 /net/ipv4/tcp_input.c
parent9593782585e0cf70babe787a8463d492a68b1744 (diff)
[I/OAT]: TCP recv offload to I/OAT
Locks down user pages and sets up for DMA in tcp_recvmsg, then calls dma_async_try_early_copy in tcp_v4_do_rcv Signed-off-by: Chris Leech <christopher.leech@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c74
1 files changed, 67 insertions, 7 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index b5521a9d3dc1..c6d62f0a9966 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -71,6 +71,7 @@
71#include <net/inet_common.h> 71#include <net/inet_common.h>
72#include <linux/ipsec.h> 72#include <linux/ipsec.h>
73#include <asm/unaligned.h> 73#include <asm/unaligned.h>
74#include <net/netdma.h>
74 75
75int sysctl_tcp_timestamps = 1; 76int sysctl_tcp_timestamps = 1;
76int sysctl_tcp_window_scaling = 1; 77int sysctl_tcp_window_scaling = 1;
@@ -3785,6 +3786,50 @@ static inline int tcp_checksum_complete_user(struct sock *sk, struct sk_buff *sk
3785 __tcp_checksum_complete_user(sk, skb); 3786 __tcp_checksum_complete_user(sk, skb);
3786} 3787}
3787 3788
3789#ifdef CONFIG_NET_DMA
3790static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, int hlen)
3791{
3792 struct tcp_sock *tp = tcp_sk(sk);
3793 int chunk = skb->len - hlen;
3794 int dma_cookie;
3795 int copied_early = 0;
3796
3797 if (tp->ucopy.wakeup)
3798 return 0;
3799
3800 if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
3801 tp->ucopy.dma_chan = get_softnet_dma();
3802
3803 if (tp->ucopy.dma_chan && skb->ip_summed == CHECKSUM_UNNECESSARY) {
3804
3805 dma_cookie = dma_skb_copy_datagram_iovec(tp->ucopy.dma_chan,
3806 skb, hlen, tp->ucopy.iov, chunk, tp->ucopy.pinned_list);
3807
3808 if (dma_cookie < 0)
3809 goto out;
3810
3811 tp->ucopy.dma_cookie = dma_cookie;
3812 copied_early = 1;
3813
3814 tp->ucopy.len -= chunk;
3815 tp->copied_seq += chunk;
3816 tcp_rcv_space_adjust(sk);
3817
3818 if ((tp->ucopy.len == 0) ||
3819 (tcp_flag_word(skb->h.th) & TCP_FLAG_PSH) ||
3820 (atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1))) {
3821 tp->ucopy.wakeup = 1;
3822 sk->sk_data_ready(sk, 0);
3823 }
3824 } else if (chunk > 0) {
3825 tp->ucopy.wakeup = 1;
3826 sk->sk_data_ready(sk, 0);
3827 }
3828out:
3829 return copied_early;
3830}
3831#endif /* CONFIG_NET_DMA */
3832
3788/* 3833/*
3789 * TCP receive function for the ESTABLISHED state. 3834 * TCP receive function for the ESTABLISHED state.
3790 * 3835 *
@@ -3901,14 +3946,23 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
3901 } 3946 }
3902 } else { 3947 } else {
3903 int eaten = 0; 3948 int eaten = 0;
3949 int copied_early = 0;
3904 3950
3905 if (tp->ucopy.task == current && 3951 if (tp->copied_seq == tp->rcv_nxt &&
3906 tp->copied_seq == tp->rcv_nxt && 3952 len - tcp_header_len <= tp->ucopy.len) {
3907 len - tcp_header_len <= tp->ucopy.len && 3953#ifdef CONFIG_NET_DMA
3908 sock_owned_by_user(sk)) { 3954 if (tcp_dma_try_early_copy(sk, skb, tcp_header_len)) {
3909 __set_current_state(TASK_RUNNING); 3955 copied_early = 1;
3956 eaten = 1;
3957 }
3958#endif
3959 if (tp->ucopy.task == current && sock_owned_by_user(sk) && !copied_early) {
3960 __set_current_state(TASK_RUNNING);
3910 3961
3911 if (!tcp_copy_to_iovec(sk, skb, tcp_header_len)) { 3962 if (!tcp_copy_to_iovec(sk, skb, tcp_header_len))
3963 eaten = 1;
3964 }
3965 if (eaten) {
3912 /* Predicted packet is in window by definition. 3966 /* Predicted packet is in window by definition.
3913 * seq == rcv_nxt and rcv_wup <= rcv_nxt. 3967 * seq == rcv_nxt and rcv_wup <= rcv_nxt.
3914 * Hence, check seq<=rcv_wup reduces to: 3968 * Hence, check seq<=rcv_wup reduces to:
@@ -3924,8 +3978,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
3924 __skb_pull(skb, tcp_header_len); 3978 __skb_pull(skb, tcp_header_len);
3925 tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; 3979 tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
3926 NET_INC_STATS_BH(LINUX_MIB_TCPHPHITSTOUSER); 3980 NET_INC_STATS_BH(LINUX_MIB_TCPHPHITSTOUSER);
3927 eaten = 1;
3928 } 3981 }
3982 if (copied_early)
3983 tcp_cleanup_rbuf(sk, skb->len);
3929 } 3984 }
3930 if (!eaten) { 3985 if (!eaten) {
3931 if (tcp_checksum_complete_user(sk, skb)) 3986 if (tcp_checksum_complete_user(sk, skb))
@@ -3966,6 +4021,11 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
3966 4021
3967 __tcp_ack_snd_check(sk, 0); 4022 __tcp_ack_snd_check(sk, 0);
3968no_ack: 4023no_ack:
4024#ifdef CONFIG_NET_DMA
4025 if (copied_early)
4026 __skb_queue_tail(&sk->sk_async_wait_queue, skb);
4027 else
4028#endif
3969 if (eaten) 4029 if (eaten)
3970 __kfree_skb(skb); 4030 __kfree_skb(skb);
3971 else 4031 else