aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2016-05-19 04:37:48 -0400
committerJohannes Berg <johannes.berg@intel.com>2016-06-09 05:31:27 -0400
commit80a83cfc434b1e3afe38974570b460db4898bec6 (patch)
treef2774b8d416c3341ec57312fe39c6633d380be70 /net/mac80211
parent0662799023de4be686263b0a4f4b7910999172b9 (diff)
mac80211: skip netdev queue control with software queuing
Qdiscs are designed with no regard to 802.11 aggregation requirements and hand out packet-by-packet with no guarantee they are destined to the same tid. This does more bad than good no matter how fairly a given qdisc may behave on an ethernet interface. Software queuing used per-AC netdev subqueue congestion control whenever a global AC limit was hit. This meant in practice a single station or tid queue could starve others rather easily. This could resonate with qdiscs in a bad way or could just end up with poor aggregation performance. Increasing the AC limit would increase induced latency which is also bad. Disabling qdiscs by default and performing taildrop instead of netdev subqueue congestion control on the other hand makes it possible for tid queues to fill up "in the meantime" while preventing stations starving each other. This increases aggregation opportunities and should allow software queuing based drivers achieve better performance by utilizing airtime more efficiently with big aggregates. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c18
-rw-r--r--net/mac80211/main.c3
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/tx.c75
-rw-r--r--net/mac80211/util.c11
6 files changed, 66 insertions, 45 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9438c9406687..634603320374 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -856,7 +856,7 @@ struct ieee80211_sub_if_data {
856 bool control_port_no_encrypt; 856 bool control_port_no_encrypt;
857 int encrypt_headroom; 857 int encrypt_headroom;
858 858
859 atomic_t txqs_len[IEEE80211_NUM_ACS]; 859 atomic_t num_tx_queued;
860 struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; 860 struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
861 struct mac80211_qos_map __rcu *qos_map; 861 struct mac80211_qos_map __rcu *qos_map;
862 862
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index c59af3eb9fa4..609c5174d798 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -976,13 +976,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
976 976
977 if (sdata->vif.txq) { 977 if (sdata->vif.txq) {
978 struct txq_info *txqi = to_txq_info(sdata->vif.txq); 978 struct txq_info *txqi = to_txq_info(sdata->vif.txq);
979 int n = skb_queue_len(&txqi->queue);
979 980
980 spin_lock_bh(&txqi->queue.lock); 981 spin_lock_bh(&txqi->queue.lock);
981 ieee80211_purge_tx_queue(&local->hw, &txqi->queue); 982 ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
983 atomic_sub(n, &sdata->num_tx_queued);
982 txqi->byte_cnt = 0; 984 txqi->byte_cnt = 0;
983 spin_unlock_bh(&txqi->queue.lock); 985 spin_unlock_bh(&txqi->queue.lock);
984
985 atomic_set(&sdata->txqs_len[txqi->txq.ac], 0);
986 } 986 }
987 987
988 if (local->open_count == 0) 988 if (local->open_count == 0)
@@ -1198,6 +1198,12 @@ static void ieee80211_if_setup(struct net_device *dev)
1198 dev->destructor = ieee80211_if_free; 1198 dev->destructor = ieee80211_if_free;
1199} 1199}
1200 1200
1201static void ieee80211_if_setup_no_queue(struct net_device *dev)
1202{
1203 ieee80211_if_setup(dev);
1204 dev->priv_flags |= IFF_NO_QUEUE;
1205}
1206
1201static void ieee80211_iface_work(struct work_struct *work) 1207static void ieee80211_iface_work(struct work_struct *work)
1202{ 1208{
1203 struct ieee80211_sub_if_data *sdata = 1209 struct ieee80211_sub_if_data *sdata =
@@ -1707,6 +1713,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1707 struct net_device *ndev = NULL; 1713 struct net_device *ndev = NULL;
1708 struct ieee80211_sub_if_data *sdata = NULL; 1714 struct ieee80211_sub_if_data *sdata = NULL;
1709 struct txq_info *txqi; 1715 struct txq_info *txqi;
1716 void (*if_setup)(struct net_device *dev);
1710 int ret, i; 1717 int ret, i;
1711 int txqs = 1; 1718 int txqs = 1;
1712 1719
@@ -1734,12 +1741,17 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1734 txq_size += sizeof(struct txq_info) + 1741 txq_size += sizeof(struct txq_info) +
1735 local->hw.txq_data_size; 1742 local->hw.txq_data_size;
1736 1743
1744 if (local->ops->wake_tx_queue)
1745 if_setup = ieee80211_if_setup_no_queue;
1746 else
1747 if_setup = ieee80211_if_setup;
1748
1737 if (local->hw.queues >= IEEE80211_NUM_ACS) 1749 if (local->hw.queues >= IEEE80211_NUM_ACS)
1738 txqs = IEEE80211_NUM_ACS; 1750 txqs = IEEE80211_NUM_ACS;
1739 1751
1740 ndev = alloc_netdev_mqs(size + txq_size, 1752 ndev = alloc_netdev_mqs(size + txq_size,
1741 name, name_assign_type, 1753 name, name_assign_type,
1742 ieee80211_if_setup, txqs, 1); 1754 if_setup, txqs, 1);
1743 if (!ndev) 1755 if (!ndev)
1744 return -ENOMEM; 1756 return -ENOMEM;
1745 dev_net_set(ndev, wiphy_net(local->hw.wiphy)); 1757 dev_net_set(ndev, wiphy_net(local->hw.wiphy));
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 7ee91d6151d1..160ac6b8b9a1 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1055,9 +1055,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
1055 1055
1056 local->dynamic_ps_forced_timeout = -1; 1056 local->dynamic_ps_forced_timeout = -1;
1057 1057
1058 if (!local->hw.txq_ac_max_pending)
1059 local->hw.txq_ac_max_pending = 64;
1060
1061 result = ieee80211_wep_init(local); 1058 result = ieee80211_wep_init(local);
1062 if (result < 0) 1059 if (result < 0)
1063 wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", 1060 wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 5ccfdbd406bd..177cc6cd6416 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -116,7 +116,7 @@ static void __cleanup_single_sta(struct sta_info *sta)
116 int n = skb_queue_len(&txqi->queue); 116 int n = skb_queue_len(&txqi->queue);
117 117
118 ieee80211_purge_tx_queue(&local->hw, &txqi->queue); 118 ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
119 atomic_sub(n, &sdata->txqs_len[txqi->txq.ac]); 119 atomic_sub(n, &sdata->num_tx_queued);
120 txqi->byte_cnt = 0; 120 txqi->byte_cnt = 0;
121 } 121 }
122 } 122 }
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 203044379ce0..3e77da195ce8 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1236,27 +1236,21 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1236 return TX_CONTINUE; 1236 return TX_CONTINUE;
1237} 1237}
1238 1238
1239static void ieee80211_drv_tx(struct ieee80211_local *local, 1239static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
1240 struct ieee80211_vif *vif, 1240 struct ieee80211_vif *vif,
1241 struct ieee80211_sta *pubsta, 1241 struct ieee80211_sta *pubsta,
1242 struct sk_buff *skb) 1242 struct sk_buff *skb)
1243{ 1243{
1244 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1244 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1245 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1246 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1245 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1247 struct ieee80211_tx_control control = {
1248 .sta = pubsta,
1249 };
1250 struct ieee80211_txq *txq = NULL; 1246 struct ieee80211_txq *txq = NULL;
1251 struct txq_info *txqi;
1252 u8 ac;
1253 1247
1254 if ((info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) || 1248 if ((info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) ||
1255 (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)) 1249 (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
1256 goto tx_normal; 1250 return NULL;
1257 1251
1258 if (!ieee80211_is_data(hdr->frame_control)) 1252 if (!ieee80211_is_data(hdr->frame_control))
1259 goto tx_normal; 1253 return NULL;
1260 1254
1261 if (pubsta) { 1255 if (pubsta) {
1262 u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; 1256 u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
@@ -1267,25 +1261,28 @@ static void ieee80211_drv_tx(struct ieee80211_local *local,
1267 } 1261 }
1268 1262
1269 if (!txq) 1263 if (!txq)
1270 goto tx_normal; 1264 return NULL;
1271 1265
1272 ac = txq->ac; 1266 return to_txq_info(txq);
1273 txqi = to_txq_info(txq); 1267}
1274 atomic_inc(&sdata->txqs_len[ac]);
1275 if (atomic_read(&sdata->txqs_len[ac]) >= local->hw.txq_ac_max_pending)
1276 netif_stop_subqueue(sdata->dev, ac);
1277 1268
1278 spin_lock_bh(&txqi->queue.lock); 1269static void ieee80211_txq_enqueue(struct ieee80211_local *local,
1279 txqi->byte_cnt += skb->len; 1270 struct txq_info *txqi,
1280 __skb_queue_tail(&txqi->queue, skb); 1271 struct sk_buff *skb)
1281 spin_unlock_bh(&txqi->queue.lock); 1272{
1273 struct ieee80211_sub_if_data *sdata = vif_to_sdata(txqi->txq.vif);
1282 1274
1283 drv_wake_tx_queue(local, txqi); 1275 lockdep_assert_held(&txqi->queue.lock);
1284 1276
1285 return; 1277 if (atomic_read(&sdata->num_tx_queued) >= TOTAL_MAX_TX_BUFFER ||
1278 txqi->queue.qlen >= STA_MAX_TX_BUFFER) {
1279 ieee80211_free_txskb(&local->hw, skb);
1280 return;
1281 }
1286 1282
1287tx_normal: 1283 atomic_inc(&sdata->num_tx_queued);
1288 drv_tx(local, &control, skb); 1284 txqi->byte_cnt += skb->len;
1285 __skb_queue_tail(&txqi->queue, skb);
1289} 1286}
1290 1287
1291struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, 1288struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
@@ -1296,7 +1293,6 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
1296 struct txq_info *txqi = container_of(txq, struct txq_info, txq); 1293 struct txq_info *txqi = container_of(txq, struct txq_info, txq);
1297 struct ieee80211_hdr *hdr; 1294 struct ieee80211_hdr *hdr;
1298 struct sk_buff *skb = NULL; 1295 struct sk_buff *skb = NULL;
1299 u8 ac = txq->ac;
1300 1296
1301 spin_lock_bh(&txqi->queue.lock); 1297 spin_lock_bh(&txqi->queue.lock);
1302 1298
@@ -1307,12 +1303,9 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
1307 if (!skb) 1303 if (!skb)
1308 goto out; 1304 goto out;
1309 1305
1306 atomic_dec(&sdata->num_tx_queued);
1310 txqi->byte_cnt -= skb->len; 1307 txqi->byte_cnt -= skb->len;
1311 1308
1312 atomic_dec(&sdata->txqs_len[ac]);
1313 if (__netif_subqueue_stopped(sdata->dev, ac))
1314 ieee80211_propagate_queue_wake(local, sdata->vif.hw_queue[ac]);
1315
1316 hdr = (struct ieee80211_hdr *)skb->data; 1309 hdr = (struct ieee80211_hdr *)skb->data;
1317 if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) { 1310 if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) {
1318 struct sta_info *sta = container_of(txq->sta, struct sta_info, 1311 struct sta_info *sta = container_of(txq->sta, struct sta_info,
@@ -1343,7 +1336,9 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
1343 struct sk_buff_head *skbs, 1336 struct sk_buff_head *skbs,
1344 bool txpending) 1337 bool txpending)
1345{ 1338{
1339 struct ieee80211_tx_control control = {};
1346 struct sk_buff *skb, *tmp; 1340 struct sk_buff *skb, *tmp;
1341 struct txq_info *txqi;
1347 unsigned long flags; 1342 unsigned long flags;
1348 1343
1349 skb_queue_walk_safe(skbs, skb, tmp) { 1344 skb_queue_walk_safe(skbs, skb, tmp) {
@@ -1358,6 +1353,21 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
1358 } 1353 }
1359#endif 1354#endif
1360 1355
1356 txqi = ieee80211_get_txq(local, vif, sta, skb);
1357 if (txqi) {
1358 info->control.vif = vif;
1359
1360 __skb_unlink(skb, skbs);
1361
1362 spin_lock_bh(&txqi->queue.lock);
1363 ieee80211_txq_enqueue(local, txqi, skb);
1364 spin_unlock_bh(&txqi->queue.lock);
1365
1366 drv_wake_tx_queue(local, txqi);
1367
1368 continue;
1369 }
1370
1361 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 1371 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
1362 if (local->queue_stop_reasons[q] || 1372 if (local->queue_stop_reasons[q] ||
1363 (!txpending && !skb_queue_empty(&local->pending[q]))) { 1373 (!txpending && !skb_queue_empty(&local->pending[q]))) {
@@ -1400,9 +1410,10 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
1400 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 1410 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
1401 1411
1402 info->control.vif = vif; 1412 info->control.vif = vif;
1413 control.sta = sta;
1403 1414
1404 __skb_unlink(skb, skbs); 1415 __skb_unlink(skb, skbs);
1405 ieee80211_drv_tx(local, vif, sta, skb); 1416 drv_tx(local, &control, skb);
1406 } 1417 }
1407 1418
1408 return true; 1419 return true;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 905003f75c4d..0db46442bdcf 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -244,6 +244,9 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
244 struct ieee80211_sub_if_data *sdata; 244 struct ieee80211_sub_if_data *sdata;
245 int n_acs = IEEE80211_NUM_ACS; 245 int n_acs = IEEE80211_NUM_ACS;
246 246
247 if (local->ops->wake_tx_queue)
248 return;
249
247 if (local->hw.queues < IEEE80211_NUM_ACS) 250 if (local->hw.queues < IEEE80211_NUM_ACS)
248 n_acs = 1; 251 n_acs = 1;
249 252
@@ -260,11 +263,6 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
260 for (ac = 0; ac < n_acs; ac++) { 263 for (ac = 0; ac < n_acs; ac++) {
261 int ac_queue = sdata->vif.hw_queue[ac]; 264 int ac_queue = sdata->vif.hw_queue[ac];
262 265
263 if (local->ops->wake_tx_queue &&
264 (atomic_read(&sdata->txqs_len[ac]) >
265 local->hw.txq_ac_max_pending))
266 continue;
267
268 if (ac_queue == queue || 266 if (ac_queue == queue ||
269 (sdata->vif.cab_queue == queue && 267 (sdata->vif.cab_queue == queue &&
270 local->queue_stop_reasons[ac_queue] == 0 && 268 local->queue_stop_reasons[ac_queue] == 0 &&
@@ -352,6 +350,9 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
352 if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue])) 350 if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue]))
353 return; 351 return;
354 352
353 if (local->ops->wake_tx_queue)
354 return;
355
355 if (local->hw.queues < IEEE80211_NUM_ACS) 356 if (local->hw.queues < IEEE80211_NUM_ACS)
356 n_acs = 1; 357 n_acs = 1;
357 358