Commit 51cb6db0 authored by David S. Miller's avatar David S. Miller

mac80211: Reimplement WME using ->select_queue().

The only behavior change is that we do not drop packets under any
circumstances.  If that is absolutely needed, we could easily add it
back.

With cleanups and help from Johannes Berg.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eae792b7
......@@ -847,20 +847,12 @@ static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
static inline int ieee80211_num_regular_queues(struct ieee80211_hw *hw)
{
#ifdef CONFIG_MAC80211_QOS
return hw->queues;
#else
return 1;
#endif
}
static inline int ieee80211_num_queues(struct ieee80211_hw *hw)
{
#ifdef CONFIG_MAC80211_QOS
return hw->queues + hw->ampdu_queues;
#else
return 1;
#endif
}
static inline struct ieee80211_rate *
......
......@@ -11,17 +11,6 @@ config MAC80211
This option enables the hardware independent IEEE 802.11
networking stack.
config MAC80211_QOS
def_bool y
depends on MAC80211
depends on NET_SCHED
depends on BROKEN
comment "QoS/HT support disabled"
depends on MAC80211 && !MAC80211_QOS
comment "QoS/HT support needs CONFIG_NET_SCHED"
depends on MAC80211 && !NET_SCHED
menu "Rate control algorithm selection"
depends on MAC80211 != n
......
......@@ -18,10 +18,10 @@ mac80211-y := \
tx.o \
key.o \
util.o \
wme.o \
event.o
mac80211-$(CONFIG_MAC80211_LEDS) += led.o
mac80211-$(CONFIG_MAC80211_QOS) += wme.o
mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
debugfs.o \
debugfs_sta.o \
......
......@@ -25,6 +25,7 @@
#include <linux/etherdevice.h>
#include <net/wireless.h>
#include <net/iw_handler.h>
#include <net/mac80211.h>
#include "key.h"
#include "sta_info.h"
......@@ -537,6 +538,9 @@ enum {
IEEE80211_ADDBA_MSG = 4,
};
/* maximum number of hardware queues we support. */
#define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES)
struct ieee80211_local {
/* embed the driver visible part.
* don't cast (use the static inlines below), but we keep
......@@ -545,6 +549,8 @@ struct ieee80211_local {
const struct ieee80211_ops *ops;
unsigned long queue_pool[BITS_TO_LONGS(QD_MAX_QUEUES)];
struct net_device *mdev; /* wmaster# - "master" 802.11 device */
int open_count;
int monitors, cooked_mntrs;
......@@ -740,15 +746,6 @@ struct ieee80211_local {
#endif
};
static inline int ieee80211_is_multiqueue(struct ieee80211_local *local)
{
#ifdef CONFIG_MAC80211_QOS
return netif_is_multiqueue(local->mdev);
#else
return 0;
#endif
}
static inline struct ieee80211_sub_if_data *
IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
{
......
......@@ -114,7 +114,7 @@ static int ieee80211_master_open(struct net_device *dev)
if (res)
return res;
netif_start_queue(local->mdev);
netif_tx_start_all_queues(local->mdev);
return 0;
}
......@@ -375,7 +375,7 @@ static int ieee80211_open(struct net_device *dev)
queue_work(local->hw.workqueue, &ifsta->work);
}
netif_start_queue(dev);
netif_tx_start_all_queues(dev);
return 0;
err_del_interface:
......@@ -400,7 +400,7 @@ static int ieee80211_stop(struct net_device *dev)
/*
* Stop TX on this interface first.
*/
netif_stop_queue(dev);
netif_tx_stop_all_queues(dev);
/*
* Now delete all active aggregation sessions.
......@@ -554,7 +554,6 @@ static int ieee80211_stop(struct net_device *dev)
int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
{
struct ieee80211_local *local = hw_to_local(hw);
struct netdev_queue *txq;
struct sta_info *sta;
struct ieee80211_sub_if_data *sdata;
u16 start_seq_num = 0;
......@@ -619,11 +618,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
(unsigned long)&sta->timer_to_tid[tid];
init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
/* ensure that TX flow won't interrupt us
* until the end of the call to requeue function */
txq = netdev_get_tx_queue(local->mdev, 0);
spin_lock_bh(&txq->lock);
/* create a new queue for this aggregation */
ret = ieee80211_ht_agg_queue_add(local, sta, tid);
......@@ -661,7 +655,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
/* Will put all the packets in the new SW queue */
ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
spin_unlock_bh(&txq->lock);
spin_unlock_bh(&sta->lock);
/* send an addBA request */
......@@ -687,7 +680,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
err_unlock_queue:
kfree(sta->ampdu_mlme.tid_tx[tid]);
sta->ampdu_mlme.tid_tx[tid] = NULL;
spin_unlock_bh(&txq->lock);
ret = -EBUSY;
err_unlock_sta:
spin_unlock_bh(&sta->lock);
......@@ -812,7 +804,6 @@ EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
{
struct ieee80211_local *local = hw_to_local(hw);
struct netdev_queue *txq;
struct sta_info *sta;
u8 *state;
int agg_queue;
......@@ -844,8 +835,9 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
state = &sta->ampdu_mlme.tid_state_tx[tid];
/* NOTE: no need to use sta->lock in this state check, as
* ieee80211_stop_tx_ba_session will let only
* one stop call to pass through per sta/tid */
* ieee80211_stop_tx_ba_session will let only one stop call to
* pass through per sta/tid
*/
if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
......@@ -860,19 +852,14 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
agg_queue = sta->tid_to_tx_q[tid];
/* avoid ordering issues: we are the only one that can modify
* the content of the qdiscs */
txq = netdev_get_tx_queue(local->mdev, 0);
spin_lock_bh(&txq->lock);
/* remove the queue for this aggregation */
ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
spin_unlock_bh(&txq->lock);
/* we just requeued the all the frames that were in the removed
* queue, and since we might miss a softirq we do netif_schedule_queue.
* ieee80211_wake_queue is not used here as this queue is not
* necessarily stopped */
netif_schedule_queue(txq);
/* We just requeued the all the frames that were in the
* removed queue, and since we might miss a softirq we do
* netif_schedule_queue. ieee80211_wake_queue is not used
* here as this queue is not necessarily stopped
*/
netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue));
spin_lock_bh(&sta->lock);
*state = HT_AGG_STATE_IDLE;
sta->ampdu_mlme.addba_req_num[tid] = 0;
......@@ -1660,17 +1647,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
* We use the number of queues for feature tests (QoS, HT) internally
* so restrict them appropriately.
*/
#ifdef CONFIG_MAC80211_QOS
if (hw->queues > IEEE80211_MAX_QUEUES)
hw->queues = IEEE80211_MAX_QUEUES;
if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES)
hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES;
if (hw->queues < 4)
hw->ampdu_queues = 0;
#else
hw->queues = 1;
hw->ampdu_queues = 0;
#endif
mdev = alloc_netdev_mq(sizeof(struct wireless_dev),
"wmaster%d", ether_setup,
......@@ -1754,7 +1736,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
goto fail_wep;
}
ieee80211_install_qdisc(local->mdev);
local->mdev->select_queue = ieee80211_select_queue;
/* add one default STA interface */
result = ieee80211_if_add(local, "wlan%d", NULL,
......@@ -1852,23 +1834,11 @@ static int __init ieee80211_init(void)
ret = rc80211_pid_init();
if (ret)
goto out;
ret = ieee80211_wme_register();
if (ret) {
printk(KERN_DEBUG "ieee80211_init: failed to "
"initialize WME (err=%d)\n", ret);
goto out_cleanup_pid;
}
return ret;
ieee80211_debugfs_netdev_init();
return 0;
out_cleanup_pid:
rc80211_pid_exit();
out:
return ret;
}
static void __exit ieee80211_exit(void)
......@@ -1884,7 +1854,6 @@ static void __exit ieee80211_exit(void)
if (mesh_allocated)
ieee80211s_stop();
ieee80211_wme_unregister();
ieee80211_debugfs_netdev_exit();
}
......
......@@ -363,12 +363,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
if (test_bit(queue, local->queues_pending)) {
tasklet_schedule(&local->tx_pending_tasklet);
} else {
if (ieee80211_is_multiqueue(local)) {
netif_wake_subqueue(local->mdev, queue);
} else {
WARN_ON(queue != 0);
netif_wake_queue(local->mdev);
}
}
}
EXPORT_SYMBOL(ieee80211_wake_queue);
......@@ -377,12 +372,7 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
{
struct ieee80211_local *local = hw_to_local(hw);
if (ieee80211_is_multiqueue(local)) {
netif_stop_subqueue(local->mdev, queue);
} else {
WARN_ON(queue != 0);
netif_stop_queue(local->mdev);
}
}
EXPORT_SYMBOL(ieee80211_stop_queue);
......
This diff is collapsed.
......@@ -23,45 +23,12 @@
extern const int ieee802_1d_to_ac[8];
#ifdef CONFIG_MAC80211_QOS
void ieee80211_install_qdisc(struct net_device *dev);
int ieee80211_qdisc_installed(struct net_device *dev);
u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb);
int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
struct sta_info *sta, u16 tid);
void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
struct sta_info *sta, u16 tid,
u8 requeue);
void ieee80211_requeue(struct ieee80211_local *local, int queue);
int ieee80211_wme_register(void);
void ieee80211_wme_unregister(void);
#else
static inline void ieee80211_install_qdisc(struct net_device *dev)
{
}
static inline int ieee80211_qdisc_installed(struct net_device *dev)
{
return 0;
}
static inline int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
struct sta_info *sta, u16 tid)
{
return -EAGAIN;
}
static inline void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
struct sta_info *sta, u16 tid,
u8 requeue)
{
}
static inline void ieee80211_requeue(struct ieee80211_local *local, int queue)
{
}
static inline int ieee80211_wme_register(void)
{
return 0;
}
static inline void ieee80211_wme_unregister(void)
{
}
#endif /* CONFIG_NET_SCHED */
#endif /* _WME_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment