summaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorToke Høiland-Jørgensen <toke@toke.dk>2017-10-31 12:27:46 +0100
committerJohannes Berg <johannes.berg@intel.com>2017-12-11 12:40:24 +0100
commitb0d52ad821843a6c5badebd80feef9f871904fa6 (patch)
tree6962b03bd69935102294e2038ae615309091f3d4 /net/mac80211/tx.c
parente937b8da5a591f141fe41aa48a2e898df9888c95 (diff)
downloadlinux-b0d52ad821843a6c5badebd80feef9f871904fa6.tar.bz2
mac80211: Add airtime account and scheduling to TXQs
This adds airtime accounting and scheduling to the mac80211 TXQ scheduler. A new hardware flag, AIRTIME_ACCOUNTING, is added that drivers can set if they support reporting airtime usage of transmissions. When this flag is set, mac80211 will expect the actual airtime usage to be reported in the tx_time and rx_time fields of the respective status structs. When airtime information is present, mac80211 will schedule TXQs (through ieee80211_next_txq()) in a way that enforces airtime fairness between active stations. This scheduling works the same way as the ath9k in-driver airtime fairness scheduling. Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 842881ca8f20..18381581b5e9 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3566,7 +3566,7 @@ bool ieee80211_schedule_txq(struct ieee80211_hw *hw,
spin_lock_bh(&local->active_txq_lock);
if (list_empty(&txqi->schedule_order)) {
- list_add_tail(&txqi->schedule_order, &local->active_txqs);
+ list_add_tail(&txqi->schedule_order, &local->active_txqs_new);
ret = true;
}
@@ -3580,14 +3580,35 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
struct txq_info *txqi = NULL;
+ struct list_head *head;
spin_lock_bh(&local->active_txq_lock);
- if (list_empty(&local->active_txqs))
- goto out;
+begin:
+ head = &local->active_txqs_new;
+ if (list_empty(head)) {
+ head = &local->active_txqs_old;
+ if (list_empty(head))
+ goto out;
+ }
+
+ txqi = list_first_entry(head, struct txq_info, schedule_order);
+
+ if (txqi->txq.sta) {
+ struct sta_info *sta = container_of(txqi->txq.sta,
+ struct sta_info, sta);
+
+ spin_lock_bh(&sta->lock);
+ if (sta->airtime_deficit < 0) {
+ sta->airtime_deficit += IEEE80211_AIRTIME_QUANTUM;
+ list_move_tail(&txqi->schedule_order,
+ &local->active_txqs_old);
+ spin_unlock_bh(&sta->lock);
+ goto begin;
+ }
+ spin_unlock_bh(&sta->lock);
+ }
- txqi = list_first_entry(&local->active_txqs,
- struct txq_info, schedule_order);
list_del_init(&txqi->schedule_order);
out: