aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000
diff options
context:
space:
mode:
authorDave Graham <david.graham@intel.com>2008-10-09 17:29:26 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-09 17:29:26 -0400
commit3ed30676f5bc9960c67644fa37c5fdc36ae47b5b (patch)
treec95e30027cec695c1ede5a967f084cd508e571f4 /drivers/net/e1000
parentaf807c82978ec1b8c5120b59b78ef951b3e4603b (diff)
e1000: don't generate bad checksums for tcp packets with 0 csum
When offloading transmit checksums only, the driver was not correctly configuring the hardware to handle the case of a zero checksum. For UDP the correct behavior is to leave it alone, but for tcp the checksum must be changed from 0x0000 to 0xFFFF. The hardware takes care of this case but only if it is told the packet is tcp. same patch as e1000e Signed-off-by: Dave Graham <david.graham@intel.com> Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e1000')
-rw-r--r--drivers/net/e1000/e1000_main.c55
1 files changed, 36 insertions, 19 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 2ab44db29fac..3bafaede7916 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -2873,32 +2873,49 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter,
2873 struct e1000_buffer *buffer_info; 2873 struct e1000_buffer *buffer_info;
2874 unsigned int i; 2874 unsigned int i;
2875 u8 css; 2875 u8 css;
2876 u32 cmd_len = E1000_TXD_CMD_DEXT;
2876 2877
2877 if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { 2878 if (skb->ip_summed != CHECKSUM_PARTIAL)
2878 css = skb_transport_offset(skb); 2879 return false;
2879 2880
2880 i = tx_ring->next_to_use; 2881 switch (skb->protocol) {
2881 buffer_info = &tx_ring->buffer_info[i]; 2882 case __constant_htons(ETH_P_IP):
2882 context_desc = E1000_CONTEXT_DESC(*tx_ring, i); 2883 if (ip_hdr(skb)->protocol == IPPROTO_TCP)
2884 cmd_len |= E1000_TXD_CMD_TCP;
2885 break;
2886 case __constant_htons(ETH_P_IPV6):
2887 /* XXX not handling all IPV6 headers */
2888 if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
2889 cmd_len |= E1000_TXD_CMD_TCP;
2890 break;
2891 default:
2892 if (unlikely(net_ratelimit()))
2893 DPRINTK(DRV, WARNING,
2894 "checksum_partial proto=%x!\n", skb->protocol);
2895 break;
2896 }
2883 2897
2884 context_desc->lower_setup.ip_config = 0; 2898 css = skb_transport_offset(skb);
2885 context_desc->upper_setup.tcp_fields.tucss = css;
2886 context_desc->upper_setup.tcp_fields.tucso =
2887 css + skb->csum_offset;
2888 context_desc->upper_setup.tcp_fields.tucse = 0;
2889 context_desc->tcp_seg_setup.data = 0;
2890 context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
2891 2899
2892 buffer_info->time_stamp = jiffies; 2900 i = tx_ring->next_to_use;
2893 buffer_info->next_to_watch = i; 2901 buffer_info = &tx_ring->buffer_info[i];
2902 context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
2894 2903
2895 if (unlikely(++i == tx_ring->count)) i = 0; 2904 context_desc->lower_setup.ip_config = 0;
2896 tx_ring->next_to_use = i; 2905 context_desc->upper_setup.tcp_fields.tucss = css;
2906 context_desc->upper_setup.tcp_fields.tucso =
2907 css + skb->csum_offset;
2908 context_desc->upper_setup.tcp_fields.tucse = 0;
2909 context_desc->tcp_seg_setup.data = 0;
2910 context_desc->cmd_and_length = cpu_to_le32(cmd_len);
2897 2911
2898 return true; 2912 buffer_info->time_stamp = jiffies;
2899 } 2913 buffer_info->next_to_watch = i;
2900 2914
2901 return false; 2915 if (unlikely(++i == tx_ring->count)) i = 0;
2916 tx_ring->next_to_use = i;
2917
2918 return true;
2902} 2919}
2903 2920
2904#define E1000_MAX_TXD_PWR 12 2921#define E1000_MAX_TXD_PWR 12