aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevich@gmail.com>2014-08-25 10:34:50 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-25 20:27:09 -0400
commit1c53730a04fb651e35af0a12bd35f6a00481f53c (patch)
tree63b0bcb0a08e91cf19fdcbf710a261b1c7fcc5bc /drivers/net
parent06f4d0333e86e302da3ac8386f873d5e353baf2e (diff)
bna: Support TSO and partial checksum with non-accelerated vlans.
This device claims TSO and checksum support for vlans. It also allows a user to control vlan acceleration offloading. As such, it is possible to turn off vlan acceleration and configure a vlan which will continue to support TSO. In such situation the packet passed down the the device will contain a vlan header and skb->protocol will be set to ETH_P_8021Q. The device assumes that skb->protocol contains network protocol value and uses that value to set up TSO information. This results in corrupted frames sent on the wire. This patch extract the protocol value correctly and corrects TSO and checksums for non-accelerated traffic. CC: Rasesh Mody <rmody@brocade.com> Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index ff8cae5e2535..ffc92a41d75b 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -2506,7 +2506,7 @@ bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
2506 * For TSO, the TCP checksum field is seeded with pseudo-header sum 2506 * For TSO, the TCP checksum field is seeded with pseudo-header sum
2507 * excluding the length field. 2507 * excluding the length field.
2508 */ 2508 */
2509 if (skb->protocol == htons(ETH_P_IP)) { 2509 if (vlan_get_protocol(skb) == htons(ETH_P_IP)) {
2510 struct iphdr *iph = ip_hdr(skb); 2510 struct iphdr *iph = ip_hdr(skb);
2511 2511
2512 /* Do we really need these? */ 2512 /* Do we really need these? */
@@ -2870,12 +2870,13 @@ bnad_txq_wi_prepare(struct bnad *bnad, struct bna_tcb *tcb,
2870 } 2870 }
2871 2871
2872 if (skb->ip_summed == CHECKSUM_PARTIAL) { 2872 if (skb->ip_summed == CHECKSUM_PARTIAL) {
2873 __be16 net_proto = vlan_get_protocol(skb);
2873 u8 proto = 0; 2874 u8 proto = 0;
2874 2875
2875 if (skb->protocol == htons(ETH_P_IP)) 2876 if (net_proto == htons(ETH_P_IP))
2876 proto = ip_hdr(skb)->protocol; 2877 proto = ip_hdr(skb)->protocol;
2877#ifdef NETIF_F_IPV6_CSUM 2878#ifdef NETIF_F_IPV6_CSUM
2878 else if (skb->protocol == htons(ETH_P_IPV6)) { 2879 else if (net_proto == htons(ETH_P_IPV6)) {
2879 /* nexthdr may not be TCP immediately. */ 2880 /* nexthdr may not be TCP immediately. */
2880 proto = ipv6_hdr(skb)->nexthdr; 2881 proto = ipv6_hdr(skb)->nexthdr;
2881 } 2882 }