bnx2x: VLAN tagged packets without VLAN offload
Wrong handling of tagged packet if VLAN offload is disabled caused packets to get corrupted Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a5e9a7cfad
commit
0c6671b0d9
2 changed files with 40 additions and 14 deletions
|
@ -20,6 +20,11 @@
|
||||||
* (you will need to reboot afterwards) */
|
* (you will need to reboot afterwards) */
|
||||||
/* #define BNX2X_STOP_ON_ERROR */
|
/* #define BNX2X_STOP_ON_ERROR */
|
||||||
|
|
||||||
|
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
|
||||||
|
#define BCM_VLAN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* error/debug prints */
|
/* error/debug prints */
|
||||||
|
|
||||||
#define DRV_MODULE_NAME "bnx2x"
|
#define DRV_MODULE_NAME "bnx2x"
|
||||||
|
@ -78,11 +83,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef NETIF_F_HW_VLAN_TX
|
|
||||||
#define BCM_VLAN 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define U64_LO(x) (u32)(((u64)(x)) & 0xffffffff)
|
#define U64_LO(x) (u32)(((u64)(x)) & 0xffffffff)
|
||||||
#define U64_HI(x) (u32)(((u64)(x)) >> 32)
|
#define U64_HI(x) (u32)(((u64)(x)) >> 32)
|
||||||
#define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo))
|
#define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo))
|
||||||
|
@ -804,6 +804,8 @@ struct bnx2x {
|
||||||
#define TPA_ENABLE_FLAG 0x80
|
#define TPA_ENABLE_FLAG 0x80
|
||||||
#define NO_MCP_FLAG 0x100
|
#define NO_MCP_FLAG 0x100
|
||||||
#define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG)
|
#define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG)
|
||||||
|
#define HW_VLAN_TX_FLAG 0x400
|
||||||
|
#define HW_VLAN_RX_FLAG 0x800
|
||||||
|
|
||||||
int func;
|
int func;
|
||||||
#define BP_PORT(bp) (bp->func % PORT_MAX)
|
#define BP_PORT(bp) (bp->func % PORT_MAX)
|
||||||
|
|
|
@ -38,9 +38,7 @@
|
||||||
#include <linux/time.h>
|
#include <linux/time.h>
|
||||||
#include <linux/ethtool.h>
|
#include <linux/ethtool.h>
|
||||||
#include <linux/mii.h>
|
#include <linux/mii.h>
|
||||||
#ifdef NETIF_F_HW_VLAN_TX
|
|
||||||
#include <linux/if_vlan.h>
|
#include <linux/if_vlan.h>
|
||||||
#endif
|
|
||||||
#include <net/ip.h>
|
#include <net/ip.h>
|
||||||
#include <net/tcp.h>
|
#include <net/tcp.h>
|
||||||
#include <net/checksum.h>
|
#include <net/checksum.h>
|
||||||
|
@ -1283,6 +1281,13 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
|
||||||
if (likely(new_skb)) {
|
if (likely(new_skb)) {
|
||||||
/* fix ip xsum and give it to the stack */
|
/* fix ip xsum and give it to the stack */
|
||||||
/* (no need to map the new skb) */
|
/* (no need to map the new skb) */
|
||||||
|
#ifdef BCM_VLAN
|
||||||
|
int is_vlan_cqe =
|
||||||
|
(le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
|
||||||
|
PARSING_FLAGS_VLAN);
|
||||||
|
int is_not_hwaccel_vlan_cqe =
|
||||||
|
(is_vlan_cqe && (!(bp->flags & HW_VLAN_RX_FLAG)));
|
||||||
|
#endif
|
||||||
|
|
||||||
prefetch(skb);
|
prefetch(skb);
|
||||||
prefetch(((char *)(skb)) + 128);
|
prefetch(((char *)(skb)) + 128);
|
||||||
|
@ -1307,6 +1312,12 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
|
|
||||||
iph = (struct iphdr *)skb->data;
|
iph = (struct iphdr *)skb->data;
|
||||||
|
#ifdef BCM_VLAN
|
||||||
|
/* If there is no Rx VLAN offloading -
|
||||||
|
take VLAN tag into an account */
|
||||||
|
if (unlikely(is_not_hwaccel_vlan_cqe))
|
||||||
|
iph = (struct iphdr *)((u8 *)iph + VLAN_HLEN);
|
||||||
|
#endif
|
||||||
iph->check = 0;
|
iph->check = 0;
|
||||||
iph->check = ip_fast_csum((u8 *)iph, iph->ihl);
|
iph->check = ip_fast_csum((u8 *)iph, iph->ihl);
|
||||||
}
|
}
|
||||||
|
@ -1314,9 +1325,8 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
|
||||||
if (!bnx2x_fill_frag_skb(bp, fp, skb,
|
if (!bnx2x_fill_frag_skb(bp, fp, skb,
|
||||||
&cqe->fast_path_cqe, cqe_idx)) {
|
&cqe->fast_path_cqe, cqe_idx)) {
|
||||||
#ifdef BCM_VLAN
|
#ifdef BCM_VLAN
|
||||||
if ((bp->vlgrp != NULL) &&
|
if ((bp->vlgrp != NULL) && is_vlan_cqe &&
|
||||||
(le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
|
(!is_not_hwaccel_vlan_cqe))
|
||||||
PARSING_FLAGS_VLAN))
|
|
||||||
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
|
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
|
||||||
le16_to_cpu(cqe->fast_path_cqe.
|
le16_to_cpu(cqe->fast_path_cqe.
|
||||||
vlan_tag));
|
vlan_tag));
|
||||||
|
@ -1560,7 +1570,7 @@ reuse_rx:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BCM_VLAN
|
#ifdef BCM_VLAN
|
||||||
if ((bp->vlgrp != NULL) &&
|
if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) &&
|
||||||
(le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
|
(le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
|
||||||
PARSING_FLAGS_VLAN))
|
PARSING_FLAGS_VLAN))
|
||||||
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
|
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
|
||||||
|
@ -4538,7 +4548,7 @@ static void bnx2x_set_client_config(struct bnx2x *bp)
|
||||||
tstorm_client.config_flags =
|
tstorm_client.config_flags =
|
||||||
TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
|
TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
|
||||||
#ifdef BCM_VLAN
|
#ifdef BCM_VLAN
|
||||||
if (bp->rx_mode && bp->vlgrp) {
|
if (bp->rx_mode && bp->vlgrp && (bp->flags & HW_VLAN_RX_FLAG)) {
|
||||||
tstorm_client.config_flags |=
|
tstorm_client.config_flags |=
|
||||||
TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE;
|
TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE;
|
||||||
DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
|
DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
|
||||||
|
@ -9567,11 +9577,14 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
"sending pkt %u @%p next_idx %u bd %u @%p\n",
|
"sending pkt %u @%p next_idx %u bd %u @%p\n",
|
||||||
pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_bd);
|
pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_bd);
|
||||||
|
|
||||||
if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb)) {
|
#ifdef BCM_VLAN
|
||||||
|
if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) &&
|
||||||
|
(bp->flags & HW_VLAN_TX_FLAG)) {
|
||||||
tx_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb));
|
tx_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb));
|
||||||
tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG;
|
tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG;
|
||||||
vlan_off += 4;
|
vlan_off += 4;
|
||||||
} else
|
} else
|
||||||
|
#endif
|
||||||
tx_bd->vlan = cpu_to_le16(pkt_prod);
|
tx_bd->vlan = cpu_to_le16(pkt_prod);
|
||||||
|
|
||||||
if (xmit_type) {
|
if (xmit_type) {
|
||||||
|
@ -10017,6 +10030,16 @@ static void bnx2x_vlan_rx_register(struct net_device *dev,
|
||||||
struct bnx2x *bp = netdev_priv(dev);
|
struct bnx2x *bp = netdev_priv(dev);
|
||||||
|
|
||||||
bp->vlgrp = vlgrp;
|
bp->vlgrp = vlgrp;
|
||||||
|
|
||||||
|
/* Set flags according to the required capabilities */
|
||||||
|
bp->flags &= ~(HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
|
||||||
|
|
||||||
|
if (dev->features & NETIF_F_HW_VLAN_TX)
|
||||||
|
bp->flags |= HW_VLAN_TX_FLAG;
|
||||||
|
|
||||||
|
if (dev->features & NETIF_F_HW_VLAN_RX)
|
||||||
|
bp->flags |= HW_VLAN_RX_FLAG;
|
||||||
|
|
||||||
if (netif_running(dev))
|
if (netif_running(dev))
|
||||||
bnx2x_set_client_config(bp);
|
bnx2x_set_client_config(bp);
|
||||||
}
|
}
|
||||||
|
@ -10173,6 +10196,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
|
||||||
dev->features |= NETIF_F_HIGHDMA;
|
dev->features |= NETIF_F_HIGHDMA;
|
||||||
#ifdef BCM_VLAN
|
#ifdef BCM_VLAN
|
||||||
dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
|
dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
|
||||||
|
bp->flags |= (HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
|
||||||
#endif
|
#endif
|
||||||
dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
|
dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
|
||||||
dev->features |= NETIF_F_TSO6;
|
dev->features |= NETIF_F_TSO6;
|
||||||
|
|
Loading…
Add table
Reference in a new issue