mac80211: merge johill's tx queue stop fix patch from the linux-wireless list - fixes...
[openwrt.git] / package / mac80211 / patches / 550-queue_stop_fix.patch
1 --- a/net/mac80211/iface.c
2 +++ b/net/mac80211/iface.c
3 @@ -15,12 +15,14 @@
4 #include <linux/netdevice.h>
5 #include <linux/rtnetlink.h>
6 #include <net/mac80211.h>
7 +#include <net/ieee80211_radiotap.h>
8 #include "ieee80211_i.h"
9 #include "sta_info.h"
10 #include "debugfs_netdev.h"
11 #include "mesh.h"
12 #include "led.h"
13 #include "driver-ops.h"
14 +#include "wme.h"
15
16 /**
17 * DOC: Interface list locking
18 @@ -644,6 +646,37 @@ static void ieee80211_teardown_sdata(str
19 WARN_ON(flushed);
20 }
21
22 +static u16 ieee80211_netdev_select_queue(struct net_device *dev,
23 + struct sk_buff *skb)
24 +{
25 + return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
26 +}
27 +
28 +static u16 ieee80211_monitor_select_queue(struct net_device *dev,
29 + struct sk_buff *skb)
30 +{
31 + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
32 + struct ieee80211_local *local = sdata->local;
33 + struct ieee80211_hdr *hdr;
34 + struct ieee80211_radiotap_header *rtap = (void *)skb->data;
35 +
36 + if (local->hw.queues < 4)
37 + return 0;
38 +
39 + if (skb->len < 4 ||
40 + skb->len < rtap->it_len + 2 /* frame control */)
41 + return 0; /* doesn't matter, frame will be dropped */
42 +
43 + hdr = (void *)((u8 *)skb->data + rtap->it_len);
44 +
45 + if (!ieee80211_is_data(hdr->frame_control)) {
46 + skb->priority = 7;
47 + return ieee802_1d_to_ac[skb->priority];
48 + }
49 +
50 + return ieee80211_downgrade_queue(local, skb);
51 +}
52 +
53 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
54 static const struct net_device_ops ieee80211_dataif_ops = {
55 .ndo_open = ieee80211_open,
56 @@ -653,6 +686,7 @@ static const struct net_device_ops ieee8
57 .ndo_set_multicast_list = ieee80211_set_multicast_list,
58 .ndo_change_mtu = ieee80211_change_mtu,
59 .ndo_set_mac_address = eth_mac_addr,
60 + .ndo_select_queue = ieee80211_monitor_select_queue,
61 };
62
63 static const struct net_device_ops ieee80211_monitorif_ops = {
64 @@ -663,6 +697,7 @@ static const struct net_device_ops ieee8
65 .ndo_set_multicast_list = ieee80211_set_multicast_list,
66 .ndo_change_mtu = ieee80211_change_mtu,
67 .ndo_set_mac_address = eth_mac_addr,
68 + .ndo_select_queue = ieee80211_monitor_select_queue,
69 };
70 #endif
71
72 @@ -677,6 +712,7 @@ static void ieee80211_if_setup(struct ne
73 dev->change_mtu = ieee80211_change_mtu;
74 dev->open = ieee80211_open;
75 dev->stop = ieee80211_stop;
76 + dev->select_queue = ieee80211_netdev_select_queue;
77 /* we will validate the address ourselves in ->open */
78 dev->validate_addr = NULL;
79 #endif
80 @@ -725,6 +761,7 @@ static void ieee80211_setup_sdata(struct
81 sdata->dev->netdev_ops = &ieee80211_monitorif_ops;
82 #else
83 sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit;
84 + sdata->dev->select_queue = ieee80211_monitor_select_queue;
85 #endif
86 sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
87 MONITOR_FLAG_OTHER_BSS;
88 @@ -794,8 +831,8 @@ int ieee80211_if_add(struct ieee80211_lo
89
90 ASSERT_RTNL();
91
92 - ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
93 - name, ieee80211_if_setup);
94 + ndev = alloc_netdev_mq(sizeof(*sdata) + local->hw.vif_data_size,
95 + name, ieee80211_if_setup, local->hw.queues);
96 if (!ndev)
97 return -ENOMEM;
98 dev_net_set(ndev, wiphy_net(local->hw.wiphy));
99 --- a/net/mac80211/rx.c
100 +++ b/net/mac80211/rx.c
101 @@ -1747,7 +1747,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
102 memset(info, 0, sizeof(*info));
103 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
104 info->control.vif = &rx->sdata->vif;
105 - ieee80211_select_queue(local, fwd_skb);
106 + skb_set_queue_mapping(skb,
107 + ieee80211_select_queue(rx->sdata, fwd_skb));
108 + ieee80211_set_qos_hdr(local, skb);
109 if (is_multicast_ether_addr(fwd_hdr->addr1))
110 IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
111 fwded_mcast);
112 --- a/net/mac80211/tx.c
113 +++ b/net/mac80211/tx.c
114 @@ -1507,7 +1507,7 @@ static void ieee80211_xmit(struct ieee80
115 return;
116 }
117
118 - ieee80211_select_queue(local, skb);
119 + ieee80211_set_qos_hdr(local, skb);
120 ieee80211_tx(sdata, skb, false);
121 rcu_read_unlock();
122 }
123 @@ -2286,6 +2286,9 @@ void ieee80211_tx_skb(struct ieee80211_s
124 skb_set_network_header(skb, 0);
125 skb_set_transport_header(skb, 0);
126
127 + /* send all internal mgmt frames on VO */
128 + skb_set_queue_mapping(skb, 0);
129 +
130 /*
131 * The other path calling ieee80211_xmit is from the tasklet,
132 * and while we can handle concurrent transmissions locking
133 --- a/net/mac80211/util.c
134 +++ b/net/mac80211/util.c
135 @@ -269,6 +269,7 @@ static void __ieee80211_wake_queue(struc
136 enum queue_stop_reason reason)
137 {
138 struct ieee80211_local *local = hw_to_local(hw);
139 + struct ieee80211_sub_if_data *sdata;
140
141 if (WARN_ON(queue >= hw->queues))
142 return;
143 @@ -281,6 +282,11 @@ static void __ieee80211_wake_queue(struc
144
145 if (!skb_queue_empty(&local->pending[queue]))
146 tasklet_schedule(&local->tx_pending_tasklet);
147 +
148 + rcu_read_lock();
149 + list_for_each_entry_rcu(sdata, &local->interfaces, list)
150 + netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue));
151 + rcu_read_unlock();
152 }
153
154 void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
155 @@ -305,11 +311,17 @@ static void __ieee80211_stop_queue(struc
156 enum queue_stop_reason reason)
157 {
158 struct ieee80211_local *local = hw_to_local(hw);
159 + struct ieee80211_sub_if_data *sdata;
160
161 if (WARN_ON(queue >= hw->queues))
162 return;
163
164 __set_bit(reason, &local->queue_stop_reasons[queue]);
165 +
166 + rcu_read_lock();
167 + list_for_each_entry_rcu(sdata, &local->interfaces, list)
168 + netif_tx_stop_queue(netdev_get_tx_queue(sdata->dev, queue));
169 + rcu_read_unlock();
170 }
171
172 void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
173 --- a/net/mac80211/wme.c
174 +++ b/net/mac80211/wme.c
175 @@ -44,22 +44,69 @@ static int wme_downgrade_ac(struct sk_bu
176 }
177
178
179 -/* Indicate which queue to use. */
180 -static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb)
181 +/* Indicate which queue to use. */
182 +u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
183 + struct sk_buff *skb)
184 {
185 - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
186 + struct ieee80211_local *local = sdata->local;
187 + struct sta_info *sta = NULL;
188 + u32 sta_flags = 0;
189 + const u8 *ra = NULL;
190 + bool qos = false;
191
192 - if (!ieee80211_is_data(hdr->frame_control)) {
193 - /* management frames go on AC_VO queue, but are sent
194 - * without QoS control fields */
195 - return 0;
196 + if (local->hw.queues < 4 || skb->len < 6) {
197 + skb->priority = 0; /* required for correct WPA/11i MIC */
198 + return min_t(u16, local->hw.queues - 1,
199 + ieee802_1d_to_ac[skb->priority]);
200 + }
201 +
202 + rcu_read_lock();
203 + switch (sdata->vif.type) {
204 + case NL80211_IFTYPE_AP_VLAN:
205 + rcu_read_lock();
206 + sta = rcu_dereference(sdata->u.vlan.sta);
207 + if (sta)
208 + sta_flags = get_sta_flags(sta);
209 + rcu_read_unlock();
210 + if (sta)
211 + break;
212 + case NL80211_IFTYPE_AP:
213 + ra = skb->data;
214 + break;
215 + case NL80211_IFTYPE_WDS:
216 + ra = sdata->u.wds.remote_addr;
217 + break;
218 +#ifdef CONFIG_MAC80211_MESH
219 + case NL80211_IFTYPE_MESH_POINT:
220 + /*
221 + * XXX: This is clearly broken ... but already was before,
222 + * because ieee80211_fill_mesh_addresses() would clear A1
223 + * except for multicast addresses.
224 + */
225 + break;
226 +#endif
227 + case NL80211_IFTYPE_STATION:
228 + ra = sdata->u.mgd.bssid;
229 + break;
230 + case NL80211_IFTYPE_ADHOC:
231 + ra = skb->data;
232 + break;
233 + default:
234 + break;
235 }
236
237 - if (0 /* injected */) {
238 - /* use AC from radiotap */
239 + if (!sta && ra && !is_multicast_ether_addr(ra)) {
240 + sta = sta_info_get(sdata, ra);
241 + if (sta)
242 + sta_flags = get_sta_flags(sta);
243 }
244
245 - if (!ieee80211_is_data_qos(hdr->frame_control)) {
246 + if (sta_flags & WLAN_STA_WME)
247 + qos = true;
248 +
249 + rcu_read_unlock();
250 +
251 + if (!qos) {
252 skb->priority = 0; /* required for correct WPA/11i MIC */
253 return ieee802_1d_to_ac[skb->priority];
254 }
255 @@ -68,6 +115,12 @@ static u16 classify80211(struct ieee8021
256 * data frame has */
257 skb->priority = cfg80211_classify8021d(skb);
258
259 + return ieee80211_downgrade_queue(local, skb);
260 +}
261 +
262 +u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
263 + struct sk_buff *skb)
264 +{
265 /* in case we are a client verify acm is not set for this ac */
266 while (unlikely(local->wmm_acm & BIT(skb->priority))) {
267 if (wme_downgrade_ac(skb)) {
268 @@ -85,24 +138,17 @@ static u16 classify80211(struct ieee8021
269 return ieee802_1d_to_ac[skb->priority];
270 }
271
272 -void ieee80211_select_queue(struct ieee80211_local *local, struct sk_buff *skb)
273 +void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb)
274 {
275 - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
276 - u16 queue;
277 - u8 tid;
278 -
279 - queue = classify80211(local, skb);
280 - if (unlikely(queue >= local->hw.queues))
281 - queue = local->hw.queues - 1;
282 -
283 - /*
284 - * Now we know the 1d priority, fill in the QoS header if
285 - * there is one (and we haven't done this before).
286 - */
287 + struct ieee80211_hdr *hdr = (void *)skb->data;
288 +
289 + /* Fill in the QoS header if there is one. */
290 if (ieee80211_is_data_qos(hdr->frame_control)) {
291 u8 *p = ieee80211_get_qos_ctl(hdr);
292 - u8 ack_policy = 0;
293 + u8 ack_policy = 0, tid;
294 +
295 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
296 +
297 if (unlikely(local->wifi_wme_noack_test))
298 ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
299 QOS_CONTROL_ACK_POLICY_SHIFT;
300 @@ -110,6 +156,4 @@ void ieee80211_select_queue(struct ieee8
301 *p++ = ack_policy | tid;
302 *p = 0;
303 }
304 -
305 - skb_set_queue_mapping(skb, queue);
306 }
307 --- a/net/mac80211/wme.h
308 +++ b/net/mac80211/wme.h
309 @@ -20,7 +20,11 @@
310
311 extern const int ieee802_1d_to_ac[8];
312
313 -void ieee80211_select_queue(struct ieee80211_local *local,
314 - struct sk_buff *skb);
315 +u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
316 + struct sk_buff *skb);
317 +void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb);
318 +u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
319 + struct sk_buff *skb);
320 +
321
322 #endif /* _WME_H */
This page took 0.053556 seconds and 5 git commands to generate.