|
@@ -15,12 +15,14 @@
|
|
#include <linux/netdevice.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/rtnetlink.h>
|
|
#include <linux/rtnetlink.h>
|
|
#include <net/mac80211.h>
|
|
#include <net/mac80211.h>
|
|
|
|
+#include <net/ieee80211_radiotap.h>
|
|
#include "ieee80211_i.h"
|
|
#include "ieee80211_i.h"
|
|
#include "sta_info.h"
|
|
#include "sta_info.h"
|
|
#include "debugfs_netdev.h"
|
|
#include "debugfs_netdev.h"
|
|
#include "mesh.h"
|
|
#include "mesh.h"
|
|
#include "led.h"
|
|
#include "led.h"
|
|
#include "driver-ops.h"
|
|
#include "driver-ops.h"
|
|
|
|
+#include "wme.h"
|
|
|
|
|
|
/**
|
|
/**
|
|
* DOC: Interface list locking
|
|
* DOC: Interface list locking
|
|
@@ -314,7 +316,7 @@ static int ieee80211_open(struct net_device *dev)
|
|
if (sdata->vif.type == NL80211_IFTYPE_STATION)
|
|
if (sdata->vif.type == NL80211_IFTYPE_STATION)
|
|
ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
|
|
ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
|
|
|
|
|
|
- netif_start_queue(dev);
|
|
|
|
|
|
+ netif_tx_start_all_queues(dev);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
err_del_interface:
|
|
err_del_interface:
|
|
@@ -343,7 +345,7 @@ static int ieee80211_stop(struct net_device *dev)
|
|
/*
|
|
/*
|
|
* Stop TX on this interface first.
|
|
* Stop TX on this interface first.
|
|
*/
|
|
*/
|
|
- netif_stop_queue(dev);
|
|
|
|
|
|
+ netif_tx_stop_all_queues(dev);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Now delete all active aggregation sessions.
|
|
* Now delete all active aggregation sessions.
|
|
@@ -644,6 +646,12 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
|
|
WARN_ON(flushed);
|
|
WARN_ON(flushed);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static u16 ieee80211_netdev_select_queue(struct net_device *dev,
|
|
|
|
+ struct sk_buff *skb)
|
|
|
|
+{
|
|
|
|
+ return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct net_device_ops ieee80211_dataif_ops = {
|
|
static const struct net_device_ops ieee80211_dataif_ops = {
|
|
.ndo_open = ieee80211_open,
|
|
.ndo_open = ieee80211_open,
|
|
.ndo_stop = ieee80211_stop,
|
|
.ndo_stop = ieee80211_stop,
|
|
@@ -652,8 +660,38 @@ static const struct net_device_ops ieee80211_dataif_ops = {
|
|
.ndo_set_multicast_list = ieee80211_set_multicast_list,
|
|
.ndo_set_multicast_list = ieee80211_set_multicast_list,
|
|
.ndo_change_mtu = ieee80211_change_mtu,
|
|
.ndo_change_mtu = ieee80211_change_mtu,
|
|
.ndo_set_mac_address = eth_mac_addr,
|
|
.ndo_set_mac_address = eth_mac_addr,
|
|
|
|
+ .ndo_select_queue = ieee80211_netdev_select_queue,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static u16 ieee80211_monitor_select_queue(struct net_device *dev,
|
|
|
|
+ struct sk_buff *skb)
|
|
|
|
+{
|
|
|
|
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
|
|
|
+ struct ieee80211_local *local = sdata->local;
|
|
|
|
+ struct ieee80211_hdr *hdr;
|
|
|
|
+ struct ieee80211_radiotap_header *rtap = (void *)skb->data;
|
|
|
|
+ u8 *p;
|
|
|
|
+
|
|
|
|
+ if (local->hw.queues < 4)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ if (skb->len < 4 ||
|
|
|
|
+ skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */)
|
|
|
|
+ return 0; /* doesn't matter, frame will be dropped */
|
|
|
|
+
|
|
|
|
+ hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
|
|
|
|
+
|
|
|
|
+ if (!ieee80211_is_data_qos(hdr->frame_control)) {
|
|
|
|
+ skb->priority = 7;
|
|
|
|
+ return ieee802_1d_to_ac[skb->priority];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ p = ieee80211_get_qos_ctl(hdr);
|
|
|
|
+ skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
|
|
|
|
+
|
|
|
|
+ return ieee80211_downgrade_queue(local, skb);
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct net_device_ops ieee80211_monitorif_ops = {
|
|
static const struct net_device_ops ieee80211_monitorif_ops = {
|
|
.ndo_open = ieee80211_open,
|
|
.ndo_open = ieee80211_open,
|
|
.ndo_stop = ieee80211_stop,
|
|
.ndo_stop = ieee80211_stop,
|
|
@@ -662,6 +700,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
|
|
.ndo_set_multicast_list = ieee80211_set_multicast_list,
|
|
.ndo_set_multicast_list = ieee80211_set_multicast_list,
|
|
.ndo_change_mtu = ieee80211_change_mtu,
|
|
.ndo_change_mtu = ieee80211_change_mtu,
|
|
.ndo_set_mac_address = eth_mac_addr,
|
|
.ndo_set_mac_address = eth_mac_addr,
|
|
|
|
+ .ndo_select_queue = ieee80211_monitor_select_queue,
|
|
};
|
|
};
|
|
|
|
|
|
static void ieee80211_if_setup(struct net_device *dev)
|
|
static void ieee80211_if_setup(struct net_device *dev)
|
|
@@ -768,8 +807,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
|
|
|
|
|
ASSERT_RTNL();
|
|
ASSERT_RTNL();
|
|
|
|
|
|
- ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
|
|
|
|
- name, ieee80211_if_setup);
|
|
|
|
|
|
+ ndev = alloc_netdev_mq(sizeof(*sdata) + local->hw.vif_data_size,
|
|
|
|
+ name, ieee80211_if_setup, local->hw.queues);
|
|
if (!ndev)
|
|
if (!ndev)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
dev_net_set(ndev, wiphy_net(local->hw.wiphy));
|
|
dev_net_set(ndev, wiphy_net(local->hw.wiphy));
|