Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c6671b0 authored by Eilon Greenstein's avatar Eilon Greenstein Committed by David S. Miller
Browse files

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: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a5e9a7cf
Loading
Loading
Loading
Loading
+7 −5
Original line number Original line Diff line number Diff line
@@ -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)
+33 −9
Original line number Original line Diff line number Diff line
@@ -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 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
		}
		}


#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;