diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/agg-tx.c | 8 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 24 | ||||
-rw-r--r-- | net/mac80211/iface.c | 12 | ||||
-rw-r--r-- | net/mac80211/main.c | 7 | ||||
-rw-r--r-- | net/mac80211/rx.c | 2 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 14 | ||||
-rw-r--r-- | net/mac80211/tx.c | 136 | ||||
-rw-r--r-- | net/mac80211/util.c | 23 |
8 files changed, 162 insertions, 64 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 42fa81031dfa..5650c46bf91a 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -194,17 +194,21 @@ static void | |||
194 | ieee80211_agg_stop_txq(struct sta_info *sta, int tid) | 194 | ieee80211_agg_stop_txq(struct sta_info *sta, int tid) |
195 | { | 195 | { |
196 | struct ieee80211_txq *txq = sta->sta.txq[tid]; | 196 | struct ieee80211_txq *txq = sta->sta.txq[tid]; |
197 | struct ieee80211_sub_if_data *sdata; | ||
198 | struct fq *fq; | ||
197 | struct txq_info *txqi; | 199 | struct txq_info *txqi; |
198 | 200 | ||
199 | if (!txq) | 201 | if (!txq) |
200 | return; | 202 | return; |
201 | 203 | ||
202 | txqi = to_txq_info(txq); | 204 | txqi = to_txq_info(txq); |
205 | sdata = vif_to_sdata(txq->vif); | ||
206 | fq = &sdata->local->fq; | ||
203 | 207 | ||
204 | /* Lock here to protect against further seqno updates on dequeue */ | 208 | /* Lock here to protect against further seqno updates on dequeue */ |
205 | spin_lock_bh(&txqi->queue.lock); | 209 | spin_lock_bh(&fq->lock); |
206 | set_bit(IEEE80211_TXQ_STOP, &txqi->flags); | 210 | set_bit(IEEE80211_TXQ_STOP, &txqi->flags); |
207 | spin_unlock_bh(&txqi->queue.lock); | 211 | spin_unlock_bh(&fq->lock); |
208 | } | 212 | } |
209 | 213 | ||
210 | static void | 214 | static void |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 634603320374..6f8375f1df88 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <net/ieee80211_radiotap.h> | 30 | #include <net/ieee80211_radiotap.h> |
31 | #include <net/cfg80211.h> | 31 | #include <net/cfg80211.h> |
32 | #include <net/mac80211.h> | 32 | #include <net/mac80211.h> |
33 | #include <net/fq.h> | ||
33 | #include "key.h" | 34 | #include "key.h" |
34 | #include "sta_info.h" | 35 | #include "sta_info.h" |
35 | #include "debug.h" | 36 | #include "debug.h" |
@@ -805,10 +806,17 @@ enum txq_info_flags { | |||
805 | IEEE80211_TXQ_NO_AMSDU, | 806 | IEEE80211_TXQ_NO_AMSDU, |
806 | }; | 807 | }; |
807 | 808 | ||
809 | /** | ||
810 | * struct txq_info - per tid queue | ||
811 | * | ||
812 | * @tin: contains packets split into multiple flows | ||
813 | * @def_flow: used as a fallback flow when a packet destined to @tin hashes to | ||
814 | * a fq_flow which is already owned by a different tin | ||
815 | */ | ||
808 | struct txq_info { | 816 | struct txq_info { |
809 | struct sk_buff_head queue; | 817 | struct fq_tin tin; |
818 | struct fq_flow def_flow; | ||
810 | unsigned long flags; | 819 | unsigned long flags; |
811 | unsigned long byte_cnt; | ||
812 | 820 | ||
813 | /* keep last! */ | 821 | /* keep last! */ |
814 | struct ieee80211_txq txq; | 822 | struct ieee80211_txq txq; |
@@ -1099,6 +1107,8 @@ struct ieee80211_local { | |||
1099 | * it first anyway so they become a no-op */ | 1107 | * it first anyway so they become a no-op */ |
1100 | struct ieee80211_hw hw; | 1108 | struct ieee80211_hw hw; |
1101 | 1109 | ||
1110 | struct fq fq; | ||
1111 | |||
1102 | const struct ieee80211_ops *ops; | 1112 | const struct ieee80211_ops *ops; |
1103 | 1113 | ||
1104 | /* | 1114 | /* |
@@ -1931,9 +1941,13 @@ static inline bool ieee80211_can_run_worker(struct ieee80211_local *local) | |||
1931 | return true; | 1941 | return true; |
1932 | } | 1942 | } |
1933 | 1943 | ||
1934 | void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata, | 1944 | int ieee80211_txq_setup_flows(struct ieee80211_local *local); |
1935 | struct sta_info *sta, | 1945 | void ieee80211_txq_teardown_flows(struct ieee80211_local *local); |
1936 | struct txq_info *txq, int tid); | 1946 | void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata, |
1947 | struct sta_info *sta, | ||
1948 | struct txq_info *txq, int tid); | ||
1949 | void ieee80211_txq_purge(struct ieee80211_local *local, | ||
1950 | struct txq_info *txqi); | ||
1937 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1951 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1938 | u16 transaction, u16 auth_alg, u16 status, | 1952 | u16 transaction, u16 auth_alg, u16 status, |
1939 | const u8 *extra, size_t extra_len, const u8 *bssid, | 1953 | const u8 *extra, size_t extra_len, const u8 *bssid, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 609c5174d798..b123a9e325b3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -779,6 +779,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
779 | bool going_down) | 779 | bool going_down) |
780 | { | 780 | { |
781 | struct ieee80211_local *local = sdata->local; | 781 | struct ieee80211_local *local = sdata->local; |
782 | struct fq *fq = &local->fq; | ||
782 | unsigned long flags; | 783 | unsigned long flags; |
783 | struct sk_buff *skb, *tmp; | 784 | struct sk_buff *skb, *tmp; |
784 | u32 hw_reconf_flags = 0; | 785 | u32 hw_reconf_flags = 0; |
@@ -976,13 +977,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
976 | 977 | ||
977 | if (sdata->vif.txq) { | 978 | if (sdata->vif.txq) { |
978 | struct txq_info *txqi = to_txq_info(sdata->vif.txq); | 979 | struct txq_info *txqi = to_txq_info(sdata->vif.txq); |
979 | int n = skb_queue_len(&txqi->queue); | ||
980 | 980 | ||
981 | spin_lock_bh(&txqi->queue.lock); | 981 | spin_lock_bh(&fq->lock); |
982 | ieee80211_purge_tx_queue(&local->hw, &txqi->queue); | 982 | ieee80211_txq_purge(local, txqi); |
983 | atomic_sub(n, &sdata->num_tx_queued); | 983 | spin_unlock_bh(&fq->lock); |
984 | txqi->byte_cnt = 0; | ||
985 | spin_unlock_bh(&txqi->queue.lock); | ||
986 | } | 984 | } |
987 | 985 | ||
988 | if (local->open_count == 0) | 986 | if (local->open_count == 0) |
@@ -1792,7 +1790,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1792 | 1790 | ||
1793 | if (txq_size) { | 1791 | if (txq_size) { |
1794 | txqi = netdev_priv(ndev) + size; | 1792 | txqi = netdev_priv(ndev) + size; |
1795 | ieee80211_init_tx_queue(sdata, NULL, txqi, 0); | 1793 | ieee80211_txq_init(sdata, NULL, txqi, 0); |
1796 | } | 1794 | } |
1797 | 1795 | ||
1798 | sdata->dev = ndev; | 1796 | sdata->dev = ndev; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 160ac6b8b9a1..d00ea9b13f49 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1086,6 +1086,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1086 | 1086 | ||
1087 | rtnl_unlock(); | 1087 | rtnl_unlock(); |
1088 | 1088 | ||
1089 | result = ieee80211_txq_setup_flows(local); | ||
1090 | if (result) | ||
1091 | goto fail_flows; | ||
1092 | |||
1089 | #ifdef CONFIG_INET | 1093 | #ifdef CONFIG_INET |
1090 | local->ifa_notifier.notifier_call = ieee80211_ifa_changed; | 1094 | local->ifa_notifier.notifier_call = ieee80211_ifa_changed; |
1091 | result = register_inetaddr_notifier(&local->ifa_notifier); | 1095 | result = register_inetaddr_notifier(&local->ifa_notifier); |
@@ -1111,6 +1115,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1111 | #if defined(CONFIG_INET) || defined(CONFIG_IPV6) | 1115 | #if defined(CONFIG_INET) || defined(CONFIG_IPV6) |
1112 | fail_ifa: | 1116 | fail_ifa: |
1113 | #endif | 1117 | #endif |
1118 | ieee80211_txq_teardown_flows(local); | ||
1119 | fail_flows: | ||
1114 | rtnl_lock(); | 1120 | rtnl_lock(); |
1115 | rate_control_deinitialize(local); | 1121 | rate_control_deinitialize(local); |
1116 | ieee80211_remove_interfaces(local); | 1122 | ieee80211_remove_interfaces(local); |
@@ -1169,6 +1175,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1169 | skb_queue_purge(&local->skb_queue); | 1175 | skb_queue_purge(&local->skb_queue); |
1170 | skb_queue_purge(&local->skb_queue_unreliable); | 1176 | skb_queue_purge(&local->skb_queue_unreliable); |
1171 | skb_queue_purge(&local->skb_queue_tdls_chsw); | 1177 | skb_queue_purge(&local->skb_queue_tdls_chsw); |
1178 | ieee80211_txq_teardown_flows(local); | ||
1172 | 1179 | ||
1173 | destroy_workqueue(local->workqueue); | 1180 | destroy_workqueue(local->workqueue); |
1174 | wiphy_unregister(local->hw.wiphy); | 1181 | wiphy_unregister(local->hw.wiphy); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5e65e838992a..9a1eb70cb120 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1268,7 +1268,7 @@ static void sta_ps_start(struct sta_info *sta) | |||
1268 | for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) { | 1268 | for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) { |
1269 | struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]); | 1269 | struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]); |
1270 | 1270 | ||
1271 | if (!skb_queue_len(&txqi->queue)) | 1271 | if (!txqi->tin.backlog_packets) |
1272 | set_bit(tid, &sta->txq_buffered_tids); | 1272 | set_bit(tid, &sta->txq_buffered_tids); |
1273 | else | 1273 | else |
1274 | clear_bit(tid, &sta->txq_buffered_tids); | 1274 | clear_bit(tid, &sta->txq_buffered_tids); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 177cc6cd6416..76b737dcc36f 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -90,6 +90,7 @@ static void __cleanup_single_sta(struct sta_info *sta) | |||
90 | struct tid_ampdu_tx *tid_tx; | 90 | struct tid_ampdu_tx *tid_tx; |
91 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 91 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
92 | struct ieee80211_local *local = sdata->local; | 92 | struct ieee80211_local *local = sdata->local; |
93 | struct fq *fq = &local->fq; | ||
93 | struct ps_data *ps; | 94 | struct ps_data *ps; |
94 | 95 | ||
95 | if (test_sta_flag(sta, WLAN_STA_PS_STA) || | 96 | if (test_sta_flag(sta, WLAN_STA_PS_STA) || |
@@ -113,11 +114,10 @@ static void __cleanup_single_sta(struct sta_info *sta) | |||
113 | if (sta->sta.txq[0]) { | 114 | if (sta->sta.txq[0]) { |
114 | for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { | 115 | for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { |
115 | struct txq_info *txqi = to_txq_info(sta->sta.txq[i]); | 116 | struct txq_info *txqi = to_txq_info(sta->sta.txq[i]); |
116 | int n = skb_queue_len(&txqi->queue); | ||
117 | 117 | ||
118 | ieee80211_purge_tx_queue(&local->hw, &txqi->queue); | 118 | spin_lock_bh(&fq->lock); |
119 | atomic_sub(n, &sdata->num_tx_queued); | 119 | ieee80211_txq_purge(local, txqi); |
120 | txqi->byte_cnt = 0; | 120 | spin_unlock_bh(&fq->lock); |
121 | } | 121 | } |
122 | } | 122 | } |
123 | 123 | ||
@@ -368,7 +368,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
368 | for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { | 368 | for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { |
369 | struct txq_info *txq = txq_data + i * size; | 369 | struct txq_info *txq = txq_data + i * size; |
370 | 370 | ||
371 | ieee80211_init_tx_queue(sdata, sta, txq, i); | 371 | ieee80211_txq_init(sdata, sta, txq, i); |
372 | } | 372 | } |
373 | } | 373 | } |
374 | 374 | ||
@@ -1211,7 +1211,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1211 | for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { | 1211 | for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { |
1212 | struct txq_info *txqi = to_txq_info(sta->sta.txq[i]); | 1212 | struct txq_info *txqi = to_txq_info(sta->sta.txq[i]); |
1213 | 1213 | ||
1214 | if (!skb_queue_len(&txqi->queue)) | 1214 | if (!txqi->tin.backlog_packets) |
1215 | continue; | 1215 | continue; |
1216 | 1216 | ||
1217 | drv_wake_tx_queue(local, txqi); | 1217 | drv_wake_tx_queue(local, txqi); |
@@ -1648,7 +1648,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
1648 | for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) { | 1648 | for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) { |
1649 | struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]); | 1649 | struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]); |
1650 | 1650 | ||
1651 | if (!(tids & BIT(tid)) || skb_queue_len(&txqi->queue)) | 1651 | if (!(tids & BIT(tid)) || txqi->tin.backlog_packets) |
1652 | continue; | 1652 | continue; |
1653 | 1653 | ||
1654 | sta_info_recalc_tim(sta); | 1654 | sta_info_recalc_tim(sta); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 3e77da195ce8..1d8343fca6d4 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
26 | #include <net/mac80211.h> | 26 | #include <net/mac80211.h> |
27 | #include <asm/unaligned.h> | 27 | #include <asm/unaligned.h> |
28 | #include <net/fq_impl.h> | ||
28 | 29 | ||
29 | #include "ieee80211_i.h" | 30 | #include "ieee80211_i.h" |
30 | #include "driver-ops.h" | 31 | #include "driver-ops.h" |
@@ -1266,46 +1267,121 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local, | |||
1266 | return to_txq_info(txq); | 1267 | return to_txq_info(txq); |
1267 | } | 1268 | } |
1268 | 1269 | ||
1270 | static struct sk_buff *fq_tin_dequeue_func(struct fq *fq, | ||
1271 | struct fq_tin *tin, | ||
1272 | struct fq_flow *flow) | ||
1273 | { | ||
1274 | return fq_flow_dequeue(fq, flow); | ||
1275 | } | ||
1276 | |||
1277 | static void fq_skb_free_func(struct fq *fq, | ||
1278 | struct fq_tin *tin, | ||
1279 | struct fq_flow *flow, | ||
1280 | struct sk_buff *skb) | ||
1281 | { | ||
1282 | struct ieee80211_local *local; | ||
1283 | |||
1284 | local = container_of(fq, struct ieee80211_local, fq); | ||
1285 | ieee80211_free_txskb(&local->hw, skb); | ||
1286 | } | ||
1287 | |||
1288 | static struct fq_flow *fq_flow_get_default_func(struct fq *fq, | ||
1289 | struct fq_tin *tin, | ||
1290 | int idx, | ||
1291 | struct sk_buff *skb) | ||
1292 | { | ||
1293 | struct txq_info *txqi; | ||
1294 | |||
1295 | txqi = container_of(tin, struct txq_info, tin); | ||
1296 | return &txqi->def_flow; | ||
1297 | } | ||
1298 | |||
1269 | static void ieee80211_txq_enqueue(struct ieee80211_local *local, | 1299 | static void ieee80211_txq_enqueue(struct ieee80211_local *local, |
1270 | struct txq_info *txqi, | 1300 | struct txq_info *txqi, |
1271 | struct sk_buff *skb) | 1301 | struct sk_buff *skb) |
1272 | { | 1302 | { |
1273 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(txqi->txq.vif); | 1303 | struct fq *fq = &local->fq; |
1304 | struct fq_tin *tin = &txqi->tin; | ||
1274 | 1305 | ||
1275 | lockdep_assert_held(&txqi->queue.lock); | 1306 | fq_tin_enqueue(fq, tin, skb, |
1307 | fq_skb_free_func, | ||
1308 | fq_flow_get_default_func); | ||
1309 | } | ||
1276 | 1310 | ||
1277 | if (atomic_read(&sdata->num_tx_queued) >= TOTAL_MAX_TX_BUFFER || | 1311 | void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata, |
1278 | txqi->queue.qlen >= STA_MAX_TX_BUFFER) { | 1312 | struct sta_info *sta, |
1279 | ieee80211_free_txskb(&local->hw, skb); | 1313 | struct txq_info *txqi, int tid) |
1280 | return; | 1314 | { |
1315 | fq_tin_init(&txqi->tin); | ||
1316 | fq_flow_init(&txqi->def_flow); | ||
1317 | |||
1318 | txqi->txq.vif = &sdata->vif; | ||
1319 | |||
1320 | if (sta) { | ||
1321 | txqi->txq.sta = &sta->sta; | ||
1322 | sta->sta.txq[tid] = &txqi->txq; | ||
1323 | txqi->txq.tid = tid; | ||
1324 | txqi->txq.ac = ieee802_1d_to_ac[tid & 7]; | ||
1325 | } else { | ||
1326 | sdata->vif.txq = &txqi->txq; | ||
1327 | txqi->txq.tid = 0; | ||
1328 | txqi->txq.ac = IEEE80211_AC_BE; | ||
1281 | } | 1329 | } |
1330 | } | ||
1282 | 1331 | ||
1283 | atomic_inc(&sdata->num_tx_queued); | 1332 | void ieee80211_txq_purge(struct ieee80211_local *local, |
1284 | txqi->byte_cnt += skb->len; | 1333 | struct txq_info *txqi) |
1285 | __skb_queue_tail(&txqi->queue, skb); | 1334 | { |
1335 | struct fq *fq = &local->fq; | ||
1336 | struct fq_tin *tin = &txqi->tin; | ||
1337 | |||
1338 | fq_tin_reset(fq, tin, fq_skb_free_func); | ||
1339 | } | ||
1340 | |||
1341 | int ieee80211_txq_setup_flows(struct ieee80211_local *local) | ||
1342 | { | ||
1343 | struct fq *fq = &local->fq; | ||
1344 | int ret; | ||
1345 | |||
1346 | if (!local->ops->wake_tx_queue) | ||
1347 | return 0; | ||
1348 | |||
1349 | ret = fq_init(fq, 4096); | ||
1350 | if (ret) | ||
1351 | return ret; | ||
1352 | |||
1353 | return 0; | ||
1354 | } | ||
1355 | |||
1356 | void ieee80211_txq_teardown_flows(struct ieee80211_local *local) | ||
1357 | { | ||
1358 | struct fq *fq = &local->fq; | ||
1359 | |||
1360 | if (!local->ops->wake_tx_queue) | ||
1361 | return; | ||
1362 | |||
1363 | fq_reset(fq, fq_skb_free_func); | ||
1286 | } | 1364 | } |
1287 | 1365 | ||
1288 | struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, | 1366 | struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, |
1289 | struct ieee80211_txq *txq) | 1367 | struct ieee80211_txq *txq) |
1290 | { | 1368 | { |
1291 | struct ieee80211_local *local = hw_to_local(hw); | 1369 | struct ieee80211_local *local = hw_to_local(hw); |
1292 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif); | ||
1293 | struct txq_info *txqi = container_of(txq, struct txq_info, txq); | 1370 | struct txq_info *txqi = container_of(txq, struct txq_info, txq); |
1294 | struct ieee80211_hdr *hdr; | 1371 | struct ieee80211_hdr *hdr; |
1295 | struct sk_buff *skb = NULL; | 1372 | struct sk_buff *skb = NULL; |
1373 | struct fq *fq = &local->fq; | ||
1374 | struct fq_tin *tin = &txqi->tin; | ||
1296 | 1375 | ||
1297 | spin_lock_bh(&txqi->queue.lock); | 1376 | spin_lock_bh(&fq->lock); |
1298 | 1377 | ||
1299 | if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags)) | 1378 | if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags)) |
1300 | goto out; | 1379 | goto out; |
1301 | 1380 | ||
1302 | skb = __skb_dequeue(&txqi->queue); | 1381 | skb = fq_tin_dequeue(fq, tin, fq_tin_dequeue_func); |
1303 | if (!skb) | 1382 | if (!skb) |
1304 | goto out; | 1383 | goto out; |
1305 | 1384 | ||
1306 | atomic_dec(&sdata->num_tx_queued); | ||
1307 | txqi->byte_cnt -= skb->len; | ||
1308 | |||
1309 | hdr = (struct ieee80211_hdr *)skb->data; | 1385 | hdr = (struct ieee80211_hdr *)skb->data; |
1310 | if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) { | 1386 | if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) { |
1311 | struct sta_info *sta = container_of(txq->sta, struct sta_info, | 1387 | struct sta_info *sta = container_of(txq->sta, struct sta_info, |
@@ -1320,7 +1396,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, | |||
1320 | } | 1396 | } |
1321 | 1397 | ||
1322 | out: | 1398 | out: |
1323 | spin_unlock_bh(&txqi->queue.lock); | 1399 | spin_unlock_bh(&fq->lock); |
1324 | 1400 | ||
1325 | if (skb && skb_has_frag_list(skb) && | 1401 | if (skb && skb_has_frag_list(skb) && |
1326 | !ieee80211_hw_check(&local->hw, TX_FRAG_LIST)) | 1402 | !ieee80211_hw_check(&local->hw, TX_FRAG_LIST)) |
@@ -1337,6 +1413,7 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
1337 | bool txpending) | 1413 | bool txpending) |
1338 | { | 1414 | { |
1339 | struct ieee80211_tx_control control = {}; | 1415 | struct ieee80211_tx_control control = {}; |
1416 | struct fq *fq = &local->fq; | ||
1340 | struct sk_buff *skb, *tmp; | 1417 | struct sk_buff *skb, *tmp; |
1341 | struct txq_info *txqi; | 1418 | struct txq_info *txqi; |
1342 | unsigned long flags; | 1419 | unsigned long flags; |
@@ -1359,9 +1436,9 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
1359 | 1436 | ||
1360 | __skb_unlink(skb, skbs); | 1437 | __skb_unlink(skb, skbs); |
1361 | 1438 | ||
1362 | spin_lock_bh(&txqi->queue.lock); | 1439 | spin_lock_bh(&fq->lock); |
1363 | ieee80211_txq_enqueue(local, txqi, skb); | 1440 | ieee80211_txq_enqueue(local, txqi, skb); |
1364 | spin_unlock_bh(&txqi->queue.lock); | 1441 | spin_unlock_bh(&fq->lock); |
1365 | 1442 | ||
1366 | drv_wake_tx_queue(local, txqi); | 1443 | drv_wake_tx_queue(local, txqi); |
1367 | 1444 | ||
@@ -2893,6 +2970,9 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata, | |||
2893 | struct sk_buff *skb) | 2970 | struct sk_buff *skb) |
2894 | { | 2971 | { |
2895 | struct ieee80211_local *local = sdata->local; | 2972 | struct ieee80211_local *local = sdata->local; |
2973 | struct fq *fq = &local->fq; | ||
2974 | struct fq_tin *tin; | ||
2975 | struct fq_flow *flow; | ||
2896 | u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | 2976 | u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
2897 | struct ieee80211_txq *txq = sta->sta.txq[tid]; | 2977 | struct ieee80211_txq *txq = sta->sta.txq[tid]; |
2898 | struct txq_info *txqi; | 2978 | struct txq_info *txqi; |
@@ -2904,6 +2984,7 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata, | |||
2904 | __be16 len; | 2984 | __be16 len; |
2905 | void *data; | 2985 | void *data; |
2906 | bool ret = false; | 2986 | bool ret = false; |
2987 | unsigned int orig_len; | ||
2907 | int n = 1, nfrags; | 2988 | int n = 1, nfrags; |
2908 | 2989 | ||
2909 | if (!ieee80211_hw_check(&local->hw, TX_AMSDU)) | 2990 | if (!ieee80211_hw_check(&local->hw, TX_AMSDU)) |
@@ -2920,12 +3001,20 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata, | |||
2920 | max_amsdu_len = min_t(int, max_amsdu_len, | 3001 | max_amsdu_len = min_t(int, max_amsdu_len, |
2921 | sta->sta.max_rc_amsdu_len); | 3002 | sta->sta.max_rc_amsdu_len); |
2922 | 3003 | ||
2923 | spin_lock_bh(&txqi->queue.lock); | 3004 | spin_lock_bh(&fq->lock); |
2924 | 3005 | ||
2925 | head = skb_peek_tail(&txqi->queue); | 3006 | /* TODO: Ideally aggregation should be done on dequeue to remain |
3007 | * responsive to environment changes. | ||
3008 | */ | ||
3009 | |||
3010 | tin = &txqi->tin; | ||
3011 | flow = fq_flow_classify(fq, tin, skb, fq_flow_get_default_func); | ||
3012 | head = skb_peek_tail(&flow->queue); | ||
2926 | if (!head) | 3013 | if (!head) |
2927 | goto out; | 3014 | goto out; |
2928 | 3015 | ||
3016 | orig_len = head->len; | ||
3017 | |||
2929 | if (skb->len + head->len > max_amsdu_len) | 3018 | if (skb->len + head->len > max_amsdu_len) |
2930 | goto out; | 3019 | goto out; |
2931 | 3020 | ||
@@ -2964,8 +3053,13 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata, | |||
2964 | head->data_len += skb->len; | 3053 | head->data_len += skb->len; |
2965 | *frag_tail = skb; | 3054 | *frag_tail = skb; |
2966 | 3055 | ||
3056 | flow->backlog += head->len - orig_len; | ||
3057 | tin->backlog_bytes += head->len - orig_len; | ||
3058 | |||
3059 | fq_recalc_backlog(fq, tin, flow); | ||
3060 | |||
2967 | out: | 3061 | out: |
2968 | spin_unlock_bh(&txqi->queue.lock); | 3062 | spin_unlock_bh(&fq->lock); |
2969 | 3063 | ||
2970 | return ret; | 3064 | return ret; |
2971 | } | 3065 | } |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0db46442bdcf..42bf0b6685e8 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -3389,25 +3389,6 @@ u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo) | |||
3389 | return buf; | 3389 | return buf; |
3390 | } | 3390 | } |
3391 | 3391 | ||
3392 | void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata, | ||
3393 | struct sta_info *sta, | ||
3394 | struct txq_info *txqi, int tid) | ||
3395 | { | ||
3396 | skb_queue_head_init(&txqi->queue); | ||
3397 | txqi->txq.vif = &sdata->vif; | ||
3398 | |||
3399 | if (sta) { | ||
3400 | txqi->txq.sta = &sta->sta; | ||
3401 | sta->sta.txq[tid] = &txqi->txq; | ||
3402 | txqi->txq.tid = tid; | ||
3403 | txqi->txq.ac = ieee802_1d_to_ac[tid & 7]; | ||
3404 | } else { | ||
3405 | sdata->vif.txq = &txqi->txq; | ||
3406 | txqi->txq.tid = 0; | ||
3407 | txqi->txq.ac = IEEE80211_AC_BE; | ||
3408 | } | ||
3409 | } | ||
3410 | |||
3411 | void ieee80211_txq_get_depth(struct ieee80211_txq *txq, | 3392 | void ieee80211_txq_get_depth(struct ieee80211_txq *txq, |
3412 | unsigned long *frame_cnt, | 3393 | unsigned long *frame_cnt, |
3413 | unsigned long *byte_cnt) | 3394 | unsigned long *byte_cnt) |
@@ -3415,9 +3396,9 @@ void ieee80211_txq_get_depth(struct ieee80211_txq *txq, | |||
3415 | struct txq_info *txqi = to_txq_info(txq); | 3396 | struct txq_info *txqi = to_txq_info(txq); |
3416 | 3397 | ||
3417 | if (frame_cnt) | 3398 | if (frame_cnt) |
3418 | *frame_cnt = txqi->queue.qlen; | 3399 | *frame_cnt = txqi->tin.backlog_packets; |
3419 | 3400 | ||
3420 | if (byte_cnt) | 3401 | if (byte_cnt) |
3421 | *byte_cnt = txqi->byte_cnt; | 3402 | *byte_cnt = txqi->tin.backlog_bytes; |
3422 | } | 3403 | } |
3423 | EXPORT_SYMBOL(ieee80211_txq_get_depth); | 3404 | EXPORT_SYMBOL(ieee80211_txq_get_depth); |