[PATCH ath-next v3 4/9] wifi: ath11k: report tx airtime and enable airtime fairness
Julius Bairaktaris <[email protected]>
| Newsgroups | org.kernel.vger.linux-wireless,org.infradead.lists.ath11k,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
mac80211's airtime scheduler charges sta->airtime[ac].deficit from one place, ieee80211_sta_register_airtime(). Unlike AQL there is no estimator fallback, and ath11k never calls it, so the ATF feature bit cannot be advertised on its own: the deficit would only ever be replenished, every station would stay permanently in credit, and the DRR would be inert. The bit is not a no-op in that state either, because it also moves txq insertion to the head of the active list, which __ieee80211_schedule_txq() documents as safe only because the DRR moves a station back once its deficit goes negative. fes_duration_us arrives with every PPDU's stats and is already accumulated into arsta->tx_duration a few lines above. Register it, and set the feature bit in the same change so the two cannot be separated. The access category the airtime is charged to comes from the TID, and the ack/BA status TLV that ath11k took it from is emitted only for a PPDU that drew a response. A transmission that timed out, was filtered or was aborted names its TID only in the completion and rate TLVs, both of which already reach the driver and were read nowhere. Take the first of the three the firmware supplied that names one of the sixteen QoS TIDs; a PPDU that names none is charged to best effort, the access category mac80211 queues a frame without a QoS TID in. Measured on an IPQ8074 AP with two stations on one radio, a 1x1 VHT client and a 2x2 HE client, both receiving at once. Before, 'iw station set <mac> airtime_weight' is refused with -EOPNOTSUPP and the per-station airtime file reads zero. After, the weight is accepted and read back, TX airtime accumulates, and the per-AC deficits move. What the deficit can do with that is bounded by how the driver hands frames to the hardware, which the following patches change; the airtime share this alone produces is reported with them rather than here. fes_duration_us spans the frame exchange sequence, so it includes the SIFS and the responding BlockAck, time the radio spends receiving; the airtime registered is therefore larger than the airtime transmitted. It is also a per-PPDU field, so on a downlink MU PPDU each user is charged the whole sequence. No per-user duration is reported in these stats. On the firmware tested here every PPDU carried exactly one user, measured over 21051 PPDUs, so the MU case is latent rather than observed. Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1 Assisted-by: Claude:claude-opus-5 Signed-off-by: Julius Bairaktaris <[email protected]> --- drivers/net/wireless/ath/ath11k/dp_rx.c | 20 ++++++++++++++++++++ drivers/net/wireless/ath/ath11k/mac.c | 2 ++ 2 files changed, 22 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 33425707c084..28aaf39cf342 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -1377,6 +1377,7 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar, u16 rate = 0, succ_pkts = 0; u32 tx_duration = 0; u8 tid = HTT_PPDU_STATS_NON_QOS_TID; + u8 airtime_tid; bool is_ampdu = false; if (!(usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_RATE))) @@ -1485,6 +1486,25 @@ ath11k_update_per_peer_tx_stats(struct ath11k *ar, arsta->txrate.bw = ath11k_mac_bw_to_mac80211_bw(bw); arsta->tx_duration += tx_duration; + + /* The ack/BA status TLV is emitted only for a PPDU that drew a + * response, so a transmission that timed out, was filtered or was + * aborted names its TID only in the completion and rate TLVs. Take the + * first of the three the firmware supplied that names one of the sixteen + * QoS TIDs; a PPDU that names none is charged to best effort, the access + * category mac80211 queues a frame without a QoS TID in. + */ + airtime_tid = tid; + if (airtime_tid >= IEEE80211_NUM_TIDS && + usr_stats->tlv_flags & BIT(HTT_PPDU_STATS_TAG_USR_COMPLTN_COMMON)) + airtime_tid = usr_stats->cmpltn_cmn.tid_num; + if (airtime_tid >= IEEE80211_NUM_TIDS) + airtime_tid = user_rate->tid_num; + if (airtime_tid >= IEEE80211_NUM_TIDS) + airtime_tid = 0; + + if (tx_duration) + ieee80211_sta_register_airtime(sta, airtime_tid, tx_duration, 0); memcpy(&arsta->last_txrate, &arsta->txrate, sizeof(struct rate_info)); /* PPDU stats reported for mgmt packet doesn't have valid tx bytes. diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 38f641bbc53c..40a2b6d2f804 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -10593,6 +10593,8 @@ static int __ath11k_mac_register(struct ath11k *ar) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_AQL); + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_STA_TX_PWR); if (test_bit(WMI_TLV_SERVICE_BSS_COLOR_OFFLOAD, ar->ab->wmi_ab.svc_map)) { -- 2.53.0