cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

debugfs_sta.c (21470B)


      1// SPDX-License-Identifier: ISC
      2/*
      3 * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
      4 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
      5 */
      6
      7#include "core.h"
      8#include "wmi-ops.h"
      9#include "txrx.h"
     10#include "debug.h"
     11
     12static void ath10k_rx_stats_update_amsdu_subfrm(struct ath10k *ar,
     13						struct ath10k_sta_tid_stats *stats,
     14						u32 msdu_count)
     15{
     16	if (msdu_count == 1)
     17		stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_1]++;
     18	else if (msdu_count == 2)
     19		stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_2]++;
     20	else if (msdu_count == 3)
     21		stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_3]++;
     22	else if (msdu_count == 4)
     23		stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_4]++;
     24	else if (msdu_count > 4)
     25		stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MORE]++;
     26}
     27
     28static void ath10k_rx_stats_update_ampdu_subfrm(struct ath10k *ar,
     29						struct ath10k_sta_tid_stats *stats,
     30						u32 mpdu_count)
     31{
     32	if (mpdu_count <= 10)
     33		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_10]++;
     34	else if (mpdu_count <= 20)
     35		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_20]++;
     36	else if (mpdu_count <= 30)
     37		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_30]++;
     38	else if (mpdu_count <= 40)
     39		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_40]++;
     40	else if (mpdu_count <= 50)
     41		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_50]++;
     42	else if (mpdu_count <= 60)
     43		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_60]++;
     44	else if (mpdu_count > 60)
     45		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MORE]++;
     46}
     47
     48void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid,
     49					  struct htt_rx_indication_mpdu_range *ranges,
     50					  int num_ranges)
     51{
     52	struct ath10k_sta *arsta;
     53	struct ath10k_peer *peer;
     54	int i;
     55
     56	if (tid > IEEE80211_NUM_TIDS || !(ar->sta_tid_stats_mask & BIT(tid)))
     57		return;
     58
     59	rcu_read_lock();
     60	spin_lock_bh(&ar->data_lock);
     61
     62	peer = ath10k_peer_find_by_id(ar, peer_id);
     63	if (!peer || !peer->sta)
     64		goto out;
     65
     66	arsta = (struct ath10k_sta *)peer->sta->drv_priv;
     67
     68	for (i = 0; i < num_ranges; i++)
     69		ath10k_rx_stats_update_ampdu_subfrm(ar,
     70						    &arsta->tid_stats[tid],
     71						    ranges[i].mpdu_count);
     72
     73out:
     74	spin_unlock_bh(&ar->data_lock);
     75	rcu_read_unlock();
     76}
     77
     78void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
     79				    unsigned long num_msdus,
     80				    enum ath10k_pkt_rx_err err,
     81				    unsigned long unchain_cnt,
     82				    unsigned long drop_cnt,
     83				    unsigned long drop_cnt_filter,
     84				    unsigned long queued_msdus)
     85{
     86	struct ieee80211_sta *sta;
     87	struct ath10k_sta *arsta;
     88	struct ieee80211_hdr *hdr;
     89	struct ath10k_sta_tid_stats *stats;
     90	u8 tid = IEEE80211_NUM_TIDS;
     91	bool non_data_frm = false;
     92
     93	hdr = (struct ieee80211_hdr *)first_hdr;
     94	if (!ieee80211_is_data(hdr->frame_control))
     95		non_data_frm = true;
     96
     97	if (ieee80211_is_data_qos(hdr->frame_control))
     98		tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
     99
    100	if (!(ar->sta_tid_stats_mask & BIT(tid)) || non_data_frm)
    101		return;
    102
    103	rcu_read_lock();
    104
    105	sta = ieee80211_find_sta_by_ifaddr(ar->hw, hdr->addr2, NULL);
    106	if (!sta)
    107		goto exit;
    108
    109	arsta = (struct ath10k_sta *)sta->drv_priv;
    110
    111	spin_lock_bh(&ar->data_lock);
    112	stats = &arsta->tid_stats[tid];
    113	stats->rx_pkt_from_fw += num_msdus;
    114	stats->rx_pkt_unchained += unchain_cnt;
    115	stats->rx_pkt_drop_chained += drop_cnt;
    116	stats->rx_pkt_drop_filter += drop_cnt_filter;
    117	if (err != ATH10K_PKT_RX_ERR_MAX)
    118		stats->rx_pkt_err[err] += queued_msdus;
    119	stats->rx_pkt_queued_for_mac += queued_msdus;
    120	ath10k_rx_stats_update_amsdu_subfrm(ar, &arsta->tid_stats[tid],
    121					    num_msdus);
    122	spin_unlock_bh(&ar->data_lock);
    123
    124exit:
    125	rcu_read_unlock();
    126}
    127
    128static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar,
    129						     struct ath10k_fw_stats *stats)
    130{
    131	struct ath10k_fw_extd_stats_peer *peer;
    132	struct ieee80211_sta *sta;
    133	struct ath10k_sta *arsta;
    134
    135	rcu_read_lock();
    136	list_for_each_entry(peer, &stats->peers_extd, list) {
    137		sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
    138						   NULL);
    139		if (!sta)
    140			continue;
    141		arsta = (struct ath10k_sta *)sta->drv_priv;
    142		arsta->rx_duration += (u64)peer->rx_duration;
    143	}
    144	rcu_read_unlock();
    145}
    146
    147static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar,
    148						struct ath10k_fw_stats *stats)
    149{
    150	struct ath10k_fw_stats_peer *peer;
    151	struct ieee80211_sta *sta;
    152	struct ath10k_sta *arsta;
    153
    154	rcu_read_lock();
    155	list_for_each_entry(peer, &stats->peers, list) {
    156		sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
    157						   NULL);
    158		if (!sta)
    159			continue;
    160		arsta = (struct ath10k_sta *)sta->drv_priv;
    161		arsta->rx_duration += (u64)peer->rx_duration;
    162	}
    163	rcu_read_unlock();
    164}
    165
    166void ath10k_sta_update_rx_duration(struct ath10k *ar,
    167				   struct ath10k_fw_stats *stats)
    168{
    169	if (stats->extended)
    170		ath10k_sta_update_extd_stats_rx_duration(ar, stats);
    171	else
    172		ath10k_sta_update_stats_rx_duration(ar, stats);
    173}
    174
    175static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
    176					     char __user *user_buf,
    177					     size_t count, loff_t *ppos)
    178{
    179	struct ieee80211_sta *sta = file->private_data;
    180	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
    181	struct ath10k *ar = arsta->arvif->ar;
    182	char buf[32];
    183	int len = 0;
    184
    185	mutex_lock(&ar->conf_mutex);
    186	len = scnprintf(buf, sizeof(buf) - len, "aggregation mode: %s\n",
    187			(arsta->aggr_mode == ATH10K_DBG_AGGR_MODE_AUTO) ?
    188			"auto" : "manual");
    189	mutex_unlock(&ar->conf_mutex);
    190
    191	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    192}
    193
    194static ssize_t ath10k_dbg_sta_write_aggr_mode(struct file *file,
    195					      const char __user *user_buf,
    196					      size_t count, loff_t *ppos)
    197{
    198	struct ieee80211_sta *sta = file->private_data;
    199	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
    200	struct ath10k *ar = arsta->arvif->ar;
    201	u32 aggr_mode;
    202	int ret;
    203
    204	if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
    205		return -EINVAL;
    206
    207	if (aggr_mode >= ATH10K_DBG_AGGR_MODE_MAX)
    208		return -EINVAL;
    209
    210	mutex_lock(&ar->conf_mutex);
    211	if ((ar->state != ATH10K_STATE_ON) ||
    212	    (aggr_mode == arsta->aggr_mode)) {
    213		ret = count;
    214		goto out;
    215	}
    216
    217	ret = ath10k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
    218	if (ret) {
    219		ath10k_warn(ar, "failed to clear addba session ret: %d\n", ret);
    220		goto out;
    221	}
    222
    223	arsta->aggr_mode = aggr_mode;
    224out:
    225	mutex_unlock(&ar->conf_mutex);
    226	return ret;
    227}
    228
    229static const struct file_operations fops_aggr_mode = {
    230	.read = ath10k_dbg_sta_read_aggr_mode,
    231	.write = ath10k_dbg_sta_write_aggr_mode,
    232	.open = simple_open,
    233	.owner = THIS_MODULE,
    234	.llseek = default_llseek,
    235};
    236
    237static ssize_t ath10k_dbg_sta_write_addba(struct file *file,
    238					  const char __user *user_buf,
    239					  size_t count, loff_t *ppos)
    240{
    241	struct ieee80211_sta *sta = file->private_data;
    242	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
    243	struct ath10k *ar = arsta->arvif->ar;
    244	u32 tid, buf_size;
    245	int ret;
    246	char buf[64] = {0};
    247
    248	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
    249				     user_buf, count);
    250	if (ret <= 0)
    251		return ret;
    252
    253	ret = sscanf(buf, "%u %u", &tid, &buf_size);
    254	if (ret != 2)
    255		return -EINVAL;
    256
    257	/* Valid TID values are 0 through 15 */
    258	if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
    259		return -EINVAL;
    260
    261	mutex_lock(&ar->conf_mutex);
    262	if ((ar->state != ATH10K_STATE_ON) ||
    263	    (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
    264		ret = count;
    265		goto out;
    266	}
    267
    268	ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
    269				    tid, buf_size);
    270	if (ret) {
    271		ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
    272			    arsta->arvif->vdev_id, sta->addr, tid, buf_size);
    273	}
    274
    275	ret = count;
    276out:
    277	mutex_unlock(&ar->conf_mutex);
    278	return ret;
    279}
    280
    281static const struct file_operations fops_addba = {
    282	.write = ath10k_dbg_sta_write_addba,
    283	.open = simple_open,
    284	.owner = THIS_MODULE,
    285	.llseek = default_llseek,
    286};
    287
    288static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file,
    289					       const char __user *user_buf,
    290					       size_t count, loff_t *ppos)
    291{
    292	struct ieee80211_sta *sta = file->private_data;
    293	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
    294	struct ath10k *ar = arsta->arvif->ar;
    295	u32 tid, status;
    296	int ret;
    297	char buf[64] = {0};
    298
    299	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
    300				     user_buf, count);
    301	if (ret <= 0)
    302		return ret;
    303
    304	ret = sscanf(buf, "%u %u", &tid, &status);
    305	if (ret != 2)
    306		return -EINVAL;
    307
    308	/* Valid TID values are 0 through 15 */
    309	if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
    310		return -EINVAL;
    311
    312	mutex_lock(&ar->conf_mutex);
    313	if ((ar->state != ATH10K_STATE_ON) ||
    314	    (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
    315		ret = count;
    316		goto out;
    317	}
    318
    319	ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
    320					tid, status);
    321	if (ret) {
    322		ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
    323			    arsta->arvif->vdev_id, sta->addr, tid, status);
    324	}
    325	ret = count;
    326out:
    327	mutex_unlock(&ar->conf_mutex);
    328	return ret;
    329}
    330
    331static const struct file_operations fops_addba_resp = {
    332	.write = ath10k_dbg_sta_write_addba_resp,
    333	.open = simple_open,
    334	.owner = THIS_MODULE,
    335	.llseek = default_llseek,
    336};
    337
    338static ssize_t ath10k_dbg_sta_write_delba(struct file *file,
    339					  const char __user *user_buf,
    340					  size_t count, loff_t *ppos)
    341{
    342	struct ieee80211_sta *sta = file->private_data;
    343	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
    344	struct ath10k *ar = arsta->arvif->ar;
    345	u32 tid, initiator, reason;
    346	int ret;
    347	char buf[64] = {0};
    348
    349	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
    350				     user_buf, count);
    351	if (ret <= 0)
    352		return ret;
    353
    354	ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
    355	if (ret != 3)
    356		return -EINVAL;
    357
    358	/* Valid TID values are 0 through 15 */
    359	if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
    360		return -EINVAL;
    361
    362	mutex_lock(&ar->conf_mutex);
    363	if ((ar->state != ATH10K_STATE_ON) ||
    364	    (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
    365		ret = count;
    366		goto out;
    367	}
    368
    369	ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
    370				    tid, initiator, reason);
    371	if (ret) {
    372		ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
    373			    arsta->arvif->vdev_id, sta->addr, tid, initiator,
    374			    reason);
    375	}
    376	ret = count;
    377out:
    378	mutex_unlock(&ar->conf_mutex);
    379	return ret;
    380}
    381
    382static const struct file_operations fops_delba = {
    383	.write = ath10k_dbg_sta_write_delba,
    384	.open = simple_open,
    385	.owner = THIS_MODULE,
    386	.llseek = default_llseek,
    387};
    388
    389static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(struct file *file,
    390						      char __user *user_buf,
    391						      size_t count,
    392						      loff_t *ppos)
    393{
    394	struct ieee80211_sta *sta = file->private_data;
    395	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
    396	struct ath10k *ar = arsta->arvif->ar;
    397	char buf[8];
    398	int len = 0;
    399
    400	mutex_lock(&ar->conf_mutex);
    401	len = scnprintf(buf, sizeof(buf) - len,
    402			"Write 1 to once trigger the debug logs\n");
    403	mutex_unlock(&ar->conf_mutex);
    404
    405	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    406}
    407
    408static ssize_t
    409ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
    410					const char __user *user_buf,
    411					size_t count, loff_t *ppos)
    412{
    413	struct ieee80211_sta *sta = file->private_data;
    414	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
    415	struct ath10k *ar = arsta->arvif->ar;
    416	u8 peer_debug_trigger;
    417	int ret;
    418
    419	if (kstrtou8_from_user(user_buf, count, 0, &peer_debug_trigger))
    420		return -EINVAL;
    421
    422	if (peer_debug_trigger != 1)
    423		return -EINVAL;
    424
    425	mutex_lock(&ar->conf_mutex);
    426
    427	if (ar->state != ATH10K_STATE_ON) {
    428		ret = -ENETDOWN;
    429		goto out;
    430	}
    431
    432	ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
    433					ar->wmi.peer_param->debug, peer_debug_trigger);
    434	if (ret) {
    435		ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
    436			    ret);
    437		goto out;
    438	}
    439out:
    440	mutex_unlock(&ar->conf_mutex);
    441	return count;
    442}
    443
    444static const struct file_operations fops_peer_debug_trigger = {
    445	.open = simple_open,
    446	.read = ath10k_dbg_sta_read_peer_debug_trigger,
    447	.write = ath10k_dbg_sta_write_peer_debug_trigger,
    448	.owner = THIS_MODULE,
    449	.llseek = default_llseek,
    450};
    451
    452static ssize_t ath10k_dbg_sta_read_peer_ps_state(struct file *file,
    453						 char __user *user_buf,
    454						 size_t count, loff_t *ppos)
    455{
    456	struct ieee80211_sta *sta = file->private_data;
    457	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
    458	struct ath10k *ar = arsta->arvif->ar;
    459	char buf[20];
    460	int len = 0;
    461
    462	spin_lock_bh(&ar->data_lock);
    463
    464	len = scnprintf(buf, sizeof(buf) - len, "%d\n",
    465			arsta->peer_ps_state);
    466
    467	spin_unlock_bh(&ar->data_lock);
    468
    469	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    470}
    471
    472static const struct file_operations fops_peer_ps_state = {
    473	.open = simple_open,
    474	.read = ath10k_dbg_sta_read_peer_ps_state,
    475	.owner = THIS_MODULE,
    476	.llseek = default_llseek,
    477};
    478
    479static char *get_err_str(enum ath10k_pkt_rx_err i)
    480{
    481	switch (i) {
    482	case ATH10K_PKT_RX_ERR_FCS:
    483		return "fcs_err";
    484	case ATH10K_PKT_RX_ERR_TKIP:
    485		return "tkip_err";
    486	case ATH10K_PKT_RX_ERR_CRYPT:
    487		return "crypt_err";
    488	case ATH10K_PKT_RX_ERR_PEER_IDX_INVAL:
    489		return "peer_idx_inval";
    490	case ATH10K_PKT_RX_ERR_MAX:
    491		return "unknown";
    492	}
    493
    494	return "unknown";
    495}
    496
    497static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i)
    498{
    499	switch (i) {
    500	case ATH10K_AMPDU_SUBFRM_NUM_10:
    501		return "upto 10";
    502	case ATH10K_AMPDU_SUBFRM_NUM_20:
    503		return "11-20";
    504	case ATH10K_AMPDU_SUBFRM_NUM_30:
    505		return "21-30";
    506	case ATH10K_AMPDU_SUBFRM_NUM_40:
    507		return "31-40";
    508	case ATH10K_AMPDU_SUBFRM_NUM_50:
    509		return "41-50";
    510	case ATH10K_AMPDU_SUBFRM_NUM_60:
    511		return "51-60";
    512	case ATH10K_AMPDU_SUBFRM_NUM_MORE:
    513		return ">60";
    514	case ATH10K_AMPDU_SUBFRM_NUM_MAX:
    515		return "0";
    516	}
    517
    518	return "0";
    519}
    520
    521static char *get_num_amsdu_subfrm_str(enum ath10k_amsdu_subfrm_num i)
    522{
    523	switch (i) {
    524	case ATH10K_AMSDU_SUBFRM_NUM_1:
    525		return "1";
    526	case ATH10K_AMSDU_SUBFRM_NUM_2:
    527		return "2";
    528	case ATH10K_AMSDU_SUBFRM_NUM_3:
    529		return "3";
    530	case ATH10K_AMSDU_SUBFRM_NUM_4:
    531		return "4";
    532	case ATH10K_AMSDU_SUBFRM_NUM_MORE:
    533		return ">4";
    534	case ATH10K_AMSDU_SUBFRM_NUM_MAX:
    535		return "0";
    536	}
    537
    538	return "0";
    539}
    540
    541#define PRINT_TID_STATS(_field, _tabs) \
    542	do { \
    543		int k = 0; \
    544		for (j = 0; j <= IEEE80211_NUM_TIDS; j++) { \
    545			if (ar->sta_tid_stats_mask & BIT(j))  { \
    546				len += scnprintf(buf + len, buf_len - len, \
    547						 "[%02d] %-10lu  ", \
    548						 j, stats[j]._field); \
    549				k++; \
    550				if (k % 8 == 0)  { \
    551					len += scnprintf(buf + len, \
    552							 buf_len - len, "\n"); \
    553					len += scnprintf(buf + len, \
    554							 buf_len - len, \
    555							 _tabs); \
    556				} \
    557			} \
    558		} \
    559		len += scnprintf(buf + len, buf_len - len, "\n"); \
    560	} while (0)
    561
    562static ssize_t ath10k_dbg_sta_read_tid_stats(struct file *file,
    563					     char __user *user_buf,
    564					     size_t count, loff_t *ppos)
    565{
    566	struct ieee80211_sta *sta = file->private_data;
    567	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
    568	struct ath10k *ar = arsta->arvif->ar;
    569	struct ath10k_sta_tid_stats *stats = arsta->tid_stats;
    570	size_t len = 0, buf_len = 1048 * IEEE80211_NUM_TIDS;
    571	char *buf;
    572	int i, j;
    573	ssize_t ret;
    574
    575	buf = kzalloc(buf_len, GFP_KERNEL);
    576	if (!buf)
    577		return -ENOMEM;
    578
    579	mutex_lock(&ar->conf_mutex);
    580
    581	spin_lock_bh(&ar->data_lock);
    582
    583	len += scnprintf(buf + len, buf_len - len,
    584			 "\n\t\tDriver Rx pkt stats per tid, ([tid] count)\n");
    585	len += scnprintf(buf + len, buf_len - len,
    586			 "\t\t------------------------------------------\n");
    587	len += scnprintf(buf + len, buf_len - len, "MSDUs from FW\t\t\t");
    588	PRINT_TID_STATS(rx_pkt_from_fw, "\t\t\t\t");
    589
    590	len += scnprintf(buf + len, buf_len - len, "MSDUs unchained\t\t\t");
    591	PRINT_TID_STATS(rx_pkt_unchained, "\t\t\t\t");
    592
    593	len += scnprintf(buf + len, buf_len - len,
    594			 "MSDUs locally dropped:chained\t");
    595	PRINT_TID_STATS(rx_pkt_drop_chained, "\t\t\t\t");
    596
    597	len += scnprintf(buf + len, buf_len - len,
    598			 "MSDUs locally dropped:filtered\t");
    599	PRINT_TID_STATS(rx_pkt_drop_filter, "\t\t\t\t");
    600
    601	len += scnprintf(buf + len, buf_len - len,
    602			 "MSDUs queued for mac80211\t");
    603	PRINT_TID_STATS(rx_pkt_queued_for_mac, "\t\t\t\t");
    604
    605	for (i = 0; i < ATH10K_PKT_RX_ERR_MAX; i++) {
    606		len += scnprintf(buf + len, buf_len - len,
    607				 "MSDUs with error:%s\t", get_err_str(i));
    608		PRINT_TID_STATS(rx_pkt_err[i], "\t\t\t\t");
    609	}
    610
    611	len += scnprintf(buf + len, buf_len - len, "\n");
    612	for (i = 0; i < ATH10K_AMPDU_SUBFRM_NUM_MAX; i++) {
    613		len += scnprintf(buf + len, buf_len - len,
    614				 "A-MPDU num subframes %s\t",
    615				 get_num_ampdu_subfrm_str(i));
    616		PRINT_TID_STATS(rx_pkt_ampdu[i], "\t\t\t\t");
    617	}
    618
    619	len += scnprintf(buf + len, buf_len - len, "\n");
    620	for (i = 0; i < ATH10K_AMSDU_SUBFRM_NUM_MAX; i++) {
    621		len += scnprintf(buf + len, buf_len - len,
    622				 "A-MSDU num subframes %s\t\t",
    623				 get_num_amsdu_subfrm_str(i));
    624		PRINT_TID_STATS(rx_pkt_amsdu[i], "\t\t\t\t");
    625	}
    626
    627	spin_unlock_bh(&ar->data_lock);
    628
    629	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
    630
    631	kfree(buf);
    632
    633	mutex_unlock(&ar->conf_mutex);
    634
    635	return ret;
    636}
    637
    638static const struct file_operations fops_tid_stats_dump = {
    639	.open = simple_open,
    640	.read = ath10k_dbg_sta_read_tid_stats,
    641	.owner = THIS_MODULE,
    642	.llseek = default_llseek,
    643};
    644
    645static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file,
    646					    char __user *user_buf,
    647					    size_t count, loff_t *ppos)
    648{
    649	struct ieee80211_sta *sta = file->private_data;
    650	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
    651	struct ath10k *ar = arsta->arvif->ar;
    652	struct ath10k_htt_data_stats *stats;
    653	const char *str_name[ATH10K_STATS_TYPE_MAX] = {"succ", "fail",
    654						       "retry", "ampdu"};
    655	const char *str[ATH10K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
    656	int len = 0, i, j, k, retval = 0;
    657	const int size = 16 * 4096;
    658	char *buf;
    659
    660	buf = kzalloc(size, GFP_KERNEL);
    661	if (!buf)
    662		return -ENOMEM;
    663
    664	mutex_lock(&ar->conf_mutex);
    665
    666	if (!arsta->tx_stats) {
    667		ath10k_warn(ar, "failed to get tx stats");
    668		mutex_unlock(&ar->conf_mutex);
    669		kfree(buf);
    670		return 0;
    671	}
    672
    673	spin_lock_bh(&ar->data_lock);
    674	for (k = 0; k < ATH10K_STATS_TYPE_MAX; k++) {
    675		for (j = 0; j < ATH10K_COUNTER_TYPE_MAX; j++) {
    676			stats = &arsta->tx_stats->stats[k];
    677			len += scnprintf(buf + len, size - len, "%s_%s\n",
    678					 str_name[k],
    679					 str[j]);
    680			len += scnprintf(buf + len, size - len,
    681					 " VHT MCS %s\n",
    682					 str[j]);
    683			for (i = 0; i < ATH10K_VHT_MCS_NUM; i++)
    684				len += scnprintf(buf + len, size - len,
    685						 "  %llu ",
    686						 stats->vht[j][i]);
    687			len += scnprintf(buf + len, size - len, "\n");
    688			len += scnprintf(buf + len, size - len, " HT MCS %s\n",
    689					 str[j]);
    690			for (i = 0; i < ATH10K_HT_MCS_NUM; i++)
    691				len += scnprintf(buf + len, size - len,
    692						 "  %llu ", stats->ht[j][i]);
    693			len += scnprintf(buf + len, size - len, "\n");
    694			len += scnprintf(buf + len, size - len,
    695					" BW %s (20,5,10,40,80,160 MHz)\n", str[j]);
    696			len += scnprintf(buf + len, size - len,
    697					 "  %llu %llu %llu %llu %llu %llu\n",
    698					 stats->bw[j][0], stats->bw[j][1],
    699					 stats->bw[j][2], stats->bw[j][3],
    700					 stats->bw[j][4], stats->bw[j][5]);
    701			len += scnprintf(buf + len, size - len,
    702					 " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
    703			len += scnprintf(buf + len, size - len,
    704					 "  %llu %llu %llu %llu\n",
    705					 stats->nss[j][0], stats->nss[j][1],
    706					 stats->nss[j][2], stats->nss[j][3]);
    707			len += scnprintf(buf + len, size - len,
    708					 " GI %s (LGI,SGI)\n",
    709					 str[j]);
    710			len += scnprintf(buf + len, size - len, "  %llu %llu\n",
    711					 stats->gi[j][0], stats->gi[j][1]);
    712			len += scnprintf(buf + len, size - len,
    713					 " legacy rate %s (1,2 ... Mbps)\n  ",
    714					 str[j]);
    715			for (i = 0; i < ATH10K_LEGACY_NUM; i++)
    716				len += scnprintf(buf + len, size - len, "%llu ",
    717						 stats->legacy[j][i]);
    718			len += scnprintf(buf + len, size - len, "\n");
    719			len += scnprintf(buf + len, size - len,
    720					 " Rate table %s (1,2 ... Mbps)\n  ",
    721					 str[j]);
    722			for (i = 0; i < ATH10K_RATE_TABLE_NUM; i++) {
    723				len += scnprintf(buf + len, size - len, "%llu ",
    724						 stats->rate_table[j][i]);
    725				if (!((i + 1) % 8))
    726					len +=
    727					scnprintf(buf + len, size - len, "\n  ");
    728			}
    729		}
    730	}
    731
    732	len += scnprintf(buf + len, size - len,
    733			 "\nTX duration\n %llu usecs\n",
    734			 arsta->tx_stats->tx_duration);
    735	len += scnprintf(buf + len, size - len,
    736			"BA fails\n %llu\n", arsta->tx_stats->ba_fails);
    737	len += scnprintf(buf + len, size - len,
    738			"ack fails\n %llu\n", arsta->tx_stats->ack_fails);
    739	spin_unlock_bh(&ar->data_lock);
    740
    741	if (len > size)
    742		len = size;
    743	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
    744	kfree(buf);
    745
    746	mutex_unlock(&ar->conf_mutex);
    747	return retval;
    748}
    749
    750static const struct file_operations fops_tx_stats = {
    751	.read = ath10k_dbg_sta_dump_tx_stats,
    752	.open = simple_open,
    753	.owner = THIS_MODULE,
    754	.llseek = default_llseek,
    755};
    756
    757void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
    758			    struct ieee80211_sta *sta, struct dentry *dir)
    759{
    760	struct ath10k *ar = hw->priv;
    761
    762	debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
    763	debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
    764	debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
    765	debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
    766	debugfs_create_file("peer_debug_trigger", 0600, dir, sta,
    767			    &fops_peer_debug_trigger);
    768	debugfs_create_file("dump_tid_stats", 0400, dir, sta,
    769			    &fops_tid_stats_dump);
    770
    771	if (ath10k_peer_stats_enabled(ar) &&
    772	    ath10k_debug_is_extd_tx_stats_enabled(ar))
    773		debugfs_create_file("tx_stats", 0400, dir, sta,
    774				    &fops_tx_stats);
    775	debugfs_create_file("peer_ps_state", 0400, dir, sta,
    776			    &fops_peer_ps_state);
    777}