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) ...@@ -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) static inline int ieee80211_num_regular_queues(struct ieee80211_hw *hw)
{ {
#ifdef CONFIG_MAC80211_QOS
return hw->queues; return hw->queues;
#else
return 1;
#endif
} }
static inline int ieee80211_num_queues(struct ieee80211_hw *hw) static inline int ieee80211_num_queues(struct ieee80211_hw *hw)
{ {
#ifdef CONFIG_MAC80211_QOS
return hw->queues + hw->ampdu_queues; return hw->queues + hw->ampdu_queues;
#else
return 1;
#endif
} }
static inline struct ieee80211_rate * static inline struct ieee80211_rate *
......
...@@ -11,17 +11,6 @@ config MAC80211 ...@@ -11,17 +11,6 @@ config MAC80211
This option enables the hardware independent IEEE 802.11 This option enables the hardware independent IEEE 802.11
networking stack. 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" menu "Rate control algorithm selection"
depends on MAC80211 != n depends on MAC80211 != n
......
...@@ -18,10 +18,10 @@ mac80211-y := \ ...@@ -18,10 +18,10 @@ mac80211-y := \
tx.o \ tx.o \
key.o \ key.o \
util.o \ util.o \
wme.o \
event.o event.o
mac80211-$(CONFIG_MAC80211_LEDS) += led.o mac80211-$(CONFIG_MAC80211_LEDS) += led.o
mac80211-$(CONFIG_MAC80211_QOS) += wme.o
mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
debugfs.o \ debugfs.o \
debugfs_sta.o \ debugfs_sta.o \
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <net/wireless.h> #include <net/wireless.h>
#include <net/iw_handler.h> #include <net/iw_handler.h>
#include <net/mac80211.h>
#include "key.h" #include "key.h"
#include "sta_info.h" #include "sta_info.h"
...@@ -537,6 +538,9 @@ enum { ...@@ -537,6 +538,9 @@ enum {
IEEE80211_ADDBA_MSG = 4, 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 { struct ieee80211_local {
/* embed the driver visible part. /* embed the driver visible part.
* don't cast (use the static inlines below), but we keep * don't cast (use the static inlines below), but we keep
...@@ -545,6 +549,8 @@ struct ieee80211_local { ...@@ -545,6 +549,8 @@ struct ieee80211_local {
const struct ieee80211_ops *ops; const struct ieee80211_ops *ops;
unsigned long queue_pool[BITS_TO_LONGS(QD_MAX_QUEUES)];
struct net_device *mdev; /* wmaster# - "master" 802.11 device */ struct net_device *mdev; /* wmaster# - "master" 802.11 device */
int open_count; int open_count;
int monitors, cooked_mntrs; int monitors, cooked_mntrs;
...@@ -740,15 +746,6 @@ struct ieee80211_local { ...@@ -740,15 +746,6 @@ struct ieee80211_local {
#endif #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 * static inline struct ieee80211_sub_if_data *
IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
{ {
......
...@@ -114,7 +114,7 @@ static int ieee80211_master_open(struct net_device *dev) ...@@ -114,7 +114,7 @@ static int ieee80211_master_open(struct net_device *dev)
if (res) if (res)
return res; return res;
netif_start_queue(local->mdev); netif_tx_start_all_queues(local->mdev);
return 0; return 0;
} }
...@@ -375,7 +375,7 @@ static int ieee80211_open(struct net_device *dev) ...@@ -375,7 +375,7 @@ static int ieee80211_open(struct net_device *dev)
queue_work(local->hw.workqueue, &ifsta->work); queue_work(local->hw.workqueue, &ifsta->work);
} }
netif_start_queue(dev); netif_tx_start_all_queues(dev);
return 0; return 0;
err_del_interface: err_del_interface:
...@@ -400,7 +400,7 @@ static int ieee80211_stop(struct net_device *dev) ...@@ -400,7 +400,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.
...@@ -554,7 +554,6 @@ static int ieee80211_stop(struct net_device *dev) ...@@ -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) int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_local *local = hw_to_local(hw);
struct netdev_queue *txq;
struct sta_info *sta; struct sta_info *sta;
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
u16 start_seq_num = 0; u16 start_seq_num = 0;
...@@ -619,11 +618,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) ...@@ -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]; (unsigned long)&sta->timer_to_tid[tid];
init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); 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 */ /* create a new queue for this aggregation */
ret = ieee80211_ht_agg_queue_add(local, sta, tid); ret = ieee80211_ht_agg_queue_add(local, sta, tid);
...@@ -650,7 +644,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) ...@@ -650,7 +644,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
/* No need to requeue the packets in the agg queue, since we /* No need to requeue the packets in the agg queue, since we
* held the tx lock: no packet could be enqueued to the newly * held the tx lock: no packet could be enqueued to the newly
* allocated queue */ * allocated queue */
ieee80211_ht_agg_queue_remove(local, sta, tid, 0); ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "BA request denied - HW unavailable for" printk(KERN_DEBUG "BA request denied - HW unavailable for"
" tid %d\n", tid); " tid %d\n", tid);
...@@ -661,7 +655,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 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 */ /* Will put all the packets in the new SW queue */
ieee80211_requeue(local, ieee802_1d_to_ac[tid]); ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
spin_unlock_bh(&txq->lock);
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
/* send an addBA request */ /* send an addBA request */
...@@ -687,7 +680,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) ...@@ -687,7 +680,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
err_unlock_queue: err_unlock_queue:
kfree(sta->ampdu_mlme.tid_tx[tid]); kfree(sta->ampdu_mlme.tid_tx[tid]);
sta->ampdu_mlme.tid_tx[tid] = NULL; sta->ampdu_mlme.tid_tx[tid] = NULL;
spin_unlock_bh(&txq->lock);
ret = -EBUSY; ret = -EBUSY;
err_unlock_sta: err_unlock_sta:
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
...@@ -812,7 +804,6 @@ EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); ...@@ -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) void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_local *local = hw_to_local(hw);
struct netdev_queue *txq;
struct sta_info *sta; struct sta_info *sta;
u8 *state; u8 *state;
int agg_queue; int agg_queue;
...@@ -844,8 +835,9 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) ...@@ -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]; state = &sta->ampdu_mlme.tid_state_tx[tid];
/* NOTE: no need to use sta->lock in this state check, as /* NOTE: no need to use sta->lock in this state check, as
* ieee80211_stop_tx_ba_session will let only * ieee80211_stop_tx_ba_session will let only one stop call to
* one stop call to pass through per sta/tid */ * pass through per sta/tid
*/
if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); 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) ...@@ -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]; 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); 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 /* We just requeued the all the frames that were in the
* queue, and since we might miss a softirq we do netif_schedule_queue. * removed queue, and since we might miss a softirq we do
* ieee80211_wake_queue is not used here as this queue is not * netif_schedule_queue. ieee80211_wake_queue is not used
* necessarily stopped */ * here as this queue is not necessarily stopped
netif_schedule_queue(txq); */
netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue));
spin_lock_bh(&sta->lock); spin_lock_bh(&sta->lock);
*state = HT_AGG_STATE_IDLE; *state = HT_AGG_STATE_IDLE;
sta->ampdu_mlme.addba_req_num[tid] = 0; sta->ampdu_mlme.addba_req_num[tid] = 0;
...@@ -1660,17 +1647,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -1660,17 +1647,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
* We use the number of queues for feature tests (QoS, HT) internally * We use the number of queues for feature tests (QoS, HT) internally
* so restrict them appropriately. * so restrict them appropriately.
*/ */
#ifdef CONFIG_MAC80211_QOS
if (hw->queues > IEEE80211_MAX_QUEUES) if (hw->queues > IEEE80211_MAX_QUEUES)
hw->queues = IEEE80211_MAX_QUEUES; hw->queues = IEEE80211_MAX_QUEUES;
if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES)
hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES;
if (hw->queues < 4) if (hw->queues < 4)
hw->ampdu_queues = 0; hw->ampdu_queues = 0;
#else
hw->queues = 1;
hw->ampdu_queues = 0;
#endif
mdev = alloc_netdev_mq(sizeof(struct wireless_dev), mdev = alloc_netdev_mq(sizeof(struct wireless_dev),
"wmaster%d", ether_setup, "wmaster%d", ether_setup,
...@@ -1754,7 +1736,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ...@@ -1754,7 +1736,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
goto fail_wep; goto fail_wep;
} }
ieee80211_install_qdisc(local->mdev); local->mdev->select_queue = ieee80211_select_queue;
/* add one default STA interface */ /* add one default STA interface */
result = ieee80211_if_add(local, "wlan%d", NULL, result = ieee80211_if_add(local, "wlan%d", NULL,
...@@ -1852,23 +1834,11 @@ static int __init ieee80211_init(void) ...@@ -1852,23 +1834,11 @@ static int __init ieee80211_init(void)
ret = rc80211_pid_init(); ret = rc80211_pid_init();
if (ret) if (ret)
goto out; return ret;
ret = ieee80211_wme_register();
if (ret) {
printk(KERN_DEBUG "ieee80211_init: failed to "
"initialize WME (err=%d)\n", ret);
goto out_cleanup_pid;
}
ieee80211_debugfs_netdev_init(); ieee80211_debugfs_netdev_init();
return 0; return 0;
out_cleanup_pid:
rc80211_pid_exit();
out:
return ret;
} }
static void __exit ieee80211_exit(void) static void __exit ieee80211_exit(void)
...@@ -1884,7 +1854,6 @@ static void __exit ieee80211_exit(void) ...@@ -1884,7 +1854,6 @@ static void __exit ieee80211_exit(void)
if (mesh_allocated) if (mesh_allocated)
ieee80211s_stop(); ieee80211s_stop();
ieee80211_wme_unregister();
ieee80211_debugfs_netdev_exit(); ieee80211_debugfs_netdev_exit();
} }
......
...@@ -363,12 +363,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) ...@@ -363,12 +363,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
if (test_bit(queue, local->queues_pending)) { if (test_bit(queue, local->queues_pending)) {
tasklet_schedule(&local->tx_pending_tasklet); tasklet_schedule(&local->tx_pending_tasklet);
} else { } else {
if (ieee80211_is_multiqueue(local)) { netif_wake_subqueue(local->mdev, queue);
netif_wake_subqueue(local->mdev, queue);
} else {
WARN_ON(queue != 0);
netif_wake_queue(local->mdev);
}
} }
} }
EXPORT_SYMBOL(ieee80211_wake_queue); EXPORT_SYMBOL(ieee80211_wake_queue);
...@@ -377,12 +372,7 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) ...@@ -377,12 +372,7 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_local *local = hw_to_local(hw);
if (ieee80211_is_multiqueue(local)) { netif_stop_subqueue(local->mdev, queue);
netif_stop_subqueue(local->mdev, queue);
} else {
WARN_ON(queue != 0);
netif_stop_queue(local->mdev);
}
} }
EXPORT_SYMBOL(ieee80211_stop_queue); EXPORT_SYMBOL(ieee80211_stop_queue);
......
This diff is collapsed.
...@@ -23,45 +23,12 @@ ...@@ -23,45 +23,12 @@
extern const int ieee802_1d_to_ac[8]; extern const int ieee802_1d_to_ac[8];
#ifdef CONFIG_MAC80211_QOS u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb);
void ieee80211_install_qdisc(struct net_device *dev);
int ieee80211_qdisc_installed(struct net_device *dev);
int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
struct sta_info *sta, u16 tid); struct sta_info *sta, u16 tid);
void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local, void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
struct sta_info *sta, u16 tid, struct sta_info *sta, u16 tid,
u8 requeue); u8 requeue);
void ieee80211_requeue(struct ieee80211_local *local, int queue); 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 */ #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