162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#include <linux/netdevice.h>
662306a36Sopenharmony_ci#include <linux/types.h>
762306a36Sopenharmony_ci#include <linux/skbuff.h>
862306a36Sopenharmony_ci#include <linux/debugfs.h>
962306a36Sopenharmony_ci#include <linux/ieee80211.h>
1062306a36Sopenharmony_ci#include <linux/export.h>
1162306a36Sopenharmony_ci#include <net/mac80211.h>
1262306a36Sopenharmony_ci#include "rc80211_minstrel_ht.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistruct minstrel_debugfs_info {
1562306a36Sopenharmony_ci	size_t len;
1662306a36Sopenharmony_ci	char buf[];
1762306a36Sopenharmony_ci};
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic ssize_t
2062306a36Sopenharmony_ciminstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	struct minstrel_debugfs_info *ms;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	ms = file->private_data;
2562306a36Sopenharmony_ci	return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
2662306a36Sopenharmony_ci}
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic int
2962306a36Sopenharmony_ciminstrel_stats_release(struct inode *inode, struct file *file)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	kfree(file->private_data);
3262306a36Sopenharmony_ci	return 0;
3362306a36Sopenharmony_ci}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic bool
3662306a36Sopenharmony_ciminstrel_ht_is_sample_rate(struct minstrel_ht_sta *mi, int idx)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	int type, i;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	for (type = 0; type < ARRAY_SIZE(mi->sample); type++)
4162306a36Sopenharmony_ci		for (i = 0; i < MINSTREL_SAMPLE_RATES; i++)
4262306a36Sopenharmony_ci			if (mi->sample[type].cur_sample_rates[i] == idx)
4362306a36Sopenharmony_ci				return true;
4462306a36Sopenharmony_ci	return false;
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic char *
4862306a36Sopenharmony_ciminstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	const struct mcs_group *mg;
5162306a36Sopenharmony_ci	unsigned int j, tp_max, tp_avg, eprob, tx_time;
5262306a36Sopenharmony_ci	char htmode = '2';
5362306a36Sopenharmony_ci	char gimode = 'L';
5462306a36Sopenharmony_ci	u32 gflags;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	if (!mi->supported[i])
5762306a36Sopenharmony_ci		return p;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	mg = &minstrel_mcs_groups[i];
6062306a36Sopenharmony_ci	gflags = mg->flags;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH)
6362306a36Sopenharmony_ci		htmode = '4';
6462306a36Sopenharmony_ci	else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH)
6562306a36Sopenharmony_ci		htmode = '8';
6662306a36Sopenharmony_ci	if (gflags & IEEE80211_TX_RC_SHORT_GI)
6762306a36Sopenharmony_ci		gimode = 'S';
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	for (j = 0; j < MCS_GROUP_RATES; j++) {
7062306a36Sopenharmony_ci		struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
7162306a36Sopenharmony_ci		int idx = MI_RATE(i, j);
7262306a36Sopenharmony_ci		unsigned int duration;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci		if (!(mi->supported[i] & BIT(j)))
7562306a36Sopenharmony_ci			continue;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci		if (gflags & IEEE80211_TX_RC_MCS) {
7862306a36Sopenharmony_ci			p += sprintf(p, "HT%c0  ", htmode);
7962306a36Sopenharmony_ci			p += sprintf(p, "%cGI  ", gimode);
8062306a36Sopenharmony_ci			p += sprintf(p, "%d  ", mg->streams);
8162306a36Sopenharmony_ci		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
8262306a36Sopenharmony_ci			p += sprintf(p, "VHT%c0 ", htmode);
8362306a36Sopenharmony_ci			p += sprintf(p, "%cGI ", gimode);
8462306a36Sopenharmony_ci			p += sprintf(p, "%d  ", mg->streams);
8562306a36Sopenharmony_ci		} else if (i == MINSTREL_OFDM_GROUP) {
8662306a36Sopenharmony_ci			p += sprintf(p, "OFDM       ");
8762306a36Sopenharmony_ci			p += sprintf(p, "1 ");
8862306a36Sopenharmony_ci		} else {
8962306a36Sopenharmony_ci			p += sprintf(p, "CCK    ");
9062306a36Sopenharmony_ci			p += sprintf(p, "%cP  ", j < 4 ? 'L' : 'S');
9162306a36Sopenharmony_ci			p += sprintf(p, "1 ");
9262306a36Sopenharmony_ci		}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci		*(p++) = (idx == mi->max_tp_rate[0]) ? 'A' : ' ';
9562306a36Sopenharmony_ci		*(p++) = (idx == mi->max_tp_rate[1]) ? 'B' : ' ';
9662306a36Sopenharmony_ci		*(p++) = (idx == mi->max_tp_rate[2]) ? 'C' : ' ';
9762306a36Sopenharmony_ci		*(p++) = (idx == mi->max_tp_rate[3]) ? 'D' : ' ';
9862306a36Sopenharmony_ci		*(p++) = (idx == mi->max_prob_rate) ? 'P' : ' ';
9962306a36Sopenharmony_ci		*(p++) = minstrel_ht_is_sample_rate(mi, idx) ? 'S' : ' ';
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci		if (gflags & IEEE80211_TX_RC_MCS) {
10262306a36Sopenharmony_ci			p += sprintf(p, "  MCS%-2u", (mg->streams - 1) * 8 + j);
10362306a36Sopenharmony_ci		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
10462306a36Sopenharmony_ci			p += sprintf(p, "  MCS%-1u/%1u", j, mg->streams);
10562306a36Sopenharmony_ci		} else {
10662306a36Sopenharmony_ci			int r;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci			if (i == MINSTREL_OFDM_GROUP)
10962306a36Sopenharmony_ci				r = minstrel_ofdm_bitrates[j % 8];
11062306a36Sopenharmony_ci			else
11162306a36Sopenharmony_ci				r = minstrel_cck_bitrates[j % 4];
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci			p += sprintf(p, "   %2u.%1uM", r / 10, r % 10);
11462306a36Sopenharmony_ci		}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci		p += sprintf(p, "  %3u  ", idx);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci		/* tx_time[rate(i)] in usec */
11962306a36Sopenharmony_ci		duration = mg->duration[j];
12062306a36Sopenharmony_ci		duration <<= mg->shift;
12162306a36Sopenharmony_ci		tx_time = DIV_ROUND_CLOSEST(duration, 1000);
12262306a36Sopenharmony_ci		p += sprintf(p, "%6u  ", tx_time);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
12562306a36Sopenharmony_ci		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg);
12662306a36Sopenharmony_ci		eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci		p += sprintf(p, "%4u.%1u    %4u.%1u     %3u.%1u"
12962306a36Sopenharmony_ci				"     %3u   %3u %-3u   "
13062306a36Sopenharmony_ci				"%9llu   %-9llu\n",
13162306a36Sopenharmony_ci				tp_max / 10, tp_max % 10,
13262306a36Sopenharmony_ci				tp_avg / 10, tp_avg % 10,
13362306a36Sopenharmony_ci				eprob / 10, eprob % 10,
13462306a36Sopenharmony_ci				mrs->retry_count,
13562306a36Sopenharmony_ci				mrs->last_success,
13662306a36Sopenharmony_ci				mrs->last_attempts,
13762306a36Sopenharmony_ci				(unsigned long long)mrs->succ_hist,
13862306a36Sopenharmony_ci				(unsigned long long)mrs->att_hist);
13962306a36Sopenharmony_ci	}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	return p;
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic int
14562306a36Sopenharmony_ciminstrel_ht_stats_open(struct inode *inode, struct file *file)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	struct minstrel_ht_sta *mi = inode->i_private;
14862306a36Sopenharmony_ci	struct minstrel_debugfs_info *ms;
14962306a36Sopenharmony_ci	unsigned int i;
15062306a36Sopenharmony_ci	char *p;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	ms = kmalloc(32768, GFP_KERNEL);
15362306a36Sopenharmony_ci	if (!ms)
15462306a36Sopenharmony_ci		return -ENOMEM;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	file->private_data = ms;
15762306a36Sopenharmony_ci	p = ms->buf;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	p += sprintf(p, "\n");
16062306a36Sopenharmony_ci	p += sprintf(p,
16162306a36Sopenharmony_ci		     "              best    ____________rate__________    ____statistics___    _____last____    ______sum-of________\n");
16262306a36Sopenharmony_ci	p += sprintf(p,
16362306a36Sopenharmony_ci		     "mode guard #  rate   [name   idx airtime  max_tp]  [avg(tp) avg(prob)]  [retry|suc|att]  [#success | #attempts]\n");
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
16662306a36Sopenharmony_ci	for (i = 0; i < MINSTREL_CCK_GROUP; i++)
16762306a36Sopenharmony_ci		p = minstrel_ht_stats_dump(mi, i, p);
16862306a36Sopenharmony_ci	for (i++; i < ARRAY_SIZE(mi->groups); i++)
16962306a36Sopenharmony_ci		p = minstrel_ht_stats_dump(mi, i, p);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	p += sprintf(p, "\nTotal packet count::    ideal %d      "
17262306a36Sopenharmony_ci			"lookaround %d\n",
17362306a36Sopenharmony_ci			max(0, (int) mi->total_packets - (int) mi->sample_packets),
17462306a36Sopenharmony_ci			mi->sample_packets);
17562306a36Sopenharmony_ci	if (mi->avg_ampdu_len)
17662306a36Sopenharmony_ci		p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d\n",
17762306a36Sopenharmony_ci			MINSTREL_TRUNC(mi->avg_ampdu_len),
17862306a36Sopenharmony_ci			MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
17962306a36Sopenharmony_ci	ms->len = p - ms->buf;
18062306a36Sopenharmony_ci	WARN_ON(ms->len + sizeof(*ms) > 32768);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	return nonseekable_open(inode, file);
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic const struct file_operations minstrel_ht_stat_fops = {
18662306a36Sopenharmony_ci	.owner = THIS_MODULE,
18762306a36Sopenharmony_ci	.open = minstrel_ht_stats_open,
18862306a36Sopenharmony_ci	.read = minstrel_stats_read,
18962306a36Sopenharmony_ci	.release = minstrel_stats_release,
19062306a36Sopenharmony_ci	.llseek = no_llseek,
19162306a36Sopenharmony_ci};
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistatic char *
19462306a36Sopenharmony_ciminstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	const struct mcs_group *mg;
19762306a36Sopenharmony_ci	unsigned int j, tp_max, tp_avg, eprob, tx_time;
19862306a36Sopenharmony_ci	char htmode = '2';
19962306a36Sopenharmony_ci	char gimode = 'L';
20062306a36Sopenharmony_ci	u32 gflags;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	if (!mi->supported[i])
20362306a36Sopenharmony_ci		return p;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	mg = &minstrel_mcs_groups[i];
20662306a36Sopenharmony_ci	gflags = mg->flags;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH)
20962306a36Sopenharmony_ci		htmode = '4';
21062306a36Sopenharmony_ci	else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH)
21162306a36Sopenharmony_ci		htmode = '8';
21262306a36Sopenharmony_ci	if (gflags & IEEE80211_TX_RC_SHORT_GI)
21362306a36Sopenharmony_ci		gimode = 'S';
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	for (j = 0; j < MCS_GROUP_RATES; j++) {
21662306a36Sopenharmony_ci		struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
21762306a36Sopenharmony_ci		int idx = MI_RATE(i, j);
21862306a36Sopenharmony_ci		unsigned int duration;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci		if (!(mi->supported[i] & BIT(j)))
22162306a36Sopenharmony_ci			continue;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci		if (gflags & IEEE80211_TX_RC_MCS) {
22462306a36Sopenharmony_ci			p += sprintf(p, "HT%c0,", htmode);
22562306a36Sopenharmony_ci			p += sprintf(p, "%cGI,", gimode);
22662306a36Sopenharmony_ci			p += sprintf(p, "%d,", mg->streams);
22762306a36Sopenharmony_ci		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
22862306a36Sopenharmony_ci			p += sprintf(p, "VHT%c0,", htmode);
22962306a36Sopenharmony_ci			p += sprintf(p, "%cGI,", gimode);
23062306a36Sopenharmony_ci			p += sprintf(p, "%d,", mg->streams);
23162306a36Sopenharmony_ci		} else if (i == MINSTREL_OFDM_GROUP) {
23262306a36Sopenharmony_ci			p += sprintf(p, "OFDM,,1,");
23362306a36Sopenharmony_ci		} else {
23462306a36Sopenharmony_ci			p += sprintf(p, "CCK,");
23562306a36Sopenharmony_ci			p += sprintf(p, "%cP,", j < 4 ? 'L' : 'S');
23662306a36Sopenharmony_ci			p += sprintf(p, "1,");
23762306a36Sopenharmony_ci		}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[0]) ? "A" : ""));
24062306a36Sopenharmony_ci		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[1]) ? "B" : ""));
24162306a36Sopenharmony_ci		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[2]) ? "C" : ""));
24262306a36Sopenharmony_ci		p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[3]) ? "D" : ""));
24362306a36Sopenharmony_ci		p += sprintf(p, "%s" ,((idx == mi->max_prob_rate) ? "P" : ""));
24462306a36Sopenharmony_ci		p += sprintf(p, "%s", (minstrel_ht_is_sample_rate(mi, idx) ? "S" : ""));
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci		if (gflags & IEEE80211_TX_RC_MCS) {
24762306a36Sopenharmony_ci			p += sprintf(p, ",MCS%-2u,", (mg->streams - 1) * 8 + j);
24862306a36Sopenharmony_ci		} else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
24962306a36Sopenharmony_ci			p += sprintf(p, ",MCS%-1u/%1u,", j, mg->streams);
25062306a36Sopenharmony_ci		} else {
25162306a36Sopenharmony_ci			int r;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci			if (i == MINSTREL_OFDM_GROUP)
25462306a36Sopenharmony_ci				r = minstrel_ofdm_bitrates[j % 8];
25562306a36Sopenharmony_ci			else
25662306a36Sopenharmony_ci				r = minstrel_cck_bitrates[j % 4];
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci			p += sprintf(p, ",%2u.%1uM,", r / 10, r % 10);
25962306a36Sopenharmony_ci		}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci		p += sprintf(p, "%u,", idx);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci		duration = mg->duration[j];
26462306a36Sopenharmony_ci		duration <<= mg->shift;
26562306a36Sopenharmony_ci		tx_time = DIV_ROUND_CLOSEST(duration, 1000);
26662306a36Sopenharmony_ci		p += sprintf(p, "%u,", tx_time);
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
26962306a36Sopenharmony_ci		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg);
27062306a36Sopenharmony_ci		eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,"
27362306a36Sopenharmony_ci				"%u,%llu,%llu,",
27462306a36Sopenharmony_ci				tp_max / 10, tp_max % 10,
27562306a36Sopenharmony_ci				tp_avg / 10, tp_avg % 10,
27662306a36Sopenharmony_ci				eprob / 10, eprob % 10,
27762306a36Sopenharmony_ci				mrs->retry_count,
27862306a36Sopenharmony_ci				mrs->last_success,
27962306a36Sopenharmony_ci				mrs->last_attempts,
28062306a36Sopenharmony_ci				(unsigned long long)mrs->succ_hist,
28162306a36Sopenharmony_ci				(unsigned long long)mrs->att_hist);
28262306a36Sopenharmony_ci		p += sprintf(p, "%d,%d,%d.%d\n",
28362306a36Sopenharmony_ci				max(0, (int) mi->total_packets -
28462306a36Sopenharmony_ci				(int) mi->sample_packets),
28562306a36Sopenharmony_ci				mi->sample_packets,
28662306a36Sopenharmony_ci				MINSTREL_TRUNC(mi->avg_ampdu_len),
28762306a36Sopenharmony_ci				MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	return p;
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_cistatic int
29462306a36Sopenharmony_ciminstrel_ht_stats_csv_open(struct inode *inode, struct file *file)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	struct minstrel_ht_sta *mi = inode->i_private;
29762306a36Sopenharmony_ci	struct minstrel_debugfs_info *ms;
29862306a36Sopenharmony_ci	unsigned int i;
29962306a36Sopenharmony_ci	char *p;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	ms = kmalloc(32768, GFP_KERNEL);
30262306a36Sopenharmony_ci	if (!ms)
30362306a36Sopenharmony_ci		return -ENOMEM;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	file->private_data = ms;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	p = ms->buf;
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	p = minstrel_ht_stats_csv_dump(mi, MINSTREL_CCK_GROUP, p);
31062306a36Sopenharmony_ci	for (i = 0; i < MINSTREL_CCK_GROUP; i++)
31162306a36Sopenharmony_ci		p = minstrel_ht_stats_csv_dump(mi, i, p);
31262306a36Sopenharmony_ci	for (i++; i < ARRAY_SIZE(mi->groups); i++)
31362306a36Sopenharmony_ci		p = minstrel_ht_stats_csv_dump(mi, i, p);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	ms->len = p - ms->buf;
31662306a36Sopenharmony_ci	WARN_ON(ms->len + sizeof(*ms) > 32768);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	return nonseekable_open(inode, file);
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic const struct file_operations minstrel_ht_stat_csv_fops = {
32262306a36Sopenharmony_ci	.owner = THIS_MODULE,
32362306a36Sopenharmony_ci	.open = minstrel_ht_stats_csv_open,
32462306a36Sopenharmony_ci	.read = minstrel_stats_read,
32562306a36Sopenharmony_ci	.release = minstrel_stats_release,
32662306a36Sopenharmony_ci	.llseek = no_llseek,
32762306a36Sopenharmony_ci};
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_civoid
33062306a36Sopenharmony_ciminstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
33162306a36Sopenharmony_ci{
33262306a36Sopenharmony_ci	debugfs_create_file("rc_stats", 0444, dir, priv_sta,
33362306a36Sopenharmony_ci			    &minstrel_ht_stat_fops);
33462306a36Sopenharmony_ci	debugfs_create_file("rc_stats_csv", 0444, dir, priv_sta,
33562306a36Sopenharmony_ci			    &minstrel_ht_stat_csv_fops);
33662306a36Sopenharmony_ci}
337