]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From 0c6671b0d94f706dfc20cb22d792218ba9814412 Mon Sep 17 00:00:00 2001 |
2 | From: Eilon Greenstein <eilong@broadcom.com> | |
3 | Date: Wed, 14 Jan 2009 21:26:51 -0800 | |
4 | Subject: bnx2x: VLAN tagged packets without VLAN offload | |
5 | Acked-by: Karsten Keil <kkeil@novell.com> | |
6 | Reference: bnc#472500 | |
7 | ||
8 | Wrong handling of tagged packet if VLAN offload is disabled caused | |
9 | packets to get corrupted | |
10 | ||
11 | Signed-off-by: Eilon Greenstein <eilong@broadcom.com> | |
12 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
13 | --- | |
14 | drivers/net/bnx2x.h | 12 +++++++----- | |
15 | drivers/net/bnx2x_main.c | 42 +++++++++++++++++++++++++++++++++--------- | |
16 | 2 files changed, 40 insertions(+), 14 deletions(-) | |
17 | ||
18 | Index: linux-2.6.27-bnx2x_2/drivers/net/bnx2x.h | |
19 | =================================================================== | |
20 | --- linux-2.6.27-bnx2x_2.orig/drivers/net/bnx2x.h | |
21 | +++ linux-2.6.27-bnx2x_2/drivers/net/bnx2x.h | |
22 | @@ -20,6 +20,11 @@ | |
23 | * (you will need to reboot afterwards) */ | |
24 | /* #define BNX2X_STOP_ON_ERROR */ | |
25 | ||
26 | +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) | |
27 | +#define BCM_VLAN 1 | |
28 | +#endif | |
29 | + | |
30 | + | |
31 | /* error/debug prints */ | |
32 | ||
33 | #define DRV_MODULE_NAME "bnx2x" | |
34 | @@ -78,11 +83,6 @@ | |
35 | #endif | |
36 | ||
37 | ||
38 | -#ifdef NETIF_F_HW_VLAN_TX | |
39 | -#define BCM_VLAN 1 | |
40 | -#endif | |
41 | - | |
42 | - | |
43 | #define U64_LO(x) (u32)(((u64)(x)) & 0xffffffff) | |
44 | #define U64_HI(x) (u32)(((u64)(x)) >> 32) | |
45 | #define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo)) | |
46 | @@ -804,6 +804,8 @@ struct bnx2x { | |
47 | #define TPA_ENABLE_FLAG 0x80 | |
48 | #define NO_MCP_FLAG 0x100 | |
49 | #define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG) | |
50 | +#define HW_VLAN_TX_FLAG 0x400 | |
51 | +#define HW_VLAN_RX_FLAG 0x800 | |
52 | ||
53 | int func; | |
54 | #define BP_PORT(bp) (bp->func % PORT_MAX) | |
55 | Index: linux-2.6.27-bnx2x_2/drivers/net/bnx2x_main.c | |
56 | =================================================================== | |
57 | --- linux-2.6.27-bnx2x_2.orig/drivers/net/bnx2x_main.c | |
58 | +++ linux-2.6.27-bnx2x_2/drivers/net/bnx2x_main.c | |
59 | @@ -38,9 +38,7 @@ | |
60 | #include <linux/time.h> | |
61 | #include <linux/ethtool.h> | |
62 | #include <linux/mii.h> | |
63 | -#ifdef NETIF_F_HW_VLAN_TX | |
64 | - #include <linux/if_vlan.h> | |
65 | -#endif | |
66 | +#include <linux/if_vlan.h> | |
67 | #include <net/ip.h> | |
68 | #include <net/tcp.h> | |
69 | #include <net/checksum.h> | |
70 | @@ -1283,6 +1281,13 @@ static void bnx2x_tpa_stop(struct bnx2x | |
71 | if (likely(new_skb)) { | |
72 | /* fix ip xsum and give it to the stack */ | |
73 | /* (no need to map the new skb) */ | |
74 | +#ifdef BCM_VLAN | |
75 | + int is_vlan_cqe = | |
76 | + (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & | |
77 | + PARSING_FLAGS_VLAN); | |
78 | + int is_not_hwaccel_vlan_cqe = | |
79 | + (is_vlan_cqe && (!(bp->flags & HW_VLAN_RX_FLAG))); | |
80 | +#endif | |
81 | ||
82 | prefetch(skb); | |
83 | prefetch(((char *)(skb)) + 128); | |
84 | @@ -1307,6 +1312,12 @@ static void bnx2x_tpa_stop(struct bnx2x | |
85 | struct iphdr *iph; | |
86 | ||
87 | iph = (struct iphdr *)skb->data; | |
88 | +#ifdef BCM_VLAN | |
89 | + /* If there is no Rx VLAN offloading - | |
90 | + take VLAN tag into an account */ | |
91 | + if (unlikely(is_not_hwaccel_vlan_cqe)) | |
92 | + iph = (struct iphdr *)((u8 *)iph + VLAN_HLEN); | |
93 | +#endif | |
94 | iph->check = 0; | |
95 | iph->check = ip_fast_csum((u8 *)iph, iph->ihl); | |
96 | } | |
97 | @@ -1314,9 +1325,8 @@ static void bnx2x_tpa_stop(struct bnx2x | |
98 | if (!bnx2x_fill_frag_skb(bp, fp, skb, | |
99 | &cqe->fast_path_cqe, cqe_idx)) { | |
100 | #ifdef BCM_VLAN | |
101 | - if ((bp->vlgrp != NULL) && | |
102 | - (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & | |
103 | - PARSING_FLAGS_VLAN)) | |
104 | + if ((bp->vlgrp != NULL) && is_vlan_cqe && | |
105 | + (!is_not_hwaccel_vlan_cqe)) | |
106 | vlan_hwaccel_receive_skb(skb, bp->vlgrp, | |
107 | le16_to_cpu(cqe->fast_path_cqe. | |
108 | vlan_tag)); | |
109 | @@ -1561,7 +1571,7 @@ reuse_rx: | |
110 | } | |
111 | ||
112 | #ifdef BCM_VLAN | |
113 | - if ((bp->vlgrp != NULL) && | |
114 | + if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) && | |
115 | (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & | |
116 | PARSING_FLAGS_VLAN)) | |
117 | vlan_hwaccel_receive_skb(skb, bp->vlgrp, | |
118 | @@ -4541,7 +4551,7 @@ static void bnx2x_set_client_config(stru | |
119 | tstorm_client.config_flags = | |
120 | TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE; | |
121 | #ifdef BCM_VLAN | |
122 | - if (bp->rx_mode && bp->vlgrp) { | |
123 | + if (bp->rx_mode && bp->vlgrp && (bp->flags & HW_VLAN_RX_FLAG)) { | |
124 | tstorm_client.config_flags |= | |
125 | TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE; | |
126 | DP(NETIF_MSG_IFUP, "vlan removal enabled\n"); | |
127 | @@ -9571,11 +9581,14 @@ static int bnx2x_start_xmit(struct sk_bu | |
128 | "sending pkt %u @%p next_idx %u bd %u @%p\n", | |
129 | pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_bd); | |
130 | ||
131 | - if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb)) { | |
132 | +#ifdef BCM_VLAN | |
133 | + if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) && | |
134 | + (bp->flags & HW_VLAN_TX_FLAG)) { | |
135 | tx_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb)); | |
136 | tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG; | |
137 | vlan_off += 4; | |
138 | } else | |
139 | +#endif | |
140 | tx_bd->vlan = cpu_to_le16(pkt_prod); | |
141 | ||
142 | if (xmit_type) { | |
143 | @@ -10024,6 +10037,16 @@ static void bnx2x_vlan_rx_register(struc | |
144 | struct bnx2x *bp = netdev_priv(dev); | |
145 | ||
146 | bp->vlgrp = vlgrp; | |
147 | + | |
148 | + /* Set flags according to the required capabilities */ | |
149 | + bp->flags &= ~(HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG); | |
150 | + | |
151 | + if (dev->features & NETIF_F_HW_VLAN_TX) | |
152 | + bp->flags |= HW_VLAN_TX_FLAG; | |
153 | + | |
154 | + if (dev->features & NETIF_F_HW_VLAN_RX) | |
155 | + bp->flags |= HW_VLAN_RX_FLAG; | |
156 | + | |
157 | if (netif_running(dev)) | |
158 | bnx2x_set_client_config(bp); | |
159 | } | |
160 | @@ -10175,6 +10198,7 @@ static int __devinit bnx2x_init_dev(stru | |
161 | dev->features |= NETIF_F_HIGHDMA; | |
162 | #ifdef BCM_VLAN | |
163 | dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); | |
164 | + bp->flags |= (HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG); | |
165 | #endif | |
166 | dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); | |
167 | dev->features |= NETIF_F_TSO6; |