aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-04-03 10:28:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-04-11 16:23:50 -0400
commit3a25a8c8b75b430c4f4022918e26fa51d557ecde (patch)
treed4863b7f17c2ea44fb523e29951b6bd202ddb1ad /net/mac80211/tx.c
parent4b6f1dd6a6faf4ed8d209bbd548e78b15e55aee8 (diff)
mac80211: add improved HW queue control
mac80211 currently only supports one hardware queue per AC. This is already problematic for off-channel uses since if we go off channel while the BE queue is full and then try to send an off-channel frame the frame will never go out. This will become worse when we support multi-channel since then a queue on one channel might be full, but we have to stop the software queue for all channels. That is obviously not desirable. To address this problem allow drivers to register more hardware queues, and allow them to map them to virtual interfaces. When they stop a hardware queue the corresponding AC software queues on the correct interfaces will be stopped as well. Additionally, there's an off-channel queue to solve that problem and a per-interface after-DTIM beacon queue. This allows drivers to manage software queues closer to how the hardware works. Currently, there's a limit of 16 hardware queues. This may or may not be sufficient, we can adjust it as needed. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index a8d0188ab408..4f6aac16ac3a 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -400,6 +400,8 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
400 return TX_CONTINUE; 400 return TX_CONTINUE;
401 401
402 info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; 402 info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
403 if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
404 info->hw_queue = tx->sdata->vif.cab_queue;
403 405
404 /* device releases frame after DTIM beacon */ 406 /* device releases frame after DTIM beacon */
405 if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) 407 if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING))
@@ -1214,11 +1216,19 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
1214 bool txpending) 1216 bool txpending)
1215{ 1217{
1216 struct sk_buff *skb, *tmp; 1218 struct sk_buff *skb, *tmp;
1217 struct ieee80211_tx_info *info;
1218 unsigned long flags; 1219 unsigned long flags;
1219 1220
1220 skb_queue_walk_safe(skbs, skb, tmp) { 1221 skb_queue_walk_safe(skbs, skb, tmp) {
1221 int q = skb_get_queue_mapping(skb); 1222 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1223 int q = info->hw_queue;
1224
1225#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1226 if (WARN_ON_ONCE(q >= local->hw.queues)) {
1227 __skb_unlink(skb, skbs);
1228 dev_kfree_skb(skb);
1229 continue;
1230 }
1231#endif
1222 1232
1223 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 1233 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
1224 if (local->queue_stop_reasons[q] || 1234 if (local->queue_stop_reasons[q] ||
@@ -1240,7 +1250,6 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
1240 } 1250 }
1241 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 1251 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
1242 1252
1243 info = IEEE80211_SKB_CB(skb);
1244 info->control.vif = vif; 1253 info->control.vif = vif;
1245 info->control.sta = sta; 1254 info->control.sta = sta;
1246 1255
@@ -1284,9 +1293,14 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
1284 switch (sdata->vif.type) { 1293 switch (sdata->vif.type) {
1285 case NL80211_IFTYPE_MONITOR: 1294 case NL80211_IFTYPE_MONITOR:
1286 sdata = rcu_dereference(local->monitor_sdata); 1295 sdata = rcu_dereference(local->monitor_sdata);
1287 if (sdata) 1296 if (sdata) {
1288 vif = &sdata->vif; 1297 vif = &sdata->vif;
1289 else 1298 info->hw_queue =
1299 vif->hw_queue[skb_get_queue_mapping(skb)];
1300 } else if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) {
1301 dev_kfree_skb(skb);
1302 return true;
1303 } else
1290 vif = NULL; 1304 vif = NULL;
1291 break; 1305 break;
1292 case NL80211_IFTYPE_AP_VLAN: 1306 case NL80211_IFTYPE_AP_VLAN:
@@ -1402,6 +1416,12 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
1402 tx.channel = local->hw.conf.channel; 1416 tx.channel = local->hw.conf.channel;
1403 info->band = tx.channel->band; 1417 info->band = tx.channel->band;
1404 1418
1419 /* set up hw_queue value early */
1420 if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
1421 !(local->hw.flags & IEEE80211_HW_QUEUE_CONTROL))
1422 info->hw_queue =
1423 sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
1424
1405 if (!invoke_tx_handlers(&tx)) 1425 if (!invoke_tx_handlers(&tx))
1406 result = __ieee80211_tx(local, &tx.skbs, led_len, 1426 result = __ieee80211_tx(local, &tx.skbs, led_len,
1407 tx.sta, txpending); 1427 tx.sta, txpending);
@@ -2172,7 +2192,6 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
2172void ieee80211_tx_pending(unsigned long data) 2192void ieee80211_tx_pending(unsigned long data)
2173{ 2193{
2174 struct ieee80211_local *local = (struct ieee80211_local *)data; 2194 struct ieee80211_local *local = (struct ieee80211_local *)data;
2175 struct ieee80211_sub_if_data *sdata;
2176 unsigned long flags; 2195 unsigned long flags;
2177 int i; 2196 int i;
2178 bool txok; 2197 bool txok;
@@ -2209,8 +2228,7 @@ void ieee80211_tx_pending(unsigned long data)
2209 } 2228 }
2210 2229
2211 if (skb_queue_empty(&local->pending[i])) 2230 if (skb_queue_empty(&local->pending[i]))
2212 list_for_each_entry_rcu(sdata, &local->interfaces, list) 2231 ieee80211_propagate_queue_wake(local, i);
2213 netif_wake_subqueue(sdata->dev, i);
2214 } 2232 }
2215 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 2233 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
2216 2234
@@ -2717,11 +2735,13 @@ EXPORT_SYMBOL(ieee80211_get_buffered_bc);
2717void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, 2735void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
2718 struct sk_buff *skb, int tid) 2736 struct sk_buff *skb, int tid)
2719{ 2737{
2738 int ac = ieee802_1d_to_ac[tid];
2739
2720 skb_set_mac_header(skb, 0); 2740 skb_set_mac_header(skb, 0);
2721 skb_set_network_header(skb, 0); 2741 skb_set_network_header(skb, 0);
2722 skb_set_transport_header(skb, 0); 2742 skb_set_transport_header(skb, 0);
2723 2743
2724 skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); 2744 skb_set_queue_mapping(skb, ac);
2725 skb->priority = tid; 2745 skb->priority = tid;
2726 2746
2727 /* 2747 /*