diff options
Diffstat (limited to 'net/mac80211/iface.c')
| -rw-r--r-- | net/mac80211/iface.c | 47 |
1 files changed, 43 insertions, 4 deletions
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 | ||
| 649 | static 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 | |||
| 647 | static const struct net_device_ops ieee80211_dataif_ops = { | 655 | static 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 | ||
| 666 | static 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 | |||
| 657 | static const struct net_device_ops ieee80211_monitorif_ops = { | 695 | static 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 | ||
| 667 | static void ieee80211_if_setup(struct net_device *dev) | 706 | static 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)); |
