aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 80c16f6e2af6..c261cdb359eb 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
@@ -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,34 @@ 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
674 if (local->hw.queues < 4)
675 return 0;
676
677 if (skb->len < 4 ||
678 skb->len < rtap->it_len + 2 /* frame control */)
679 return 0; /* doesn't matter, frame will be dropped */
680
681 hdr = (void *)((u8 *)skb->data + rtap->it_len);
682
683 if (!ieee80211_is_data(hdr->frame_control)) {
684 skb->priority = 7;
685 return ieee802_1d_to_ac[skb->priority];
686 }
687
688 return ieee80211_downgrade_queue(local, skb);
689}
690
657static const struct net_device_ops ieee80211_monitorif_ops = { 691static const struct net_device_ops ieee80211_monitorif_ops = {
658 .ndo_open = ieee80211_open, 692 .ndo_open = ieee80211_open,
659 .ndo_stop = ieee80211_stop, 693 .ndo_stop = ieee80211_stop,
@@ -662,6 +696,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
662 .ndo_set_multicast_list = ieee80211_set_multicast_list, 696 .ndo_set_multicast_list = ieee80211_set_multicast_list,
663 .ndo_change_mtu = ieee80211_change_mtu, 697 .ndo_change_mtu = ieee80211_change_mtu,
664 .ndo_set_mac_address = eth_mac_addr, 698 .ndo_set_mac_address = eth_mac_addr,
699 .ndo_select_queue = ieee80211_monitor_select_queue,
665}; 700};
666 701
667static void ieee80211_if_setup(struct net_device *dev) 702static void ieee80211_if_setup(struct net_device *dev)
@@ -768,8 +803,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
768 803
769 ASSERT_RTNL(); 804 ASSERT_RTNL();
770 805
771 ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, 806 ndev = alloc_netdev_mq(sizeof(*sdata) + local->hw.vif_data_size,
772 name, ieee80211_if_setup); 807 name, ieee80211_if_setup, local->hw.queues);
773 if (!ndev) 808 if (!ndev)
774 return -ENOMEM; 809 return -ENOMEM;
775 dev_net_set(ndev, wiphy_net(local->hw.wiphy)); 810 dev_net_set(ndev, wiphy_net(local->hw.wiphy));