]>
Commit | Line | Data |
---|---|---|
6460db5f FG |
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 |