diff --git a/drivers/net/ethernet/lantiq/ltq_toe_drv.c b/drivers/net/ethernet/lantiq/ltq_toe_drv.c index 90fc33b210f2644eaf9c44e16dd5da619fd5ae8e..34bea62b3c7fed6cf0f67d0f78d99f944600e579 100644 --- a/drivers/net/ethernet/lantiq/ltq_toe_drv.c +++ b/drivers/net/ethernet/lantiq/ltq_toe_drv.c @@ -28,6 +28,8 @@ #include <linux/netdevice.h> #include <linux/skbuff.h> #include <linux/tcp.h> +#include <linux/if_vlan.h> +#include <linux/ip.h> #include <lantiq.h> #include <lantiq_soc.h> @@ -434,9 +436,11 @@ static void lro_process_output_context(int port, int oc_flag_no) #ifdef LRO_DEBUG struct tcphdr *tcp_hdr; #endif - struct sk_buff *frag_skb = NULL, *last_frag_skb = NULL; unsigned long tso_rl_flags; + struct iphdr *ip_hdr; + struct ethhdr *eth; + int network_depth = 0; oc_flag = ltq_toe_r32(LRO_OC_FLAG(port, oc_flag_no)); pr_debug("LRO done and OC_FLAG: %x\n", oc_flag); @@ -545,6 +549,16 @@ static void lro_process_output_context(int port, int oc_flag_no) dbg_info[dbg_head].aggr_len = skb->len - 62; dbg_head = (dbg_head + 1) % LRO_MAX_DBG_INFO; #endif + /* re-compute the IP header checksum since HW has modified + the IP header's total_len field */ + eth = (struct ethhdr *)(skb->data + PMAC_HDR_SIZE); + skb->mac_len = ETH_HLEN + PMAC_HDR_SIZE; + __vlan_get_protocol(skb, eth->h_proto, &network_depth); + ip_hdr = (struct iphdr *)(skb->data + network_depth); + ip_hdr->check = 0; + ip_hdr->check = ip_fast_csum((unsigned char *)ip_hdr, ip_hdr->ihl); + skb->mac_len = 0; + /* Send it to datapath library */ dp_rx(skb, 0); }