Loading drivers/net/wireless/ath/wil6210/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -39,3 +39,12 @@ config WIL6210_TRACING option if you are interested in debugging the driver. If unsure, say Y to make it easier to debug problems. config WIL6210_PLATFORM_MSM bool "wil6210 MSM platform specific support" depends on WIL6210 depends on ARCH_MSM default y ---help--- Say Y here to enable wil6210 driver support for MSM platform specific features drivers/net/wireless/ath/wil6210/Makefile +3 −0 Original line number Diff line number Diff line Loading @@ -10,7 +10,10 @@ wil6210-y += interrupt.o wil6210-y += txrx.o wil6210-y += debug.o wil6210-y += rx_reorder.o wil6210-y += fw.o wil6210-$(CONFIG_WIL6210_TRACING) += trace.o wil6210-y += wil_platform.o wil6210-$(CONFIG_WIL6210_PLATFORM_MSM) += wil_platform_msm.o # for tracing framework to find trace.h CFLAGS_trace.o := -I$(src) Loading drivers/net/wireless/ath/wil6210/cfg80211.c +104 −28 Original line number Diff line number Diff line /* * Copyright (c) 2012 Qualcomm Atheros, Inc. * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading Loading @@ -296,6 +296,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, n = min(request->n_channels, 4U); for (i = 0; i < n; i++) { int ch = request->channels[i]->hw_value; if (ch == 0) { wil_err(wil, "Scan requested for unknown frequency %dMhz\n", Loading @@ -308,15 +309,47 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, request->channels[i]->center_freq); } if (request->ie_len) print_hex_dump_bytes("Scan IE ", DUMP_PREFIX_OFFSET, request->ie, request->ie_len); else wil_dbg_misc(wil, "Scan has no IE's\n"); rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie); if (rc) { wil_err(wil, "Aborting scan, set_ie failed: %d\n", rc); goto out; } rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); if (rc) out: if (rc) { del_timer_sync(&wil->scan_timer); wil->scan_request = NULL; } return rc; } static void wil_print_connect_params(struct wil6210_priv *wil, struct cfg80211_connect_params *sme) { wil_info(wil, "Connecting to:\n"); if (sme->channel) { wil_info(wil, " Channel: %d freq %d\n", sme->channel->hw_value, sme->channel->center_freq); } if (sme->bssid) wil_info(wil, " BSSID: %pM\n", sme->bssid); if (sme->ssid) print_hex_dump(KERN_INFO, " SSID: ", DUMP_PREFIX_OFFSET, 16, 1, sme->ssid, sme->ssid_len, true); wil_info(wil, " Privacy: %s\n", sme->privacy ? "secure" : "open"); } static int wil_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) Loading @@ -333,6 +366,8 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, test_bit(wil_status_fwconnected, &wil->status)) return -EALREADY; wil_print_connect_params(wil, sme); bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid, sme->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); Loading @@ -358,23 +393,23 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, sme->ie_len); goto out; } /* * For secure assoc, send: * (1) WMI_DELETE_CIPHER_KEY_CMD * (2) WMI_SET_APPIE_CMD */ /* For secure assoc, send WMI_DELETE_CIPHER_KEY_CMD */ rc = wmi_del_cipher_key(wil, 0, bss->bssid); if (rc) { wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n"); goto out; } /* WMI_SET_APPIE_CMD */ } /* WMI_SET_APPIE_CMD. ie may contain rsn info as well as other info * elements. Send it also in case it's empty, to erase previously set * ies in FW. */ rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); if (rc) { wil_err(wil, "WMI_SET_APPIE_CMD failed\n"); goto out; } } /* WMI_CONNECT_CMD */ memset(&conn, 0, sizeof(conn)); Loading Loading @@ -619,6 +654,45 @@ static int wil_fix_bcon(struct wil6210_priv *wil, return rc; } static int wil_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_beacon_data *bcon) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; wil_dbg_misc(wil, "%s()\n", __func__); if (wil_fix_bcon(wil, bcon)) { wil_dbg_misc(wil, "Fixed bcon\n"); wil_print_bcon_data(bcon); } /* FW do not form regular beacon, so bcon IE's are not set * For the DMG bcon, when it will be supported, bcon IE's will * be reused; add something like: * wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, * bcon->beacon_ies); */ rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, bcon->proberesp_ies); if (rc) { wil_err(wil, "set_ie(PROBE_RESP) failed\n"); return rc; } rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, bcon->assocresp_ies); if (rc) { wil_err(wil, "set_ie(ASSOC_RESP) failed\n"); return rc; } return 0; } static int wil_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ap_settings *info) Loading Loading @@ -656,12 +730,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, mutex_lock(&wil->mutex); rc = wil_reset(wil); if (rc) goto out; /* Rx VRING. */ rc = wil_rx_init(wil); __wil_down(wil); rc = __wil_up(wil); if (rc) goto out; Loading @@ -669,9 +739,6 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, if (rc) goto out; /* MAC address - pre-requisite for other commands */ wmi_set_mac_address(wil, ndev->dev_addr); /* IE's */ /* bcon 'head IE's are not relevant for 60g band */ /* Loading @@ -693,7 +760,6 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, if (rc) goto out; netif_carrier_on(ndev); out: Loading @@ -704,7 +770,7 @@ out: static int wil_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) { int rc = 0; int rc, rc1; struct wil6210_priv *wil = wiphy_to_wil(wiphy); wil_dbg_misc(wil, "%s()\n", __func__); Loading @@ -713,8 +779,12 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, rc = wmi_pcp_stop(wil); __wil_down(wil); rc1 = __wil_up(wil); mutex_unlock(&wil->mutex); return rc; return min(rc, rc1); } static int wil_cfg80211_del_station(struct wiphy *wiphy, Loading Loading @@ -744,6 +814,7 @@ static struct cfg80211_ops wil_cfg80211_ops = { .del_key = wil_cfg80211_del_key, .set_default_key = wil_cfg80211_set_default_key, /* AP mode */ .change_beacon = wil_cfg80211_change_beacon, .start_ap = wil_cfg80211_start_ap, .stop_ap = wil_cfg80211_stop_ap, .del_station = wil_cfg80211_del_station, Loading @@ -753,6 +824,7 @@ static void wil_wiphy_init(struct wiphy *wiphy) { /* TODO: set real value */ wiphy->max_scan_ssids = 10; wiphy->max_scan_ie_len = WMI_MAX_IE_LEN; wiphy->max_num_pmkids = 0 /* TODO: */; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | Loading @@ -762,7 +834,7 @@ static void wil_wiphy_init(struct wiphy *wiphy) */ wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; dev_warn(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", __func__, wiphy->flags); wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | Loading @@ -784,7 +856,9 @@ struct wireless_dev *wil_cfg80211_init(struct device *dev) int rc = 0; struct wireless_dev *wdev; wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); dev_dbg(dev, "%s()\n", __func__); wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); if (!wdev) return ERR_PTR(-ENOMEM); Loading Loading @@ -816,6 +890,8 @@ void wil_wdev_free(struct wil6210_priv *wil) { struct wireless_dev *wdev = wil_to_wdev(wil); dev_dbg(wil_to_dev(wil), "%s()\n", __func__); if (!wdev) return; Loading drivers/net/wireless/ath/wil6210/debugfs.c +291 −98 Original line number Diff line number Diff line /* * Copyright (c) 2012 Qualcomm Atheros, Inc. * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading @@ -22,6 +22,7 @@ #include <linux/power_supply.h> #include "wil6210.h" #include "wmi.h" #include "txrx.h" /* Nasty hack. Better have per device instances */ Loading @@ -29,6 +30,21 @@ static u32 mem_addr; static u32 dbg_txdesc_index; static u32 dbg_vring_index; /* 24+ for Rx, 0..23 for Tx */ enum dbg_off_type { doff_u32 = 0, doff_x32 = 1, doff_ulong = 2, doff_io32 = 3, }; /* offset to "wil" */ struct dbg_off { const char *name; umode_t mode; ulong off; enum dbg_off_type type; }; static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, const char *name, struct vring *vring, char _s, char _h) Loading @@ -45,20 +61,22 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, if (x) seq_printf(s, "0x%08x\n", ioread32(x)); else seq_printf(s, "???\n"); seq_puts(s, "???\n"); if (vring->va && (vring->size < 1025)) { uint i; for (i = 0; i < vring->size; i++) { volatile struct vring_tx_desc *d = &vring->va[i].tx; if ((i % 64) == 0 && (i != 0)) seq_printf(s, "\n"); seq_puts(s, "\n"); seq_printf(s, "%c", (d->dma.status & BIT(0)) ? _s : (vring->ctx[i].skb ? _h : 'h')); } seq_printf(s, "\n"); seq_puts(s, "\n"); } seq_printf(s, "}\n"); seq_puts(s, "}\n"); } static int wil_vring_debugfs_show(struct seq_file *s, void *data) Loading @@ -69,7 +87,7 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data) wil_print_vring(s, wil, "rx", &wil->vring_rx, 'S', '_'); for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { struct vring *vring = &(wil->vring_tx[i]); struct vring *vring = &wil->vring_tx[i]; struct vring_tx_data *txdata = &wil->vring_tx_data[i]; if (vring->va) { Loading Loading @@ -147,7 +165,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, if (!wmi_addr(wil, r.base) || !wmi_addr(wil, r.tail) || !wmi_addr(wil, r.head)) { seq_printf(s, " ??? pointers are garbage?\n"); seq_puts(s, " ??? pointers are garbage?\n"); goto out; } Loading @@ -166,6 +184,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, le32_to_cpu(d.addr)); if (0 == wmi_read_hdr(wil, d.addr, &hdr)) { u16 len = le16_to_cpu(hdr.len); seq_printf(s, " -> %04x %04x %04x %02x\n", le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type), hdr.flags); Loading @@ -183,6 +202,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, wil_memcpy_fromio_32(databuf, src, len); while (n < len) { int l = min(len - n, 16); hex_dump_to_buffer(databuf + n, l, 16, 1, printbuf, sizeof(printbuf), Loading @@ -192,11 +212,11 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, } } } else { seq_printf(s, "\n"); seq_puts(s, "\n"); } } out: seq_printf(s, "}\n"); seq_puts(s, "}\n"); } static int wil_mbox_debugfs_show(struct seq_file *s, void *data) Loading Loading @@ -244,9 +264,9 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get, static struct dentry *wil_debugfs_create_iomem_x32(const char *name, umode_t mode, struct dentry *parent, void __iomem *value) void *value) { return debugfs_create_file(name, mode, parent, (void * __force)value, return debugfs_create_file(name, mode, parent, value, &fops_iomem_x32); } Loading @@ -255,11 +275,13 @@ 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"); Loading @@ -270,6 +292,62 @@ static struct dentry *wil_debugfs_create_ulong(const char *name, umode_t mode, return debugfs_create_file(name, mode, parent, value, &wil_fops_ulong); } /** * wil6210_debugfs_init_offset - create set of debugfs files * @wil - driver's context, used for printing * @dbg - directory on the debugfs, where files will be created * @base - base address used in address calculation * @tbl - table with file descriptions. Should be terminated with empty element. * * Creates files accordingly to the @tbl. */ static void wil6210_debugfs_init_offset(struct wil6210_priv *wil, struct dentry *dbg, void *base, const struct dbg_off * const tbl) { int i; for (i = 0; tbl[i].name; i++) { struct dentry *f; switch (tbl[i].type) { case doff_u32: f = debugfs_create_u32(tbl[i].name, tbl[i].mode, dbg, base + tbl[i].off); break; case doff_x32: f = debugfs_create_x32(tbl[i].name, tbl[i].mode, dbg, base + tbl[i].off); break; case doff_ulong: f = wil_debugfs_create_ulong(tbl[i].name, tbl[i].mode, dbg, base + tbl[i].off); break; case doff_io32: f = wil_debugfs_create_iomem_x32(tbl[i].name, tbl[i].mode, dbg, base + tbl[i].off); break; default: f = ERR_PTR(-EINVAL); } if (IS_ERR_OR_NULL(f)) wil_err(wil, "Create file \"%s\": err %ld\n", tbl[i].name, PTR_ERR(f)); } } static const struct dbg_off isr_off[] = { {"ICC", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICC), doff_io32}, {"ICR", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICR), doff_io32}, {"ICM", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICM), doff_io32}, {"ICS", S_IWUSR, offsetof(struct RGF_ICR, ICS), doff_io32}, {"IMV", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, IMV), doff_io32}, {"IMS", S_IWUSR, offsetof(struct RGF_ICR, IMS), doff_io32}, {"IMC", S_IWUSR, offsetof(struct RGF_ICR, IMC), doff_io32}, {}, }; static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, const char *name, struct dentry *parent, u32 off) Loading @@ -279,24 +357,19 @@ static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, if (IS_ERR_OR_NULL(d)) return -ENODEV; wil_debugfs_create_iomem_x32("ICC", S_IRUGO | S_IWUSR, d, wil->csr + off); wil_debugfs_create_iomem_x32("ICR", S_IRUGO | S_IWUSR, d, wil->csr + off + 4); wil_debugfs_create_iomem_x32("ICM", S_IRUGO | S_IWUSR, d, wil->csr + off + 8); wil_debugfs_create_iomem_x32("ICS", S_IWUSR, d, wil->csr + off + 12); wil_debugfs_create_iomem_x32("IMV", S_IRUGO | S_IWUSR, d, wil->csr + off + 16); wil_debugfs_create_iomem_x32("IMS", S_IWUSR, d, wil->csr + off + 20); wil_debugfs_create_iomem_x32("IMC", S_IWUSR, d, wil->csr + off + 24); wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr + off, isr_off); return 0; } static const struct dbg_off pseudo_isr_off[] = { {"CAUSE", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE), doff_io32}, {"MASK_SW", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW), doff_io32}, {"MASK_FW", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW), doff_io32}, {}, }; static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, struct dentry *parent) { Loading @@ -305,16 +378,19 @@ static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, if (IS_ERR_OR_NULL(d)) return -ENODEV; wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO, d, wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO, d, wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO, d, wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW)); wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr, pseudo_isr_off); return 0; } static const struct dbg_off itr_cnt_off[] = { {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_TRSH), doff_io32}, {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_DATA), doff_io32}, {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_CRL), doff_io32}, {}, }; static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil, struct dentry *parent) { Loading @@ -323,12 +399,8 @@ 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 | S_IWUSR, d, wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_TRSH)); 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 | S_IWUSR, d, wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL)); wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr, itr_cnt_off); return 0; } Loading Loading @@ -411,6 +483,7 @@ struct dentry *wil_debugfs_create_ioblob(const char *name, { return debugfs_create_file(name, mode, parent, blob, &fops_ioblob); } /*---reset---*/ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, size_t len, loff_t *ppos) Loading @@ -436,6 +509,7 @@ 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) Loading @@ -446,6 +520,7 @@ static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf, bool on; char *kbuf = kmalloc(len + 1, GFP_KERNEL); if (!kbuf) return -ENOMEM; if (copy_from_user(kbuf, buf, len)) { Loading Loading @@ -482,6 +557,7 @@ 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, Loading @@ -491,8 +567,8 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf, struct wiphy *wiphy = wil_to_wiphy(wil); struct wireless_dev *wdev = wil_to_wdev(wil); int rc; void *frame = kmalloc(len, GFP_KERNEL); if (!frame) return -ENOMEM; Loading Loading @@ -558,8 +634,10 @@ static void wil_seq_hexdump(struct seq_file *s, void *p, int len, { char printbuf[16 * 3 + 2]; int i = 0; while (i < len) { int l = min(len - i, 16); hex_dump_to_buffer(p + i, l, 16, 1, printbuf, sizeof(printbuf), false); seq_printf(s, "%s%s\n", prefix, printbuf); Loading Loading @@ -597,10 +675,8 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) struct wil6210_priv *wil = s->private; struct vring *vring; bool tx = (dbg_vring_index < WIL6210_MAX_TX_RINGS); if (tx) vring = &(wil->vring_tx[dbg_vring_index]); else vring = &wil->vring_rx; vring = tx ? &wil->vring_tx[dbg_vring_index] : &wil->vring_rx; if (!vring->va) { if (tx) Loading @@ -615,7 +691,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) * only field used, .dma.length, is the same */ volatile struct vring_tx_desc *d = &(vring->va[dbg_txdesc_index].tx); &vring->va[dbg_txdesc_index].tx; volatile u32 *u = (volatile u32 *)d; struct sk_buff *skb = vring->ctx[dbg_txdesc_index].skb; Loading @@ -635,7 +711,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) wil_seq_print_skb(s, skb); kfree_skb(skb); } seq_printf(s, "}\n"); seq_puts(s, "}\n"); } else { if (tx) seq_printf(s, "[%2d] TxDesc index (%d) >= size (%d)\n", Loading @@ -662,16 +738,79 @@ static const struct file_operations fops_txdesc = { }; /*---------beamforming------------*/ static char *wil_bfstatus_str(u32 status) { switch (status) { case 0: return "Failed"; case 1: return "OK"; case 2: return "Retrying"; default: return "??"; } } static bool is_all_zeros(void * const x_, size_t sz) { /* if reply is all-0, ignore this CID */ u32 *x = x_; int n; for (n = 0; n < sz / sizeof(*x); n++) if (x[n]) return false; return true; } static int wil_bf_debugfs_show(struct seq_file *s, void *data) { int rc; int i; struct wil6210_priv *wil = s->private; seq_printf(s, "TSF : 0x%016llx\n" "TxMCS : %d\n" "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n", wil->stats.tsf, wil->stats.bf_mcs, wil->stats.my_rx_sector, wil->stats.my_tx_sector, wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); struct wmi_notify_req_cmd cmd = { .interval_usec = 0, }; struct { struct wil6210_mbox_hdr_wmi wmi; struct wmi_notify_req_done_event evt; } __packed reply; for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { u32 status; cmd.cid = i; rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20); /* if reply is all-0, ignore this CID */ if (rc || is_all_zeros(&reply.evt, sizeof(reply.evt))) continue; status = le32_to_cpu(reply.evt.status); seq_printf(s, "CID %d {\n" " TSF = 0x%016llx\n" " TxMCS = %2d TxTpt = %4d\n" " SQI = %4d\n" " Status = 0x%08x %s\n" " Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n" " Goodput(rx:tx) %4d:%4d\n" "}\n", i, le64_to_cpu(reply.evt.tsf), le16_to_cpu(reply.evt.bf_mcs), le32_to_cpu(reply.evt.tx_tpt), reply.evt.sqi, status, wil_bfstatus_str(status), le16_to_cpu(reply.evt.my_rx_sector), le16_to_cpu(reply.evt.my_tx_sector), le16_to_cpu(reply.evt.other_rx_sector), le16_to_cpu(reply.evt.other_tx_sector), le32_to_cpu(reply.evt.rx_goodput), le32_to_cpu(reply.evt.tx_goodput)); } return 0; } Loading @@ -686,6 +825,7 @@ static const struct file_operations fops_bf = { .read = seq_read, .llseek = seq_lseek, }; /*---------SSID------------*/ static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) Loading Loading @@ -748,10 +888,10 @@ static int wil_temp_debugfs_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; u32 t_m, t_r; int rc = wmi_get_temperature(wil, &t_m, &t_r); if (rc) { seq_printf(s, "Failed\n"); seq_puts(s, "Failed\n"); return 0; } Loading Loading @@ -807,6 +947,7 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data) 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 "; Loading Loading @@ -867,7 +1008,6 @@ static int wil_info_debugfs_show(struct seq_file *s, void *data) rxf_old = rxf; txf_old = txf; #define CHECK_QSTATE(x) (state & BIT(__QUEUE_STATE_ ## x)) ? \ " " __stringify(x) : "" Loading Loading @@ -902,6 +1042,7 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r) { int i; u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size; seq_printf(s, "0x%03x [", r->head_seq_num); for (i = 0; i < r->buf_size; i++) { if (i == index) Loading @@ -916,10 +1057,12 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; int i, tid; unsigned long flags; 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 "; Loading @@ -935,13 +1078,16 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data) (p->data_port_open ? " data_port_open" : "")); if (p->status == wil_sta_connected) { spin_lock_irqsave(&p->tid_rx_lock, flags); for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { struct wil_tid_ampdu_rx *r = p->tid_rx[tid]; if (r) { seq_printf(s, "[%2d] ", tid); wil_print_rxtid(s, r); } } spin_unlock_irqrestore(&p->tid_rx_lock, flags); } } Loading Loading @@ -981,6 +1127,87 @@ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, } } /* misc files */ static const struct { const char *name; umode_t mode; const struct file_operations *fops; } dbg_files[] = { {"mbox", S_IRUGO, &fops_mbox}, {"vrings", S_IRUGO, &fops_vring}, {"stations", S_IRUGO, &fops_sta}, {"desc", S_IRUGO, &fops_txdesc}, {"bf", S_IRUGO, &fops_bf}, {"ssid", S_IRUGO | S_IWUSR, &fops_ssid}, {"mem_val", S_IRUGO, &fops_memread}, {"reset", S_IWUSR, &fops_reset}, {"rxon", S_IWUSR, &fops_rxon}, {"tx_mgmt", S_IWUSR, &fops_txmgmt}, {"wmi_send", S_IWUSR, &fops_wmi}, {"temp", S_IRUGO, &fops_temp}, {"freq", S_IRUGO, &fops_freq}, {"link", S_IRUGO, &fops_link}, {"info", S_IRUGO, &fops_info}, }; static void wil6210_debugfs_init_files(struct wil6210_priv *wil, struct dentry *dbg) { int i; for (i = 0; i < ARRAY_SIZE(dbg_files); i++) debugfs_create_file(dbg_files[i].name, dbg_files[i].mode, dbg, wil, dbg_files[i].fops); } /* interrupt control blocks */ static const struct { const char *name; u32 icr_off; } dbg_icr[] = { {"USER_ICR", HOSTADDR(RGF_USER_USER_ICR)}, {"DMA_EP_TX_ICR", HOSTADDR(RGF_DMA_EP_TX_ICR)}, {"DMA_EP_RX_ICR", HOSTADDR(RGF_DMA_EP_RX_ICR)}, {"DMA_EP_MISC_ICR", HOSTADDR(RGF_DMA_EP_MISC_ICR)}, }; static void wil6210_debugfs_init_isr(struct wil6210_priv *wil, struct dentry *dbg) { int i; for (i = 0; i < ARRAY_SIZE(dbg_icr); i++) wil6210_debugfs_create_ISR(wil, dbg_icr[i].name, dbg, dbg_icr[i].icr_off); } #define WIL_FIELD(name, mode, type) { __stringify(name), mode, \ offsetof(struct wil6210_priv, name), type} /* fields in struct wil6210_priv */ static const struct dbg_off dbg_wil_off[] = { WIL_FIELD(secure_pcp, S_IRUGO | S_IWUSR, doff_u32), WIL_FIELD(status, S_IRUGO | S_IWUSR, doff_ulong), WIL_FIELD(fw_version, S_IRUGO, doff_u32), WIL_FIELD(hw_version, S_IRUGO, doff_x32), {}, }; static const struct dbg_off dbg_wil_regs[] = { {"RGF_MAC_MTRL_COUNTER_0", S_IRUGO, HOSTADDR(RGF_MAC_MTRL_COUNTER_0), doff_io32}, {"RGF_USER_USAGE_1", S_IRUGO, HOSTADDR(RGF_USER_USAGE_1), doff_io32}, {}, }; /* static parameters */ static const struct dbg_off dbg_statics[] = { {"desc_index", S_IRUGO | S_IWUSR, (ulong)&dbg_txdesc_index, doff_u32}, {"vring_index", S_IRUGO | S_IWUSR, (ulong)&dbg_vring_index, doff_u32}, {"mem_addr", S_IRUGO | S_IWUSR, (ulong)&mem_addr, doff_u32}, {}, }; int wil6210_debugfs_init(struct wil6210_priv *wil) { struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, Loading @@ -989,51 +1216,17 @@ int wil6210_debugfs_init(struct wil6210_priv *wil) if (IS_ERR_OR_NULL(dbg)) return -ENODEV; debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox); debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring); debugfs_create_file("stations", S_IRUGO, dbg, wil, &fops_sta); debugfs_create_file("desc", S_IRUGO, dbg, wil, &fops_txdesc); debugfs_create_u32("desc_index", S_IRUGO | S_IWUSR, dbg, &dbg_txdesc_index); debugfs_create_u32("vring_index", S_IRUGO | S_IWUSR, dbg, &dbg_vring_index); debugfs_create_file("bf", S_IRUGO, dbg, wil, &fops_bf); 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)); wil6210_debugfs_create_ISR(wil, "DMA_EP_TX_ICR", dbg, HOSTADDR(RGF_DMA_EP_TX_ICR)); wil6210_debugfs_create_ISR(wil, "DMA_EP_RX_ICR", dbg, HOSTADDR(RGF_DMA_EP_RX_ICR)); wil6210_debugfs_create_ISR(wil, "DMA_EP_MISC_ICR", dbg, HOSTADDR(RGF_DMA_EP_MISC_ICR)); wil6210_debugfs_create_pseudo_ISR(wil, dbg); wil6210_debugfs_create_ITR_CNT(wil, dbg); wil6210_debugfs_init_files(wil, dbg); wil6210_debugfs_init_isr(wil, dbg); wil6210_debugfs_init_blobs(wil, dbg); wil6210_debugfs_init_offset(wil, dbg, wil, dbg_wil_off); wil6210_debugfs_init_offset(wil, dbg, (void * __force)wil->csr, dbg_wil_regs); wil6210_debugfs_init_offset(wil, dbg, NULL, dbg_statics); 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); wil6210_debugfs_create_pseudo_ISR(wil, dbg); wil6210_debugfs_init_blobs(wil, dbg); wil6210_debugfs_create_ITR_CNT(wil, dbg); return 0; } Loading Loading
drivers/net/wireless/ath/wil6210/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -39,3 +39,12 @@ config WIL6210_TRACING option if you are interested in debugging the driver. If unsure, say Y to make it easier to debug problems. config WIL6210_PLATFORM_MSM bool "wil6210 MSM platform specific support" depends on WIL6210 depends on ARCH_MSM default y ---help--- Say Y here to enable wil6210 driver support for MSM platform specific features
drivers/net/wireless/ath/wil6210/Makefile +3 −0 Original line number Diff line number Diff line Loading @@ -10,7 +10,10 @@ wil6210-y += interrupt.o wil6210-y += txrx.o wil6210-y += debug.o wil6210-y += rx_reorder.o wil6210-y += fw.o wil6210-$(CONFIG_WIL6210_TRACING) += trace.o wil6210-y += wil_platform.o wil6210-$(CONFIG_WIL6210_PLATFORM_MSM) += wil_platform_msm.o # for tracing framework to find trace.h CFLAGS_trace.o := -I$(src) Loading
drivers/net/wireless/ath/wil6210/cfg80211.c +104 −28 Original line number Diff line number Diff line /* * Copyright (c) 2012 Qualcomm Atheros, Inc. * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading Loading @@ -296,6 +296,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, n = min(request->n_channels, 4U); for (i = 0; i < n; i++) { int ch = request->channels[i]->hw_value; if (ch == 0) { wil_err(wil, "Scan requested for unknown frequency %dMhz\n", Loading @@ -308,15 +309,47 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, request->channels[i]->center_freq); } if (request->ie_len) print_hex_dump_bytes("Scan IE ", DUMP_PREFIX_OFFSET, request->ie, request->ie_len); else wil_dbg_misc(wil, "Scan has no IE's\n"); rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie); if (rc) { wil_err(wil, "Aborting scan, set_ie failed: %d\n", rc); goto out; } rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); if (rc) out: if (rc) { del_timer_sync(&wil->scan_timer); wil->scan_request = NULL; } return rc; } static void wil_print_connect_params(struct wil6210_priv *wil, struct cfg80211_connect_params *sme) { wil_info(wil, "Connecting to:\n"); if (sme->channel) { wil_info(wil, " Channel: %d freq %d\n", sme->channel->hw_value, sme->channel->center_freq); } if (sme->bssid) wil_info(wil, " BSSID: %pM\n", sme->bssid); if (sme->ssid) print_hex_dump(KERN_INFO, " SSID: ", DUMP_PREFIX_OFFSET, 16, 1, sme->ssid, sme->ssid_len, true); wil_info(wil, " Privacy: %s\n", sme->privacy ? "secure" : "open"); } static int wil_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) Loading @@ -333,6 +366,8 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, test_bit(wil_status_fwconnected, &wil->status)) return -EALREADY; wil_print_connect_params(wil, sme); bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid, sme->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); Loading @@ -358,23 +393,23 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, sme->ie_len); goto out; } /* * For secure assoc, send: * (1) WMI_DELETE_CIPHER_KEY_CMD * (2) WMI_SET_APPIE_CMD */ /* For secure assoc, send WMI_DELETE_CIPHER_KEY_CMD */ rc = wmi_del_cipher_key(wil, 0, bss->bssid); if (rc) { wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n"); goto out; } /* WMI_SET_APPIE_CMD */ } /* WMI_SET_APPIE_CMD. ie may contain rsn info as well as other info * elements. Send it also in case it's empty, to erase previously set * ies in FW. */ rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); if (rc) { wil_err(wil, "WMI_SET_APPIE_CMD failed\n"); goto out; } } /* WMI_CONNECT_CMD */ memset(&conn, 0, sizeof(conn)); Loading Loading @@ -619,6 +654,45 @@ static int wil_fix_bcon(struct wil6210_priv *wil, return rc; } static int wil_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_beacon_data *bcon) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; wil_dbg_misc(wil, "%s()\n", __func__); if (wil_fix_bcon(wil, bcon)) { wil_dbg_misc(wil, "Fixed bcon\n"); wil_print_bcon_data(bcon); } /* FW do not form regular beacon, so bcon IE's are not set * For the DMG bcon, when it will be supported, bcon IE's will * be reused; add something like: * wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, * bcon->beacon_ies); */ rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, bcon->proberesp_ies); if (rc) { wil_err(wil, "set_ie(PROBE_RESP) failed\n"); return rc; } rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, bcon->assocresp_ies); if (rc) { wil_err(wil, "set_ie(ASSOC_RESP) failed\n"); return rc; } return 0; } static int wil_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ap_settings *info) Loading Loading @@ -656,12 +730,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, mutex_lock(&wil->mutex); rc = wil_reset(wil); if (rc) goto out; /* Rx VRING. */ rc = wil_rx_init(wil); __wil_down(wil); rc = __wil_up(wil); if (rc) goto out; Loading @@ -669,9 +739,6 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, if (rc) goto out; /* MAC address - pre-requisite for other commands */ wmi_set_mac_address(wil, ndev->dev_addr); /* IE's */ /* bcon 'head IE's are not relevant for 60g band */ /* Loading @@ -693,7 +760,6 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, if (rc) goto out; netif_carrier_on(ndev); out: Loading @@ -704,7 +770,7 @@ out: static int wil_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) { int rc = 0; int rc, rc1; struct wil6210_priv *wil = wiphy_to_wil(wiphy); wil_dbg_misc(wil, "%s()\n", __func__); Loading @@ -713,8 +779,12 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, rc = wmi_pcp_stop(wil); __wil_down(wil); rc1 = __wil_up(wil); mutex_unlock(&wil->mutex); return rc; return min(rc, rc1); } static int wil_cfg80211_del_station(struct wiphy *wiphy, Loading Loading @@ -744,6 +814,7 @@ static struct cfg80211_ops wil_cfg80211_ops = { .del_key = wil_cfg80211_del_key, .set_default_key = wil_cfg80211_set_default_key, /* AP mode */ .change_beacon = wil_cfg80211_change_beacon, .start_ap = wil_cfg80211_start_ap, .stop_ap = wil_cfg80211_stop_ap, .del_station = wil_cfg80211_del_station, Loading @@ -753,6 +824,7 @@ static void wil_wiphy_init(struct wiphy *wiphy) { /* TODO: set real value */ wiphy->max_scan_ssids = 10; wiphy->max_scan_ie_len = WMI_MAX_IE_LEN; wiphy->max_num_pmkids = 0 /* TODO: */; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | Loading @@ -762,7 +834,7 @@ static void wil_wiphy_init(struct wiphy *wiphy) */ wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; dev_warn(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", __func__, wiphy->flags); wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | Loading @@ -784,7 +856,9 @@ struct wireless_dev *wil_cfg80211_init(struct device *dev) int rc = 0; struct wireless_dev *wdev; wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); dev_dbg(dev, "%s()\n", __func__); wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); if (!wdev) return ERR_PTR(-ENOMEM); Loading Loading @@ -816,6 +890,8 @@ void wil_wdev_free(struct wil6210_priv *wil) { struct wireless_dev *wdev = wil_to_wdev(wil); dev_dbg(wil_to_dev(wil), "%s()\n", __func__); if (!wdev) return; Loading
drivers/net/wireless/ath/wil6210/debugfs.c +291 −98 Original line number Diff line number Diff line /* * Copyright (c) 2012 Qualcomm Atheros, Inc. * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above Loading @@ -22,6 +22,7 @@ #include <linux/power_supply.h> #include "wil6210.h" #include "wmi.h" #include "txrx.h" /* Nasty hack. Better have per device instances */ Loading @@ -29,6 +30,21 @@ static u32 mem_addr; static u32 dbg_txdesc_index; static u32 dbg_vring_index; /* 24+ for Rx, 0..23 for Tx */ enum dbg_off_type { doff_u32 = 0, doff_x32 = 1, doff_ulong = 2, doff_io32 = 3, }; /* offset to "wil" */ struct dbg_off { const char *name; umode_t mode; ulong off; enum dbg_off_type type; }; static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, const char *name, struct vring *vring, char _s, char _h) Loading @@ -45,20 +61,22 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, if (x) seq_printf(s, "0x%08x\n", ioread32(x)); else seq_printf(s, "???\n"); seq_puts(s, "???\n"); if (vring->va && (vring->size < 1025)) { uint i; for (i = 0; i < vring->size; i++) { volatile struct vring_tx_desc *d = &vring->va[i].tx; if ((i % 64) == 0 && (i != 0)) seq_printf(s, "\n"); seq_puts(s, "\n"); seq_printf(s, "%c", (d->dma.status & BIT(0)) ? _s : (vring->ctx[i].skb ? _h : 'h')); } seq_printf(s, "\n"); seq_puts(s, "\n"); } seq_printf(s, "}\n"); seq_puts(s, "}\n"); } static int wil_vring_debugfs_show(struct seq_file *s, void *data) Loading @@ -69,7 +87,7 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data) wil_print_vring(s, wil, "rx", &wil->vring_rx, 'S', '_'); for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { struct vring *vring = &(wil->vring_tx[i]); struct vring *vring = &wil->vring_tx[i]; struct vring_tx_data *txdata = &wil->vring_tx_data[i]; if (vring->va) { Loading Loading @@ -147,7 +165,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, if (!wmi_addr(wil, r.base) || !wmi_addr(wil, r.tail) || !wmi_addr(wil, r.head)) { seq_printf(s, " ??? pointers are garbage?\n"); seq_puts(s, " ??? pointers are garbage?\n"); goto out; } Loading @@ -166,6 +184,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, le32_to_cpu(d.addr)); if (0 == wmi_read_hdr(wil, d.addr, &hdr)) { u16 len = le16_to_cpu(hdr.len); seq_printf(s, " -> %04x %04x %04x %02x\n", le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type), hdr.flags); Loading @@ -183,6 +202,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, wil_memcpy_fromio_32(databuf, src, len); while (n < len) { int l = min(len - n, 16); hex_dump_to_buffer(databuf + n, l, 16, 1, printbuf, sizeof(printbuf), Loading @@ -192,11 +212,11 @@ static void wil_print_ring(struct seq_file *s, const char *prefix, } } } else { seq_printf(s, "\n"); seq_puts(s, "\n"); } } out: seq_printf(s, "}\n"); seq_puts(s, "}\n"); } static int wil_mbox_debugfs_show(struct seq_file *s, void *data) Loading Loading @@ -244,9 +264,9 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get, static struct dentry *wil_debugfs_create_iomem_x32(const char *name, umode_t mode, struct dentry *parent, void __iomem *value) void *value) { return debugfs_create_file(name, mode, parent, (void * __force)value, return debugfs_create_file(name, mode, parent, value, &fops_iomem_x32); } Loading @@ -255,11 +275,13 @@ 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"); Loading @@ -270,6 +292,62 @@ static struct dentry *wil_debugfs_create_ulong(const char *name, umode_t mode, return debugfs_create_file(name, mode, parent, value, &wil_fops_ulong); } /** * wil6210_debugfs_init_offset - create set of debugfs files * @wil - driver's context, used for printing * @dbg - directory on the debugfs, where files will be created * @base - base address used in address calculation * @tbl - table with file descriptions. Should be terminated with empty element. * * Creates files accordingly to the @tbl. */ static void wil6210_debugfs_init_offset(struct wil6210_priv *wil, struct dentry *dbg, void *base, const struct dbg_off * const tbl) { int i; for (i = 0; tbl[i].name; i++) { struct dentry *f; switch (tbl[i].type) { case doff_u32: f = debugfs_create_u32(tbl[i].name, tbl[i].mode, dbg, base + tbl[i].off); break; case doff_x32: f = debugfs_create_x32(tbl[i].name, tbl[i].mode, dbg, base + tbl[i].off); break; case doff_ulong: f = wil_debugfs_create_ulong(tbl[i].name, tbl[i].mode, dbg, base + tbl[i].off); break; case doff_io32: f = wil_debugfs_create_iomem_x32(tbl[i].name, tbl[i].mode, dbg, base + tbl[i].off); break; default: f = ERR_PTR(-EINVAL); } if (IS_ERR_OR_NULL(f)) wil_err(wil, "Create file \"%s\": err %ld\n", tbl[i].name, PTR_ERR(f)); } } static const struct dbg_off isr_off[] = { {"ICC", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICC), doff_io32}, {"ICR", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICR), doff_io32}, {"ICM", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICM), doff_io32}, {"ICS", S_IWUSR, offsetof(struct RGF_ICR, ICS), doff_io32}, {"IMV", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, IMV), doff_io32}, {"IMS", S_IWUSR, offsetof(struct RGF_ICR, IMS), doff_io32}, {"IMC", S_IWUSR, offsetof(struct RGF_ICR, IMC), doff_io32}, {}, }; static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, const char *name, struct dentry *parent, u32 off) Loading @@ -279,24 +357,19 @@ static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, if (IS_ERR_OR_NULL(d)) return -ENODEV; wil_debugfs_create_iomem_x32("ICC", S_IRUGO | S_IWUSR, d, wil->csr + off); wil_debugfs_create_iomem_x32("ICR", S_IRUGO | S_IWUSR, d, wil->csr + off + 4); wil_debugfs_create_iomem_x32("ICM", S_IRUGO | S_IWUSR, d, wil->csr + off + 8); wil_debugfs_create_iomem_x32("ICS", S_IWUSR, d, wil->csr + off + 12); wil_debugfs_create_iomem_x32("IMV", S_IRUGO | S_IWUSR, d, wil->csr + off + 16); wil_debugfs_create_iomem_x32("IMS", S_IWUSR, d, wil->csr + off + 20); wil_debugfs_create_iomem_x32("IMC", S_IWUSR, d, wil->csr + off + 24); wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr + off, isr_off); return 0; } static const struct dbg_off pseudo_isr_off[] = { {"CAUSE", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE), doff_io32}, {"MASK_SW", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW), doff_io32}, {"MASK_FW", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW), doff_io32}, {}, }; static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, struct dentry *parent) { Loading @@ -305,16 +378,19 @@ static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, if (IS_ERR_OR_NULL(d)) return -ENODEV; wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO, d, wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO, d, wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO, d, wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW)); wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr, pseudo_isr_off); return 0; } static const struct dbg_off itr_cnt_off[] = { {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_TRSH), doff_io32}, {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_DATA), doff_io32}, {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_CRL), doff_io32}, {}, }; static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil, struct dentry *parent) { Loading @@ -323,12 +399,8 @@ 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 | S_IWUSR, d, wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_TRSH)); 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 | S_IWUSR, d, wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL)); wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr, itr_cnt_off); return 0; } Loading Loading @@ -411,6 +483,7 @@ struct dentry *wil_debugfs_create_ioblob(const char *name, { return debugfs_create_file(name, mode, parent, blob, &fops_ioblob); } /*---reset---*/ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, size_t len, loff_t *ppos) Loading @@ -436,6 +509,7 @@ 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) Loading @@ -446,6 +520,7 @@ static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf, bool on; char *kbuf = kmalloc(len + 1, GFP_KERNEL); if (!kbuf) return -ENOMEM; if (copy_from_user(kbuf, buf, len)) { Loading Loading @@ -482,6 +557,7 @@ 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, Loading @@ -491,8 +567,8 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf, struct wiphy *wiphy = wil_to_wiphy(wil); struct wireless_dev *wdev = wil_to_wdev(wil); int rc; void *frame = kmalloc(len, GFP_KERNEL); if (!frame) return -ENOMEM; Loading Loading @@ -558,8 +634,10 @@ static void wil_seq_hexdump(struct seq_file *s, void *p, int len, { char printbuf[16 * 3 + 2]; int i = 0; while (i < len) { int l = min(len - i, 16); hex_dump_to_buffer(p + i, l, 16, 1, printbuf, sizeof(printbuf), false); seq_printf(s, "%s%s\n", prefix, printbuf); Loading Loading @@ -597,10 +675,8 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) struct wil6210_priv *wil = s->private; struct vring *vring; bool tx = (dbg_vring_index < WIL6210_MAX_TX_RINGS); if (tx) vring = &(wil->vring_tx[dbg_vring_index]); else vring = &wil->vring_rx; vring = tx ? &wil->vring_tx[dbg_vring_index] : &wil->vring_rx; if (!vring->va) { if (tx) Loading @@ -615,7 +691,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) * only field used, .dma.length, is the same */ volatile struct vring_tx_desc *d = &(vring->va[dbg_txdesc_index].tx); &vring->va[dbg_txdesc_index].tx; volatile u32 *u = (volatile u32 *)d; struct sk_buff *skb = vring->ctx[dbg_txdesc_index].skb; Loading @@ -635,7 +711,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) wil_seq_print_skb(s, skb); kfree_skb(skb); } seq_printf(s, "}\n"); seq_puts(s, "}\n"); } else { if (tx) seq_printf(s, "[%2d] TxDesc index (%d) >= size (%d)\n", Loading @@ -662,16 +738,79 @@ static const struct file_operations fops_txdesc = { }; /*---------beamforming------------*/ static char *wil_bfstatus_str(u32 status) { switch (status) { case 0: return "Failed"; case 1: return "OK"; case 2: return "Retrying"; default: return "??"; } } static bool is_all_zeros(void * const x_, size_t sz) { /* if reply is all-0, ignore this CID */ u32 *x = x_; int n; for (n = 0; n < sz / sizeof(*x); n++) if (x[n]) return false; return true; } static int wil_bf_debugfs_show(struct seq_file *s, void *data) { int rc; int i; struct wil6210_priv *wil = s->private; seq_printf(s, "TSF : 0x%016llx\n" "TxMCS : %d\n" "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n", wil->stats.tsf, wil->stats.bf_mcs, wil->stats.my_rx_sector, wil->stats.my_tx_sector, wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); struct wmi_notify_req_cmd cmd = { .interval_usec = 0, }; struct { struct wil6210_mbox_hdr_wmi wmi; struct wmi_notify_req_done_event evt; } __packed reply; for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { u32 status; cmd.cid = i; rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20); /* if reply is all-0, ignore this CID */ if (rc || is_all_zeros(&reply.evt, sizeof(reply.evt))) continue; status = le32_to_cpu(reply.evt.status); seq_printf(s, "CID %d {\n" " TSF = 0x%016llx\n" " TxMCS = %2d TxTpt = %4d\n" " SQI = %4d\n" " Status = 0x%08x %s\n" " Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n" " Goodput(rx:tx) %4d:%4d\n" "}\n", i, le64_to_cpu(reply.evt.tsf), le16_to_cpu(reply.evt.bf_mcs), le32_to_cpu(reply.evt.tx_tpt), reply.evt.sqi, status, wil_bfstatus_str(status), le16_to_cpu(reply.evt.my_rx_sector), le16_to_cpu(reply.evt.my_tx_sector), le16_to_cpu(reply.evt.other_rx_sector), le16_to_cpu(reply.evt.other_tx_sector), le32_to_cpu(reply.evt.rx_goodput), le32_to_cpu(reply.evt.tx_goodput)); } return 0; } Loading @@ -686,6 +825,7 @@ static const struct file_operations fops_bf = { .read = seq_read, .llseek = seq_lseek, }; /*---------SSID------------*/ static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) Loading Loading @@ -748,10 +888,10 @@ static int wil_temp_debugfs_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; u32 t_m, t_r; int rc = wmi_get_temperature(wil, &t_m, &t_r); if (rc) { seq_printf(s, "Failed\n"); seq_puts(s, "Failed\n"); return 0; } Loading Loading @@ -807,6 +947,7 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data) 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 "; Loading Loading @@ -867,7 +1008,6 @@ static int wil_info_debugfs_show(struct seq_file *s, void *data) rxf_old = rxf; txf_old = txf; #define CHECK_QSTATE(x) (state & BIT(__QUEUE_STATE_ ## x)) ? \ " " __stringify(x) : "" Loading Loading @@ -902,6 +1042,7 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r) { int i; u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size; seq_printf(s, "0x%03x [", r->head_seq_num); for (i = 0; i < r->buf_size; i++) { if (i == index) Loading @@ -916,10 +1057,12 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; int i, tid; unsigned long flags; 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 "; Loading @@ -935,13 +1078,16 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data) (p->data_port_open ? " data_port_open" : "")); if (p->status == wil_sta_connected) { spin_lock_irqsave(&p->tid_rx_lock, flags); for (tid = 0; tid < WIL_STA_TID_NUM; tid++) { struct wil_tid_ampdu_rx *r = p->tid_rx[tid]; if (r) { seq_printf(s, "[%2d] ", tid); wil_print_rxtid(s, r); } } spin_unlock_irqrestore(&p->tid_rx_lock, flags); } } Loading Loading @@ -981,6 +1127,87 @@ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, } } /* misc files */ static const struct { const char *name; umode_t mode; const struct file_operations *fops; } dbg_files[] = { {"mbox", S_IRUGO, &fops_mbox}, {"vrings", S_IRUGO, &fops_vring}, {"stations", S_IRUGO, &fops_sta}, {"desc", S_IRUGO, &fops_txdesc}, {"bf", S_IRUGO, &fops_bf}, {"ssid", S_IRUGO | S_IWUSR, &fops_ssid}, {"mem_val", S_IRUGO, &fops_memread}, {"reset", S_IWUSR, &fops_reset}, {"rxon", S_IWUSR, &fops_rxon}, {"tx_mgmt", S_IWUSR, &fops_txmgmt}, {"wmi_send", S_IWUSR, &fops_wmi}, {"temp", S_IRUGO, &fops_temp}, {"freq", S_IRUGO, &fops_freq}, {"link", S_IRUGO, &fops_link}, {"info", S_IRUGO, &fops_info}, }; static void wil6210_debugfs_init_files(struct wil6210_priv *wil, struct dentry *dbg) { int i; for (i = 0; i < ARRAY_SIZE(dbg_files); i++) debugfs_create_file(dbg_files[i].name, dbg_files[i].mode, dbg, wil, dbg_files[i].fops); } /* interrupt control blocks */ static const struct { const char *name; u32 icr_off; } dbg_icr[] = { {"USER_ICR", HOSTADDR(RGF_USER_USER_ICR)}, {"DMA_EP_TX_ICR", HOSTADDR(RGF_DMA_EP_TX_ICR)}, {"DMA_EP_RX_ICR", HOSTADDR(RGF_DMA_EP_RX_ICR)}, {"DMA_EP_MISC_ICR", HOSTADDR(RGF_DMA_EP_MISC_ICR)}, }; static void wil6210_debugfs_init_isr(struct wil6210_priv *wil, struct dentry *dbg) { int i; for (i = 0; i < ARRAY_SIZE(dbg_icr); i++) wil6210_debugfs_create_ISR(wil, dbg_icr[i].name, dbg, dbg_icr[i].icr_off); } #define WIL_FIELD(name, mode, type) { __stringify(name), mode, \ offsetof(struct wil6210_priv, name), type} /* fields in struct wil6210_priv */ static const struct dbg_off dbg_wil_off[] = { WIL_FIELD(secure_pcp, S_IRUGO | S_IWUSR, doff_u32), WIL_FIELD(status, S_IRUGO | S_IWUSR, doff_ulong), WIL_FIELD(fw_version, S_IRUGO, doff_u32), WIL_FIELD(hw_version, S_IRUGO, doff_x32), {}, }; static const struct dbg_off dbg_wil_regs[] = { {"RGF_MAC_MTRL_COUNTER_0", S_IRUGO, HOSTADDR(RGF_MAC_MTRL_COUNTER_0), doff_io32}, {"RGF_USER_USAGE_1", S_IRUGO, HOSTADDR(RGF_USER_USAGE_1), doff_io32}, {}, }; /* static parameters */ static const struct dbg_off dbg_statics[] = { {"desc_index", S_IRUGO | S_IWUSR, (ulong)&dbg_txdesc_index, doff_u32}, {"vring_index", S_IRUGO | S_IWUSR, (ulong)&dbg_vring_index, doff_u32}, {"mem_addr", S_IRUGO | S_IWUSR, (ulong)&mem_addr, doff_u32}, {}, }; int wil6210_debugfs_init(struct wil6210_priv *wil) { struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, Loading @@ -989,51 +1216,17 @@ int wil6210_debugfs_init(struct wil6210_priv *wil) if (IS_ERR_OR_NULL(dbg)) return -ENODEV; debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox); debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring); debugfs_create_file("stations", S_IRUGO, dbg, wil, &fops_sta); debugfs_create_file("desc", S_IRUGO, dbg, wil, &fops_txdesc); debugfs_create_u32("desc_index", S_IRUGO | S_IWUSR, dbg, &dbg_txdesc_index); debugfs_create_u32("vring_index", S_IRUGO | S_IWUSR, dbg, &dbg_vring_index); debugfs_create_file("bf", S_IRUGO, dbg, wil, &fops_bf); 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)); wil6210_debugfs_create_ISR(wil, "DMA_EP_TX_ICR", dbg, HOSTADDR(RGF_DMA_EP_TX_ICR)); wil6210_debugfs_create_ISR(wil, "DMA_EP_RX_ICR", dbg, HOSTADDR(RGF_DMA_EP_RX_ICR)); wil6210_debugfs_create_ISR(wil, "DMA_EP_MISC_ICR", dbg, HOSTADDR(RGF_DMA_EP_MISC_ICR)); wil6210_debugfs_create_pseudo_ISR(wil, dbg); wil6210_debugfs_create_ITR_CNT(wil, dbg); wil6210_debugfs_init_files(wil, dbg); wil6210_debugfs_init_isr(wil, dbg); wil6210_debugfs_init_blobs(wil, dbg); wil6210_debugfs_init_offset(wil, dbg, wil, dbg_wil_off); wil6210_debugfs_init_offset(wil, dbg, (void * __force)wil->csr, dbg_wil_regs); wil6210_debugfs_init_offset(wil, dbg, NULL, dbg_statics); 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); wil6210_debugfs_create_pseudo_ISR(wil, dbg); wil6210_debugfs_init_blobs(wil, dbg); wil6210_debugfs_create_ITR_CNT(wil, dbg); return 0; } Loading