aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c3
-rw-r--r--net/mac80211/driver-trace.h2
-rw-r--r--net/mac80211/ibss.c2
-rw-r--r--net/mac80211/iface.c47
-rw-r--r--net/mac80211/mlme.c8
-rw-r--r--net/mac80211/rate.c3
-rw-r--r--net/mac80211/rc80211_pid_algo.c2
-rw-r--r--net/mac80211/rx.c8
-rw-r--r--net/mac80211/scan.c28
-rw-r--r--net/mac80211/tx.c5
-rw-r--r--net/mac80211/util.c12
-rw-r--r--net/mac80211/wme.c96
-rw-r--r--net/mac80211/wme.h8
13 files changed, 171 insertions, 53 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6dc3579c0ac5..9ae1a4760b58 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1331,6 +1331,9 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1331 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 1331 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1332 struct ieee80211_conf *conf = &local->hw.conf; 1332 struct ieee80211_conf *conf = &local->hw.conf;
1333 1333
1334 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1335 return -EOPNOTSUPP;
1336
1334 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) 1337 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
1335 return -EOPNOTSUPP; 1338 return -EOPNOTSUPP;
1336 1339
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index ee94ea0c67e9..da8497ef7063 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -680,7 +680,7 @@ TRACE_EVENT(drv_ampdu_action,
680 __entry->ret = ret; 680 __entry->ret = ret;
681 __entry->action = action; 681 __entry->action = action;
682 __entry->tid = tid; 682 __entry->tid = tid;
683 __entry->ssn = *ssn; 683 __entry->ssn = ssn ? *ssn : 0;
684 ), 684 ),
685 685
686 TP_printk( 686 TP_printk(
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 1f2db647bb5c..22f0c2aa7a89 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -647,7 +647,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
647 } 647 }
648 if (pos[1] != 0 && 648 if (pos[1] != 0 &&
649 (pos[1] != ifibss->ssid_len || 649 (pos[1] != ifibss->ssid_len ||
650 !memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) { 650 memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) {
651 /* Ignore ProbeReq for foreign SSID */ 651 /* Ignore ProbeReq for foreign SSID */
652 return; 652 return;
653 } 653 }
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 80c16f6e2af6..32abae3ce32a 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -15,12 +15,14 @@
15#include <linux/netdevice.h> 15#include <linux/netdevice.h>
16#include <linux/rtnetlink.h> 16#include <linux/rtnetlink.h>
17#include <net/mac80211.h> 17#include <net/mac80211.h>
18#include <net/ieee80211_radiotap.h>
18#include "ieee80211_i.h" 19#include "ieee80211_i.h"
19#include "sta_info.h" 20#include "sta_info.h"
20#include "debugfs_netdev.h" 21#include "debugfs_netdev.h"
21#include "mesh.h" 22#include "mesh.h"
22#include "led.h" 23#include "led.h"
23#include "driver-ops.h" 24#include "driver-ops.h"
25#include "wme.h"
24 26
25/** 27/**
26 * DOC: Interface list locking 28 * DOC: Interface list locking
@@ -314,7 +316,7 @@ static int ieee80211_open(struct net_device *dev)
314 if (sdata->vif.type == NL80211_IFTYPE_STATION) 316 if (sdata->vif.type == NL80211_IFTYPE_STATION)
315 ieee80211_queue_work(&local->hw, &sdata->u.mgd.work); 317 ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
316 318
317 netif_start_queue(dev); 319 netif_tx_start_all_queues(dev);
318 320
319 return 0; 321 return 0;
320 err_del_interface: 322 err_del_interface:
@@ -343,7 +345,7 @@ static int ieee80211_stop(struct net_device *dev)
343 /* 345 /*
344 * Stop TX on this interface first. 346 * Stop TX on this interface first.
345 */ 347 */
346 netif_stop_queue(dev); 348 netif_tx_stop_all_queues(dev);
347 349
348 /* 350 /*
349 * Now delete all active aggregation sessions. 351 * Now delete all active aggregation sessions.
@@ -644,6 +646,12 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
644 WARN_ON(flushed); 646 WARN_ON(flushed);
645} 647}
646 648
649static u16 ieee80211_netdev_select_queue(struct net_device *dev,
650 struct sk_buff *skb)
651{
652 return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
653}
654
647static const struct net_device_ops ieee80211_dataif_ops = { 655static const struct net_device_ops ieee80211_dataif_ops = {
648 .ndo_open = ieee80211_open, 656 .ndo_open = ieee80211_open,
649 .ndo_stop = ieee80211_stop, 657 .ndo_stop = ieee80211_stop,
@@ -652,8 +660,38 @@ static const struct net_device_ops ieee80211_dataif_ops = {
652 .ndo_set_multicast_list = ieee80211_set_multicast_list, 660 .ndo_set_multicast_list = ieee80211_set_multicast_list,
653 .ndo_change_mtu = ieee80211_change_mtu, 661 .ndo_change_mtu = ieee80211_change_mtu,
654 .ndo_set_mac_address = eth_mac_addr, 662 .ndo_set_mac_address = eth_mac_addr,
663 .ndo_select_queue = ieee80211_netdev_select_queue,
655}; 664};
656 665
666static u16 ieee80211_monitor_select_queue(struct net_device *dev,
667 struct sk_buff *skb)
668{
669 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
670 struct ieee80211_local *local = sdata->local;
671 struct ieee80211_hdr *hdr;
672 struct ieee80211_radiotap_header *rtap = (void *)skb->data;
673 u8 *p;
674
675 if (local->hw.queues < 4)
676 return 0;
677
678 if (skb->len < 4 ||
679 skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */)
680 return 0; /* doesn't matter, frame will be dropped */
681
682 hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
683
684 if (!ieee80211_is_data_qos(hdr->frame_control)) {
685 skb->priority = 7;
686 return ieee802_1d_to_ac[skb->priority];
687 }
688
689 p = ieee80211_get_qos_ctl(hdr);
690 skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
691
692 return ieee80211_downgrade_queue(local, skb);
693}
694
657static const struct net_device_ops ieee80211_monitorif_ops = { 695static const struct net_device_ops ieee80211_monitorif_ops = {
658 .ndo_open = ieee80211_open, 696 .ndo_open = ieee80211_open,
659 .ndo_stop = ieee80211_stop, 697 .ndo_stop = ieee80211_stop,
@@ -662,6 +700,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
662 .ndo_set_multicast_list = ieee80211_set_multicast_list, 700 .ndo_set_multicast_list = ieee80211_set_multicast_list,
663 .ndo_change_mtu = ieee80211_change_mtu, 701 .ndo_change_mtu = ieee80211_change_mtu,
664 .ndo_set_mac_address = eth_mac_addr, 702 .ndo_set_mac_address = eth_mac_addr,
703 .ndo_select_queue = ieee80211_monitor_select_queue,
665}; 704};
666 705
667static void ieee80211_if_setup(struct net_device *dev) 706static void ieee80211_if_setup(struct net_device *dev)
@@ -768,8 +807,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
768 807
769 ASSERT_RTNL(); 808 ASSERT_RTNL();
770 809
771 ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, 810 ndev = alloc_netdev_mq(sizeof(*sdata) + local->hw.vif_data_size,
772 name, ieee80211_if_setup); 811 name, ieee80211_if_setup, local->hw.queues);
773 if (!ndev) 812 if (!ndev)
774 return -ENOMEM; 813 return -ENOMEM;
775 dev_net_set(ndev, wiphy_net(local->hw.wiphy)); 814 dev_net_set(ndev, wiphy_net(local->hw.wiphy));
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index c79e59f82fd9..05a18f43e1bf 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -942,7 +942,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
942 ieee80211_recalc_ps(local, -1); 942 ieee80211_recalc_ps(local, -1);
943 mutex_unlock(&local->iflist_mtx); 943 mutex_unlock(&local->iflist_mtx);
944 944
945 netif_start_queue(sdata->dev); 945 netif_tx_start_all_queues(sdata->dev);
946 netif_carrier_on(sdata->dev); 946 netif_carrier_on(sdata->dev);
947} 947}
948 948
@@ -1074,7 +1074,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1074 * time -- we don't want the scan code to enable queues. 1074 * time -- we don't want the scan code to enable queues.
1075 */ 1075 */
1076 1076
1077 netif_stop_queue(sdata->dev); 1077 netif_tx_stop_all_queues(sdata->dev);
1078 netif_carrier_off(sdata->dev); 1078 netif_carrier_off(sdata->dev);
1079 1079
1080 rcu_read_lock(); 1080 rcu_read_lock();
@@ -1963,7 +1963,9 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1963 rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); 1963 rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
1964 break; 1964 break;
1965 case IEEE80211_STYPE_ACTION: 1965 case IEEE80211_STYPE_ACTION:
1966 /* XXX: differentiate, can only happen for CSA now! */ 1966 if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
1967 break;
1968
1967 ieee80211_sta_process_chanswitch(sdata, 1969 ieee80211_sta_process_chanswitch(sdata,
1968 &mgmt->u.action.u.chan_switch.sw_elem, 1970 &mgmt->u.action.u.chan_switch.sw_elem,
1969 ifmgd->associated); 1971 ifmgd->associated);
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index b9007f80cb92..12a2bff7dcdb 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -245,6 +245,9 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
245 info->control.rates[i].count = 1; 245 info->control.rates[i].count = 1;
246 } 246 }
247 247
248 if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
249 return;
250
248 if (sta && sdata->force_unicast_rateidx > -1) { 251 if (sta && sdata->force_unicast_rateidx > -1) {
249 info->control.rates[0].idx = sdata->force_unicast_rateidx; 252 info->control.rates[0].idx = sdata->force_unicast_rateidx;
250 } else { 253 } else {
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
index 699d3ed869c4..29bc4c516238 100644
--- a/net/mac80211/rc80211_pid_algo.c
+++ b/net/mac80211/rc80211_pid_algo.c
@@ -190,7 +190,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
190 rate_control_pid_normalize(pinfo, sband->n_bitrates); 190 rate_control_pid_normalize(pinfo, sband->n_bitrates);
191 191
192 /* Compute the proportional, integral and derivative errors. */ 192 /* Compute the proportional, integral and derivative errors. */
193 err_prop = (pinfo->target << RC_PID_ARITH_SHIFT) - pf; 193 err_prop = (pinfo->target - pf) << RC_PID_ARITH_SHIFT;
194 194
195 err_avg = spinfo->err_avg_sc >> pinfo->smoothing_shift; 195 err_avg = spinfo->err_avg_sc >> pinfo->smoothing_shift;
196 spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop; 196 spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9f2807aeaf52..82a30c1bf3ab 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1746,7 +1746,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1746 memset(info, 0, sizeof(*info)); 1746 memset(info, 0, sizeof(*info));
1747 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; 1747 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
1748 info->control.vif = &rx->sdata->vif; 1748 info->control.vif = &rx->sdata->vif;
1749 ieee80211_select_queue(local, fwd_skb); 1749 skb_set_queue_mapping(skb,
1750 ieee80211_select_queue(rx->sdata, fwd_skb));
1751 ieee80211_set_qos_hdr(local, skb);
1750 if (is_multicast_ether_addr(fwd_hdr->addr1)) 1752 if (is_multicast_ether_addr(fwd_hdr->addr1))
1751 IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, 1753 IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
1752 fwded_mcast); 1754 fwded_mcast);
@@ -2013,6 +2015,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2013 } 2015 }
2014 break; 2016 break;
2015 default: 2017 default:
2018 /* do not process rejected action frames */
2019 if (mgmt->u.action.category & 0x80)
2020 return RX_DROP_MONITOR;
2021
2016 return RX_CONTINUE; 2022 return RX_CONTINUE;
2017 } 2023 }
2018 2024
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index f1a4c7160300..bc17cf7d68db 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -353,10 +353,10 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
353 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 353 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
354 if (sdata->u.mgd.associated) { 354 if (sdata->u.mgd.associated) {
355 ieee80211_scan_ps_disable(sdata); 355 ieee80211_scan_ps_disable(sdata);
356 netif_wake_queue(sdata->dev); 356 netif_tx_wake_all_queues(sdata->dev);
357 } 357 }
358 } else 358 } else
359 netif_wake_queue(sdata->dev); 359 netif_tx_wake_all_queues(sdata->dev);
360 360
361 /* re-enable beaconing */ 361 /* re-enable beaconing */
362 if (sdata->vif.type == NL80211_IFTYPE_AP || 362 if (sdata->vif.type == NL80211_IFTYPE_AP ||
@@ -411,7 +411,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
411 * are handled in the scan state machine 411 * are handled in the scan state machine
412 */ 412 */
413 if (sdata->vif.type != NL80211_IFTYPE_STATION) 413 if (sdata->vif.type != NL80211_IFTYPE_STATION)
414 netif_stop_queue(sdata->dev); 414 netif_tx_stop_all_queues(sdata->dev);
415 } 415 }
416 mutex_unlock(&local->iflist_mtx); 416 mutex_unlock(&local->iflist_mtx);
417 417
@@ -439,6 +439,16 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
439 if (local->scan_req) 439 if (local->scan_req)
440 return -EBUSY; 440 return -EBUSY;
441 441
442 if (req != local->int_scan_req &&
443 sdata->vif.type == NL80211_IFTYPE_STATION &&
444 !list_empty(&ifmgd->work_list)) {
445 /* actually wait for the work it's doing to finish/time out */
446 set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request);
447 local->scan_req = req;
448 local->scan_sdata = sdata;
449 return 0;
450 }
451
442 if (local->ops->hw_scan) { 452 if (local->ops->hw_scan) {
443 u8 *ies; 453 u8 *ies;
444 454
@@ -463,14 +473,6 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
463 local->scan_req = req; 473 local->scan_req = req;
464 local->scan_sdata = sdata; 474 local->scan_sdata = sdata;
465 475
466 if (req != local->int_scan_req &&
467 sdata->vif.type == NL80211_IFTYPE_STATION &&
468 !list_empty(&ifmgd->work_list)) {
469 /* actually wait for the work it's doing to finish/time out */
470 set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request);
471 return 0;
472 }
473
474 if (local->ops->hw_scan) 476 if (local->ops->hw_scan)
475 __set_bit(SCAN_HW_SCANNING, &local->scanning); 477 __set_bit(SCAN_HW_SCANNING, &local->scanning);
476 else 478 else
@@ -575,7 +577,7 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca
575 continue; 577 continue;
576 578
577 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 579 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
578 netif_stop_queue(sdata->dev); 580 netif_tx_stop_all_queues(sdata->dev);
579 if (sdata->u.mgd.associated) 581 if (sdata->u.mgd.associated)
580 ieee80211_scan_ps_enable(sdata); 582 ieee80211_scan_ps_enable(sdata);
581 } 583 }
@@ -610,7 +612,7 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca
610 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 612 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
611 if (sdata->u.mgd.associated) 613 if (sdata->u.mgd.associated)
612 ieee80211_scan_ps_disable(sdata); 614 ieee80211_scan_ps_disable(sdata);
613 netif_wake_queue(sdata->dev); 615 netif_tx_wake_all_queues(sdata->dev);
614 } 616 }
615 } 617 }
616 mutex_unlock(&local->iflist_mtx); 618 mutex_unlock(&local->iflist_mtx);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 27ceaefd7bc8..ac210b586702 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1512,7 +1512,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1512 return; 1512 return;
1513 } 1513 }
1514 1514
1515 ieee80211_select_queue(local, skb); 1515 ieee80211_set_qos_hdr(local, skb);
1516 ieee80211_tx(sdata, skb, false); 1516 ieee80211_tx(sdata, skb, false);
1517 rcu_read_unlock(); 1517 rcu_read_unlock();
1518} 1518}
@@ -2291,6 +2291,9 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
2291 skb_set_network_header(skb, 0); 2291 skb_set_network_header(skb, 0);
2292 skb_set_transport_header(skb, 0); 2292 skb_set_transport_header(skb, 0);
2293 2293
2294 /* send all internal mgmt frames on VO */
2295 skb_set_queue_mapping(skb, 0);
2296
2294 /* 2297 /*
2295 * The other path calling ieee80211_xmit is from the tasklet, 2298 * The other path calling ieee80211_xmit is from the tasklet,
2296 * and while we can handle concurrent transmissions locking 2299 * and while we can handle concurrent transmissions locking
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index dc76267e436e..3848140313f5 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -269,6 +269,7 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
269 enum queue_stop_reason reason) 269 enum queue_stop_reason reason)
270{ 270{
271 struct ieee80211_local *local = hw_to_local(hw); 271 struct ieee80211_local *local = hw_to_local(hw);
272 struct ieee80211_sub_if_data *sdata;
272 273
273 if (WARN_ON(queue >= hw->queues)) 274 if (WARN_ON(queue >= hw->queues))
274 return; 275 return;
@@ -281,6 +282,11 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
281 282
282 if (!skb_queue_empty(&local->pending[queue])) 283 if (!skb_queue_empty(&local->pending[queue]))
283 tasklet_schedule(&local->tx_pending_tasklet); 284 tasklet_schedule(&local->tx_pending_tasklet);
285
286 rcu_read_lock();
287 list_for_each_entry_rcu(sdata, &local->interfaces, list)
288 netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue));
289 rcu_read_unlock();
284} 290}
285 291
286void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, 292void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
@@ -305,11 +311,17 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
305 enum queue_stop_reason reason) 311 enum queue_stop_reason reason)
306{ 312{
307 struct ieee80211_local *local = hw_to_local(hw); 313 struct ieee80211_local *local = hw_to_local(hw);
314 struct ieee80211_sub_if_data *sdata;
308 315
309 if (WARN_ON(queue >= hw->queues)) 316 if (WARN_ON(queue >= hw->queues))
310 return; 317 return;
311 318
312 __set_bit(reason, &local->queue_stop_reasons[queue]); 319 __set_bit(reason, &local->queue_stop_reasons[queue]);
320
321 rcu_read_lock();
322 list_for_each_entry_rcu(sdata, &local->interfaces, list)
323 netif_tx_stop_queue(netdev_get_tx_queue(sdata->dev, queue));
324 rcu_read_unlock();
313} 325}
314 326
315void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, 327void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index b19b7696f3a2..79d887dae738 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -44,22 +44,69 @@ static int wme_downgrade_ac(struct sk_buff *skb)
44} 44}
45 45
46 46
47/* Indicate which queue to use. */ 47/* Indicate which queue to use. */
48static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) 48u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
49 struct sk_buff *skb)
49{ 50{
50 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 51 struct ieee80211_local *local = sdata->local;
52 struct sta_info *sta = NULL;
53 u32 sta_flags = 0;
54 const u8 *ra = NULL;
55 bool qos = false;
51 56
52 if (!ieee80211_is_data(hdr->frame_control)) { 57 if (local->hw.queues < 4 || skb->len < 6) {
53 /* management frames go on AC_VO queue, but are sent 58 skb->priority = 0; /* required for correct WPA/11i MIC */
54 * without QoS control fields */ 59 return min_t(u16, local->hw.queues - 1,
55 return 0; 60 ieee802_1d_to_ac[skb->priority]);
61 }
62
63 rcu_read_lock();
64 switch (sdata->vif.type) {
65 case NL80211_IFTYPE_AP_VLAN:
66 rcu_read_lock();
67 sta = rcu_dereference(sdata->u.vlan.sta);
68 if (sta)
69 sta_flags = get_sta_flags(sta);
70 rcu_read_unlock();
71 if (sta)
72 break;
73 case NL80211_IFTYPE_AP:
74 ra = skb->data;
75 break;
76 case NL80211_IFTYPE_WDS:
77 ra = sdata->u.wds.remote_addr;
78 break;
79#ifdef CONFIG_MAC80211_MESH
80 case NL80211_IFTYPE_MESH_POINT:
81 /*
82 * XXX: This is clearly broken ... but already was before,
83 * because ieee80211_fill_mesh_addresses() would clear A1
84 * except for multicast addresses.
85 */
86 break;
87#endif
88 case NL80211_IFTYPE_STATION:
89 ra = sdata->u.mgd.bssid;
90 break;
91 case NL80211_IFTYPE_ADHOC:
92 ra = skb->data;
93 break;
94 default:
95 break;
56 } 96 }
57 97
58 if (0 /* injected */) { 98 if (!sta && ra && !is_multicast_ether_addr(ra)) {
59 /* use AC from radiotap */ 99 sta = sta_info_get(local, ra);
100 if (sta)
101 sta_flags = get_sta_flags(sta);
60 } 102 }
61 103
62 if (!ieee80211_is_data_qos(hdr->frame_control)) { 104 if (sta_flags & WLAN_STA_WME)
105 qos = true;
106
107 rcu_read_unlock();
108
109 if (!qos) {
63 skb->priority = 0; /* required for correct WPA/11i MIC */ 110 skb->priority = 0; /* required for correct WPA/11i MIC */
64 return ieee802_1d_to_ac[skb->priority]; 111 return ieee802_1d_to_ac[skb->priority];
65 } 112 }
@@ -68,6 +115,12 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb)
68 * data frame has */ 115 * data frame has */
69 skb->priority = cfg80211_classify8021d(skb); 116 skb->priority = cfg80211_classify8021d(skb);
70 117
118 return ieee80211_downgrade_queue(local, skb);
119}
120
121u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
122 struct sk_buff *skb)
123{
71 /* in case we are a client verify acm is not set for this ac */ 124 /* in case we are a client verify acm is not set for this ac */
72 while (unlikely(local->wmm_acm & BIT(skb->priority))) { 125 while (unlikely(local->wmm_acm & BIT(skb->priority))) {
73 if (wme_downgrade_ac(skb)) { 126 if (wme_downgrade_ac(skb)) {
@@ -85,24 +138,17 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb)
85 return ieee802_1d_to_ac[skb->priority]; 138 return ieee802_1d_to_ac[skb->priority];
86} 139}
87 140
88void ieee80211_select_queue(struct ieee80211_local *local, struct sk_buff *skb) 141void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb)
89{ 142{
90 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 143 struct ieee80211_hdr *hdr = (void *)skb->data;
91 u16 queue; 144
92 u8 tid; 145 /* Fill in the QoS header if there is one. */
93
94 queue = classify80211(local, skb);
95 if (unlikely(queue >= local->hw.queues))
96 queue = local->hw.queues - 1;
97
98 /*
99 * Now we know the 1d priority, fill in the QoS header if
100 * there is one (and we haven't done this before).
101 */
102 if (ieee80211_is_data_qos(hdr->frame_control)) { 146 if (ieee80211_is_data_qos(hdr->frame_control)) {
103 u8 *p = ieee80211_get_qos_ctl(hdr); 147 u8 *p = ieee80211_get_qos_ctl(hdr);
104 u8 ack_policy = 0; 148 u8 ack_policy = 0, tid;
149
105 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; 150 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
151
106 if (unlikely(local->wifi_wme_noack_test)) 152 if (unlikely(local->wifi_wme_noack_test))
107 ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK << 153 ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
108 QOS_CONTROL_ACK_POLICY_SHIFT; 154 QOS_CONTROL_ACK_POLICY_SHIFT;
@@ -110,6 +156,4 @@ void ieee80211_select_queue(struct ieee80211_local *local, struct sk_buff *skb)
110 *p++ = ack_policy | tid; 156 *p++ = ack_policy | tid;
111 *p = 0; 157 *p = 0;
112 } 158 }
113
114 skb_set_queue_mapping(skb, queue);
115} 159}
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
index d4fd87ca5118..6053b1c9feee 100644
--- a/net/mac80211/wme.h
+++ b/net/mac80211/wme.h
@@ -20,7 +20,11 @@
20 20
21extern const int ieee802_1d_to_ac[8]; 21extern const int ieee802_1d_to_ac[8];
22 22
23void ieee80211_select_queue(struct ieee80211_local *local, 23u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
24 struct sk_buff *skb); 24 struct sk_buff *skb);
25void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb);
26u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
27 struct sk_buff *skb);
28
25 29
26#endif /* _WME_H */ 30#endif /* _WME_H */