|
@@ -2453,6 +2453,62 @@ out:
|
|
|
rcu_read_unlock();
|
|
|
}
|
|
|
|
|
|
+static void ath10k_fetch_10_2_tx_stats(struct ath10k *ar, u8 *data)
|
|
|
+{
|
|
|
+ struct ath10k_pktlog_hdr *hdr = (struct ath10k_pktlog_hdr *)data;
|
|
|
+ struct ath10k_per_peer_tx_stats *p_tx_stats = &ar->peer_tx_stats;
|
|
|
+ struct ath10k_10_2_peer_tx_stats *tx_stats;
|
|
|
+ struct ieee80211_sta *sta;
|
|
|
+ struct ath10k_peer *peer;
|
|
|
+ u16 log_type = __le16_to_cpu(hdr->log_type);
|
|
|
+ u32 peer_id = 0, i;
|
|
|
+
|
|
|
+ if (log_type != ATH_PKTLOG_TYPE_TX_STAT)
|
|
|
+ return;
|
|
|
+
|
|
|
+ tx_stats = (struct ath10k_10_2_peer_tx_stats *)((hdr->payload) +
|
|
|
+ ATH10K_10_2_TX_STATS_OFFSET);
|
|
|
+
|
|
|
+ if (!tx_stats->tx_ppdu_cnt)
|
|
|
+ return;
|
|
|
+
|
|
|
+ peer_id = tx_stats->peer_id;
|
|
|
+
|
|
|
+ rcu_read_lock();
|
|
|
+ spin_lock_bh(&ar->data_lock);
|
|
|
+ peer = ath10k_peer_find_by_id(ar, peer_id);
|
|
|
+ if (!peer) {
|
|
|
+ ath10k_warn(ar, "Invalid peer id %d in peer stats buffer\n",
|
|
|
+ peer_id);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ sta = peer->sta;
|
|
|
+ for (i = 0; i < tx_stats->tx_ppdu_cnt; i++) {
|
|
|
+ p_tx_stats->succ_bytes =
|
|
|
+ __le16_to_cpu(tx_stats->success_bytes[i]);
|
|
|
+ p_tx_stats->retry_bytes =
|
|
|
+ __le16_to_cpu(tx_stats->retry_bytes[i]);
|
|
|
+ p_tx_stats->failed_bytes =
|
|
|
+ __le16_to_cpu(tx_stats->failed_bytes[i]);
|
|
|
+ p_tx_stats->ratecode = tx_stats->ratecode[i];
|
|
|
+ p_tx_stats->flags = tx_stats->flags[i];
|
|
|
+ p_tx_stats->succ_pkts = tx_stats->success_pkts[i];
|
|
|
+ p_tx_stats->retry_pkts = tx_stats->retry_pkts[i];
|
|
|
+ p_tx_stats->failed_pkts = tx_stats->failed_pkts[i];
|
|
|
+
|
|
|
+ ath10k_update_per_peer_tx_stats(ar, sta, p_tx_stats);
|
|
|
+ }
|
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
|
+ rcu_read_unlock();
|
|
|
+
|
|
|
+ return;
|
|
|
+
|
|
|
+out:
|
|
|
+ spin_unlock_bh(&ar->data_lock);
|
|
|
+ rcu_read_unlock();
|
|
|
+}
|
|
|
+
|
|
|
bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
|
|
{
|
|
|
struct ath10k_htt *htt = &ar->htt;
|
|
@@ -2570,6 +2626,10 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
|
|
skb->len -
|
|
|
offsetof(struct htt_resp,
|
|
|
pktlog_msg.payload));
|
|
|
+
|
|
|
+ if (ath10k_peer_stats_enabled(ar))
|
|
|
+ ath10k_fetch_10_2_tx_stats(ar,
|
|
|
+ resp->pktlog_msg.payload);
|
|
|
break;
|
|
|
}
|
|
|
case HTT_T2H_MSG_TYPE_RX_FLUSH: {
|