Skip to content

Commit

Permalink
bnx2x: VLAN tagged packets without VLAN offload
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Eilon Greenstein authored and David S. Miller committed Jan 15, 2009
1 parent a5e9a7c commit 0c6671b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 14 deletions.
12 changes: 7 additions & 5 deletions drivers/net/bnx2x.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
* (you will need to reboot afterwards) */
/* #define BNX2X_STOP_ON_ERROR */

#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#define BCM_VLAN 1
#endif


/* error/debug prints */

#define DRV_MODULE_NAME "bnx2x"
Expand Down Expand Up @@ -78,11 +83,6 @@
#endif


#ifdef NETIF_F_HW_VLAN_TX
#define BCM_VLAN 1
#endif


#define U64_LO(x) (u32)(((u64)(x)) & 0xffffffff)
#define U64_HI(x) (u32)(((u64)(x)) >> 32)
#define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo))
Expand Down Expand Up @@ -804,6 +804,8 @@ struct bnx2x {
#define TPA_ENABLE_FLAG 0x80
#define NO_MCP_FLAG 0x100
#define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG)
#define HW_VLAN_TX_FLAG 0x400
#define HW_VLAN_RX_FLAG 0x800

int func;
#define BP_PORT(bp) (bp->func % PORT_MAX)
Expand Down
42 changes: 33 additions & 9 deletions drivers/net/bnx2x_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@
#include <linux/time.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#ifdef NETIF_F_HW_VLAN_TX
#include <linux/if_vlan.h>
#endif
#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <net/checksum.h>
Expand Down Expand Up @@ -1283,6 +1281,13 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
if (likely(new_skb)) {
/* fix ip xsum and give it to the stack */
/* (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(((char *)(skb)) + 128);
Expand All @@ -1307,16 +1312,21 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
struct iphdr *iph;

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 = ip_fast_csum((u8 *)iph, iph->ihl);
}

if (!bnx2x_fill_frag_skb(bp, fp, skb,
&cqe->fast_path_cqe, cqe_idx)) {
#ifdef BCM_VLAN
if ((bp->vlgrp != NULL) &&
(le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
PARSING_FLAGS_VLAN))
if ((bp->vlgrp != NULL) && is_vlan_cqe &&
(!is_not_hwaccel_vlan_cqe))
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
le16_to_cpu(cqe->fast_path_cqe.
vlan_tag));
Expand Down Expand Up @@ -1560,7 +1570,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
}

#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) &
PARSING_FLAGS_VLAN))
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
Expand Down Expand Up @@ -4538,7 +4548,7 @@ static void bnx2x_set_client_config(struct bnx2x *bp)
tstorm_client.config_flags =
TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
#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_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE;
DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
Expand Down Expand Up @@ -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",
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->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG;
vlan_off += 4;
} else
#endif
tx_bd->vlan = cpu_to_le16(pkt_prod);

if (xmit_type) {
Expand Down Expand Up @@ -10017,6 +10030,16 @@ static void bnx2x_vlan_rx_register(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev);

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))
bnx2x_set_client_config(bp);
}
Expand Down Expand Up @@ -10173,6 +10196,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
dev->features |= NETIF_F_HIGHDMA;
#ifdef BCM_VLAN
dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
bp->flags |= (HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
#endif
dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
dev->features |= NETIF_F_TSO6;
Expand Down

0 comments on commit 0c6671b

Please sign in to comment.