aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/wl1271_debugfs.c
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@nokia.com>2009-08-06 16:25:28 +0300
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:12:46 -0400
commitf5fc0f86b02afef1119b523623b4cde41475bc8c (patch)
tree793be075412781fef4fcd752032e9b3680eaf96f /drivers/net/wireless/wl12xx/wl1271_debugfs.c
parentcfg80211: fix disassociation warning due to misuse of wdev->current_bss (diff)
downloadlinux-dev-f5fc0f86b02afef1119b523623b4cde41475bc8c.tar.xz
linux-dev-f5fc0f86b02afef1119b523623b4cde41475bc8c.zip
wl1271: add wl1271 driver files
This driver supports the wl1271 chipset from Texas Instruments based on the WiLink(tm) 6.0 mobile platform. Support for wl1273 should be relatively easy to add. This chipset is designed for embedded devices, with good powersaving capabilities. The wl1271 chipset is the successor of wl1251 and supports the 802.11b/g/n standards, but currently this driver supports only b/g. More information about this chipset can be found here: http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?templateId=6123&navigationId=12762&contentId=29993 Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_debugfs.c')
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_debugfs.c518
1 files changed, 518 insertions, 0 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
new file mode 100644
index 000000000000..c1805e5f8964
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
@@ -0,0 +1,518 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "wl1271_debugfs.h"
+
+#include <linux/skbuff.h>
+
+#include "wl1271.h"
+#include "wl1271_acx.h"
+#include "wl1271_ps.h"
+
+/* ms */
+#define WL1271_DEBUGFS_STATS_LIFETIME 1000
+
+/* debugfs macros idea from mac80211 */
+
+#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
+static ssize_t name## _read(struct file *file, char __user *userbuf, \
+ size_t count, loff_t *ppos) \
+{ \
+ struct wl1271 *wl = file->private_data; \
+ char buf[buflen]; \
+ int res; \
+ \
+ res = scnprintf(buf, buflen, fmt "\n", ##value); \
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+} \
+ \
+static const struct file_operations name## _ops = { \
+ .read = name## _read, \
+ .open = wl1271_open_file_generic, \
+};
+
+#define DEBUGFS_ADD(name, parent) \
+ wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \
+ wl, &name## _ops); \
+ if (IS_ERR(wl->debugfs.name)) { \
+ ret = PTR_ERR(wl->debugfs.name); \
+ wl->debugfs.name = NULL; \
+ goto out; \
+ }
+
+#define DEBUGFS_DEL(name) \
+ do { \
+ debugfs_remove(wl->debugfs.name); \
+ wl->debugfs.name = NULL; \
+ } while (0)
+
+#define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt) \
+static ssize_t sub## _ ##name## _read(struct file *file, \
+ char __user *userbuf, \
+ size_t count, loff_t *ppos) \
+{ \
+ struct wl1271 *wl = file->private_data; \
+ char buf[buflen]; \
+ int res; \
+ \
+ wl1271_debugfs_update_stats(wl); \
+ \
+ res = scnprintf(buf, buflen, fmt "\n", \
+ wl->stats.fw_stats->sub.name); \
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+} \
+ \
+static const struct file_operations sub## _ ##name## _ops = { \
+ .read = sub## _ ##name## _read, \
+ .open = wl1271_open_file_generic, \
+};
+
+#define DEBUGFS_FWSTATS_ADD(sub, name) \
+ DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics)
+
+#define DEBUGFS_FWSTATS_DEL(sub, name) \
+ DEBUGFS_DEL(sub## _ ##name)
+
+static void wl1271_debugfs_update_stats(struct wl1271 *wl)
+{
+ int ret;
+
+ mutex_lock(&wl->mutex);
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
+ if (wl->state == WL1271_STATE_ON &&
+ time_after(jiffies, wl->stats.fw_stats_update +
+ msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {
+ wl1271_acx_statistics(wl, wl->stats.fw_stats);
+ wl->stats.fw_stats_update = jiffies;
+ }
+
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+static int wl1271_open_file_generic(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u");
+DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u");
+DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u");
+DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u");
+DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u");
+/* skipping wep.reserved */
+DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u");
+DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u");
+DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u");
+/* skipping cont_miss_bcns_spread for now */
+DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u");
+DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u");
+DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u");
+DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u");
+DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u");
+
+DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data,
+ 20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u");
+DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u");
+
+DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count);
+DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u",
+ wl->stats.excessive_retries);
+
+static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ u32 queue_len;
+ char buf[20];
+ int res;
+
+ queue_len = skb_queue_len(&wl->tx_queue);
+
+ res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+
+static const struct file_operations tx_queue_len_ops = {
+ .read = tx_queue_len_read,
+ .open = wl1271_open_file_generic,
+};
+
+static void wl1271_debugfs_delete_files(struct wl1271 *wl)
+{
+ DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
+
+ DEBUGFS_FWSTATS_DEL(rx, out_of_mem);
+ DEBUGFS_FWSTATS_DEL(rx, hdr_overflow);
+ DEBUGFS_FWSTATS_DEL(rx, hw_stuck);
+ DEBUGFS_FWSTATS_DEL(rx, dropped);
+ DEBUGFS_FWSTATS_DEL(rx, fcs_err);
+ DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig);
+ DEBUGFS_FWSTATS_DEL(rx, path_reset);
+ DEBUGFS_FWSTATS_DEL(rx, reset_counter);
+
+ DEBUGFS_FWSTATS_DEL(dma, rx_requested);
+ DEBUGFS_FWSTATS_DEL(dma, rx_errors);
+ DEBUGFS_FWSTATS_DEL(dma, tx_requested);
+ DEBUGFS_FWSTATS_DEL(dma, tx_errors);
+
+ DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt);
+ DEBUGFS_FWSTATS_DEL(isr, fiqs);
+ DEBUGFS_FWSTATS_DEL(isr, rx_headers);
+ DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow);
+ DEBUGFS_FWSTATS_DEL(isr, rx_rdys);
+ DEBUGFS_FWSTATS_DEL(isr, irqs);
+ DEBUGFS_FWSTATS_DEL(isr, tx_procs);
+ DEBUGFS_FWSTATS_DEL(isr, decrypt_done);
+ DEBUGFS_FWSTATS_DEL(isr, dma0_done);
+ DEBUGFS_FWSTATS_DEL(isr, dma1_done);
+ DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete);
+ DEBUGFS_FWSTATS_DEL(isr, commands);
+ DEBUGFS_FWSTATS_DEL(isr, rx_procs);
+ DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes);
+ DEBUGFS_FWSTATS_DEL(isr, host_acknowledges);
+ DEBUGFS_FWSTATS_DEL(isr, pci_pm);
+ DEBUGFS_FWSTATS_DEL(isr, wakeups);
+ DEBUGFS_FWSTATS_DEL(isr, low_rssi);
+
+ DEBUGFS_FWSTATS_DEL(wep, addr_key_count);
+ DEBUGFS_FWSTATS_DEL(wep, default_key_count);
+ /* skipping wep.reserved */
+ DEBUGFS_FWSTATS_DEL(wep, key_not_found);
+ DEBUGFS_FWSTATS_DEL(wep, decrypt_fail);
+ DEBUGFS_FWSTATS_DEL(wep, packets);
+ DEBUGFS_FWSTATS_DEL(wep, interrupt);
+
+ DEBUGFS_FWSTATS_DEL(pwr, ps_enter);
+ DEBUGFS_FWSTATS_DEL(pwr, elp_enter);
+ DEBUGFS_FWSTATS_DEL(pwr, missing_bcns);
+ DEBUGFS_FWSTATS_DEL(pwr, wake_on_host);
+ DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp);
+ DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps);
+ DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps);
+ DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons);
+ DEBUGFS_FWSTATS_DEL(pwr, power_save_off);
+ DEBUGFS_FWSTATS_DEL(pwr, enable_ps);
+ DEBUGFS_FWSTATS_DEL(pwr, disable_ps);
+ DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps);
+ /* skipping cont_miss_bcns_spread for now */
+ DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons);
+
+ DEBUGFS_FWSTATS_DEL(mic, rx_pkts);
+ DEBUGFS_FWSTATS_DEL(mic, calc_failure);
+
+ DEBUGFS_FWSTATS_DEL(aes, encrypt_fail);
+ DEBUGFS_FWSTATS_DEL(aes, decrypt_fail);
+ DEBUGFS_FWSTATS_DEL(aes, encrypt_packets);
+ DEBUGFS_FWSTATS_DEL(aes, decrypt_packets);
+ DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt);
+ DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt);
+
+ DEBUGFS_FWSTATS_DEL(event, heart_beat);
+ DEBUGFS_FWSTATS_DEL(event, calibration);
+ DEBUGFS_FWSTATS_DEL(event, rx_mismatch);
+ DEBUGFS_FWSTATS_DEL(event, rx_mem_empty);
+ DEBUGFS_FWSTATS_DEL(event, rx_pool);
+ DEBUGFS_FWSTATS_DEL(event, oom_late);
+ DEBUGFS_FWSTATS_DEL(event, phy_transmit_error);
+ DEBUGFS_FWSTATS_DEL(event, tx_stuck);
+
+ DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts);
+ DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts);
+ DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime);
+ DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn);
+ DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn);
+ DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization);
+ DEBUGFS_FWSTATS_DEL(ps, upsd_utilization);
+
+ DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop);
+ DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data);
+
+ DEBUGFS_DEL(tx_queue_len);
+ DEBUGFS_DEL(retry_count);
+ DEBUGFS_DEL(excessive_retries);
+}
+
+static int wl1271_debugfs_add_files(struct wl1271 *wl)
+{
+ int ret = 0;
+
+ DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow);
+
+ DEBUGFS_FWSTATS_ADD(rx, out_of_mem);
+ DEBUGFS_FWSTATS_ADD(rx, hdr_overflow);
+ DEBUGFS_FWSTATS_ADD(rx, hw_stuck);
+ DEBUGFS_FWSTATS_ADD(rx, dropped);
+ DEBUGFS_FWSTATS_ADD(rx, fcs_err);
+ DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig);
+ DEBUGFS_FWSTATS_ADD(rx, path_reset);
+ DEBUGFS_FWSTATS_ADD(rx, reset_counter);
+
+ DEBUGFS_FWSTATS_ADD(dma, rx_requested);
+ DEBUGFS_FWSTATS_ADD(dma, rx_errors);
+ DEBUGFS_FWSTATS_ADD(dma, tx_requested);
+ DEBUGFS_FWSTATS_ADD(dma, tx_errors);
+
+ DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt);
+ DEBUGFS_FWSTATS_ADD(isr, fiqs);
+ DEBUGFS_FWSTATS_ADD(isr, rx_headers);
+ DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow);
+ DEBUGFS_FWSTATS_ADD(isr, rx_rdys);
+ DEBUGFS_FWSTATS_ADD(isr, irqs);
+ DEBUGFS_FWSTATS_ADD(isr, tx_procs);
+ DEBUGFS_FWSTATS_ADD(isr, decrypt_done);
+ DEBUGFS_FWSTATS_ADD(isr, dma0_done);
+ DEBUGFS_FWSTATS_ADD(isr, dma1_done);
+ DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete);
+ DEBUGFS_FWSTATS_ADD(isr, commands);
+ DEBUGFS_FWSTATS_ADD(isr, rx_procs);
+ DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes);
+ DEBUGFS_FWSTATS_ADD(isr, host_acknowledges);
+ DEBUGFS_FWSTATS_ADD(isr, pci_pm);
+ DEBUGFS_FWSTATS_ADD(isr, wakeups);
+ DEBUGFS_FWSTATS_ADD(isr, low_rssi);
+
+ DEBUGFS_FWSTATS_ADD(wep, addr_key_count);
+ DEBUGFS_FWSTATS_ADD(wep, default_key_count);
+ /* skipping wep.reserved */
+ DEBUGFS_FWSTATS_ADD(wep, key_not_found);
+ DEBUGFS_FWSTATS_ADD(wep, decrypt_fail);
+ DEBUGFS_FWSTATS_ADD(wep, packets);
+ DEBUGFS_FWSTATS_ADD(wep, interrupt);
+
+ DEBUGFS_FWSTATS_ADD(pwr, ps_enter);
+ DEBUGFS_FWSTATS_ADD(pwr, elp_enter);
+ DEBUGFS_FWSTATS_ADD(pwr, missing_bcns);
+ DEBUGFS_FWSTATS_ADD(pwr, wake_on_host);
+ DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp);
+ DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps);
+ DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps);
+ DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons);
+ DEBUGFS_FWSTATS_ADD(pwr, power_save_off);
+ DEBUGFS_FWSTATS_ADD(pwr, enable_ps);
+ DEBUGFS_FWSTATS_ADD(pwr, disable_ps);
+ DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps);
+ /* skipping cont_miss_bcns_spread for now */
+ DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons);
+
+ DEBUGFS_FWSTATS_ADD(mic, rx_pkts);
+ DEBUGFS_FWSTATS_ADD(mic, calc_failure);
+
+ DEBUGFS_FWSTATS_ADD(aes, encrypt_fail);
+ DEBUGFS_FWSTATS_ADD(aes, decrypt_fail);
+ DEBUGFS_FWSTATS_ADD(aes, encrypt_packets);
+ DEBUGFS_FWSTATS_ADD(aes, decrypt_packets);
+ DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt);
+ DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt);
+
+ DEBUGFS_FWSTATS_ADD(event, heart_beat);
+ DEBUGFS_FWSTATS_ADD(event, calibration);
+ DEBUGFS_FWSTATS_ADD(event, rx_mismatch);
+ DEBUGFS_FWSTATS_ADD(event, rx_mem_empty);
+ DEBUGFS_FWSTATS_ADD(event, rx_pool);
+ DEBUGFS_FWSTATS_ADD(event, oom_late);
+ DEBUGFS_FWSTATS_ADD(event, phy_transmit_error);
+ DEBUGFS_FWSTATS_ADD(event, tx_stuck);
+
+ DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts);
+ DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts);
+ DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime);
+ DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn);
+ DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn);
+ DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization);
+ DEBUGFS_FWSTATS_ADD(ps, upsd_utilization);
+
+ DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop);
+ DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data);
+ DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data);
+
+ DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir);
+ DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
+ DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
+
+out:
+ if (ret < 0)
+ wl1271_debugfs_delete_files(wl);
+
+ return ret;
+}
+
+void wl1271_debugfs_reset(struct wl1271 *wl)
+{
+ memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
+ wl->stats.retry_count = 0;
+ wl->stats.excessive_retries = 0;
+}
+
+int wl1271_debugfs_init(struct wl1271 *wl)
+{
+ int ret;
+
+ wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+
+ if (IS_ERR(wl->debugfs.rootdir)) {
+ ret = PTR_ERR(wl->debugfs.rootdir);
+ wl->debugfs.rootdir = NULL;
+ goto err;
+ }
+
+ wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics",
+ wl->debugfs.rootdir);
+
+ if (IS_ERR(wl->debugfs.fw_statistics)) {
+ ret = PTR_ERR(wl->debugfs.fw_statistics);
+ wl->debugfs.fw_statistics = NULL;
+ goto err_root;
+ }
+
+ wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats),
+ GFP_KERNEL);
+
+ if (!wl->stats.fw_stats) {
+ ret = -ENOMEM;
+ goto err_fw;
+ }
+
+ wl->stats.fw_stats_update = jiffies;
+
+ ret = wl1271_debugfs_add_files(wl);
+
+ if (ret < 0)
+ goto err_file;
+
+ return 0;
+
+err_file:
+ kfree(wl->stats.fw_stats);
+ wl->stats.fw_stats = NULL;
+
+err_fw:
+ debugfs_remove(wl->debugfs.fw_statistics);
+ wl->debugfs.fw_statistics = NULL;
+
+err_root:
+ debugfs_remove(wl->debugfs.rootdir);
+ wl->debugfs.rootdir = NULL;
+
+err:
+ return ret;
+}
+
+void wl1271_debugfs_exit(struct wl1271 *wl)
+{
+ wl1271_debugfs_delete_files(wl);
+
+ kfree(wl->stats.fw_stats);
+ wl->stats.fw_stats = NULL;
+
+ debugfs_remove(wl->debugfs.fw_statistics);
+ wl->debugfs.fw_statistics = NULL;
+
+ debugfs_remove(wl->debugfs.rootdir);
+ wl->debugfs.rootdir = NULL;
+
+}