]> git.proxmox.com Git - pve-kernel-jessie.git/blob - bnx2x-allow-adding-VLANs-while-interface-is-down.patch
update to Ubuntu 4.4.0-58-79
[pve-kernel-jessie.git] / bnx2x-allow-adding-VLANs-while-interface-is-down.patch
1 From a02cc9d3cc9f98905df214d4a57e5918473260ea Mon Sep 17 00:00:00 2001
2 From: Michal Schmidt <mschmidt@redhat.com>
3 Date: Fri, 3 Jun 2016 15:32:18 +0200
4 Subject: [PATCH] bnx2x: allow adding VLANs while interface is down
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 Since implementing VLAN filtering in commit 05cc5a39ddb74
10 ("bnx2x: add vlan filtering offload") bnx2x refuses to add a VLAN while
11 the interface is down:
12
13 # ip link add link enp3s0f0 enp3s0f0_10 type vlan id 10
14 RTNETLINK answers: Bad address
15
16 and in dmesg (with bnx2x.debug=0x20):
17 bnx2x: [bnx2x_vlan_rx_add_vid:12941(enp3s0f0)]Ignoring VLAN
18 configuration the interface is down
19
20 Other drivers have no problem with this.
21 Fix this peculiar behavior in the following way:
22 - Accept requests to add/kill VID regardless of the device state.
23 Maintain the requested list of VIDs in the bp->vlan_reg list.
24 - If the device is up, try to configure the VID list into the hardware.
25 If we run out of VLAN credits or encounter a failure configuring an
26 entry, fall back to accepting all VLANs.
27 If we successfully configure all entries from the list, turn the
28 fallback off.
29 - Use the same code for reconfiguring VLANs during NIC load.
30
31 Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
32 Acked-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
33 Signed-off-by: David S. Miller <davem@davemloft.net>
34 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
35 ---
36 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 151 ++++++++++-------------
37 1 file changed, 62 insertions(+), 89 deletions(-)
38
39 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
40 index c5fe9158..a59d55e 100644
41 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
42 +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
43 @@ -12895,52 +12895,71 @@ static int __bnx2x_vlan_configure_vid(struct bnx2x *bp, u16 vid, bool add)
44 return rc;
45 }
46
47 -int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp)
48 +static int bnx2x_vlan_configure_vid_list(struct bnx2x *bp)
49 {
50 struct bnx2x_vlan_entry *vlan;
51 int rc = 0;
52
53 - if (!bp->vlan_cnt) {
54 - DP(NETIF_MSG_IFUP, "No need to re-configure vlan filters\n");
55 - return 0;
56 - }
57 -
58 + /* Configure all non-configured entries */
59 list_for_each_entry(vlan, &bp->vlan_reg, link) {
60 - /* Prepare for cleanup in case of errors */
61 - if (rc) {
62 - vlan->hw = false;
63 - continue;
64 - }
65 -
66 - if (!vlan->hw)
67 + if (vlan->hw)
68 continue;
69
70 - DP(NETIF_MSG_IFUP, "Re-configuring vlan 0x%04x\n", vlan->vid);
71 + if (bp->vlan_cnt >= bp->vlan_credit)
72 + return -ENOBUFS;
73
74 rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true);
75 if (rc) {
76 - BNX2X_ERR("Unable to configure VLAN %d\n", vlan->vid);
77 - vlan->hw = false;
78 - rc = -EINVAL;
79 - continue;
80 + BNX2X_ERR("Unable to config VLAN %d\n", vlan->vid);
81 + return rc;
82 }
83 +
84 + DP(NETIF_MSG_IFUP, "HW configured for VLAN %d\n", vlan->vid);
85 + vlan->hw = true;
86 + bp->vlan_cnt++;
87 }
88
89 - return rc;
90 + return 0;
91 +}
92 +
93 +static void bnx2x_vlan_configure(struct bnx2x *bp, bool set_rx_mode)
94 +{
95 + bool need_accept_any_vlan;
96 +
97 + need_accept_any_vlan = !!bnx2x_vlan_configure_vid_list(bp);
98 +
99 + if (bp->accept_any_vlan != need_accept_any_vlan) {
100 + bp->accept_any_vlan = need_accept_any_vlan;
101 + DP(NETIF_MSG_IFUP, "Accept all VLAN %s\n",
102 + bp->accept_any_vlan ? "raised" : "cleared");
103 + if (set_rx_mode) {
104 + if (IS_PF(bp))
105 + bnx2x_set_rx_mode_inner(bp);
106 + else
107 + bnx2x_vfpf_storm_rx_mode(bp);
108 + }
109 + }
110 +}
111 +
112 +int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp)
113 +{
114 + struct bnx2x_vlan_entry *vlan;
115 +
116 + /* The hw forgot all entries after reload */
117 + list_for_each_entry(vlan, &bp->vlan_reg, link)
118 + vlan->hw = false;
119 + bp->vlan_cnt = 0;
120 +
121 + /* Don't set rx mode here. Our caller will do it. */
122 + bnx2x_vlan_configure(bp, false);
123 +
124 + return 0;
125 }
126
127 static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
128 {
129 struct bnx2x *bp = netdev_priv(dev);
130 struct bnx2x_vlan_entry *vlan;
131 - bool hw = false;
132 - int rc = 0;
133 -
134 - if (!netif_running(bp->dev)) {
135 - DP(NETIF_MSG_IFUP,
136 - "Ignoring VLAN configuration the interface is down\n");
137 - return -EFAULT;
138 - }
139
140 DP(NETIF_MSG_IFUP, "Adding VLAN %d\n", vid);
141
142 @@ -12948,93 +12967,47 @@ static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
143 if (!vlan)
144 return -ENOMEM;
145
146 - bp->vlan_cnt++;
147 - if (bp->vlan_cnt > bp->vlan_credit && !bp->accept_any_vlan) {
148 - DP(NETIF_MSG_IFUP, "Accept all VLAN raised\n");
149 - bp->accept_any_vlan = true;
150 - if (IS_PF(bp))
151 - bnx2x_set_rx_mode_inner(bp);
152 - else
153 - bnx2x_vfpf_storm_rx_mode(bp);
154 - } else if (bp->vlan_cnt <= bp->vlan_credit) {
155 - rc = __bnx2x_vlan_configure_vid(bp, vid, true);
156 - hw = true;
157 - }
158 -
159 vlan->vid = vid;
160 - vlan->hw = hw;
161 + vlan->hw = false;
162 + list_add_tail(&vlan->link, &bp->vlan_reg);
163
164 - if (!rc) {
165 - list_add(&vlan->link, &bp->vlan_reg);
166 - } else {
167 - bp->vlan_cnt--;
168 - kfree(vlan);
169 - }
170 -
171 - DP(NETIF_MSG_IFUP, "Adding VLAN result %d\n", rc);
172 + if (netif_running(dev))
173 + bnx2x_vlan_configure(bp, true);
174
175 - return rc;
176 + return 0;
177 }
178
179 static int bnx2x_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
180 {
181 struct bnx2x *bp = netdev_priv(dev);
182 struct bnx2x_vlan_entry *vlan;
183 + bool found = false;
184 int rc = 0;
185
186 - if (!netif_running(bp->dev)) {
187 - DP(NETIF_MSG_IFUP,
188 - "Ignoring VLAN configuration the interface is down\n");
189 - return -EFAULT;
190 - }
191 -
192 DP(NETIF_MSG_IFUP, "Removing VLAN %d\n", vid);
193
194 - if (!bp->vlan_cnt) {
195 - BNX2X_ERR("Unable to kill VLAN %d\n", vid);
196 - return -EINVAL;
197 - }
198 -
199 list_for_each_entry(vlan, &bp->vlan_reg, link)
200 - if (vlan->vid == vid)
201 + if (vlan->vid == vid) {
202 + found = true;
203 break;
204 + }
205
206 - if (vlan->vid != vid) {
207 + if (!found) {
208 BNX2X_ERR("Unable to kill VLAN %d - not found\n", vid);
209 return -EINVAL;
210 }
211
212 - if (vlan->hw)
213 + if (netif_running(dev) && vlan->hw) {
214 rc = __bnx2x_vlan_configure_vid(bp, vid, false);
215 + DP(NETIF_MSG_IFUP, "HW deconfigured for VLAN %d\n", vid);
216 + bp->vlan_cnt--;
217 + }
218
219 list_del(&vlan->link);
220 kfree(vlan);
221
222 - bp->vlan_cnt--;
223 -
224 - if (bp->vlan_cnt <= bp->vlan_credit && bp->accept_any_vlan) {
225 - /* Configure all non-configured entries */
226 - list_for_each_entry(vlan, &bp->vlan_reg, link) {
227 - if (vlan->hw)
228 - continue;
229 -
230 - rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true);
231 - if (rc) {
232 - BNX2X_ERR("Unable to config VLAN %d\n",
233 - vlan->vid);
234 - continue;
235 - }
236 - DP(NETIF_MSG_IFUP, "HW configured for VLAN %d\n",
237 - vlan->vid);
238 - vlan->hw = true;
239 - }
240 - DP(NETIF_MSG_IFUP, "Accept all VLAN Removed\n");
241 - bp->accept_any_vlan = false;
242 - if (IS_PF(bp))
243 - bnx2x_set_rx_mode_inner(bp);
244 - else
245 - bnx2x_vfpf_storm_rx_mode(bp);
246 - }
247 + if (netif_running(dev))
248 + bnx2x_vlan_configure(bp, true);
249
250 DP(NETIF_MSG_IFUP, "Removing VLAN result %d\n", rc);
251
252 --
253 2.1.4
254