diff options
author | Manikanta Pubbisetty <mpubbise@codeaurora.org> | 2019-02-11 18:47:59 +0200 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2019-02-12 20:48:12 +0200 |
commit | bb31b7cb106c0447c5cd77ed23dda5a70cce0881 (patch) | |
tree | a400a3e0c0b591176070cd49f42cac71eba4892f /drivers/net/wireless/ath/ath10k/htt_rx.c | |
parent | 4920ce3bf7e0d533441b3c8e50b40a6f1897492b (diff) |
ath10k: report tx airtime provided by fw
If supported, update transmit airtime in mac80211 with the airtime
values reported by the firmware. TX airtime of the PPDU is reported
via HTT data TX completion indication message.
A new service flag 'WMI_SERVICE_REPORT_AIRTIME' is added to advertise
the firmware support. For firmwares which do not support this feature,
TX airtime is calculated in the driver using TX bitrate.
Hardwares tested : QCA9984
Firmwares tested : 10.4-3.6.1-00841
Signed-off-by: Manikanta Pubbisetty <mpubbise@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/htt_rx.c')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/htt_rx.c | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 77f494d52ec3..d5c666c2504c 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2220,8 +2220,12 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, int status = MS(resp->data_tx_completion.flags, HTT_DATA_TX_STATUS); __le16 msdu_id, *msdus; bool rssi_enabled = false; - u8 msdu_count = 0; + u8 msdu_count = 0, num_airtime_records, tid; int i; + struct htt_data_tx_compl_ppdu_dur *ppdu_info; + struct ath10k_peer *peer; + u16 ppdu_info_offset = 0, peer_id; + u32 tx_duration; switch (status) { case HTT_DATA_TX_STATUS_NO_ACK: @@ -2245,12 +2249,12 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, resp->data_tx_completion.num_msdus); msdu_count = resp->data_tx_completion.num_msdus; + msdus = resp->data_tx_completion.msdus; if (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI) rssi_enabled = true; for (i = 0; i < msdu_count; i++) { - msdus = resp->data_tx_completion.msdus; msdu_id = msdus[i]; tx_done.msdu_id = __le16_to_cpu(msdu_id); @@ -2282,6 +2286,50 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, ath10k_txrx_tx_unref(htt, &tx_done); } } + + if (!(resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT)) + return; + + ppdu_info_offset = (msdu_count & 0x01) ? msdu_count + 1 : msdu_count; + + if (rssi_enabled) + ppdu_info_offset += ppdu_info_offset; + + if (resp->data_tx_completion.flags2 & + (HTT_TX_CMPL_FLAG_PPID_PRESENT | HTT_TX_CMPL_FLAG_PA_PRESENT)) + ppdu_info_offset += 2; + + ppdu_info = (struct htt_data_tx_compl_ppdu_dur *)&msdus[ppdu_info_offset]; + num_airtime_records = FIELD_GET(HTT_TX_COMPL_PPDU_DUR_INFO0_NUM_ENTRIES_MASK, + __le32_to_cpu(ppdu_info->info0)); + + for (i = 0; i < num_airtime_records; i++) { + struct htt_data_tx_ppdu_dur *ppdu_dur; + u32 info0; + + ppdu_dur = &ppdu_info->ppdu_dur[i]; + info0 = __le32_to_cpu(ppdu_dur->info0); + + peer_id = FIELD_GET(HTT_TX_PPDU_DUR_INFO0_PEER_ID_MASK, + info0); + rcu_read_lock(); + spin_lock_bh(&ar->data_lock); + + peer = ath10k_peer_find_by_id(ar, peer_id); + if (!peer) { + spin_unlock_bh(&ar->data_lock); + rcu_read_unlock(); + continue; + } + + tid = FIELD_GET(HTT_TX_PPDU_DUR_INFO0_TID_MASK, info0); + tx_duration = __le32_to_cpu(ppdu_dur->tx_duration); + + ieee80211_sta_register_airtime(peer->sta, tid, tx_duration, 0); + + spin_unlock_bh(&ar->data_lock); + rcu_read_unlock(); + } } static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp) |