--- /dev/null
+From 0c6671b0d94f706dfc20cb22d792218ba9814412 Mon Sep 17 00:00:00 2001
+From: Eilon Greenstein <eilong@broadcom.com>
+Date: Wed, 14 Jan 2009 21:26:51 -0800
+Subject: bnx2x: VLAN tagged packets without VLAN offload
+Acked-by: Karsten Keil <kkeil@novell.com>
+Reference: bnc#472500
+
+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>
+---
+ drivers/net/bnx2x.h | 12 +++++++-----
+ drivers/net/bnx2x_main.c | 42 +++++++++++++++++++++++++++++++++---------
+ 2 files changed, 40 insertions(+), 14 deletions(-)
+
+Index: linux-2.6.27-bnx2x_2/drivers/net/bnx2x.h
+===================================================================
+--- linux-2.6.27-bnx2x_2.orig/drivers/net/bnx2x.h
++++ linux-2.6.27-bnx2x_2/drivers/net/bnx2x.h
+@@ -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"
+@@ -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))
+@@ -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)
+Index: linux-2.6.27-bnx2x_2/drivers/net/bnx2x_main.c
+===================================================================
+--- linux-2.6.27-bnx2x_2.orig/drivers/net/bnx2x_main.c
++++ linux-2.6.27-bnx2x_2/drivers/net/bnx2x_main.c
+@@ -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>
+@@ -1283,6 +1281,13 @@ static void bnx2x_tpa_stop(struct bnx2x
+ 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);
+@@ -1307,6 +1312,12 @@ static void bnx2x_tpa_stop(struct bnx2x
+ 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);
+ }
+@@ -1314,9 +1325,8 @@ static void bnx2x_tpa_stop(struct bnx2x
+ 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));
+@@ -1561,7 +1571,7 @@ reuse_rx:
+ }
+
+ #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,
+@@ -4541,7 +4551,7 @@ static void bnx2x_set_client_config(stru
+ 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");
+@@ -9571,11 +9581,14 @@ static int bnx2x_start_xmit(struct sk_bu
+ "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) {
+@@ -10024,6 +10037,16 @@ static void bnx2x_vlan_rx_register(struc
+ 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);
+ }
+@@ -10175,6 +10198,7 @@ static int __devinit bnx2x_init_dev(stru
+ 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;