ath10k: Add rx rate histogram for data packet

Add the rate histogram for rate_index, band, ht,
vht and vht_nss for received data packet.

CRs-Fixed: 2019645
Change-Id: I52ae3b94c886b8a200162cd7d2a220548296bf91
Signed-off-by: Ashutosh Kumar <askuma@codeaurora.org>
This commit is contained in:
Ashutosh Kumar 2017-02-25 10:44:32 +05:30 committed by Gerrit - the friendly Code Review server
parent 27489753bf
commit 80501bb4e4
5 changed files with 288 additions and 2 deletions

View file

@ -2390,6 +2390,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
mutex_init(&ar->conf_mutex);
spin_lock_init(&ar->data_lock);
spin_lock_init(&ar->txqs_lock);
spin_lock_init(&ar->datapath_rx_stat_lock);
INIT_LIST_HEAD(&ar->txqs);
INIT_LIST_HEAD(&ar->peers);

View file

@ -70,6 +70,20 @@
#define ATH10K_NAPI_BUDGET 64
#define ATH10K_NAPI_QUOTA_LIMIT 60
#define ATH10K_RX_MCS_MIN 0
#define ATH10K_RX_HT_MCS_MAX 32
#define ATH10K_RX_VHT_RATEIDX_MAX 9
#define ATH10K_RX_VHT_MCS_MAX 20 /* For 2x2 */
#define ATH10K_RX_NSS_MIN 0
#define ATH10K_RX_NSS_MAX 5
enum ath10k_datapath_rx_band {
ATH10K_BAND_MIN,
ATH10K_BAND_2GHZ = ATH10K_BAND_MIN,
ATH10K_BAND_5GHZ,
ATH10K_BAND_MAX,
};
struct ath10k;
enum ath10k_bus {
@ -703,6 +717,20 @@ struct ath10k_fw_components {
struct ath10k_fw_file fw_file;
};
struct datapath_rx_stats {
u32 no_of_packets;
u32 short_gi_pkts;
u32 ht_rate_indx[ATH10K_RX_HT_MCS_MAX + 1];
u32 vht_rate_indx[ATH10K_RX_VHT_MCS_MAX + 1];
u32 ht_rate_packets;
u32 vht_rate_packets;
u32 legacy_pkt;
u32 nss[ATH10K_RX_NSS_MAX + 1];
u32 num_pkts_40Mhz;
u32 num_pkts_80Mhz;
u32 band[ATH10K_BAND_MAX + 1];
};
struct ath10k {
struct ath_common ath_common;
struct ieee80211_hw *hw;
@ -900,7 +928,10 @@ struct ath10k {
enum ath10k_spectral_mode mode;
struct ath10k_spec_scan config;
} spectral;
struct datapath_rx_stats *rx_stats;
#endif
/* prevent concurrency histogram for receiving data packet */
spinlock_t datapath_rx_stat_lock;
struct {
/* protected by conf_mutex */

View file

@ -537,6 +537,230 @@ static const struct file_operations fops_fw_stats = {
.llseek = default_llseek,
};
static inline int is_vht_rate_valid(u32 rate_indx)
{
if ((rate_indx >= ATH10K_RX_MCS_MIN) &&
(rate_indx <= ATH10K_RX_VHT_RATEIDX_MAX))
return 1;
else
return 0;
}
void fill_datapath_stats(struct ath10k *ar, struct ieee80211_rx_status *status)
{
struct datapath_rx_stats *stat_cnt = ar->rx_stats;
spin_lock_bh(&ar->datapath_rx_stat_lock);
stat_cnt->no_of_packets += 1;
if (!(stat_cnt->no_of_packets)) {
memset(stat_cnt, 0, sizeof(*stat_cnt));
stat_cnt->no_of_packets += 1;
}
if (status->flag & RX_FLAG_SHORT_GI)
stat_cnt->short_gi_pkts += 1;
if ((status->vht_nss >= ATH10K_RX_NSS_MIN) &&
(status->vht_nss < ATH10K_RX_NSS_MAX)) {
stat_cnt->nss[status->vht_nss] += 1;
if (status->flag & RX_FLAG_VHT) {
stat_cnt->vht_rate_packets += 1;
if (is_vht_rate_valid(status->rate_idx)) {
stat_cnt->vht_rate_indx[((status->vht_nss - 1) *
10) + status->rate_idx] += 1;
} else {
/*if we get index other than (>=0 and <=9)*/
stat_cnt->vht_rate_indx[ATH10K_RX_VHT_MCS_MAX] += 1;
}
} else if (status->flag & RX_FLAG_HT) {
stat_cnt->ht_rate_packets += 1;
if ((status->rate_idx >= ATH10K_RX_MCS_MIN) &&
(status->rate_idx < ATH10K_RX_HT_MCS_MAX))
stat_cnt->ht_rate_indx[status->rate_idx] += 1;
else {
/*if we get index other than (>=0 and <=31)*/
stat_cnt->ht_rate_indx[ATH10K_RX_HT_MCS_MAX] += 1;
}
} else {
/* if pkt is other than HT and VHT */
stat_cnt->legacy_pkt += 1;
}
} else {
stat_cnt->nss[ATH10K_RX_NSS_MAX] += 1;
}
if (status->flag & RX_FLAG_40MHZ)
stat_cnt->num_pkts_40Mhz += 1;
if (status->vht_flag & RX_VHT_FLAG_80MHZ)
stat_cnt->num_pkts_80Mhz += 1;
if ((status->band >= ATH10K_BAND_MIN) &&
(status->band < ATH10K_BAND_MAX)) {
stat_cnt->band[status->band] += 1;
} else {
/*if band is other than 0,1 */
stat_cnt->band[ATH10K_BAND_MAX] += 1;
}
spin_unlock_bh(&ar->datapath_rx_stat_lock);
}
size_t get_datapath_stat(char *buf, struct ath10k *ar)
{
u8 i;
struct datapath_rx_stats *stat_cnt = ar->rx_stats;
size_t j = 0;
spin_lock(&ar->datapath_rx_stat_lock);
j = snprintf(buf, ATH10K_DATAPATH_BUF_SIZE, "\nNo of packets: %u\t"
"No of short_gi packets: %u\n"
"\nHT Packets: %u \t VHT Packets: %u\n"
"\n40Mhz Packets: %u \t 80Mhz Packets: %u\n"
"\n2.4GHz: %u \t 5GHz: %u \t band-error: %u\n\n",
stat_cnt->no_of_packets,
stat_cnt->short_gi_pkts,
stat_cnt->ht_rate_packets,
stat_cnt->vht_rate_packets,
stat_cnt->num_pkts_40Mhz,
stat_cnt->num_pkts_80Mhz,
stat_cnt->band[ATH10K_BAND_2GHZ],
stat_cnt->band[ATH10K_BAND_5GHZ],
stat_cnt->band[ATH10K_BAND_MAX]);
for (i = 0; i <= ATH10K_RX_NSS_MAX; i++) {
j += snprintf(buf + j, (ATH10K_DATAPATH_BUF_SIZE - j),
"NSS-%u: %u\t", i, stat_cnt->nss[i]);
}
j += snprintf(buf + j, (ATH10K_DATAPATH_BUF_SIZE - j),
"\n\n----HT Rate index------\n");
for (i = ATH10K_RX_MCS_MIN; i < ATH10K_RX_HT_MCS_MAX;
i += 4) {
j += snprintf(buf + j, (ATH10K_DATAPATH_BUF_SIZE - j),
"ht_rate_indx[%02u]: %10u\tht_rate_indx[%02u]: %10u\t"
"ht_rate_indx[%02u]: %10u\tht_rate_indx[%02u]: %10u\n",
i, stat_cnt->ht_rate_indx[i],
i + 1, stat_cnt->ht_rate_indx[i + 1],
i + 2, stat_cnt->ht_rate_indx[i + 2],
i + 3, stat_cnt->ht_rate_indx[i + 3]);
}
j += snprintf(buf + j, (ATH10K_DATAPATH_BUF_SIZE - j),
"ht_rate_indx[OOB]: %10u\n",
stat_cnt->ht_rate_indx[ATH10K_RX_HT_MCS_MAX]);
j += snprintf(buf + j, (ATH10K_DATAPATH_BUF_SIZE - j),
"\n----VHT Rate index------\n");
for (i = ATH10K_RX_MCS_MIN;
i <= ATH10K_RX_VHT_RATEIDX_MAX; i++) {
j += snprintf(buf + j, (ATH10K_DATAPATH_BUF_SIZE - j),
"vht_rate_indx[%02u]: %10u\tvht_rate_indx[%02u]: %10u\n",
i, stat_cnt->vht_rate_indx[i],
i + 10, stat_cnt->vht_rate_indx[i + 10]);
}
j += snprintf(buf + j, (ATH10K_DATAPATH_BUF_SIZE - j),
"vht_rate_indx[%02u]: %10u\n",
i + 10, stat_cnt->vht_rate_indx[i + 10]);
j += snprintf(buf + j, (ATH10K_DATAPATH_BUF_SIZE - j),
"\nnumber of pkt other than HT and VHT(legacy) : %u\n"
"----------------------\n",
stat_cnt->legacy_pkt);
spin_unlock(&ar->datapath_rx_stat_lock);
return j;
}
static int ath10k_datapath_stats_open(struct inode *inode, struct file *file)
{
struct ath10k *ar = inode->i_private;
int ret;
spin_lock(&ar->datapath_rx_stat_lock);
if (ar->state != ATH10K_STATE_ON) {
ret = -ENETDOWN;
goto err_unlock;
}
file->private_data = ar;
spin_unlock(&ar->datapath_rx_stat_lock);
return 0;
err_unlock:
spin_unlock(&ar->datapath_rx_stat_lock);
return ret;
}
static ssize_t ath10k_datapath_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
size_t buf_len;
unsigned int ret;
void *buf = NULL;
buf = vmalloc(ATH10K_DATAPATH_BUF_SIZE);
if (!buf)
return 0;
buf_len = get_datapath_stat(buf, ar);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, buf_len);
vfree(buf);
return ret;
}
static ssize_t ath10k_datapath_stats_write(struct file *file,
const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
u32 filter;
int ret;
if (kstrtouint_from_user(ubuf, count, 0, &filter))
return -EINVAL;
spin_lock(&ar->datapath_rx_stat_lock);
if (ar->state != ATH10K_STATE_ON) {
ret = count;
goto err_unlock;
}
if (!filter)
memset(ar->rx_stats, 0, sizeof(*ar->rx_stats));
ret = count;
err_unlock:
spin_unlock(&ar->datapath_rx_stat_lock);
return ret;
}
static int ath10k_datapath_stats_release(struct inode *inode, struct file *file)
{
return 0;
}
static const struct file_operations fops_datapath_stats = {
.open = ath10k_datapath_stats_open,
.read = ath10k_datapath_stats_read,
.write = ath10k_datapath_stats_write,
.release = ath10k_datapath_stats_release,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@ -2401,7 +2625,11 @@ int ath10k_debug_create(struct ath10k *ar)
ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
if (!ar->debug.cal_data)
return -ENOMEM;
goto err_cal_data;
ar->rx_stats = vzalloc(sizeof(*ar->rx_stats));
if (!ar->rx_stats)
goto err_rx_stats;
INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
@ -2409,6 +2637,13 @@ int ath10k_debug_create(struct ath10k *ar)
INIT_LIST_HEAD(&ar->debug.fw_stats.peers_extd);
return 0;
err_rx_stats:
vfree(ar->debug.cal_data);
err_cal_data:
vfree(ar->debug.fw_crash_data);
return -ENOMEM;
}
void ath10k_debug_destroy(struct ath10k *ar)
@ -2419,6 +2654,9 @@ void ath10k_debug_destroy(struct ath10k *ar)
vfree(ar->debug.cal_data);
ar->debug.cal_data = NULL;
vfree(ar->rx_stats);
ar->rx_stats = NULL;
ath10k_debug_fw_stats_reset(ar);
kfree(ar->debug.tpc_stats);
@ -2441,6 +2679,9 @@ int ath10k_debug_register(struct ath10k *ar)
init_completion(&ar->debug.tpc_complete);
init_completion(&ar->debug.fw_stats_complete);
debugfs_create_file("datapath_rx_stats", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_datapath_stats);
debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
&fops_fw_stats);

View file

@ -59,6 +59,7 @@ enum ath10k_dbg_aggr_mode {
/* FIXME: How to calculate the buffer size sanely? */
#define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024)
#define ATH10K_DATAPATH_BUF_SIZE (1024 * 1024)
extern unsigned int ath10k_debug_mask;
@ -95,6 +96,8 @@ int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ethtool_stats *stats, u64 *data);
void fill_datapath_stats(struct ath10k *ar, struct ieee80211_rx_status *status);
size_t get_datapath_stat(char *buf, struct ath10k *ar);
#else
static inline int ath10k_debug_start(struct ath10k *ar)
{
@ -145,6 +148,16 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
return NULL;
}
static inline void fill_datapath_stats(struct ath10k *ar,
struct ieee80211_rx_status *status)
{
}
static inline size_t get_datapath_stat(char *buf, struct ath10k *ar)
{
return 0;
}
#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
#define ath10k_debug_get_et_strings NULL

View file

@ -940,7 +940,7 @@ static void ath10k_process_rx(struct ath10k *ar,
status = IEEE80211_SKB_RXCB(skb);
*status = *rx_status;
fill_datapath_stats(ar, status);
ath10k_dbg(ar, ATH10K_DBG_DATA,
"rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
skb,