diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-05-16 18:57:14 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-21 21:48:14 -0400 |
commit | e2530083609148a7835b54c431f6b8956407c1f6 (patch) | |
tree | 8ed43347541444c7a72d2c79f550f69a93cad591 /net | |
parent | eefce91a384a64c7bbf913eb08c4adfb911c3639 (diff) |
mac80211: use multi-queue master netdevice
This patch updates mac80211 and drivers to be multi-queue aware and
use that instead of the internal queue mapping. Also does a number
of cleanups in various pieces of the code that fall out and reduces
internal mac80211 state size.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/Kconfig | 14 | ||||
-rw-r--r-- | net/mac80211/Makefile | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 16 | ||||
-rw-r--r-- | net/mac80211/iface.c | 2 | ||||
-rw-r--r-- | net/mac80211/main.c | 29 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 97 | ||||
-rw-r--r-- | net/mac80211/util.c | 29 | ||||
-rw-r--r-- | net/mac80211/wme.c | 14 | ||||
-rw-r--r-- | net/mac80211/wme.h | 2 |
10 files changed, 114 insertions, 93 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index a24b459dd45a..590e00b2766c 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -7,11 +7,23 @@ config MAC80211 | |||
7 | select CRC32 | 7 | select CRC32 |
8 | select WIRELESS_EXT | 8 | select WIRELESS_EXT |
9 | select CFG80211 | 9 | select CFG80211 |
10 | select NET_SCH_FIFO | ||
11 | ---help--- | 10 | ---help--- |
12 | This option enables the hardware independent IEEE 802.11 | 11 | This option enables the hardware independent IEEE 802.11 |
13 | networking stack. | 12 | networking stack. |
14 | 13 | ||
14 | config MAC80211_QOS | ||
15 | def_bool y | ||
16 | depends on MAC80211 | ||
17 | depends on NET_SCHED | ||
18 | depends on NETDEVICES_MULTIQUEUE | ||
19 | |||
20 | comment "QoS/HT support disabled" | ||
21 | depends on MAC80211 && !MAC80211_QOS | ||
22 | comment "QoS/HT support needs CONFIG_NET_SCHED" | ||
23 | depends on MAC80211 && !NET_SCHED | ||
24 | comment "QoS/HT support needs CONFIG_NETDEVICES_MULTIQUEUE" | ||
25 | depends on MAC80211 && !NETDEVICES_MULTIQUEUE | ||
26 | |||
15 | menu "Rate control algorithm selection" | 27 | menu "Rate control algorithm selection" |
16 | depends on MAC80211 != n | 28 | depends on MAC80211 != n |
17 | 29 | ||
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 4e5847fd316c..1d2a4e010e5c 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -29,7 +29,7 @@ mac80211-y := \ | |||
29 | event.o | 29 | event.o |
30 | 30 | ||
31 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o | 31 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o |
32 | mac80211-$(CONFIG_NET_SCHED) += wme.o | 32 | mac80211-$(CONFIG_MAC80211_QOS) += wme.o |
33 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ | 33 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ |
34 | debugfs.o \ | 34 | debugfs.o \ |
35 | debugfs_sta.o \ | 35 | debugfs_sta.o \ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 86a861251e8c..7d614cdcefcb 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -594,7 +594,7 @@ struct ieee80211_local { | |||
594 | struct sta_info *sta_hash[STA_HASH_SIZE]; | 594 | struct sta_info *sta_hash[STA_HASH_SIZE]; |
595 | struct timer_list sta_cleanup; | 595 | struct timer_list sta_cleanup; |
596 | 596 | ||
597 | unsigned long state[IEEE80211_MAX_QUEUES + IEEE80211_MAX_AMPDU_QUEUES]; | 597 | unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; |
598 | struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; | 598 | struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; |
599 | struct tasklet_struct tx_pending_tasklet; | 599 | struct tasklet_struct tx_pending_tasklet; |
600 | 600 | ||
@@ -758,6 +758,15 @@ struct ieee80211_local { | |||
758 | #endif | 758 | #endif |
759 | }; | 759 | }; |
760 | 760 | ||
761 | static inline int ieee80211_is_multiqueue(struct ieee80211_local *local) | ||
762 | { | ||
763 | #ifdef CONFIG_MAC80211_QOS | ||
764 | return netif_is_multiqueue(local->mdev); | ||
765 | #else | ||
766 | return 0; | ||
767 | #endif | ||
768 | } | ||
769 | |||
761 | /* this struct represents 802.11n's RA/TID combination */ | 770 | /* this struct represents 802.11n's RA/TID combination */ |
762 | struct ieee80211_ra_tid { | 771 | struct ieee80211_ra_tid { |
763 | u8 ra[ETH_ALEN]; | 772 | u8 ra[ETH_ALEN]; |
@@ -827,11 +836,6 @@ static inline struct ieee80211_hw *local_to_hw( | |||
827 | return &local->hw; | 836 | return &local->hw; |
828 | } | 837 | } |
829 | 838 | ||
830 | enum ieee80211_link_state_t { | ||
831 | IEEE80211_LINK_STATE_XOFF = 0, | ||
832 | IEEE80211_LINK_STATE_PENDING, | ||
833 | }; | ||
834 | |||
835 | struct sta_attribute { | 839 | struct sta_attribute { |
836 | struct attribute attr; | 840 | struct attribute attr; |
837 | ssize_t (*show)(const struct sta_info *, char *buf); | 841 | ssize_t (*show)(const struct sta_info *, char *buf); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 3c64e42eb12e..984472702381 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -168,7 +168,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
168 | ifsta->flags |= IEEE80211_STA_CREATE_IBSS | | 168 | ifsta->flags |= IEEE80211_STA_CREATE_IBSS | |
169 | IEEE80211_STA_AUTO_BSSID_SEL | | 169 | IEEE80211_STA_AUTO_BSSID_SEL | |
170 | IEEE80211_STA_AUTO_CHANNEL_SEL; | 170 | IEEE80211_STA_AUTO_CHANNEL_SEL; |
171 | if (sdata->local->hw.queues >= 4) | 171 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) |
172 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; | 172 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; |
173 | 173 | ||
174 | msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev); | 174 | msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 8f1ff7ef1667..97d4a537ca2f 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1634,12 +1634,32 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1634 | if (result < 0) | 1634 | if (result < 0) |
1635 | return result; | 1635 | return result; |
1636 | 1636 | ||
1637 | /* | ||
1638 | * We use the number of queues for feature tests (QoS, HT) internally | ||
1639 | * so restrict them appropriately. | ||
1640 | */ | ||
1641 | #ifdef CONFIG_MAC80211_QOS | ||
1642 | if (hw->queues > IEEE80211_MAX_QUEUES) | ||
1643 | hw->queues = IEEE80211_MAX_QUEUES; | ||
1644 | if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) | ||
1645 | hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; | ||
1646 | if (hw->queues < 4) | ||
1647 | hw->ampdu_queues = 0; | ||
1648 | #else | ||
1649 | hw->queues = 1; | ||
1650 | hw->ampdu_queues = 0; | ||
1651 | #endif | ||
1652 | |||
1637 | /* for now, mdev needs sub_if_data :/ */ | 1653 | /* for now, mdev needs sub_if_data :/ */ |
1638 | mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), | 1654 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_sub_if_data), |
1639 | "wmaster%d", ether_setup); | 1655 | "wmaster%d", ether_setup, |
1656 | ieee80211_num_queues(hw)); | ||
1640 | if (!mdev) | 1657 | if (!mdev) |
1641 | goto fail_mdev_alloc; | 1658 | goto fail_mdev_alloc; |
1642 | 1659 | ||
1660 | if (ieee80211_num_queues(hw) > 1) | ||
1661 | mdev->features |= NETIF_F_MULTI_QUEUE; | ||
1662 | |||
1643 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); | 1663 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); |
1644 | mdev->ieee80211_ptr = &sdata->wdev; | 1664 | mdev->ieee80211_ptr = &sdata->wdev; |
1645 | sdata->wdev.wiphy = local->hw.wiphy; | 1665 | sdata->wdev.wiphy = local->hw.wiphy; |
@@ -1728,11 +1748,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1728 | goto fail_wep; | 1748 | goto fail_wep; |
1729 | } | 1749 | } |
1730 | 1750 | ||
1731 | if (hw->queues > IEEE80211_MAX_QUEUES) | ||
1732 | hw->queues = IEEE80211_MAX_QUEUES; | ||
1733 | if (hw->ampdu_queues > IEEE80211_MAX_AMPDU_QUEUES) | ||
1734 | hw->ampdu_queues = IEEE80211_MAX_AMPDU_QUEUES; | ||
1735 | |||
1736 | ieee80211_install_qdisc(local->mdev); | 1751 | ieee80211_install_qdisc(local->mdev); |
1737 | 1752 | ||
1738 | /* add one default STA interface */ | 1753 | /* add one default STA interface */ |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ef3149324d54..c24770cb02c5 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -255,7 +255,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
255 | * sta_rx_agg_session_timer_expired for useage */ | 255 | * sta_rx_agg_session_timer_expired for useage */ |
256 | sta->timer_to_tid[i] = i; | 256 | sta->timer_to_tid[i] = i; |
257 | /* tid to tx queue: initialize according to HW (0 is valid) */ | 257 | /* tid to tx queue: initialize according to HW (0 is valid) */ |
258 | sta->tid_to_tx_q[i] = local->hw.queues + local->hw.ampdu_queues; | 258 | sta->tid_to_tx_q[i] = ieee80211_num_queues(&local->hw); |
259 | /* rx */ | 259 | /* rx */ |
260 | sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; | 260 | sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; |
261 | sta->ampdu_mlme.tid_rx[i] = NULL; | 261 | sta->ampdu_mlme.tid_rx[i] = NULL; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 6268bbca148e..9273651d3d7c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -213,18 +213,6 @@ static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
213 | return dur; | 213 | return dur; |
214 | } | 214 | } |
215 | 215 | ||
216 | static inline int __ieee80211_queue_stopped(const struct ieee80211_local *local, | ||
217 | int queue) | ||
218 | { | ||
219 | return test_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]); | ||
220 | } | ||
221 | |||
222 | static inline int __ieee80211_queue_pending(const struct ieee80211_local *local, | ||
223 | int queue) | ||
224 | { | ||
225 | return test_bit(IEEE80211_LINK_STATE_PENDING, &local->state[queue]); | ||
226 | } | ||
227 | |||
228 | static int inline is_ieee80211_device(struct net_device *dev, | 216 | static int inline is_ieee80211_device(struct net_device *dev, |
229 | struct net_device *master) | 217 | struct net_device *master) |
230 | { | 218 | { |
@@ -680,7 +668,8 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
680 | * etc. | 668 | * etc. |
681 | */ | 669 | */ |
682 | if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU || | 670 | if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU || |
683 | IEEE80211_SKB_CB(tx->skb)->queue >= tx->local->hw.queues)) | 671 | skb_get_queue_mapping(tx->skb) >= |
672 | ieee80211_num_regular_queues(&tx->local->hw))) | ||
684 | return TX_DROP; | 673 | return TX_DROP; |
685 | 674 | ||
686 | first = tx->skb; | 675 | first = tx->skb; |
@@ -1098,11 +1087,9 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1098 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1087 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1099 | int ret, i; | 1088 | int ret, i; |
1100 | 1089 | ||
1101 | if (!ieee80211_qdisc_installed(local->mdev) && | 1090 | if (netif_subqueue_stopped(local->mdev, skb)) |
1102 | __ieee80211_queue_stopped(local, 0)) { | ||
1103 | netif_stop_queue(local->mdev); | ||
1104 | return IEEE80211_TX_AGAIN; | 1091 | return IEEE80211_TX_AGAIN; |
1105 | } | 1092 | |
1106 | if (skb) { | 1093 | if (skb) { |
1107 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), | 1094 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), |
1108 | "TX to low-level driver", skb); | 1095 | "TX to low-level driver", skb); |
@@ -1121,7 +1108,8 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1121 | IEEE80211_TX_CTL_USE_CTS_PROTECT | | 1108 | IEEE80211_TX_CTL_USE_CTS_PROTECT | |
1122 | IEEE80211_TX_CTL_CLEAR_PS_FILT | | 1109 | IEEE80211_TX_CTL_CLEAR_PS_FILT | |
1123 | IEEE80211_TX_CTL_FIRST_FRAGMENT); | 1110 | IEEE80211_TX_CTL_FIRST_FRAGMENT); |
1124 | if (__ieee80211_queue_stopped(local, info->queue)) | 1111 | if (netif_subqueue_stopped(local->mdev, |
1112 | tx->extra_frag[i])) | ||
1125 | return IEEE80211_TX_FRAG_AGAIN; | 1113 | return IEEE80211_TX_FRAG_AGAIN; |
1126 | if (i == tx->num_extra_frag) { | 1114 | if (i == tx->num_extra_frag) { |
1127 | info->tx_rate_idx = tx->last_frag_rate_idx; | 1115 | info->tx_rate_idx = tx->last_frag_rate_idx; |
@@ -1160,9 +1148,11 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | |||
1160 | ieee80211_tx_result res = TX_DROP, res_prepare; | 1148 | ieee80211_tx_result res = TX_DROP, res_prepare; |
1161 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1149 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1162 | int ret, i; | 1150 | int ret, i; |
1163 | int queue = info->queue; | 1151 | u16 queue; |
1164 | 1152 | ||
1165 | WARN_ON(__ieee80211_queue_pending(local, queue)); | 1153 | queue = skb_get_queue_mapping(skb); |
1154 | |||
1155 | WARN_ON(test_bit(queue, local->queues_pending)); | ||
1166 | 1156 | ||
1167 | if (unlikely(skb->len < 10)) { | 1157 | if (unlikely(skb->len < 10)) { |
1168 | dev_kfree_skb(skb); | 1158 | dev_kfree_skb(skb); |
@@ -1233,28 +1223,28 @@ retry: | |||
1233 | * queues, there's no reason for a driver to reject | 1223 | * queues, there's no reason for a driver to reject |
1234 | * a frame there, warn and drop it. | 1224 | * a frame there, warn and drop it. |
1235 | */ | 1225 | */ |
1236 | if (WARN_ON(queue >= local->hw.queues)) | 1226 | if (WARN_ON(queue >= ieee80211_num_regular_queues(&local->hw))) |
1237 | goto drop; | 1227 | goto drop; |
1238 | 1228 | ||
1239 | store = &local->pending_packet[queue]; | 1229 | store = &local->pending_packet[queue]; |
1240 | 1230 | ||
1241 | if (ret == IEEE80211_TX_FRAG_AGAIN) | 1231 | if (ret == IEEE80211_TX_FRAG_AGAIN) |
1242 | skb = NULL; | 1232 | skb = NULL; |
1243 | set_bit(IEEE80211_LINK_STATE_PENDING, | 1233 | set_bit(queue, local->queues_pending); |
1244 | &local->state[queue]); | ||
1245 | smp_mb(); | 1234 | smp_mb(); |
1246 | /* When the driver gets out of buffers during sending of | 1235 | /* |
1247 | * fragments and calls ieee80211_stop_queue, there is | 1236 | * When the driver gets out of buffers during sending of |
1248 | * a small window between IEEE80211_LINK_STATE_XOFF and | 1237 | * fragments and calls ieee80211_stop_queue, the netif |
1249 | * IEEE80211_LINK_STATE_PENDING flags are set. If a buffer | 1238 | * subqueue is stopped. There is, however, a small window |
1239 | * in which the PENDING bit is not yet set. If a buffer | ||
1250 | * gets available in that window (i.e. driver calls | 1240 | * gets available in that window (i.e. driver calls |
1251 | * ieee80211_wake_queue), we would end up with ieee80211_tx | 1241 | * ieee80211_wake_queue), we would end up with ieee80211_tx |
1252 | * called with IEEE80211_LINK_STATE_PENDING. Prevent this by | 1242 | * called with the PENDING bit still set. Prevent this by |
1253 | * continuing transmitting here when that situation is | 1243 | * continuing transmitting here when that situation is |
1254 | * possible to have happened. */ | 1244 | * possible to have happened. |
1255 | if (!__ieee80211_queue_stopped(local, queue)) { | 1245 | */ |
1256 | clear_bit(IEEE80211_LINK_STATE_PENDING, | 1246 | if (!__netif_subqueue_stopped(local->mdev, queue)) { |
1257 | &local->state[queue]); | 1247 | clear_bit(queue, local->queues_pending); |
1258 | goto retry; | 1248 | goto retry; |
1259 | } | 1249 | } |
1260 | store->skb = skb; | 1250 | store->skb = skb; |
@@ -1509,7 +1499,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1509 | } | 1499 | } |
1510 | 1500 | ||
1511 | /* receiver and we are QoS enabled, use a QoS type frame */ | 1501 | /* receiver and we are QoS enabled, use a QoS type frame */ |
1512 | if (sta_flags & WLAN_STA_WME && local->hw.queues >= 4) { | 1502 | if (sta_flags & WLAN_STA_WME && |
1503 | ieee80211_num_regular_queues(&local->hw) >= 4) { | ||
1513 | fc |= IEEE80211_STYPE_QOS_DATA; | 1504 | fc |= IEEE80211_STYPE_QOS_DATA; |
1514 | hdrlen += 2; | 1505 | hdrlen += 2; |
1515 | } | 1506 | } |
@@ -1661,41 +1652,51 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1661 | return ret; | 1652 | return ret; |
1662 | } | 1653 | } |
1663 | 1654 | ||
1664 | /* helper functions for pending packets for when queues are stopped */ | ||
1665 | 1655 | ||
1656 | /* | ||
1657 | * ieee80211_clear_tx_pending may not be called in a context where | ||
1658 | * it is possible that it packets could come in again. | ||
1659 | */ | ||
1666 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) | 1660 | void ieee80211_clear_tx_pending(struct ieee80211_local *local) |
1667 | { | 1661 | { |
1668 | int i, j; | 1662 | int i, j; |
1669 | struct ieee80211_tx_stored_packet *store; | 1663 | struct ieee80211_tx_stored_packet *store; |
1670 | 1664 | ||
1671 | for (i = 0; i < local->hw.queues; i++) { | 1665 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { |
1672 | if (!__ieee80211_queue_pending(local, i)) | 1666 | if (!test_bit(i, local->queues_pending)) |
1673 | continue; | 1667 | continue; |
1674 | store = &local->pending_packet[i]; | 1668 | store = &local->pending_packet[i]; |
1675 | kfree_skb(store->skb); | 1669 | kfree_skb(store->skb); |
1676 | for (j = 0; j < store->num_extra_frag; j++) | 1670 | for (j = 0; j < store->num_extra_frag; j++) |
1677 | kfree_skb(store->extra_frag[j]); | 1671 | kfree_skb(store->extra_frag[j]); |
1678 | kfree(store->extra_frag); | 1672 | kfree(store->extra_frag); |
1679 | clear_bit(IEEE80211_LINK_STATE_PENDING, &local->state[i]); | 1673 | clear_bit(i, local->queues_pending); |
1680 | } | 1674 | } |
1681 | } | 1675 | } |
1682 | 1676 | ||
1677 | /* | ||
1678 | * Transmit all pending packets. Called from tasklet, locks master device | ||
1679 | * TX lock so that no new packets can come in. | ||
1680 | */ | ||
1683 | void ieee80211_tx_pending(unsigned long data) | 1681 | void ieee80211_tx_pending(unsigned long data) |
1684 | { | 1682 | { |
1685 | struct ieee80211_local *local = (struct ieee80211_local *)data; | 1683 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
1686 | struct net_device *dev = local->mdev; | 1684 | struct net_device *dev = local->mdev; |
1687 | struct ieee80211_tx_stored_packet *store; | 1685 | struct ieee80211_tx_stored_packet *store; |
1688 | struct ieee80211_tx_data tx; | 1686 | struct ieee80211_tx_data tx; |
1689 | int i, ret, reschedule = 0; | 1687 | int i, ret; |
1690 | 1688 | ||
1691 | netif_tx_lock_bh(dev); | 1689 | netif_tx_lock_bh(dev); |
1692 | for (i = 0; i < local->hw.queues; i++) { | 1690 | for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { |
1693 | if (__ieee80211_queue_stopped(local, i)) | 1691 | /* Check that this queue is ok */ |
1692 | if (__netif_subqueue_stopped(local->mdev, i)) | ||
1694 | continue; | 1693 | continue; |
1695 | if (!__ieee80211_queue_pending(local, i)) { | 1694 | |
1696 | reschedule = 1; | 1695 | if (!test_bit(i, local->queues_pending)) { |
1696 | ieee80211_wake_queue(&local->hw, i); | ||
1697 | continue; | 1697 | continue; |
1698 | } | 1698 | } |
1699 | |||
1699 | store = &local->pending_packet[i]; | 1700 | store = &local->pending_packet[i]; |
1700 | tx.extra_frag = store->extra_frag; | 1701 | tx.extra_frag = store->extra_frag; |
1701 | tx.num_extra_frag = store->num_extra_frag; | 1702 | tx.num_extra_frag = store->num_extra_frag; |
@@ -1708,19 +1709,11 @@ void ieee80211_tx_pending(unsigned long data) | |||
1708 | if (ret == IEEE80211_TX_FRAG_AGAIN) | 1709 | if (ret == IEEE80211_TX_FRAG_AGAIN) |
1709 | store->skb = NULL; | 1710 | store->skb = NULL; |
1710 | } else { | 1711 | } else { |
1711 | clear_bit(IEEE80211_LINK_STATE_PENDING, | 1712 | clear_bit(i, local->queues_pending); |
1712 | &local->state[i]); | 1713 | ieee80211_wake_queue(&local->hw, i); |
1713 | reschedule = 1; | ||
1714 | } | 1714 | } |
1715 | } | 1715 | } |
1716 | netif_tx_unlock_bh(dev); | 1716 | netif_tx_unlock_bh(dev); |
1717 | if (reschedule) { | ||
1718 | if (!ieee80211_qdisc_installed(dev)) { | ||
1719 | if (!__ieee80211_queue_stopped(local, 0)) | ||
1720 | netif_wake_queue(dev); | ||
1721 | } else | ||
1722 | netif_schedule(dev); | ||
1723 | } | ||
1724 | } | 1717 | } |
1725 | 1718 | ||
1726 | /* functions for drivers to get certain frames */ | 1719 | /* functions for drivers to get certain frames */ |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d9109dee461f..4f7180b287da 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -331,17 +331,15 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) | |||
331 | { | 331 | { |
332 | struct ieee80211_local *local = hw_to_local(hw); | 332 | struct ieee80211_local *local = hw_to_local(hw); |
333 | 333 | ||
334 | if (test_and_clear_bit(IEEE80211_LINK_STATE_XOFF, | 334 | if (test_bit(queue, local->queues_pending)) { |
335 | &local->state[queue])) { | 335 | tasklet_schedule(&local->tx_pending_tasklet); |
336 | if (test_bit(IEEE80211_LINK_STATE_PENDING, | 336 | } else { |
337 | &local->state[queue])) | 337 | if (ieee80211_is_multiqueue(local)) { |
338 | tasklet_schedule(&local->tx_pending_tasklet); | 338 | netif_wake_subqueue(local->mdev, queue); |
339 | else | 339 | } else { |
340 | if (!ieee80211_qdisc_installed(local->mdev)) { | 340 | WARN_ON(queue != 0); |
341 | if (queue == 0) | 341 | netif_wake_queue(local->mdev); |
342 | netif_wake_queue(local->mdev); | 342 | } |
343 | } else | ||
344 | __netif_schedule(local->mdev); | ||
345 | } | 343 | } |
346 | } | 344 | } |
347 | EXPORT_SYMBOL(ieee80211_wake_queue); | 345 | EXPORT_SYMBOL(ieee80211_wake_queue); |
@@ -350,9 +348,12 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) | |||
350 | { | 348 | { |
351 | struct ieee80211_local *local = hw_to_local(hw); | 349 | struct ieee80211_local *local = hw_to_local(hw); |
352 | 350 | ||
353 | if (!ieee80211_qdisc_installed(local->mdev) && queue == 0) | 351 | if (ieee80211_is_multiqueue(local)) { |
352 | netif_stop_subqueue(local->mdev, queue); | ||
353 | } else { | ||
354 | WARN_ON(queue != 0); | ||
354 | netif_stop_queue(local->mdev); | 355 | netif_stop_queue(local->mdev); |
355 | set_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]); | 356 | } |
356 | } | 357 | } |
357 | EXPORT_SYMBOL(ieee80211_stop_queue); | 358 | EXPORT_SYMBOL(ieee80211_stop_queue); |
358 | 359 | ||
@@ -360,7 +361,7 @@ void ieee80211_stop_queues(struct ieee80211_hw *hw) | |||
360 | { | 361 | { |
361 | int i; | 362 | int i; |
362 | 363 | ||
363 | for (i = 0; i < hw->queues + hw->ampdu_queues; i++) | 364 | for (i = 0; i < ieee80211_num_queues(hw); i++) |
364 | ieee80211_stop_queue(hw, i); | 365 | ieee80211_stop_queue(hw, i); |
365 | } | 366 | } |
366 | EXPORT_SYMBOL(ieee80211_stop_queues); | 367 | EXPORT_SYMBOL(ieee80211_stop_queues); |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 477690f4dca7..14a9ff10a1e9 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -158,7 +158,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
158 | u8 tid; | 158 | u8 tid; |
159 | 159 | ||
160 | if (info->flags & IEEE80211_TX_CTL_REQUEUE) { | 160 | if (info->flags & IEEE80211_TX_CTL_REQUEUE) { |
161 | queue = info->queue; | 161 | queue = skb_get_queue_mapping(skb); |
162 | rcu_read_lock(); | 162 | rcu_read_lock(); |
163 | sta = sta_info_get(local, hdr->addr1); | 163 | sta = sta_info_get(local, hdr->addr1); |
164 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; | 164 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; |
@@ -219,7 +219,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
219 | err = NET_XMIT_DROP; | 219 | err = NET_XMIT_DROP; |
220 | } else { | 220 | } else { |
221 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; | 221 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; |
222 | info->queue = (unsigned int) queue; | 222 | skb_set_queue_mapping(skb, queue); |
223 | qdisc = q->queues[queue]; | 223 | qdisc = q->queues[queue]; |
224 | err = qdisc->enqueue(skb, qdisc); | 224 | err = qdisc->enqueue(skb, qdisc); |
225 | if (err == NET_XMIT_SUCCESS) { | 225 | if (err == NET_XMIT_SUCCESS) { |
@@ -240,12 +240,11 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
240 | static int wme_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd) | 240 | static int wme_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd) |
241 | { | 241 | { |
242 | struct ieee80211_sched_data *q = qdisc_priv(qd); | 242 | struct ieee80211_sched_data *q = qdisc_priv(qd); |
243 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
244 | struct Qdisc *qdisc; | 243 | struct Qdisc *qdisc; |
245 | int err; | 244 | int err; |
246 | 245 | ||
247 | /* we recorded which queue to use earlier! */ | 246 | /* we recorded which queue to use earlier! */ |
248 | qdisc = q->queues[info->queue]; | 247 | qdisc = q->queues[skb_get_queue_mapping(skb)]; |
249 | 248 | ||
250 | if ((err = qdisc->ops->requeue(skb, qdisc)) == 0) { | 249 | if ((err = qdisc->ops->requeue(skb, qdisc)) == 0) { |
251 | qd->q.qlen++; | 250 | qd->q.qlen++; |
@@ -269,11 +268,8 @@ static struct sk_buff *wme_qdiscop_dequeue(struct Qdisc* qd) | |||
269 | /* check all the h/w queues in numeric/priority order */ | 268 | /* check all the h/w queues in numeric/priority order */ |
270 | for (queue = 0; queue < QD_NUM(hw); queue++) { | 269 | for (queue = 0; queue < QD_NUM(hw); queue++) { |
271 | /* see if there is room in this hardware queue */ | 270 | /* see if there is room in this hardware queue */ |
272 | if ((test_bit(IEEE80211_LINK_STATE_XOFF, | 271 | if (__netif_subqueue_stopped(local->mdev, queue) || |
273 | &local->state[queue])) || | 272 | !test_bit(queue, q->qdisc_pool)) |
274 | (test_bit(IEEE80211_LINK_STATE_PENDING, | ||
275 | &local->state[queue])) || | ||
276 | (!test_bit(queue, q->qdisc_pool))) | ||
277 | continue; | 273 | continue; |
278 | 274 | ||
279 | /* there is space - try and get a frame */ | 275 | /* there is space - try and get a frame */ |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index fcc6b05508cc..bbdb53344817 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -31,7 +31,7 @@ static inline int WLAN_FC_IS_QOS_DATA(u16 fc) | |||
31 | return (fc & 0x8C) == 0x88; | 31 | return (fc & 0x8C) == 0x88; |
32 | } | 32 | } |
33 | 33 | ||
34 | #ifdef CONFIG_NET_SCHED | 34 | #ifdef CONFIG_MAC80211_QOS |
35 | void ieee80211_install_qdisc(struct net_device *dev); | 35 | void ieee80211_install_qdisc(struct net_device *dev); |
36 | int ieee80211_qdisc_installed(struct net_device *dev); | 36 | int ieee80211_qdisc_installed(struct net_device *dev); |
37 | int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, | 37 | int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, |