diff options
| -rw-r--r-- | drivers/net/ethernet/ibm/ibmveth.c | 17 | ||||
| -rw-r--r-- | drivers/net/ethernet/ibm/ibmveth.h | 1 | 
2 files changed, 17 insertions, 1 deletions
| diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 33ffd349fb05..29bbb628d712 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -101,6 +101,7 @@ struct ibmveth_stat ibmveth_stats[] = {  	{ "fw_enabled_ipv4_csum", IBMVETH_STAT_OFF(fw_ipv4_csum_support) },  	{ "fw_enabled_ipv6_csum", IBMVETH_STAT_OFF(fw_ipv6_csum_support) },  	{ "tx_large_packets", IBMVETH_STAT_OFF(tx_large_packets) }, +	{ "rx_large_packets", IBMVETH_STAT_OFF(rx_large_packets) }  };  /* simple methods of getting data from the current rxq entry */ @@ -1094,6 +1095,7 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)  	struct net_device *netdev = adapter->netdev;  	int frames_processed = 0;  	unsigned long lpar_rc; +	struct iphdr *iph;  restart_poll:  	while (frames_processed < budget) { @@ -1136,8 +1138,21 @@ restart_poll:  			skb_put(skb, length);  			skb->protocol = eth_type_trans(skb, netdev); -			if (csum_good) +			if (csum_good) {  				skb->ip_summed = CHECKSUM_UNNECESSARY; +				if (be16_to_cpu(skb->protocol) == ETH_P_IP) { +					iph = (struct iphdr *)skb->data; + +					/* If the IP checksum is not offloaded and if the packet +					 *  is large send, the checksum must be rebuilt. +					 */ +					if (iph->check == 0xffff) { +						iph->check = 0; +						iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); +						adapter->rx_large_packets++; +					} +				} +			}  			napi_gro_receive(napi, skb);	/* send it up */ diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h index 56d1e22bd1d3..41dedb1fb2ae 100644 --- a/drivers/net/ethernet/ibm/ibmveth.h +++ b/drivers/net/ethernet/ibm/ibmveth.h @@ -162,6 +162,7 @@ struct ibmveth_adapter {      u64 tx_map_failed;      u64 tx_send_failed;      u64 tx_large_packets; +    u64 rx_large_packets;  };  /* | 
