|
@@ -595,6 +595,105 @@ static const struct file_operations fops_credit_dist_stats = {
|
|
|
.llseek = default_llseek,
|
|
|
};
|
|
|
|
|
|
+static unsigned int print_endpoint_stat(struct htc_target *target, char *buf,
|
|
|
+ unsigned int buf_len, unsigned int len,
|
|
|
+ int offset, const char *name)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ struct htc_endpoint_stats *ep_st;
|
|
|
+ u32 *counter;
|
|
|
+
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "%s:", name);
|
|
|
+ for (i = 0; i < ENDPOINT_MAX; i++) {
|
|
|
+ ep_st = &target->endpoint[i].ep_st;
|
|
|
+ counter = ((u32 *) ep_st) + (offset / 4);
|
|
|
+ len += scnprintf(buf + len, buf_len - len, " %u", *counter);
|
|
|
+ }
|
|
|
+ len += scnprintf(buf + len, buf_len - len, "\n");
|
|
|
+
|
|
|
+ return len;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t ath6kl_endpoint_stats_read(struct file *file,
|
|
|
+ char __user *user_buf,
|
|
|
+ size_t count, loff_t *ppos)
|
|
|
+{
|
|
|
+ struct ath6kl *ar = file->private_data;
|
|
|
+ struct htc_target *target = ar->htc_target;
|
|
|
+ char *buf;
|
|
|
+ unsigned int buf_len, len = 0;
|
|
|
+ ssize_t ret_cnt;
|
|
|
+
|
|
|
+ buf_len = 1000 + ENDPOINT_MAX * 100;
|
|
|
+ buf = kzalloc(buf_len, GFP_KERNEL);
|
|
|
+ if (!buf)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+#define EPSTAT(name) \
|
|
|
+ len = print_endpoint_stat(target, buf, buf_len, len, \
|
|
|
+ offsetof(struct htc_endpoint_stats, name), \
|
|
|
+ #name)
|
|
|
+ EPSTAT(cred_low_indicate);
|
|
|
+ EPSTAT(tx_issued);
|
|
|
+ EPSTAT(tx_pkt_bundled);
|
|
|
+ EPSTAT(tx_bundles);
|
|
|
+ EPSTAT(tx_dropped);
|
|
|
+ EPSTAT(tx_cred_rpt);
|
|
|
+ EPSTAT(cred_rpt_from_rx);
|
|
|
+ EPSTAT(cred_rpt_ep0);
|
|
|
+ EPSTAT(cred_from_rx);
|
|
|
+ EPSTAT(cred_from_other);
|
|
|
+ EPSTAT(cred_from_ep0);
|
|
|
+ EPSTAT(cred_cosumd);
|
|
|
+ EPSTAT(cred_retnd);
|
|
|
+ EPSTAT(rx_pkts);
|
|
|
+ EPSTAT(rx_lkahds);
|
|
|
+ EPSTAT(rx_bundl);
|
|
|
+ EPSTAT(rx_bundle_lkahd);
|
|
|
+ EPSTAT(rx_bundle_from_hdr);
|
|
|
+ EPSTAT(rx_alloc_thresh_hit);
|
|
|
+ EPSTAT(rxalloc_thresh_byte);
|
|
|
+#undef EPSTAT
|
|
|
+
|
|
|
+ if (len > buf_len)
|
|
|
+ len = buf_len;
|
|
|
+
|
|
|
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
|
|
+ kfree(buf);
|
|
|
+ return ret_cnt;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t ath6kl_endpoint_stats_write(struct file *file,
|
|
|
+ const char __user *user_buf,
|
|
|
+ size_t count, loff_t *ppos)
|
|
|
+{
|
|
|
+ struct ath6kl *ar = file->private_data;
|
|
|
+ struct htc_target *target = ar->htc_target;
|
|
|
+ int ret, i;
|
|
|
+ u32 val;
|
|
|
+ struct htc_endpoint_stats *ep_st;
|
|
|
+
|
|
|
+ ret = kstrtou32_from_user(user_buf, count, 0, &val);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ if (val == 0) {
|
|
|
+ for (i = 0; i < ENDPOINT_MAX; i++) {
|
|
|
+ ep_st = &target->endpoint[i].ep_st;
|
|
|
+ memset(ep_st, 0, sizeof(*ep_st));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct file_operations fops_endpoint_stats = {
|
|
|
+ .open = ath6kl_debugfs_open,
|
|
|
+ .read = ath6kl_endpoint_stats_read,
|
|
|
+ .write = ath6kl_endpoint_stats_write,
|
|
|
+ .owner = THIS_MODULE,
|
|
|
+ .llseek = default_llseek,
|
|
|
+};
|
|
|
+
|
|
|
static unsigned long ath6kl_get_num_reg(void)
|
|
|
{
|
|
|
int i;
|
|
@@ -901,6 +1000,9 @@ int ath6kl_debug_init(struct ath6kl *ar)
|
|
|
debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar,
|
|
|
&fops_credit_dist_stats);
|
|
|
|
|
|
+ debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR,
|
|
|
+ ar->debugfs_phy, ar, &fops_endpoint_stats);
|
|
|
+
|
|
|
debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
|
|
|
&fops_fwlog);
|
|
|
|