mirror of
https://github.com/torvalds/linux.git
synced 2024-12-24 20:01:55 +00:00
ath10k: report estimated frame transmit airtime to improve fairness
The airtime of a transmitted frame will be estimated from last used tx rate which the firmware reports with the peer stats feature (WMI_SERVICE_PEER_STATS). The airtime is computed on the tx path and it will be reported to mac80211 upon tx completion. This change is based on Kan's orginal commit in Chromium tree ("CHROMIUM: ath10k: Implementing airtime fairness based TX scheduler") ref: https://chromium-review.googlesource.com/588190 Tested on QCA4019 with firmware version 10.4-3.2.1.1-00015 Tested on QCA9984 with firmware version 10.4-3.9.0.1-00005 Signed-off-by: Kan Yan <kyan@google.com> [rmanohar@codeaurora.org: ported only the airtime computation] Signed-off-by: Rajkumar Manoharan <rmanohar@codeaurora.org> [toke@redhat.com: Rebase to mac80211-next, add test note] Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
bb2edb7335
commit
d1ce37b783
@ -126,6 +126,7 @@ struct ath10k_skb_cb {
|
||||
u8 flags;
|
||||
u8 eid;
|
||||
u16 msdu_id;
|
||||
u16 airtime_est;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_txq *txq;
|
||||
} __packed;
|
||||
@ -498,6 +499,7 @@ struct ath10k_sta {
|
||||
u16 peer_id;
|
||||
struct rate_info txrate;
|
||||
struct ieee80211_tx_info tx_info;
|
||||
u32 last_tx_bitrate;
|
||||
|
||||
struct work_struct update_wk;
|
||||
u64 rx_duration;
|
||||
|
@ -3080,6 +3080,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
|
||||
|
||||
arsta->txrate.nss = txrate.nss;
|
||||
arsta->txrate.bw = ath10k_bw_to_mac80211_bw(txrate.bw);
|
||||
arsta->last_tx_bitrate = cfg80211_calculate_bitrate(&arsta->txrate);
|
||||
if (sgi)
|
||||
arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
|
||||
|
@ -3544,7 +3544,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
|
||||
static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_txq *txq,
|
||||
struct sk_buff *skb)
|
||||
struct sk_buff *skb, u16 airtime)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
|
||||
@ -3561,6 +3561,7 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
|
||||
|
||||
cb->vif = vif;
|
||||
cb->txq = txq;
|
||||
cb->airtime_est = airtime;
|
||||
}
|
||||
|
||||
bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar)
|
||||
@ -3948,6 +3949,49 @@ static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return estimated airtime in microsecond, which is calculated using last
|
||||
* reported TX rate. This is just a rough estimation because host driver has no
|
||||
* knowledge of the actual transmit rate, retries or aggregation. If actual
|
||||
* airtime can be reported by firmware, then delta between estimated and actual
|
||||
* airtime can be adjusted from deficit.
|
||||
*/
|
||||
#define IEEE80211_ATF_OVERHEAD 100 /* IFS + some slot time */
|
||||
#define IEEE80211_ATF_OVERHEAD_IFS 16 /* IFS only */
|
||||
static u16 ath10k_mac_update_airtime(struct ath10k *ar,
|
||||
struct ieee80211_txq *txq,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ath10k_sta *arsta;
|
||||
u32 pktlen;
|
||||
u16 airtime = 0;
|
||||
|
||||
if (!txq || !txq->sta)
|
||||
return airtime;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
arsta = (struct ath10k_sta *)txq->sta->drv_priv;
|
||||
|
||||
pktlen = skb->len + 38; /* Assume MAC header 30, SNAP 8 for most case */
|
||||
if (arsta->last_tx_bitrate) {
|
||||
/* airtime in us, last_tx_bitrate in 100kbps */
|
||||
airtime = (pktlen * 8 * (1000 / 100))
|
||||
/ arsta->last_tx_bitrate;
|
||||
/* overhead for media access time and IFS */
|
||||
airtime += IEEE80211_ATF_OVERHEAD_IFS;
|
||||
} else {
|
||||
/* This is mostly for throttle excessive BC/MC frames, and the
|
||||
* airtime/rate doesn't need be exact. Airtime of BC/MC frames
|
||||
* in 2G get some discount, which helps prevent very low rate
|
||||
* frames from being blocked for too long.
|
||||
*/
|
||||
airtime = (pktlen * 8 * (1000 / 100)) / 60; /* 6M */
|
||||
airtime += IEEE80211_ATF_OVERHEAD;
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
return airtime;
|
||||
}
|
||||
|
||||
int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
struct ieee80211_txq *txq)
|
||||
{
|
||||
@ -3963,6 +4007,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
size_t skb_len;
|
||||
bool is_mgmt, is_presp;
|
||||
int ret;
|
||||
u16 airtime;
|
||||
|
||||
spin_lock_bh(&ar->htt.tx_lock);
|
||||
ret = ath10k_htt_tx_inc_pending(htt);
|
||||
@ -3980,7 +4025,8 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb);
|
||||
airtime = ath10k_mac_update_airtime(ar, txq, skb);
|
||||
ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb, airtime);
|
||||
|
||||
skb_len = skb->len;
|
||||
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
|
||||
@ -4247,8 +4293,10 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
|
||||
bool is_mgmt;
|
||||
bool is_presp;
|
||||
int ret;
|
||||
u16 airtime;
|
||||
|
||||
ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb);
|
||||
airtime = ath10k_mac_update_airtime(ar, txq, skb);
|
||||
ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb, airtime);
|
||||
|
||||
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
|
||||
txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
|
||||
@ -8604,6 +8652,9 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
|
||||
|
||||
if (ath10k_peer_stats_enabled(ar))
|
||||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
|
||||
/*
|
||||
* on LL hardware queues are managed entirely by the FW
|
||||
* so we only advertise to mac we can do the queues thing
|
||||
|
@ -95,6 +95,10 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
wake_up(&htt->empty_tx_wq);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
|
||||
if (txq && txq->sta)
|
||||
ieee80211_sta_register_airtime(txq->sta, txq->tid,
|
||||
skb_cb->airtime_est, 0);
|
||||
|
||||
if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
|
||||
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user