1*90921014SLuciano Coelho /* 2*90921014SLuciano Coelho * This file is part of wl1251 3*90921014SLuciano Coelho * 4*90921014SLuciano Coelho * Copyright (C) 2009 Nokia Corporation 5*90921014SLuciano Coelho * 6*90921014SLuciano Coelho * This program is free software; you can redistribute it and/or 7*90921014SLuciano Coelho * modify it under the terms of the GNU General Public License 8*90921014SLuciano Coelho * version 2 as published by the Free Software Foundation. 9*90921014SLuciano Coelho * 10*90921014SLuciano Coelho * This program is distributed in the hope that it will be useful, but 11*90921014SLuciano Coelho * WITHOUT ANY WARRANTY; without even the implied warranty of 12*90921014SLuciano Coelho * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13*90921014SLuciano Coelho * General Public License for more details. 14*90921014SLuciano Coelho * 15*90921014SLuciano Coelho * You should have received a copy of the GNU General Public License 16*90921014SLuciano Coelho * along with this program; if not, write to the Free Software 17*90921014SLuciano Coelho * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18*90921014SLuciano Coelho * 02110-1301 USA 19*90921014SLuciano Coelho * 20*90921014SLuciano Coelho */ 21*90921014SLuciano Coelho 22*90921014SLuciano Coelho #include "debugfs.h" 23*90921014SLuciano Coelho 24*90921014SLuciano Coelho #include <linux/skbuff.h> 25*90921014SLuciano Coelho #include <linux/slab.h> 26*90921014SLuciano Coelho 27*90921014SLuciano Coelho #include "wl1251.h" 28*90921014SLuciano Coelho #include "acx.h" 29*90921014SLuciano Coelho #include "ps.h" 30*90921014SLuciano Coelho 31*90921014SLuciano Coelho /* ms */ 32*90921014SLuciano Coelho #define WL1251_DEBUGFS_STATS_LIFETIME 1000 33*90921014SLuciano Coelho 34*90921014SLuciano Coelho /* debugfs macros idea from mac80211 */ 35*90921014SLuciano Coelho 36*90921014SLuciano Coelho #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ 37*90921014SLuciano Coelho static ssize_t name## _read(struct file *file, char __user *userbuf, \ 38*90921014SLuciano Coelho size_t count, loff_t *ppos) \ 39*90921014SLuciano Coelho { \ 40*90921014SLuciano Coelho struct wl1251 *wl = file->private_data; \ 41*90921014SLuciano Coelho char buf[buflen]; \ 42*90921014SLuciano Coelho int res; \ 43*90921014SLuciano Coelho \ 44*90921014SLuciano Coelho res = scnprintf(buf, buflen, fmt "\n", ##value); \ 45*90921014SLuciano Coelho return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ 46*90921014SLuciano Coelho } \ 47*90921014SLuciano Coelho \ 48*90921014SLuciano Coelho static const struct file_operations name## _ops = { \ 49*90921014SLuciano Coelho .read = name## _read, \ 50*90921014SLuciano Coelho .open = wl1251_open_file_generic, \ 51*90921014SLuciano Coelho .llseek = generic_file_llseek, \ 52*90921014SLuciano Coelho }; 53*90921014SLuciano Coelho 54*90921014SLuciano Coelho #define DEBUGFS_ADD(name, parent) \ 55*90921014SLuciano Coelho wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \ 56*90921014SLuciano Coelho wl, &name## _ops); \ 57*90921014SLuciano Coelho if (IS_ERR(wl->debugfs.name)) { \ 58*90921014SLuciano Coelho ret = PTR_ERR(wl->debugfs.name); \ 59*90921014SLuciano Coelho wl->debugfs.name = NULL; \ 60*90921014SLuciano Coelho goto out; \ 61*90921014SLuciano Coelho } 62*90921014SLuciano Coelho 63*90921014SLuciano Coelho #define DEBUGFS_DEL(name) \ 64*90921014SLuciano Coelho do { \ 65*90921014SLuciano Coelho debugfs_remove(wl->debugfs.name); \ 66*90921014SLuciano Coelho wl->debugfs.name = NULL; \ 67*90921014SLuciano Coelho } while (0) 68*90921014SLuciano Coelho 69*90921014SLuciano Coelho #define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt) \ 70*90921014SLuciano Coelho static ssize_t sub## _ ##name## _read(struct file *file, \ 71*90921014SLuciano Coelho char __user *userbuf, \ 72*90921014SLuciano Coelho size_t count, loff_t *ppos) \ 73*90921014SLuciano Coelho { \ 74*90921014SLuciano Coelho struct wl1251 *wl = file->private_data; \ 75*90921014SLuciano Coelho char buf[buflen]; \ 76*90921014SLuciano Coelho int res; \ 77*90921014SLuciano Coelho \ 78*90921014SLuciano Coelho wl1251_debugfs_update_stats(wl); \ 79*90921014SLuciano Coelho \ 80*90921014SLuciano Coelho res = scnprintf(buf, buflen, fmt "\n", \ 81*90921014SLuciano Coelho wl->stats.fw_stats->sub.name); \ 82*90921014SLuciano Coelho return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ 83*90921014SLuciano Coelho } \ 84*90921014SLuciano Coelho \ 85*90921014SLuciano Coelho static const struct file_operations sub## _ ##name## _ops = { \ 86*90921014SLuciano Coelho .read = sub## _ ##name## _read, \ 87*90921014SLuciano Coelho .open = wl1251_open_file_generic, \ 88*90921014SLuciano Coelho .llseek = generic_file_llseek, \ 89*90921014SLuciano Coelho }; 90*90921014SLuciano Coelho 91*90921014SLuciano Coelho #define DEBUGFS_FWSTATS_ADD(sub, name) \ 92*90921014SLuciano Coelho DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics) 93*90921014SLuciano Coelho 94*90921014SLuciano Coelho #define DEBUGFS_FWSTATS_DEL(sub, name) \ 95*90921014SLuciano Coelho DEBUGFS_DEL(sub## _ ##name) 96*90921014SLuciano Coelho 97*90921014SLuciano Coelho static void wl1251_debugfs_update_stats(struct wl1251 *wl) 98*90921014SLuciano Coelho { 99*90921014SLuciano Coelho int ret; 100*90921014SLuciano Coelho 101*90921014SLuciano Coelho mutex_lock(&wl->mutex); 102*90921014SLuciano Coelho 103*90921014SLuciano Coelho ret = wl1251_ps_elp_wakeup(wl); 104*90921014SLuciano Coelho if (ret < 0) 105*90921014SLuciano Coelho goto out; 106*90921014SLuciano Coelho 107*90921014SLuciano Coelho if (wl->state == WL1251_STATE_ON && 108*90921014SLuciano Coelho time_after(jiffies, wl->stats.fw_stats_update + 109*90921014SLuciano Coelho msecs_to_jiffies(WL1251_DEBUGFS_STATS_LIFETIME))) { 110*90921014SLuciano Coelho wl1251_acx_statistics(wl, wl->stats.fw_stats); 111*90921014SLuciano Coelho wl->stats.fw_stats_update = jiffies; 112*90921014SLuciano Coelho } 113*90921014SLuciano Coelho 114*90921014SLuciano Coelho wl1251_ps_elp_sleep(wl); 115*90921014SLuciano Coelho 116*90921014SLuciano Coelho out: 117*90921014SLuciano Coelho mutex_unlock(&wl->mutex); 118*90921014SLuciano Coelho } 119*90921014SLuciano Coelho 120*90921014SLuciano Coelho static int wl1251_open_file_generic(struct inode *inode, struct file *file) 121*90921014SLuciano Coelho { 122*90921014SLuciano Coelho file->private_data = inode->i_private; 123*90921014SLuciano Coelho return 0; 124*90921014SLuciano Coelho } 125*90921014SLuciano Coelho 126*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u"); 127*90921014SLuciano Coelho 128*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u"); 129*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u"); 130*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u"); 131*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u"); 132*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u"); 133*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u"); 134*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u"); 135*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u"); 136*90921014SLuciano Coelho 137*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u"); 138*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u"); 139*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u"); 140*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u"); 141*90921014SLuciano Coelho 142*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u"); 143*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u"); 144*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u"); 145*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u"); 146*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u"); 147*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u"); 148*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u"); 149*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u"); 150*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u"); 151*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u"); 152*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u"); 153*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u"); 154*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u"); 155*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u"); 156*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u"); 157*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u"); 158*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u"); 159*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u"); 160*90921014SLuciano Coelho 161*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u"); 162*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u"); 163*90921014SLuciano Coelho /* skipping wep.reserved */ 164*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u"); 165*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u"); 166*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u"); 167*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u"); 168*90921014SLuciano Coelho 169*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u"); 170*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u"); 171*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u"); 172*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u"); 173*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u"); 174*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u"); 175*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u"); 176*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u"); 177*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u"); 178*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u"); 179*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u"); 180*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u"); 181*90921014SLuciano Coelho /* skipping cont_miss_bcns_spread for now */ 182*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u"); 183*90921014SLuciano Coelho 184*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u"); 185*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u"); 186*90921014SLuciano Coelho 187*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u"); 188*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u"); 189*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u"); 190*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u"); 191*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u"); 192*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u"); 193*90921014SLuciano Coelho 194*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u"); 195*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u"); 196*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u"); 197*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u"); 198*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u"); 199*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u"); 200*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u"); 201*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u"); 202*90921014SLuciano Coelho 203*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u"); 204*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u"); 205*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u"); 206*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u"); 207*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u"); 208*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u"); 209*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u"); 210*90921014SLuciano Coelho 211*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u"); 212*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u"); 213*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, 214*90921014SLuciano Coelho 20, "%u"); 215*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u"); 216*90921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u"); 217*90921014SLuciano Coelho 218*90921014SLuciano Coelho DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count); 219*90921014SLuciano Coelho DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u", 220*90921014SLuciano Coelho wl->stats.excessive_retries); 221*90921014SLuciano Coelho 222*90921014SLuciano Coelho static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, 223*90921014SLuciano Coelho size_t count, loff_t *ppos) 224*90921014SLuciano Coelho { 225*90921014SLuciano Coelho struct wl1251 *wl = file->private_data; 226*90921014SLuciano Coelho u32 queue_len; 227*90921014SLuciano Coelho char buf[20]; 228*90921014SLuciano Coelho int res; 229*90921014SLuciano Coelho 230*90921014SLuciano Coelho queue_len = skb_queue_len(&wl->tx_queue); 231*90921014SLuciano Coelho 232*90921014SLuciano Coelho res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); 233*90921014SLuciano Coelho return simple_read_from_buffer(userbuf, count, ppos, buf, res); 234*90921014SLuciano Coelho } 235*90921014SLuciano Coelho 236*90921014SLuciano Coelho static const struct file_operations tx_queue_len_ops = { 237*90921014SLuciano Coelho .read = tx_queue_len_read, 238*90921014SLuciano Coelho .open = wl1251_open_file_generic, 239*90921014SLuciano Coelho .llseek = generic_file_llseek, 240*90921014SLuciano Coelho }; 241*90921014SLuciano Coelho 242*90921014SLuciano Coelho static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf, 243*90921014SLuciano Coelho size_t count, loff_t *ppos) 244*90921014SLuciano Coelho { 245*90921014SLuciano Coelho struct wl1251 *wl = file->private_data; 246*90921014SLuciano Coelho char buf[3], status; 247*90921014SLuciano Coelho int len; 248*90921014SLuciano Coelho 249*90921014SLuciano Coelho if (wl->tx_queue_stopped) 250*90921014SLuciano Coelho status = 's'; 251*90921014SLuciano Coelho else 252*90921014SLuciano Coelho status = 'r'; 253*90921014SLuciano Coelho 254*90921014SLuciano Coelho len = scnprintf(buf, sizeof(buf), "%c\n", status); 255*90921014SLuciano Coelho return simple_read_from_buffer(userbuf, count, ppos, buf, len); 256*90921014SLuciano Coelho } 257*90921014SLuciano Coelho 258*90921014SLuciano Coelho static const struct file_operations tx_queue_status_ops = { 259*90921014SLuciano Coelho .read = tx_queue_status_read, 260*90921014SLuciano Coelho .open = wl1251_open_file_generic, 261*90921014SLuciano Coelho .llseek = generic_file_llseek, 262*90921014SLuciano Coelho }; 263*90921014SLuciano Coelho 264*90921014SLuciano Coelho static void wl1251_debugfs_delete_files(struct wl1251 *wl) 265*90921014SLuciano Coelho { 266*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); 267*90921014SLuciano Coelho 268*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rx, out_of_mem); 269*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rx, hdr_overflow); 270*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rx, hw_stuck); 271*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rx, dropped); 272*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rx, fcs_err); 273*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig); 274*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rx, path_reset); 275*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rx, reset_counter); 276*90921014SLuciano Coelho 277*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(dma, rx_requested); 278*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(dma, rx_errors); 279*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(dma, tx_requested); 280*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(dma, tx_errors); 281*90921014SLuciano Coelho 282*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt); 283*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, fiqs); 284*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, rx_headers); 285*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow); 286*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, rx_rdys); 287*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, irqs); 288*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, tx_procs); 289*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, decrypt_done); 290*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, dma0_done); 291*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, dma1_done); 292*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete); 293*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, commands); 294*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, rx_procs); 295*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes); 296*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, host_acknowledges); 297*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, pci_pm); 298*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, wakeups); 299*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(isr, low_rssi); 300*90921014SLuciano Coelho 301*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(wep, addr_key_count); 302*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(wep, default_key_count); 303*90921014SLuciano Coelho /* skipping wep.reserved */ 304*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(wep, key_not_found); 305*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(wep, decrypt_fail); 306*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(wep, packets); 307*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(wep, interrupt); 308*90921014SLuciano Coelho 309*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, ps_enter); 310*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, elp_enter); 311*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, missing_bcns); 312*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, wake_on_host); 313*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp); 314*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps); 315*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps); 316*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons); 317*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, power_save_off); 318*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, enable_ps); 319*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, disable_ps); 320*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps); 321*90921014SLuciano Coelho /* skipping cont_miss_bcns_spread for now */ 322*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons); 323*90921014SLuciano Coelho 324*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(mic, rx_pkts); 325*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(mic, calc_failure); 326*90921014SLuciano Coelho 327*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(aes, encrypt_fail); 328*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(aes, decrypt_fail); 329*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(aes, encrypt_packets); 330*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(aes, decrypt_packets); 331*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt); 332*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt); 333*90921014SLuciano Coelho 334*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(event, heart_beat); 335*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(event, calibration); 336*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(event, rx_mismatch); 337*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(event, rx_mem_empty); 338*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(event, rx_pool); 339*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(event, oom_late); 340*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(event, phy_transmit_error); 341*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(event, tx_stuck); 342*90921014SLuciano Coelho 343*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts); 344*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts); 345*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime); 346*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn); 347*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn); 348*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization); 349*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(ps, upsd_utilization); 350*90921014SLuciano Coelho 351*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop); 352*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data); 353*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); 354*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data); 355*90921014SLuciano Coelho DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); 356*90921014SLuciano Coelho 357*90921014SLuciano Coelho DEBUGFS_DEL(tx_queue_len); 358*90921014SLuciano Coelho DEBUGFS_DEL(tx_queue_status); 359*90921014SLuciano Coelho DEBUGFS_DEL(retry_count); 360*90921014SLuciano Coelho DEBUGFS_DEL(excessive_retries); 361*90921014SLuciano Coelho } 362*90921014SLuciano Coelho 363*90921014SLuciano Coelho static int wl1251_debugfs_add_files(struct wl1251 *wl) 364*90921014SLuciano Coelho { 365*90921014SLuciano Coelho int ret = 0; 366*90921014SLuciano Coelho 367*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); 368*90921014SLuciano Coelho 369*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rx, out_of_mem); 370*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rx, hdr_overflow); 371*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rx, hw_stuck); 372*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rx, dropped); 373*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rx, fcs_err); 374*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig); 375*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rx, path_reset); 376*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rx, reset_counter); 377*90921014SLuciano Coelho 378*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(dma, rx_requested); 379*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(dma, rx_errors); 380*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(dma, tx_requested); 381*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(dma, tx_errors); 382*90921014SLuciano Coelho 383*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt); 384*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, fiqs); 385*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, rx_headers); 386*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow); 387*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, rx_rdys); 388*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, irqs); 389*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, tx_procs); 390*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, decrypt_done); 391*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, dma0_done); 392*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, dma1_done); 393*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete); 394*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, commands); 395*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, rx_procs); 396*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes); 397*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, host_acknowledges); 398*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, pci_pm); 399*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, wakeups); 400*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(isr, low_rssi); 401*90921014SLuciano Coelho 402*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(wep, addr_key_count); 403*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(wep, default_key_count); 404*90921014SLuciano Coelho /* skipping wep.reserved */ 405*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(wep, key_not_found); 406*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(wep, decrypt_fail); 407*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(wep, packets); 408*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(wep, interrupt); 409*90921014SLuciano Coelho 410*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, ps_enter); 411*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, elp_enter); 412*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, missing_bcns); 413*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, wake_on_host); 414*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp); 415*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps); 416*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps); 417*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons); 418*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, power_save_off); 419*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, enable_ps); 420*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, disable_ps); 421*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps); 422*90921014SLuciano Coelho /* skipping cont_miss_bcns_spread for now */ 423*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons); 424*90921014SLuciano Coelho 425*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(mic, rx_pkts); 426*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(mic, calc_failure); 427*90921014SLuciano Coelho 428*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(aes, encrypt_fail); 429*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(aes, decrypt_fail); 430*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(aes, encrypt_packets); 431*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(aes, decrypt_packets); 432*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt); 433*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt); 434*90921014SLuciano Coelho 435*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(event, heart_beat); 436*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(event, calibration); 437*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(event, rx_mismatch); 438*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(event, rx_mem_empty); 439*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(event, rx_pool); 440*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(event, oom_late); 441*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(event, phy_transmit_error); 442*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(event, tx_stuck); 443*90921014SLuciano Coelho 444*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts); 445*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts); 446*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime); 447*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn); 448*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn); 449*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization); 450*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(ps, upsd_utilization); 451*90921014SLuciano Coelho 452*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop); 453*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data); 454*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); 455*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); 456*90921014SLuciano Coelho DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); 457*90921014SLuciano Coelho 458*90921014SLuciano Coelho DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); 459*90921014SLuciano Coelho DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir); 460*90921014SLuciano Coelho DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); 461*90921014SLuciano Coelho DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); 462*90921014SLuciano Coelho 463*90921014SLuciano Coelho out: 464*90921014SLuciano Coelho if (ret < 0) 465*90921014SLuciano Coelho wl1251_debugfs_delete_files(wl); 466*90921014SLuciano Coelho 467*90921014SLuciano Coelho return ret; 468*90921014SLuciano Coelho } 469*90921014SLuciano Coelho 470*90921014SLuciano Coelho void wl1251_debugfs_reset(struct wl1251 *wl) 471*90921014SLuciano Coelho { 472*90921014SLuciano Coelho if (wl->stats.fw_stats != NULL) 473*90921014SLuciano Coelho memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); 474*90921014SLuciano Coelho wl->stats.retry_count = 0; 475*90921014SLuciano Coelho wl->stats.excessive_retries = 0; 476*90921014SLuciano Coelho } 477*90921014SLuciano Coelho 478*90921014SLuciano Coelho int wl1251_debugfs_init(struct wl1251 *wl) 479*90921014SLuciano Coelho { 480*90921014SLuciano Coelho int ret; 481*90921014SLuciano Coelho 482*90921014SLuciano Coelho wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); 483*90921014SLuciano Coelho 484*90921014SLuciano Coelho if (IS_ERR(wl->debugfs.rootdir)) { 485*90921014SLuciano Coelho ret = PTR_ERR(wl->debugfs.rootdir); 486*90921014SLuciano Coelho wl->debugfs.rootdir = NULL; 487*90921014SLuciano Coelho goto err; 488*90921014SLuciano Coelho } 489*90921014SLuciano Coelho 490*90921014SLuciano Coelho wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics", 491*90921014SLuciano Coelho wl->debugfs.rootdir); 492*90921014SLuciano Coelho 493*90921014SLuciano Coelho if (IS_ERR(wl->debugfs.fw_statistics)) { 494*90921014SLuciano Coelho ret = PTR_ERR(wl->debugfs.fw_statistics); 495*90921014SLuciano Coelho wl->debugfs.fw_statistics = NULL; 496*90921014SLuciano Coelho goto err_root; 497*90921014SLuciano Coelho } 498*90921014SLuciano Coelho 499*90921014SLuciano Coelho wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), 500*90921014SLuciano Coelho GFP_KERNEL); 501*90921014SLuciano Coelho 502*90921014SLuciano Coelho if (!wl->stats.fw_stats) { 503*90921014SLuciano Coelho ret = -ENOMEM; 504*90921014SLuciano Coelho goto err_fw; 505*90921014SLuciano Coelho } 506*90921014SLuciano Coelho 507*90921014SLuciano Coelho wl->stats.fw_stats_update = jiffies; 508*90921014SLuciano Coelho 509*90921014SLuciano Coelho ret = wl1251_debugfs_add_files(wl); 510*90921014SLuciano Coelho 511*90921014SLuciano Coelho if (ret < 0) 512*90921014SLuciano Coelho goto err_file; 513*90921014SLuciano Coelho 514*90921014SLuciano Coelho return 0; 515*90921014SLuciano Coelho 516*90921014SLuciano Coelho err_file: 517*90921014SLuciano Coelho kfree(wl->stats.fw_stats); 518*90921014SLuciano Coelho wl->stats.fw_stats = NULL; 519*90921014SLuciano Coelho 520*90921014SLuciano Coelho err_fw: 521*90921014SLuciano Coelho debugfs_remove(wl->debugfs.fw_statistics); 522*90921014SLuciano Coelho wl->debugfs.fw_statistics = NULL; 523*90921014SLuciano Coelho 524*90921014SLuciano Coelho err_root: 525*90921014SLuciano Coelho debugfs_remove(wl->debugfs.rootdir); 526*90921014SLuciano Coelho wl->debugfs.rootdir = NULL; 527*90921014SLuciano Coelho 528*90921014SLuciano Coelho err: 529*90921014SLuciano Coelho return ret; 530*90921014SLuciano Coelho } 531*90921014SLuciano Coelho 532*90921014SLuciano Coelho void wl1251_debugfs_exit(struct wl1251 *wl) 533*90921014SLuciano Coelho { 534*90921014SLuciano Coelho wl1251_debugfs_delete_files(wl); 535*90921014SLuciano Coelho 536*90921014SLuciano Coelho kfree(wl->stats.fw_stats); 537*90921014SLuciano Coelho wl->stats.fw_stats = NULL; 538*90921014SLuciano Coelho 539*90921014SLuciano Coelho debugfs_remove(wl->debugfs.fw_statistics); 540*90921014SLuciano Coelho wl->debugfs.fw_statistics = NULL; 541*90921014SLuciano Coelho 542*90921014SLuciano Coelho debugfs_remove(wl->debugfs.rootdir); 543*90921014SLuciano Coelho wl->debugfs.rootdir = NULL; 544*90921014SLuciano Coelho 545*90921014SLuciano Coelho } 546