aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/marvell/mvneta.c
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevich@gmail.com>2014-08-25 10:34:54 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-25 17:27:10 -0700
commit817dbfa5d1bc276a72c1a577310382008e8aca0a (patch)
tree2813ef1a4959c86314ea8d3bf37fad55b143a38d /drivers/net/ethernet/marvell/mvneta.c
parenti40evf: Fix TSO and hw checksums for non-accelerated vlan packets. (diff)
downloadlinux-dev-817dbfa5d1bc276a72c1a577310382008e8aca0a.tar.xz
linux-dev-817dbfa5d1bc276a72c1a577310382008e8aca0a.zip
mvneta: Fix TSO and checksum for non-acceleration vlan traffic
This driver doesn't appear to support vlan acceleration at all. However, it does claim to support TSO and IP checksums for vlan devices. Thus any configured vlan device would end up passing down partial checksums or TSO frames. The driver also uses the value from skb->protocol to determine TSO and checksum offload information, but assumes that skb->protocol holds the l3 protocol information. As a result, vlan traffic with partial checksums or TSO will fail those checks and TSO will not happen. Fix this by using vlan_get_protocol() helper. CC: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/marvell/mvneta.c')
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index c9f1d1b7ef37..133f8c6444e0 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -1371,15 +1371,16 @@ static u32 mvneta_skb_tx_csum(struct mvneta_port *pp, struct sk_buff *skb)
{
if (skb->ip_summed == CHECKSUM_PARTIAL) {
int ip_hdr_len = 0;
+ __be16 l3_proto = vlan_get_protocol(skb);
u8 l4_proto;
- if (skb->protocol == htons(ETH_P_IP)) {
+ if (l3_proto == htons(ETH_P_IP)) {
struct iphdr *ip4h = ip_hdr(skb);
/* Calculate IPv4 checksum and L4 checksum */
ip_hdr_len = ip4h->ihl;
l4_proto = ip4h->protocol;
- } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ } else if (l3_proto == htons(ETH_P_IPV6)) {
struct ipv6hdr *ip6h = ipv6_hdr(skb);
/* Read l4_protocol from one of IPv6 extra headers */
@@ -1390,7 +1391,7 @@ static u32 mvneta_skb_tx_csum(struct mvneta_port *pp, struct sk_buff *skb)
return MVNETA_TX_L4_CSUM_NOT;
return mvneta_txq_desc_csum(skb_network_offset(skb),
- skb->protocol, ip_hdr_len, l4_proto);
+ l3_proto, ip_hdr_len, l4_proto);
}
return MVNETA_TX_L4_CSUM_NOT;