ath10k: add sta rx packet stats per tid

Added per tid sta counters for the following

- Total number MSDUs received from firmware
- Number of MSDUs received with errors like decryption, crc, mic ,etc.
- Number of MSDUs dropped in the driver
- A-MPDU/A-MSDU subframe stats
- Number of MSDUS passed to mac80211

All stats other than A-MPDU stats are only for received data frames.
A-MPDU stats might have stats for management frames when monitor
interface is active where management frames are notified both in wmi
and HTT interfaces.

These per tid stats can be enabled with tid bitmask through a debugfs
like below

 echo <tid_bitmask> > /sys/kernel/debug/ieee80211/phyX/ath10k/sta_tid_stats_mask

 tid 16 (tid_bitmask 0x10000) is used for non-qos data/management frames

The stats are read from
/sys/kernel/debug/ieee80211/phyX/netdev\:wlanX/stations/<sta_mac>/dump_tid_stats

Sample output:

 To enable rx stats for tid 0, 5 and 6,

 echo 0x00000061 > /sys/kernel/debug/ieee80211/phy0/ath10k/sta_tid_stats_mask

cat /sys/kernel/debug/ieee80211/phy0/netdev\:wlan15/stations/8c\:fd\:f0\:0a\:8e\:df/dump_tid_stats

  		Driver Rx pkt stats per tid, ([tid] count)
                ------------------------------------------
MSDUs from FW                   [00] 2567        [05] 3178        [06] 1089
MSDUs unchained                 [00] 0           [05] 0           [06] 0
MSDUs locally dropped:chained   [00] 0           [05] 0           [06] 0
MSDUs locally dropped:filtered  [00] 0           [05] 0           [06] 0
MSDUs queued for mac80211       [00] 2567        [05] 3178        [06] 1089
MSDUs with error:fcs_err        [00] 0           [05] 0           [06] 2
MSDUs with error:tkip_err       [00] 0           [05] 0           [06] 0
MSDUs with error:crypt_err      [00] 0           [05] 0           [06] 0
MSDUs with error:peer_idx_inval [00] 0           [05] 0           [06] 0

A-MPDU num subframes upto 10    [00] 2567        [05] 3178        [06] 1087
A-MPDU num subframes 11-20      [00] 0           [05] 0           [06] 0
A-MPDU num subframes 21-30      [00] 0           [05] 0           [06] 0
A-MPDU num subframes 31-40      [00] 0           [05] 0           [06] 0
A-MPDU num subframes 41-50      [00] 0           [05] 0           [06] 0
A-MPDU num subframes 51-60      [00] 0           [05] 0           [06] 0
A-MPDU num subframes >60        [00] 0           [05] 0           [06] 0

A-MSDU num subframes 1          [00] 2567        [05] 3178        [06] 1089
A-MSDU num subframes 2          [00] 0           [05] 0           [06] 0
A-MSDU num subframes 3          [00] 0           [05] 0           [06] 0
A-MSDU num subframes 4          [00] 0           [05] 0           [06] 0
A-MSDU num subframes >4         [00] 0           [05] 0           [06] 0

Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 554cd78..1b9c092 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -2143,6 +2143,48 @@ static const struct file_operations fops_fw_checksums = {
 	.llseek = default_llseek,
 };
 
+static ssize_t ath10k_sta_tid_stats_mask_read(struct file *file,
+					      char __user *user_buf,
+					      size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	size_t len;
+
+	len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->sta_tid_stats_mask);
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath10k_sta_tid_stats_mask_write(struct file *file,
+					       const char __user *user_buf,
+					       size_t count, loff_t *ppos)
+{
+	struct ath10k *ar = file->private_data;
+	char buf[32];
+	ssize_t len;
+	u32 mask;
+
+	len = min(count, sizeof(buf) - 1);
+	if (copy_from_user(buf, user_buf, len))
+		return -EFAULT;
+
+	buf[len] = '\0';
+	if (kstrtoint(buf, 0, &mask))
+		return -EINVAL;
+
+	ar->sta_tid_stats_mask = mask;
+
+	return len;
+}
+
+static const struct file_operations fops_sta_tid_stats_mask = {
+	.read = ath10k_sta_tid_stats_mask_read,
+	.write = ath10k_sta_tid_stats_mask_write,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 int ath10k_debug_create(struct ath10k *ar)
 {
 	ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
@@ -2258,6 +2300,11 @@ int ath10k_debug_register(struct ath10k *ar)
 	debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar,
 			    &fops_fw_checksums);
 
+	if (IS_ENABLED(CONFIG_MAC80211_DEBUGFS))
+		debugfs_create_file("sta_tid_stats_mask", 0600,
+				    ar->debug.debugfs_phy,
+				    ar, &fops_sta_tid_stats_mask);
+
 	return 0;
 }