summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/wil6210/debugfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/debugfs.c')
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c361
1 files changed, 325 insertions, 36 deletions
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 8d4bc4bfb664..8f66186adb8c 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -19,6 +19,7 @@
#include <linux/seq_file.h>
#include <linux/pci.h>
#include <linux/rtnetlink.h>
+#include <linux/power_supply.h>
#include "wil6210.h"
#include "txrx.h"
@@ -69,14 +70,32 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data)
for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
struct vring *vring = &(wil->vring_tx[i]);
+ struct vring_tx_data *txdata = &wil->vring_tx_data[i];
+
if (vring->va) {
int cid = wil->vring2cid_tid[i][0];
int tid = wil->vring2cid_tid[i][1];
+ u32 swhead = vring->swhead;
+ u32 swtail = vring->swtail;
+ int used = (vring->size + swhead - swtail)
+ % vring->size;
+ int avail = vring->size - used - 1;
char name[10];
+ /* performance monitoring */
+ cycles_t now = get_cycles();
+ cycles_t idle = txdata->idle * 100;
+ cycles_t total = now - txdata->begin;
+
+ do_div(idle, total);
+ txdata->begin = now;
+ txdata->idle = 0ULL;
+
snprintf(name, sizeof(name), "tx_%2d", i);
- seq_printf(s, "\n%pM CID %d TID %d\n",
- wil->sta[cid].addr, cid, tid);
+ seq_printf(s, "\n%pM CID %d TID %d [%3d|%3d] idle %3d%%\n",
+ wil->sta[cid].addr, cid, tid, used, avail,
+ (int)idle);
+
wil_print_vring(s, wil, name, vring, '_', 'H');
}
}
@@ -231,6 +250,26 @@ static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
&fops_iomem_x32);
}
+static int wil_debugfs_ulong_set(void *data, u64 val)
+{
+ *(ulong *)data = val;
+ return 0;
+}
+static int wil_debugfs_ulong_get(void *data, u64 *val)
+{
+ *val = *(ulong *)data;
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(wil_fops_ulong, wil_debugfs_ulong_get,
+ wil_debugfs_ulong_set, "%llu\n");
+
+static struct dentry *wil_debugfs_create_ulong(const char *name, umode_t mode,
+ struct dentry *parent,
+ ulong *value)
+{
+ return debugfs_create_file(name, mode, parent, value, &wil_fops_ulong);
+}
+
static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil,
const char *name,
struct dentry *parent, u32 off)
@@ -284,11 +323,11 @@ static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil,
if (IS_ERR_OR_NULL(d))
return -ENODEV;
- wil_debugfs_create_iomem_x32("TRSH", S_IRUGO, d, wil->csr +
+ wil_debugfs_create_iomem_x32("TRSH", S_IRUGO | S_IWUSR, d, wil->csr +
HOSTADDR(RGF_DMA_ITR_CNT_TRSH));
- wil_debugfs_create_iomem_x32("DATA", S_IRUGO, d, wil->csr +
+ wil_debugfs_create_iomem_x32("DATA", S_IRUGO | S_IWUSR, d, wil->csr +
HOSTADDR(RGF_DMA_ITR_CNT_DATA));
- wil_debugfs_create_iomem_x32("CTL", S_IRUGO, d, wil->csr +
+ wil_debugfs_create_iomem_x32("CTL", S_IRUGO | S_IWUSR, d, wil->csr +
HOSTADDR(RGF_DMA_ITR_CNT_CRL));
return 0;
@@ -397,6 +436,126 @@ static const struct file_operations fops_reset = {
.write = wil_write_file_reset,
.open = simple_open,
};
+/*---write channel 1..4 to rxon for it, 0 to rxoff---*/
+static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+ int rc;
+ long channel;
+ bool on;
+
+ char *kbuf = kmalloc(len + 1, GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+ if (copy_from_user(kbuf, buf, len)) {
+ kfree(kbuf);
+ return -EIO;
+ }
+
+ kbuf[len] = '\0';
+ rc = kstrtol(kbuf, 0, &channel);
+ kfree(kbuf);
+ if (rc)
+ return rc;
+
+ if ((channel < 0) || (channel > 4)) {
+ wil_err(wil, "Invalid channel %ld\n", channel);
+ return -EINVAL;
+ }
+ on = !!channel;
+
+ if (on) {
+ rc = wmi_set_channel(wil, (int)channel);
+ if (rc)
+ return rc;
+ }
+
+ rc = wmi_rxon(wil, on);
+ if (rc)
+ return rc;
+
+ return len;
+}
+
+static const struct file_operations fops_rxon = {
+ .write = wil_write_file_rxon,
+ .open = simple_open,
+};
+/*---tx_mgmt---*/
+/* Write mgmt frame to this file to send it */
+static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+ struct wiphy *wiphy = wil_to_wiphy(wil);
+ struct wireless_dev *wdev = wil_to_wdev(wil);
+ struct cfg80211_mgmt_tx_params params;
+ int rc;
+
+ void *frame = kmalloc(len, GFP_KERNEL);
+ if (!frame)
+ return -ENOMEM;
+
+ if (copy_from_user(frame, buf, len))
+ return -EIO;
+
+ params.buf = frame;
+ params.len = len;
+ params.chan = wdev->preset_chandef.chan;
+
+ rc = wil_cfg80211_mgmt_tx(wiphy, wdev, &params, NULL);
+
+ kfree(frame);
+ wil_info(wil, "%s() -> %d\n", __func__, rc);
+
+ return len;
+}
+
+static const struct file_operations fops_txmgmt = {
+ .write = wil_write_file_txmgmt,
+ .open = simple_open,
+};
+
+/* Write WMI command (w/o mbox header) to this file to send it
+ * WMI starts from wil6210_mbox_hdr_wmi header
+ */
+static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+ struct wil6210_mbox_hdr_wmi *wmi;
+ void *cmd;
+ int cmdlen = len - sizeof(struct wil6210_mbox_hdr_wmi);
+ u16 cmdid;
+ int rc, rc1;
+
+ if (cmdlen <= 0)
+ return -EINVAL;
+
+ wmi = kmalloc(len, GFP_KERNEL);
+ if (!wmi)
+ return -ENOMEM;
+
+ rc = simple_write_to_buffer(wmi, len, ppos, buf, len);
+ if (rc < 0)
+ return rc;
+
+ cmd = &wmi[1];
+ cmdid = le16_to_cpu(wmi->id);
+
+ rc1 = wmi_send(wil, cmdid, cmd, cmdlen);
+ kfree(wmi);
+
+ wil_info(wil, "%s(0x%04x[%d]) -> %d\n", __func__, cmdid, cmdlen, rc1);
+
+ return rc;
+}
+
+static const struct file_operations fops_wmi = {
+ .write = wil_write_file_wmi,
+ .open = simple_open,
+};
static void wil_seq_hexdump(struct seq_file *s, void *p, int len,
const char *prefix)
@@ -600,8 +759,8 @@ static int wil_temp_debugfs_show(struct seq_file *s, void *data)
return 0;
}
- print_temp(s, "MAC temperature :", t_m);
- print_temp(s, "Radio temperature :", t_r);
+ print_temp(s, "T_mac =", t_m);
+ print_temp(s, "T_radio =", t_r);
return 0;
}
@@ -618,6 +777,130 @@ static const struct file_operations fops_temp = {
.llseek = seq_lseek,
};
+/*---------freq------------*/
+static int wil_freq_debugfs_show(struct seq_file *s, void *data)
+{
+ struct wil6210_priv *wil = s->private;
+ struct wireless_dev *wdev = wil_to_wdev(wil);
+ u16 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0;
+
+ seq_printf(s, "Freq = %d\n", freq);
+
+ return 0;
+}
+
+static int wil_freq_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, wil_freq_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_freq = {
+ .open = wil_freq_seq_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
+/*---------link------------*/
+static int wil_link_debugfs_show(struct seq_file *s, void *data)
+{
+ struct wil6210_priv *wil = s->private;
+ struct station_info sinfo;
+ int i, rc;
+
+ for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+ struct wil_sta_info *p = &wil->sta[i];
+ char *status = "unknown";
+ switch (p->status) {
+ case wil_sta_unused:
+ status = "unused ";
+ break;
+ case wil_sta_conn_pending:
+ status = "pending ";
+ break;
+ case wil_sta_connected:
+ status = "connected";
+ break;
+ }
+ seq_printf(s, "[%d] %pM %s%s\n", i, p->addr, status,
+ (p->data_port_open ? " data_port_open" : ""));
+
+ if (p->status == wil_sta_connected) {
+ rc = wil_cid_fill_sinfo(wil, i, &sinfo);
+ if (rc)
+ return rc;
+
+ seq_printf(s, " Tx_mcs = %d\n", sinfo.txrate.mcs);
+ seq_printf(s, " Rx_mcs = %d\n", sinfo.rxrate.mcs);
+ seq_printf(s, " SQ = %d\n", sinfo.signal);
+ }
+ }
+
+ return 0;
+}
+
+static int wil_link_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, wil_link_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_link = {
+ .open = wil_link_seq_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
+/*---------info------------*/
+static int wil_info_debugfs_show(struct seq_file *s, void *data)
+{
+ struct wil6210_priv *wil = s->private;
+ struct net_device *ndev = wil_to_ndev(wil);
+ int is_ac = power_supply_is_system_supplied();
+ int rx = atomic_xchg(&wil->isr_count_rx, 0);
+ int tx = atomic_xchg(&wil->isr_count_tx, 0);
+ static ulong rxf_old, txf_old;
+ ulong rxf = ndev->stats.rx_packets;
+ ulong txf = ndev->stats.tx_packets;
+ unsigned int i;
+
+ /* >0 : AC; 0 : battery; <0 : error */
+ seq_printf(s, "AC powered : %d\n", is_ac);
+ seq_printf(s, "Rx irqs:packets : %8d : %8ld\n", rx, rxf - rxf_old);
+ seq_printf(s, "Tx irqs:packets : %8d : %8ld\n", tx, txf - txf_old);
+ rxf_old = rxf;
+ txf_old = txf;
+
+
+#define CHECK_QSTATE(x) (state & BIT(__QUEUE_STATE_ ## x)) ? \
+ " " __stringify(x) : ""
+
+ for (i = 0; i < ndev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(ndev, i);
+ unsigned long state = txq->state;
+
+ seq_printf(s, "Tx queue[%i] state : 0x%lx%s%s%s\n", i, state,
+ CHECK_QSTATE(DRV_XOFF),
+ CHECK_QSTATE(STACK_XOFF),
+ CHECK_QSTATE(FROZEN)
+ );
+ }
+#undef CHECK_QSTATE
+ return 0;
+}
+
+static int wil_info_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, wil_info_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_info = {
+ .open = wil_info_seq_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
/*---------Station matrix------------*/
static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
{
@@ -630,7 +913,7 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
else
seq_printf(s, "%c", r->reorder_buf[i] ? '*' : '_');
}
- seq_puts(s, "]\n");
+ seq_printf(s, "] last drop 0x%03x\n", r->ssn_last_drop);
}
static int wil_sta_debugfs_show(struct seq_file *s, void *data)
@@ -682,6 +965,26 @@ static const struct file_operations fops_sta = {
};
/*----------------*/
+static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
+ struct dentry *dbg)
+{
+ int i;
+ char name[32];
+
+ for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
+ struct debugfs_blob_wrapper *blob = &wil->blobs[i];
+ const struct fw_map *map = &fw_mapping[i];
+
+ if (!map->name)
+ continue;
+
+ blob->data = (void * __force)wil->csr + HOSTADDR(map->host);
+ blob->size = map->to - map->from;
+ snprintf(name, sizeof(name), "blob_%s", map->name);
+ wil_debugfs_create_ioblob(name, S_IRUGO, dbg, blob);
+ }
+}
+
int wil6210_debugfs_init(struct wil6210_priv *wil)
{
struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME,
@@ -703,6 +1006,10 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid);
debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg,
&wil->secure_pcp);
+ wil_debugfs_create_ulong("status", S_IRUGO | S_IWUSR, dbg,
+ &wil->status);
+ debugfs_create_u32("fw_version", S_IRUGO, dbg, &wil->fw_version);
+ debugfs_create_x32("hw_version", S_IRUGO, dbg, &wil->hw_version);
wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg,
HOSTADDR(RGF_USER_USER_ICR));
@@ -715,40 +1022,22 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
wil6210_debugfs_create_pseudo_ISR(wil, dbg);
wil6210_debugfs_create_ITR_CNT(wil, dbg);
+ wil_debugfs_create_iomem_x32("RGF_USER_USAGE_1", S_IRUGO, dbg,
+ wil->csr +
+ HOSTADDR(RGF_USER_USAGE_1));
debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr);
debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread);
debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset);
+ debugfs_create_file("rxon", S_IWUSR, dbg, wil, &fops_rxon);
+ debugfs_create_file("tx_mgmt", S_IWUSR, dbg, wil, &fops_txmgmt);
+ debugfs_create_file("wmi_send", S_IWUSR, dbg, wil, &fops_wmi);
debugfs_create_file("temp", S_IRUGO, dbg, wil, &fops_temp);
+ debugfs_create_file("freq", S_IRUGO, dbg, wil, &fops_freq);
+ debugfs_create_file("link", S_IRUGO, dbg, wil, &fops_link);
+ debugfs_create_file("info", S_IRUGO, dbg, wil, &fops_info);
- wil->rgf_blob.data = (void * __force)wil->csr + 0;
- wil->rgf_blob.size = 0xa000;
- wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob);
-
- wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000;
- wil->fw_code_blob.size = 0x40000;
- wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg,
- &wil->fw_code_blob);
-
- wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000;
- wil->fw_data_blob.size = 0x8000;
- wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg,
- &wil->fw_data_blob);
-
- wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000;
- wil->fw_peri_blob.size = 0x18000;
- wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg,
- &wil->fw_peri_blob);
-
- wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000;
- wil->uc_code_blob.size = 0x10000;
- wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg,
- &wil->uc_code_blob);
-
- wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000;
- wil->uc_data_blob.size = 0x4000;
- wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg,
- &wil->uc_data_blob);
+ wil6210_debugfs_init_blobs(wil, dbg);
return 0;
}