17ac9a364SKalle Valo /****************************************************************************** 27ac9a364SKalle Valo * 37ac9a364SKalle Valo * GPL LICENSE SUMMARY 47ac9a364SKalle Valo * 57ac9a364SKalle Valo * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 67ac9a364SKalle Valo * 77ac9a364SKalle Valo * This program is free software; you can redistribute it and/or modify 87ac9a364SKalle Valo * it under the terms of version 2 of the GNU General Public License as 97ac9a364SKalle Valo * published by the Free Software Foundation. 107ac9a364SKalle Valo * 117ac9a364SKalle Valo * This program is distributed in the hope that it will be useful, but 127ac9a364SKalle Valo * WITHOUT ANY WARRANTY; without even the implied warranty of 137ac9a364SKalle Valo * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 147ac9a364SKalle Valo * General Public License for more details. 157ac9a364SKalle Valo * 167ac9a364SKalle Valo * You should have received a copy of the GNU General Public License 177ac9a364SKalle Valo * along with this program; if not, write to the Free Software 187ac9a364SKalle Valo * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, 197ac9a364SKalle Valo * USA 207ac9a364SKalle Valo * 217ac9a364SKalle Valo * The full GNU General Public License is included in this distribution 227ac9a364SKalle Valo * in the file called LICENSE.GPL. 237ac9a364SKalle Valo * 247ac9a364SKalle Valo * Contact Information: 257ac9a364SKalle Valo * Intel Linux Wireless <ilw@linux.intel.com> 267ac9a364SKalle Valo * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 277ac9a364SKalle Valo *****************************************************************************/ 287ac9a364SKalle Valo #include <linux/ieee80211.h> 297ac9a364SKalle Valo #include <linux/export.h> 307ac9a364SKalle Valo #include <net/mac80211.h> 317ac9a364SKalle Valo 327ac9a364SKalle Valo #include "common.h" 337ac9a364SKalle Valo 347ac9a364SKalle Valo static void 357ac9a364SKalle Valo il_clear_traffic_stats(struct il_priv *il) 367ac9a364SKalle Valo { 377ac9a364SKalle Valo memset(&il->tx_stats, 0, sizeof(struct traffic_stats)); 387ac9a364SKalle Valo memset(&il->rx_stats, 0, sizeof(struct traffic_stats)); 397ac9a364SKalle Valo } 407ac9a364SKalle Valo 417ac9a364SKalle Valo /* 427ac9a364SKalle Valo * il_update_stats function record all the MGMT, CTRL and DATA pkt for 437ac9a364SKalle Valo * both TX and Rx . Use debugfs to display the rx/rx_stats 447ac9a364SKalle Valo */ 457ac9a364SKalle Valo void 467ac9a364SKalle Valo il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len) 477ac9a364SKalle Valo { 487ac9a364SKalle Valo struct traffic_stats *stats; 497ac9a364SKalle Valo 507ac9a364SKalle Valo if (is_tx) 517ac9a364SKalle Valo stats = &il->tx_stats; 527ac9a364SKalle Valo else 537ac9a364SKalle Valo stats = &il->rx_stats; 547ac9a364SKalle Valo 557ac9a364SKalle Valo if (ieee80211_is_mgmt(fc)) { 567ac9a364SKalle Valo switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { 577ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): 587ac9a364SKalle Valo stats->mgmt[MANAGEMENT_ASSOC_REQ]++; 597ac9a364SKalle Valo break; 607ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): 617ac9a364SKalle Valo stats->mgmt[MANAGEMENT_ASSOC_RESP]++; 627ac9a364SKalle Valo break; 637ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): 647ac9a364SKalle Valo stats->mgmt[MANAGEMENT_REASSOC_REQ]++; 657ac9a364SKalle Valo break; 667ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): 677ac9a364SKalle Valo stats->mgmt[MANAGEMENT_REASSOC_RESP]++; 687ac9a364SKalle Valo break; 697ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): 707ac9a364SKalle Valo stats->mgmt[MANAGEMENT_PROBE_REQ]++; 717ac9a364SKalle Valo break; 727ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): 737ac9a364SKalle Valo stats->mgmt[MANAGEMENT_PROBE_RESP]++; 747ac9a364SKalle Valo break; 757ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_BEACON): 767ac9a364SKalle Valo stats->mgmt[MANAGEMENT_BEACON]++; 777ac9a364SKalle Valo break; 787ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_ATIM): 797ac9a364SKalle Valo stats->mgmt[MANAGEMENT_ATIM]++; 807ac9a364SKalle Valo break; 817ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_DISASSOC): 827ac9a364SKalle Valo stats->mgmt[MANAGEMENT_DISASSOC]++; 837ac9a364SKalle Valo break; 847ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_AUTH): 857ac9a364SKalle Valo stats->mgmt[MANAGEMENT_AUTH]++; 867ac9a364SKalle Valo break; 877ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_DEAUTH): 887ac9a364SKalle Valo stats->mgmt[MANAGEMENT_DEAUTH]++; 897ac9a364SKalle Valo break; 907ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_ACTION): 917ac9a364SKalle Valo stats->mgmt[MANAGEMENT_ACTION]++; 927ac9a364SKalle Valo break; 937ac9a364SKalle Valo } 947ac9a364SKalle Valo } else if (ieee80211_is_ctl(fc)) { 957ac9a364SKalle Valo switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { 967ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_BACK_REQ): 977ac9a364SKalle Valo stats->ctrl[CONTROL_BACK_REQ]++; 987ac9a364SKalle Valo break; 997ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_BACK): 1007ac9a364SKalle Valo stats->ctrl[CONTROL_BACK]++; 1017ac9a364SKalle Valo break; 1027ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_PSPOLL): 1037ac9a364SKalle Valo stats->ctrl[CONTROL_PSPOLL]++; 1047ac9a364SKalle Valo break; 1057ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_RTS): 1067ac9a364SKalle Valo stats->ctrl[CONTROL_RTS]++; 1077ac9a364SKalle Valo break; 1087ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_CTS): 1097ac9a364SKalle Valo stats->ctrl[CONTROL_CTS]++; 1107ac9a364SKalle Valo break; 1117ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_ACK): 1127ac9a364SKalle Valo stats->ctrl[CONTROL_ACK]++; 1137ac9a364SKalle Valo break; 1147ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_CFEND): 1157ac9a364SKalle Valo stats->ctrl[CONTROL_CFEND]++; 1167ac9a364SKalle Valo break; 1177ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_CFENDACK): 1187ac9a364SKalle Valo stats->ctrl[CONTROL_CFENDACK]++; 1197ac9a364SKalle Valo break; 1207ac9a364SKalle Valo } 1217ac9a364SKalle Valo } else { 1227ac9a364SKalle Valo /* data */ 1237ac9a364SKalle Valo stats->data_cnt++; 1247ac9a364SKalle Valo stats->data_bytes += len; 1257ac9a364SKalle Valo } 1267ac9a364SKalle Valo } 1277ac9a364SKalle Valo EXPORT_SYMBOL(il_update_stats); 1287ac9a364SKalle Valo 1297ac9a364SKalle Valo /* create and remove of files */ 1307ac9a364SKalle Valo #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ 1317ac9a364SKalle Valo if (!debugfs_create_file(#name, mode, parent, il, \ 1327ac9a364SKalle Valo &il_dbgfs_##name##_ops)) \ 1337ac9a364SKalle Valo goto err; \ 1347ac9a364SKalle Valo } while (0) 1357ac9a364SKalle Valo 1367ac9a364SKalle Valo #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ 1377ac9a364SKalle Valo struct dentry *__tmp; \ 1387ac9a364SKalle Valo __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ 1397ac9a364SKalle Valo parent, ptr); \ 1407ac9a364SKalle Valo if (IS_ERR(__tmp) || !__tmp) \ 1417ac9a364SKalle Valo goto err; \ 1427ac9a364SKalle Valo } while (0) 1437ac9a364SKalle Valo 1447ac9a364SKalle Valo #define DEBUGFS_ADD_X32(name, parent, ptr) do { \ 1457ac9a364SKalle Valo struct dentry *__tmp; \ 1467ac9a364SKalle Valo __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \ 1477ac9a364SKalle Valo parent, ptr); \ 1487ac9a364SKalle Valo if (IS_ERR(__tmp) || !__tmp) \ 1497ac9a364SKalle Valo goto err; \ 1507ac9a364SKalle Valo } while (0) 1517ac9a364SKalle Valo 1527ac9a364SKalle Valo /* file operation */ 1537ac9a364SKalle Valo #define DEBUGFS_READ_FUNC(name) \ 1547ac9a364SKalle Valo static ssize_t il_dbgfs_##name##_read(struct file *file, \ 1557ac9a364SKalle Valo char __user *user_buf, \ 1567ac9a364SKalle Valo size_t count, loff_t *ppos); 1577ac9a364SKalle Valo 1587ac9a364SKalle Valo #define DEBUGFS_WRITE_FUNC(name) \ 1597ac9a364SKalle Valo static ssize_t il_dbgfs_##name##_write(struct file *file, \ 1607ac9a364SKalle Valo const char __user *user_buf, \ 1617ac9a364SKalle Valo size_t count, loff_t *ppos); 1627ac9a364SKalle Valo 1637ac9a364SKalle Valo 1647ac9a364SKalle Valo #define DEBUGFS_READ_FILE_OPS(name) \ 1657ac9a364SKalle Valo DEBUGFS_READ_FUNC(name); \ 1667ac9a364SKalle Valo static const struct file_operations il_dbgfs_##name##_ops = { \ 1677ac9a364SKalle Valo .read = il_dbgfs_##name##_read, \ 1687ac9a364SKalle Valo .open = simple_open, \ 1697ac9a364SKalle Valo .llseek = generic_file_llseek, \ 1707ac9a364SKalle Valo }; 1717ac9a364SKalle Valo 1727ac9a364SKalle Valo #define DEBUGFS_WRITE_FILE_OPS(name) \ 1737ac9a364SKalle Valo DEBUGFS_WRITE_FUNC(name); \ 1747ac9a364SKalle Valo static const struct file_operations il_dbgfs_##name##_ops = { \ 1757ac9a364SKalle Valo .write = il_dbgfs_##name##_write, \ 1767ac9a364SKalle Valo .open = simple_open, \ 1777ac9a364SKalle Valo .llseek = generic_file_llseek, \ 1787ac9a364SKalle Valo }; 1797ac9a364SKalle Valo 1807ac9a364SKalle Valo #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ 1817ac9a364SKalle Valo DEBUGFS_READ_FUNC(name); \ 1827ac9a364SKalle Valo DEBUGFS_WRITE_FUNC(name); \ 1837ac9a364SKalle Valo static const struct file_operations il_dbgfs_##name##_ops = { \ 1847ac9a364SKalle Valo .write = il_dbgfs_##name##_write, \ 1857ac9a364SKalle Valo .read = il_dbgfs_##name##_read, \ 1867ac9a364SKalle Valo .open = simple_open, \ 1877ac9a364SKalle Valo .llseek = generic_file_llseek, \ 1887ac9a364SKalle Valo }; 1897ac9a364SKalle Valo 1907ac9a364SKalle Valo static const char * 1917ac9a364SKalle Valo il_get_mgmt_string(int cmd) 1927ac9a364SKalle Valo { 1937ac9a364SKalle Valo switch (cmd) { 1947ac9a364SKalle Valo IL_CMD(MANAGEMENT_ASSOC_REQ); 1957ac9a364SKalle Valo IL_CMD(MANAGEMENT_ASSOC_RESP); 1967ac9a364SKalle Valo IL_CMD(MANAGEMENT_REASSOC_REQ); 1977ac9a364SKalle Valo IL_CMD(MANAGEMENT_REASSOC_RESP); 1987ac9a364SKalle Valo IL_CMD(MANAGEMENT_PROBE_REQ); 1997ac9a364SKalle Valo IL_CMD(MANAGEMENT_PROBE_RESP); 2007ac9a364SKalle Valo IL_CMD(MANAGEMENT_BEACON); 2017ac9a364SKalle Valo IL_CMD(MANAGEMENT_ATIM); 2027ac9a364SKalle Valo IL_CMD(MANAGEMENT_DISASSOC); 2037ac9a364SKalle Valo IL_CMD(MANAGEMENT_AUTH); 2047ac9a364SKalle Valo IL_CMD(MANAGEMENT_DEAUTH); 2057ac9a364SKalle Valo IL_CMD(MANAGEMENT_ACTION); 2067ac9a364SKalle Valo default: 2077ac9a364SKalle Valo return "UNKNOWN"; 2087ac9a364SKalle Valo 2097ac9a364SKalle Valo } 2107ac9a364SKalle Valo } 2117ac9a364SKalle Valo 2127ac9a364SKalle Valo static const char * 2137ac9a364SKalle Valo il_get_ctrl_string(int cmd) 2147ac9a364SKalle Valo { 2157ac9a364SKalle Valo switch (cmd) { 2167ac9a364SKalle Valo IL_CMD(CONTROL_BACK_REQ); 2177ac9a364SKalle Valo IL_CMD(CONTROL_BACK); 2187ac9a364SKalle Valo IL_CMD(CONTROL_PSPOLL); 2197ac9a364SKalle Valo IL_CMD(CONTROL_RTS); 2207ac9a364SKalle Valo IL_CMD(CONTROL_CTS); 2217ac9a364SKalle Valo IL_CMD(CONTROL_ACK); 2227ac9a364SKalle Valo IL_CMD(CONTROL_CFEND); 2237ac9a364SKalle Valo IL_CMD(CONTROL_CFENDACK); 2247ac9a364SKalle Valo default: 2257ac9a364SKalle Valo return "UNKNOWN"; 2267ac9a364SKalle Valo 2277ac9a364SKalle Valo } 2287ac9a364SKalle Valo } 2297ac9a364SKalle Valo 2307ac9a364SKalle Valo static ssize_t 2317ac9a364SKalle Valo il_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count, 2327ac9a364SKalle Valo loff_t *ppos) 2337ac9a364SKalle Valo { 2347ac9a364SKalle Valo 2357ac9a364SKalle Valo struct il_priv *il = file->private_data; 2367ac9a364SKalle Valo char *buf; 2377ac9a364SKalle Valo int pos = 0; 2387ac9a364SKalle Valo 2397ac9a364SKalle Valo int cnt; 2407ac9a364SKalle Valo ssize_t ret; 2417ac9a364SKalle Valo const size_t bufsz = 2427ac9a364SKalle Valo 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); 2437ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 2447ac9a364SKalle Valo if (!buf) 2457ac9a364SKalle Valo return -ENOMEM; 2467ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); 2477ac9a364SKalle Valo for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { 2487ac9a364SKalle Valo pos += 2497ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 2507ac9a364SKalle Valo il_get_mgmt_string(cnt), il->tx_stats.mgmt[cnt]); 2517ac9a364SKalle Valo } 2527ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); 2537ac9a364SKalle Valo for (cnt = 0; cnt < CONTROL_MAX; cnt++) { 2547ac9a364SKalle Valo pos += 2557ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 2567ac9a364SKalle Valo il_get_ctrl_string(cnt), il->tx_stats.ctrl[cnt]); 2577ac9a364SKalle Valo } 2587ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); 2597ac9a364SKalle Valo pos += 2607ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", 2617ac9a364SKalle Valo il->tx_stats.data_cnt); 2627ac9a364SKalle Valo pos += 2637ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", 2647ac9a364SKalle Valo il->tx_stats.data_bytes); 2657ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 2667ac9a364SKalle Valo kfree(buf); 2677ac9a364SKalle Valo return ret; 2687ac9a364SKalle Valo } 2697ac9a364SKalle Valo 2707ac9a364SKalle Valo static ssize_t 2717ac9a364SKalle Valo il_dbgfs_clear_traffic_stats_write(struct file *file, 2727ac9a364SKalle Valo const char __user *user_buf, size_t count, 2737ac9a364SKalle Valo loff_t *ppos) 2747ac9a364SKalle Valo { 2757ac9a364SKalle Valo struct il_priv *il = file->private_data; 2767ac9a364SKalle Valo u32 clear_flag; 2777ac9a364SKalle Valo char buf[8]; 2787ac9a364SKalle Valo int buf_size; 2797ac9a364SKalle Valo 2807ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 2817ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 2827ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 2837ac9a364SKalle Valo return -EFAULT; 2847ac9a364SKalle Valo if (sscanf(buf, "%x", &clear_flag) != 1) 2857ac9a364SKalle Valo return -EFAULT; 2867ac9a364SKalle Valo il_clear_traffic_stats(il); 2877ac9a364SKalle Valo 2887ac9a364SKalle Valo return count; 2897ac9a364SKalle Valo } 2907ac9a364SKalle Valo 2917ac9a364SKalle Valo static ssize_t 2927ac9a364SKalle Valo il_dbgfs_rx_stats_read(struct file *file, char __user *user_buf, size_t count, 2937ac9a364SKalle Valo loff_t *ppos) 2947ac9a364SKalle Valo { 2957ac9a364SKalle Valo 2967ac9a364SKalle Valo struct il_priv *il = file->private_data; 2977ac9a364SKalle Valo char *buf; 2987ac9a364SKalle Valo int pos = 0; 2997ac9a364SKalle Valo int cnt; 3007ac9a364SKalle Valo ssize_t ret; 3017ac9a364SKalle Valo const size_t bufsz = 3027ac9a364SKalle Valo 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); 3037ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 3047ac9a364SKalle Valo if (!buf) 3057ac9a364SKalle Valo return -ENOMEM; 3067ac9a364SKalle Valo 3077ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); 3087ac9a364SKalle Valo for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { 3097ac9a364SKalle Valo pos += 3107ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 3117ac9a364SKalle Valo il_get_mgmt_string(cnt), il->rx_stats.mgmt[cnt]); 3127ac9a364SKalle Valo } 3137ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); 3147ac9a364SKalle Valo for (cnt = 0; cnt < CONTROL_MAX; cnt++) { 3157ac9a364SKalle Valo pos += 3167ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 3177ac9a364SKalle Valo il_get_ctrl_string(cnt), il->rx_stats.ctrl[cnt]); 3187ac9a364SKalle Valo } 3197ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); 3207ac9a364SKalle Valo pos += 3217ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", 3227ac9a364SKalle Valo il->rx_stats.data_cnt); 3237ac9a364SKalle Valo pos += 3247ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", 3257ac9a364SKalle Valo il->rx_stats.data_bytes); 3267ac9a364SKalle Valo 3277ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 3287ac9a364SKalle Valo kfree(buf); 3297ac9a364SKalle Valo return ret; 3307ac9a364SKalle Valo } 3317ac9a364SKalle Valo 3327ac9a364SKalle Valo #define BYTE1_MASK 0x000000ff; 3337ac9a364SKalle Valo #define BYTE2_MASK 0x0000ffff; 3347ac9a364SKalle Valo #define BYTE3_MASK 0x00ffffff; 3357ac9a364SKalle Valo static ssize_t 3367ac9a364SKalle Valo il_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count, 3377ac9a364SKalle Valo loff_t *ppos) 3387ac9a364SKalle Valo { 3397ac9a364SKalle Valo u32 val; 3407ac9a364SKalle Valo char *buf; 3417ac9a364SKalle Valo ssize_t ret; 3427ac9a364SKalle Valo int i; 3437ac9a364SKalle Valo int pos = 0; 3447ac9a364SKalle Valo struct il_priv *il = file->private_data; 3457ac9a364SKalle Valo size_t bufsz; 3467ac9a364SKalle Valo 3477ac9a364SKalle Valo /* default is to dump the entire data segment */ 3487ac9a364SKalle Valo if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) { 3497ac9a364SKalle Valo il->dbgfs_sram_offset = 0x800000; 3507ac9a364SKalle Valo if (il->ucode_type == UCODE_INIT) 3517ac9a364SKalle Valo il->dbgfs_sram_len = il->ucode_init_data.len; 3527ac9a364SKalle Valo else 3537ac9a364SKalle Valo il->dbgfs_sram_len = il->ucode_data.len; 3547ac9a364SKalle Valo } 3557ac9a364SKalle Valo bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10; 3567ac9a364SKalle Valo buf = kmalloc(bufsz, GFP_KERNEL); 3577ac9a364SKalle Valo if (!buf) 3587ac9a364SKalle Valo return -ENOMEM; 3597ac9a364SKalle Valo pos += 3607ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", 3617ac9a364SKalle Valo il->dbgfs_sram_len); 3627ac9a364SKalle Valo pos += 3637ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", 3647ac9a364SKalle Valo il->dbgfs_sram_offset); 3657ac9a364SKalle Valo for (i = il->dbgfs_sram_len; i > 0; i -= 4) { 3667ac9a364SKalle Valo val = 3677ac9a364SKalle Valo il_read_targ_mem(il, 3687ac9a364SKalle Valo il->dbgfs_sram_offset + 3697ac9a364SKalle Valo il->dbgfs_sram_len - i); 3707ac9a364SKalle Valo if (i < 4) { 3717ac9a364SKalle Valo switch (i) { 3727ac9a364SKalle Valo case 1: 3737ac9a364SKalle Valo val &= BYTE1_MASK; 3747ac9a364SKalle Valo break; 3757ac9a364SKalle Valo case 2: 3767ac9a364SKalle Valo val &= BYTE2_MASK; 3777ac9a364SKalle Valo break; 3787ac9a364SKalle Valo case 3: 3797ac9a364SKalle Valo val &= BYTE3_MASK; 3807ac9a364SKalle Valo break; 3817ac9a364SKalle Valo } 3827ac9a364SKalle Valo } 3837ac9a364SKalle Valo if (!(i % 16)) 3847ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 3857ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); 3867ac9a364SKalle Valo } 3877ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 3887ac9a364SKalle Valo 3897ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 3907ac9a364SKalle Valo kfree(buf); 3917ac9a364SKalle Valo return ret; 3927ac9a364SKalle Valo } 3937ac9a364SKalle Valo 3947ac9a364SKalle Valo static ssize_t 3957ac9a364SKalle Valo il_dbgfs_sram_write(struct file *file, const char __user *user_buf, 3967ac9a364SKalle Valo size_t count, loff_t *ppos) 3977ac9a364SKalle Valo { 3987ac9a364SKalle Valo struct il_priv *il = file->private_data; 3997ac9a364SKalle Valo char buf[64]; 4007ac9a364SKalle Valo int buf_size; 4017ac9a364SKalle Valo u32 offset, len; 4027ac9a364SKalle Valo 4037ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 4047ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 4057ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 4067ac9a364SKalle Valo return -EFAULT; 4077ac9a364SKalle Valo 4087ac9a364SKalle Valo if (sscanf(buf, "%x,%x", &offset, &len) == 2) { 4097ac9a364SKalle Valo il->dbgfs_sram_offset = offset; 4107ac9a364SKalle Valo il->dbgfs_sram_len = len; 4117ac9a364SKalle Valo } else { 4127ac9a364SKalle Valo il->dbgfs_sram_offset = 0; 4137ac9a364SKalle Valo il->dbgfs_sram_len = 0; 4147ac9a364SKalle Valo } 4157ac9a364SKalle Valo 4167ac9a364SKalle Valo return count; 4177ac9a364SKalle Valo } 4187ac9a364SKalle Valo 4197ac9a364SKalle Valo static ssize_t 4207ac9a364SKalle Valo il_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count, 4217ac9a364SKalle Valo loff_t *ppos) 4227ac9a364SKalle Valo { 4237ac9a364SKalle Valo struct il_priv *il = file->private_data; 4247ac9a364SKalle Valo struct il_station_entry *station; 4257ac9a364SKalle Valo int max_sta = il->hw_params.max_stations; 4267ac9a364SKalle Valo char *buf; 4277ac9a364SKalle Valo int i, j, pos = 0; 4287ac9a364SKalle Valo ssize_t ret; 4297ac9a364SKalle Valo /* Add 30 for initial string */ 4307ac9a364SKalle Valo const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations); 4317ac9a364SKalle Valo 4327ac9a364SKalle Valo buf = kmalloc(bufsz, GFP_KERNEL); 4337ac9a364SKalle Valo if (!buf) 4347ac9a364SKalle Valo return -ENOMEM; 4357ac9a364SKalle Valo 4367ac9a364SKalle Valo pos += 4377ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", 4387ac9a364SKalle Valo il->num_stations); 4397ac9a364SKalle Valo 4407ac9a364SKalle Valo for (i = 0; i < max_sta; i++) { 4417ac9a364SKalle Valo station = &il->stations[i]; 4427ac9a364SKalle Valo if (!station->used) 4437ac9a364SKalle Valo continue; 4447ac9a364SKalle Valo pos += 4457ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 4467ac9a364SKalle Valo "station %d - addr: %pM, flags: %#x\n", i, 4477ac9a364SKalle Valo station->sta.sta.addr, 4487ac9a364SKalle Valo station->sta.station_flags_msk); 4497ac9a364SKalle Valo pos += 4507ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 4517ac9a364SKalle Valo "TID\tseq_num\ttxq_id\tframes\ttfds\t"); 4527ac9a364SKalle Valo pos += 4537ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 4547ac9a364SKalle Valo "start_idx\tbitmap\t\t\trate_n_flags\n"); 4557ac9a364SKalle Valo 4567ac9a364SKalle Valo for (j = 0; j < MAX_TID_COUNT; j++) { 4577ac9a364SKalle Valo pos += 4587ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 4597ac9a364SKalle Valo "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", 4607ac9a364SKalle Valo j, station->tid[j].seq_number, 4617ac9a364SKalle Valo station->tid[j].agg.txq_id, 4627ac9a364SKalle Valo station->tid[j].agg.frame_count, 4637ac9a364SKalle Valo station->tid[j].tfds_in_queue, 4647ac9a364SKalle Valo station->tid[j].agg.start_idx, 4657ac9a364SKalle Valo station->tid[j].agg.bitmap, 4667ac9a364SKalle Valo station->tid[j].agg.rate_n_flags); 4677ac9a364SKalle Valo 4687ac9a364SKalle Valo if (station->tid[j].agg.wait_for_ba) 4697ac9a364SKalle Valo pos += 4707ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 4717ac9a364SKalle Valo " - waitforba"); 4727ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 4737ac9a364SKalle Valo } 4747ac9a364SKalle Valo 4757ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 4767ac9a364SKalle Valo } 4777ac9a364SKalle Valo 4787ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 4797ac9a364SKalle Valo kfree(buf); 4807ac9a364SKalle Valo return ret; 4817ac9a364SKalle Valo } 4827ac9a364SKalle Valo 4837ac9a364SKalle Valo static ssize_t 4847ac9a364SKalle Valo il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count, 4857ac9a364SKalle Valo loff_t *ppos) 4867ac9a364SKalle Valo { 4877ac9a364SKalle Valo ssize_t ret; 4887ac9a364SKalle Valo struct il_priv *il = file->private_data; 4897ac9a364SKalle Valo int pos = 0, ofs = 0, buf_size = 0; 4907ac9a364SKalle Valo const u8 *ptr; 4917ac9a364SKalle Valo char *buf; 4927ac9a364SKalle Valo u16 eeprom_ver; 4937ac9a364SKalle Valo size_t eeprom_len = il->cfg->eeprom_size; 4947ac9a364SKalle Valo buf_size = 4 * eeprom_len + 256; 4957ac9a364SKalle Valo 4967ac9a364SKalle Valo if (eeprom_len % 16) { 4977ac9a364SKalle Valo IL_ERR("NVM size is not multiple of 16.\n"); 4987ac9a364SKalle Valo return -ENODATA; 4997ac9a364SKalle Valo } 5007ac9a364SKalle Valo 5017ac9a364SKalle Valo ptr = il->eeprom; 5027ac9a364SKalle Valo if (!ptr) { 5037ac9a364SKalle Valo IL_ERR("Invalid EEPROM memory\n"); 5047ac9a364SKalle Valo return -ENOMEM; 5057ac9a364SKalle Valo } 5067ac9a364SKalle Valo 5077ac9a364SKalle Valo /* 4 characters for byte 0xYY */ 5087ac9a364SKalle Valo buf = kzalloc(buf_size, GFP_KERNEL); 5097ac9a364SKalle Valo if (!buf) { 5107ac9a364SKalle Valo IL_ERR("Can not allocate Buffer\n"); 5117ac9a364SKalle Valo return -ENOMEM; 5127ac9a364SKalle Valo } 5137ac9a364SKalle Valo eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION); 5147ac9a364SKalle Valo pos += 5157ac9a364SKalle Valo scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n", 5167ac9a364SKalle Valo eeprom_ver); 5177ac9a364SKalle Valo for (ofs = 0; ofs < eeprom_len; ofs += 16) { 5187ac9a364SKalle Valo pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n", 5197ac9a364SKalle Valo ofs, ptr + ofs); 5207ac9a364SKalle Valo } 5217ac9a364SKalle Valo 5227ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 5237ac9a364SKalle Valo kfree(buf); 5247ac9a364SKalle Valo return ret; 5257ac9a364SKalle Valo } 5267ac9a364SKalle Valo 5277ac9a364SKalle Valo static ssize_t 5287ac9a364SKalle Valo il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, 5297ac9a364SKalle Valo loff_t *ppos) 5307ac9a364SKalle Valo { 5317ac9a364SKalle Valo struct il_priv *il = file->private_data; 5327ac9a364SKalle Valo struct ieee80211_channel *channels = NULL; 5337ac9a364SKalle Valo const struct ieee80211_supported_band *supp_band = NULL; 5347ac9a364SKalle Valo int pos = 0, i, bufsz = PAGE_SIZE; 5357ac9a364SKalle Valo char *buf; 5367ac9a364SKalle Valo ssize_t ret; 5377ac9a364SKalle Valo 5387ac9a364SKalle Valo if (!test_bit(S_GEO_CONFIGURED, &il->status)) 5397ac9a364SKalle Valo return -EAGAIN; 5407ac9a364SKalle Valo 5417ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 5427ac9a364SKalle Valo if (!buf) { 5437ac9a364SKalle Valo IL_ERR("Can not allocate Buffer\n"); 5447ac9a364SKalle Valo return -ENOMEM; 5457ac9a364SKalle Valo } 5467ac9a364SKalle Valo 5477ac9a364SKalle Valo supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ); 5487ac9a364SKalle Valo if (supp_band) { 5497ac9a364SKalle Valo channels = supp_band->channels; 5507ac9a364SKalle Valo 5517ac9a364SKalle Valo pos += 5527ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 5537ac9a364SKalle Valo "Displaying %d channels in 2.4GHz band 802.11bg):\n", 5547ac9a364SKalle Valo supp_band->n_channels); 5557ac9a364SKalle Valo 5567ac9a364SKalle Valo for (i = 0; i < supp_band->n_channels; i++) 5577ac9a364SKalle Valo pos += 5587ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 5597ac9a364SKalle Valo "%d: %ddBm: BSS%s%s, %s.\n", 5607ac9a364SKalle Valo channels[i].hw_value, 5617ac9a364SKalle Valo channels[i].max_power, 5627ac9a364SKalle Valo channels[i]. 5637ac9a364SKalle Valo flags & IEEE80211_CHAN_RADAR ? 5647ac9a364SKalle Valo " (IEEE 802.11h required)" : "", 5657ac9a364SKalle Valo ((channels[i]. 5667ac9a364SKalle Valo flags & IEEE80211_CHAN_NO_IR) || 5677ac9a364SKalle Valo (channels[i]. 5687ac9a364SKalle Valo flags & IEEE80211_CHAN_RADAR)) ? "" : 5697ac9a364SKalle Valo ", IBSS", 5707ac9a364SKalle Valo channels[i]. 5717ac9a364SKalle Valo flags & IEEE80211_CHAN_NO_IR ? 5727ac9a364SKalle Valo "passive only" : "active/passive"); 5737ac9a364SKalle Valo } 5747ac9a364SKalle Valo supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ); 5757ac9a364SKalle Valo if (supp_band) { 5767ac9a364SKalle Valo channels = supp_band->channels; 5777ac9a364SKalle Valo 5787ac9a364SKalle Valo pos += 5797ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 5807ac9a364SKalle Valo "Displaying %d channels in 5.2GHz band (802.11a)\n", 5817ac9a364SKalle Valo supp_band->n_channels); 5827ac9a364SKalle Valo 5837ac9a364SKalle Valo for (i = 0; i < supp_band->n_channels; i++) 5847ac9a364SKalle Valo pos += 5857ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 5867ac9a364SKalle Valo "%d: %ddBm: BSS%s%s, %s.\n", 5877ac9a364SKalle Valo channels[i].hw_value, 5887ac9a364SKalle Valo channels[i].max_power, 5897ac9a364SKalle Valo channels[i]. 5907ac9a364SKalle Valo flags & IEEE80211_CHAN_RADAR ? 5917ac9a364SKalle Valo " (IEEE 802.11h required)" : "", 5927ac9a364SKalle Valo ((channels[i]. 5937ac9a364SKalle Valo flags & IEEE80211_CHAN_NO_IR) || 5947ac9a364SKalle Valo (channels[i]. 5957ac9a364SKalle Valo flags & IEEE80211_CHAN_RADAR)) ? "" : 5967ac9a364SKalle Valo ", IBSS", 5977ac9a364SKalle Valo channels[i]. 5987ac9a364SKalle Valo flags & IEEE80211_CHAN_NO_IR ? 5997ac9a364SKalle Valo "passive only" : "active/passive"); 6007ac9a364SKalle Valo } 6017ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 6027ac9a364SKalle Valo kfree(buf); 6037ac9a364SKalle Valo return ret; 6047ac9a364SKalle Valo } 6057ac9a364SKalle Valo 6067ac9a364SKalle Valo static ssize_t 6077ac9a364SKalle Valo il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count, 6087ac9a364SKalle Valo loff_t *ppos) 6097ac9a364SKalle Valo { 6107ac9a364SKalle Valo 6117ac9a364SKalle Valo struct il_priv *il = file->private_data; 6127ac9a364SKalle Valo char buf[512]; 6137ac9a364SKalle Valo int pos = 0; 6147ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 6157ac9a364SKalle Valo 6167ac9a364SKalle Valo pos += 6177ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n", 6187ac9a364SKalle Valo test_bit(S_HCMD_ACTIVE, &il->status)); 6197ac9a364SKalle Valo pos += 6207ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n", 6217ac9a364SKalle Valo test_bit(S_INT_ENABLED, &il->status)); 6227ac9a364SKalle Valo pos += 6237ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_RFKILL:\t %d\n", 6247ac9a364SKalle Valo test_bit(S_RFKILL, &il->status)); 6257ac9a364SKalle Valo pos += 6267ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n", 6277ac9a364SKalle Valo test_bit(S_CT_KILL, &il->status)); 6287ac9a364SKalle Valo pos += 6297ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n", 6307ac9a364SKalle Valo test_bit(S_INIT, &il->status)); 6317ac9a364SKalle Valo pos += 6327ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n", 6337ac9a364SKalle Valo test_bit(S_ALIVE, &il->status)); 6347ac9a364SKalle Valo pos += 6357ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n", 6367ac9a364SKalle Valo test_bit(S_READY, &il->status)); 6377ac9a364SKalle Valo pos += 6387ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n", 6397ac9a364SKalle Valo test_bit(S_TEMPERATURE, &il->status)); 6407ac9a364SKalle Valo pos += 6417ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n", 6427ac9a364SKalle Valo test_bit(S_GEO_CONFIGURED, &il->status)); 6437ac9a364SKalle Valo pos += 6447ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n", 6457ac9a364SKalle Valo test_bit(S_EXIT_PENDING, &il->status)); 6467ac9a364SKalle Valo pos += 6477ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n", 6487ac9a364SKalle Valo test_bit(S_STATS, &il->status)); 6497ac9a364SKalle Valo pos += 6507ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n", 6517ac9a364SKalle Valo test_bit(S_SCANNING, &il->status)); 6527ac9a364SKalle Valo pos += 6537ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n", 6547ac9a364SKalle Valo test_bit(S_SCAN_ABORTING, &il->status)); 6557ac9a364SKalle Valo pos += 6567ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n", 6577ac9a364SKalle Valo test_bit(S_SCAN_HW, &il->status)); 6587ac9a364SKalle Valo pos += 6597ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n", 6607ac9a364SKalle Valo test_bit(S_POWER_PMI, &il->status)); 6617ac9a364SKalle Valo pos += 6627ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n", 6637ac9a364SKalle Valo test_bit(S_FW_ERROR, &il->status)); 6647ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 6657ac9a364SKalle Valo } 6667ac9a364SKalle Valo 6677ac9a364SKalle Valo static ssize_t 6687ac9a364SKalle Valo il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count, 6697ac9a364SKalle Valo loff_t *ppos) 6707ac9a364SKalle Valo { 6717ac9a364SKalle Valo 6727ac9a364SKalle Valo struct il_priv *il = file->private_data; 6737ac9a364SKalle Valo int pos = 0; 6747ac9a364SKalle Valo int cnt = 0; 6757ac9a364SKalle Valo char *buf; 6767ac9a364SKalle Valo int bufsz = 24 * 64; /* 24 items * 64 char per item */ 6777ac9a364SKalle Valo ssize_t ret; 6787ac9a364SKalle Valo 6797ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 6807ac9a364SKalle Valo if (!buf) { 6817ac9a364SKalle Valo IL_ERR("Can not allocate Buffer\n"); 6827ac9a364SKalle Valo return -ENOMEM; 6837ac9a364SKalle Valo } 6847ac9a364SKalle Valo 6857ac9a364SKalle Valo pos += 6867ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n"); 6877ac9a364SKalle Valo 6887ac9a364SKalle Valo pos += 6897ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", 6907ac9a364SKalle Valo il->isr_stats.hw); 6917ac9a364SKalle Valo pos += 6927ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", 6937ac9a364SKalle Valo il->isr_stats.sw); 6947ac9a364SKalle Valo if (il->isr_stats.sw || il->isr_stats.hw) { 6957ac9a364SKalle Valo pos += 6967ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 6977ac9a364SKalle Valo "\tLast Restarting Code: 0x%X\n", 6987ac9a364SKalle Valo il->isr_stats.err_code); 6997ac9a364SKalle Valo } 7007ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG 7017ac9a364SKalle Valo pos += 7027ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", 7037ac9a364SKalle Valo il->isr_stats.sch); 7047ac9a364SKalle Valo pos += 7057ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", 7067ac9a364SKalle Valo il->isr_stats.alive); 7077ac9a364SKalle Valo #endif 7087ac9a364SKalle Valo pos += 7097ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 7107ac9a364SKalle Valo "HW RF KILL switch toggled:\t %u\n", 7117ac9a364SKalle Valo il->isr_stats.rfkill); 7127ac9a364SKalle Valo 7137ac9a364SKalle Valo pos += 7147ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", 7157ac9a364SKalle Valo il->isr_stats.ctkill); 7167ac9a364SKalle Valo 7177ac9a364SKalle Valo pos += 7187ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", 7197ac9a364SKalle Valo il->isr_stats.wakeup); 7207ac9a364SKalle Valo 7217ac9a364SKalle Valo pos += 7227ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n", 7237ac9a364SKalle Valo il->isr_stats.rx); 7247ac9a364SKalle Valo for (cnt = 0; cnt < IL_CN_MAX; cnt++) { 7257ac9a364SKalle Valo if (il->isr_stats.handlers[cnt] > 0) 7267ac9a364SKalle Valo pos += 7277ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 7287ac9a364SKalle Valo "\tRx handler[%36s]:\t\t %u\n", 7297ac9a364SKalle Valo il_get_cmd_string(cnt), 7307ac9a364SKalle Valo il->isr_stats.handlers[cnt]); 7317ac9a364SKalle Valo } 7327ac9a364SKalle Valo 7337ac9a364SKalle Valo pos += 7347ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", 7357ac9a364SKalle Valo il->isr_stats.tx); 7367ac9a364SKalle Valo 7377ac9a364SKalle Valo pos += 7387ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", 7397ac9a364SKalle Valo il->isr_stats.unhandled); 7407ac9a364SKalle Valo 7417ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 7427ac9a364SKalle Valo kfree(buf); 7437ac9a364SKalle Valo return ret; 7447ac9a364SKalle Valo } 7457ac9a364SKalle Valo 7467ac9a364SKalle Valo static ssize_t 7477ac9a364SKalle Valo il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf, 7487ac9a364SKalle Valo size_t count, loff_t *ppos) 7497ac9a364SKalle Valo { 7507ac9a364SKalle Valo struct il_priv *il = file->private_data; 7517ac9a364SKalle Valo char buf[8]; 7527ac9a364SKalle Valo int buf_size; 7537ac9a364SKalle Valo u32 reset_flag; 7547ac9a364SKalle Valo 7557ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 7567ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 7577ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 7587ac9a364SKalle Valo return -EFAULT; 7597ac9a364SKalle Valo if (sscanf(buf, "%x", &reset_flag) != 1) 7607ac9a364SKalle Valo return -EFAULT; 7617ac9a364SKalle Valo if (reset_flag == 0) 7627ac9a364SKalle Valo il_clear_isr_stats(il); 7637ac9a364SKalle Valo 7647ac9a364SKalle Valo return count; 7657ac9a364SKalle Valo } 7667ac9a364SKalle Valo 7677ac9a364SKalle Valo static ssize_t 7687ac9a364SKalle Valo il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count, 7697ac9a364SKalle Valo loff_t *ppos) 7707ac9a364SKalle Valo { 7717ac9a364SKalle Valo struct il_priv *il = file->private_data; 7727ac9a364SKalle Valo int pos = 0, i; 7737ac9a364SKalle Valo char buf[256]; 7747ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 7757ac9a364SKalle Valo 7767ac9a364SKalle Valo for (i = 0; i < AC_NUM; i++) { 7777ac9a364SKalle Valo pos += 7787ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 7797ac9a364SKalle Valo "\tcw_min\tcw_max\taifsn\ttxop\n"); 7807ac9a364SKalle Valo pos += 7817ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 7827ac9a364SKalle Valo "AC[%d]\t%u\t%u\t%u\t%u\n", i, 7837ac9a364SKalle Valo il->qos_data.def_qos_parm.ac[i].cw_min, 7847ac9a364SKalle Valo il->qos_data.def_qos_parm.ac[i].cw_max, 7857ac9a364SKalle Valo il->qos_data.def_qos_parm.ac[i].aifsn, 7867ac9a364SKalle Valo il->qos_data.def_qos_parm.ac[i].edca_txop); 7877ac9a364SKalle Valo } 7887ac9a364SKalle Valo 7897ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 7907ac9a364SKalle Valo } 7917ac9a364SKalle Valo 7927ac9a364SKalle Valo static ssize_t 7937ac9a364SKalle Valo il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf, 7947ac9a364SKalle Valo size_t count, loff_t *ppos) 7957ac9a364SKalle Valo { 7967ac9a364SKalle Valo struct il_priv *il = file->private_data; 7977ac9a364SKalle Valo char buf[8]; 7987ac9a364SKalle Valo int buf_size; 7997ac9a364SKalle Valo int ht40; 8007ac9a364SKalle Valo 8017ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 8027ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 8037ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 8047ac9a364SKalle Valo return -EFAULT; 8057ac9a364SKalle Valo if (sscanf(buf, "%d", &ht40) != 1) 8067ac9a364SKalle Valo return -EFAULT; 8077ac9a364SKalle Valo if (!il_is_any_associated(il)) 8087ac9a364SKalle Valo il->disable_ht40 = ht40 ? true : false; 8097ac9a364SKalle Valo else { 8107ac9a364SKalle Valo IL_ERR("Sta associated with AP - " 8117ac9a364SKalle Valo "Change to 40MHz channel support is not allowed\n"); 8127ac9a364SKalle Valo return -EINVAL; 8137ac9a364SKalle Valo } 8147ac9a364SKalle Valo 8157ac9a364SKalle Valo return count; 8167ac9a364SKalle Valo } 8177ac9a364SKalle Valo 8187ac9a364SKalle Valo static ssize_t 8197ac9a364SKalle Valo il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf, 8207ac9a364SKalle Valo size_t count, loff_t *ppos) 8217ac9a364SKalle Valo { 8227ac9a364SKalle Valo struct il_priv *il = file->private_data; 8237ac9a364SKalle Valo char buf[100]; 8247ac9a364SKalle Valo int pos = 0; 8257ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 8267ac9a364SKalle Valo 8277ac9a364SKalle Valo pos += 8287ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n", 8297ac9a364SKalle Valo il->disable_ht40 ? "Disabled" : "Enabled"); 8307ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 8317ac9a364SKalle Valo } 8327ac9a364SKalle Valo 8337ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(sram); 8347ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(nvm); 8357ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(stations); 8367ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(channels); 8377ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(status); 8387ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 8397ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(qos); 8407ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); 8417ac9a364SKalle Valo 8427ac9a364SKalle Valo static ssize_t 8437ac9a364SKalle Valo il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count, 8447ac9a364SKalle Valo loff_t *ppos) 8457ac9a364SKalle Valo { 8467ac9a364SKalle Valo 8477ac9a364SKalle Valo struct il_priv *il = file->private_data; 8487ac9a364SKalle Valo struct il_tx_queue *txq; 8497ac9a364SKalle Valo struct il_queue *q; 8507ac9a364SKalle Valo char *buf; 8517ac9a364SKalle Valo int pos = 0; 8527ac9a364SKalle Valo int cnt; 8537ac9a364SKalle Valo int ret; 8547ac9a364SKalle Valo const size_t bufsz = 8557ac9a364SKalle Valo sizeof(char) * 64 * il->cfg->num_of_queues; 8567ac9a364SKalle Valo 8577ac9a364SKalle Valo if (!il->txq) { 8587ac9a364SKalle Valo IL_ERR("txq not ready\n"); 8597ac9a364SKalle Valo return -EAGAIN; 8607ac9a364SKalle Valo } 8617ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 8627ac9a364SKalle Valo if (!buf) 8637ac9a364SKalle Valo return -ENOMEM; 8647ac9a364SKalle Valo 8657ac9a364SKalle Valo for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { 8667ac9a364SKalle Valo txq = &il->txq[cnt]; 8677ac9a364SKalle Valo q = &txq->q; 8687ac9a364SKalle Valo pos += 8697ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 8707ac9a364SKalle Valo "hwq %.2d: read=%u write=%u stop=%d" 8717ac9a364SKalle Valo " swq_id=%#.2x (ac %d/hwq %d)\n", cnt, 8727ac9a364SKalle Valo q->read_ptr, q->write_ptr, 8737ac9a364SKalle Valo !!test_bit(cnt, il->queue_stopped), 8747ac9a364SKalle Valo txq->swq_id, txq->swq_id & 3, 8757ac9a364SKalle Valo (txq->swq_id >> 2) & 0x1f); 8767ac9a364SKalle Valo if (cnt >= 4) 8777ac9a364SKalle Valo continue; 8787ac9a364SKalle Valo /* for the ACs, display the stop count too */ 8797ac9a364SKalle Valo pos += 8807ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 8817ac9a364SKalle Valo " stop-count: %d\n", 8827ac9a364SKalle Valo atomic_read(&il->queue_stop_count[cnt])); 8837ac9a364SKalle Valo } 8847ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 8857ac9a364SKalle Valo kfree(buf); 8867ac9a364SKalle Valo return ret; 8877ac9a364SKalle Valo } 8887ac9a364SKalle Valo 8897ac9a364SKalle Valo static ssize_t 8907ac9a364SKalle Valo il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count, 8917ac9a364SKalle Valo loff_t *ppos) 8927ac9a364SKalle Valo { 8937ac9a364SKalle Valo 8947ac9a364SKalle Valo struct il_priv *il = file->private_data; 8957ac9a364SKalle Valo struct il_rx_queue *rxq = &il->rxq; 8967ac9a364SKalle Valo char buf[256]; 8977ac9a364SKalle Valo int pos = 0; 8987ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 8997ac9a364SKalle Valo 9007ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read); 9017ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write); 9027ac9a364SKalle Valo pos += 9037ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", 9047ac9a364SKalle Valo rxq->free_count); 9057ac9a364SKalle Valo if (rxq->rb_stts) { 9067ac9a364SKalle Valo pos += 9077ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", 9087ac9a364SKalle Valo le16_to_cpu(rxq->rb_stts-> 9097ac9a364SKalle Valo closed_rb_num) & 0x0FFF); 9107ac9a364SKalle Valo } else { 9117ac9a364SKalle Valo pos += 9127ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 9137ac9a364SKalle Valo "closed_rb_num: Not Allocated\n"); 9147ac9a364SKalle Valo } 9157ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 9167ac9a364SKalle Valo } 9177ac9a364SKalle Valo 9187ac9a364SKalle Valo static ssize_t 9197ac9a364SKalle Valo il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf, 9207ac9a364SKalle Valo size_t count, loff_t *ppos) 9217ac9a364SKalle Valo { 9227ac9a364SKalle Valo struct il_priv *il = file->private_data; 9237ac9a364SKalle Valo 9247ac9a364SKalle Valo return il->debugfs_ops->rx_stats_read(file, user_buf, count, ppos); 9257ac9a364SKalle Valo } 9267ac9a364SKalle Valo 9277ac9a364SKalle Valo static ssize_t 9287ac9a364SKalle Valo il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf, 9297ac9a364SKalle Valo size_t count, loff_t *ppos) 9307ac9a364SKalle Valo { 9317ac9a364SKalle Valo struct il_priv *il = file->private_data; 9327ac9a364SKalle Valo 9337ac9a364SKalle Valo return il->debugfs_ops->tx_stats_read(file, user_buf, count, ppos); 9347ac9a364SKalle Valo } 9357ac9a364SKalle Valo 9367ac9a364SKalle Valo static ssize_t 9377ac9a364SKalle Valo il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf, 9387ac9a364SKalle Valo size_t count, loff_t *ppos) 9397ac9a364SKalle Valo { 9407ac9a364SKalle Valo struct il_priv *il = file->private_data; 9417ac9a364SKalle Valo 9427ac9a364SKalle Valo return il->debugfs_ops->general_stats_read(file, user_buf, count, ppos); 9437ac9a364SKalle Valo } 9447ac9a364SKalle Valo 9457ac9a364SKalle Valo static ssize_t 9467ac9a364SKalle Valo il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf, 9477ac9a364SKalle Valo size_t count, loff_t *ppos) 9487ac9a364SKalle Valo { 9497ac9a364SKalle Valo 9507ac9a364SKalle Valo struct il_priv *il = file->private_data; 9517ac9a364SKalle Valo int pos = 0; 9527ac9a364SKalle Valo int cnt = 0; 9537ac9a364SKalle Valo char *buf; 9547ac9a364SKalle Valo int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100; 9557ac9a364SKalle Valo ssize_t ret; 9567ac9a364SKalle Valo struct il_sensitivity_data *data; 9577ac9a364SKalle Valo 9587ac9a364SKalle Valo data = &il->sensitivity_data; 9597ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 9607ac9a364SKalle Valo if (!buf) { 9617ac9a364SKalle Valo IL_ERR("Can not allocate Buffer\n"); 9627ac9a364SKalle Valo return -ENOMEM; 9637ac9a364SKalle Valo } 9647ac9a364SKalle Valo 9657ac9a364SKalle Valo pos += 9667ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n", 9677ac9a364SKalle Valo data->auto_corr_ofdm); 9687ac9a364SKalle Valo pos += 9697ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n", 9707ac9a364SKalle Valo data->auto_corr_ofdm_mrc); 9717ac9a364SKalle Valo pos += 9727ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n", 9737ac9a364SKalle Valo data->auto_corr_ofdm_x1); 9747ac9a364SKalle Valo pos += 9757ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n", 9767ac9a364SKalle Valo data->auto_corr_ofdm_mrc_x1); 9777ac9a364SKalle Valo pos += 9787ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n", 9797ac9a364SKalle Valo data->auto_corr_cck); 9807ac9a364SKalle Valo pos += 9817ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n", 9827ac9a364SKalle Valo data->auto_corr_cck_mrc); 9837ac9a364SKalle Valo pos += 9847ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 9857ac9a364SKalle Valo "last_bad_plcp_cnt_ofdm:\t\t %u\n", 9867ac9a364SKalle Valo data->last_bad_plcp_cnt_ofdm); 9877ac9a364SKalle Valo pos += 9887ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n", 9897ac9a364SKalle Valo data->last_fa_cnt_ofdm); 9907ac9a364SKalle Valo pos += 9917ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n", 9927ac9a364SKalle Valo data->last_bad_plcp_cnt_cck); 9937ac9a364SKalle Valo pos += 9947ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n", 9957ac9a364SKalle Valo data->last_fa_cnt_cck); 9967ac9a364SKalle Valo pos += 9977ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n", 9987ac9a364SKalle Valo data->nrg_curr_state); 9997ac9a364SKalle Valo pos += 10007ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n", 10017ac9a364SKalle Valo data->nrg_prev_state); 10027ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t"); 10037ac9a364SKalle Valo for (cnt = 0; cnt < 10; cnt++) { 10047ac9a364SKalle Valo pos += 10057ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, " %u", 10067ac9a364SKalle Valo data->nrg_value[cnt]); 10077ac9a364SKalle Valo } 10087ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 10097ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t"); 10107ac9a364SKalle Valo for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) { 10117ac9a364SKalle Valo pos += 10127ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, " %u", 10137ac9a364SKalle Valo data->nrg_silence_rssi[cnt]); 10147ac9a364SKalle Valo } 10157ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 10167ac9a364SKalle Valo pos += 10177ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n", 10187ac9a364SKalle Valo data->nrg_silence_ref); 10197ac9a364SKalle Valo pos += 10207ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n", 10217ac9a364SKalle Valo data->nrg_energy_idx); 10227ac9a364SKalle Valo pos += 10237ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n", 10247ac9a364SKalle Valo data->nrg_silence_idx); 10257ac9a364SKalle Valo pos += 10267ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n", 10277ac9a364SKalle Valo data->nrg_th_cck); 10287ac9a364SKalle Valo pos += 10297ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 10307ac9a364SKalle Valo "nrg_auto_corr_silence_diff:\t %u\n", 10317ac9a364SKalle Valo data->nrg_auto_corr_silence_diff); 10327ac9a364SKalle Valo pos += 10337ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n", 10347ac9a364SKalle Valo data->num_in_cck_no_fa); 10357ac9a364SKalle Valo pos += 10367ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n", 10377ac9a364SKalle Valo data->nrg_th_ofdm); 10387ac9a364SKalle Valo 10397ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 10407ac9a364SKalle Valo kfree(buf); 10417ac9a364SKalle Valo return ret; 10427ac9a364SKalle Valo } 10437ac9a364SKalle Valo 10447ac9a364SKalle Valo static ssize_t 10457ac9a364SKalle Valo il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf, 10467ac9a364SKalle Valo size_t count, loff_t *ppos) 10477ac9a364SKalle Valo { 10487ac9a364SKalle Valo 10497ac9a364SKalle Valo struct il_priv *il = file->private_data; 10507ac9a364SKalle Valo int pos = 0; 10517ac9a364SKalle Valo int cnt = 0; 10527ac9a364SKalle Valo char *buf; 10537ac9a364SKalle Valo int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100; 10547ac9a364SKalle Valo ssize_t ret; 10557ac9a364SKalle Valo struct il_chain_noise_data *data; 10567ac9a364SKalle Valo 10577ac9a364SKalle Valo data = &il->chain_noise_data; 10587ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 10597ac9a364SKalle Valo if (!buf) { 10607ac9a364SKalle Valo IL_ERR("Can not allocate Buffer\n"); 10617ac9a364SKalle Valo return -ENOMEM; 10627ac9a364SKalle Valo } 10637ac9a364SKalle Valo 10647ac9a364SKalle Valo pos += 10657ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n", 10667ac9a364SKalle Valo data->active_chains); 10677ac9a364SKalle Valo pos += 10687ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n", 10697ac9a364SKalle Valo data->chain_noise_a); 10707ac9a364SKalle Valo pos += 10717ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n", 10727ac9a364SKalle Valo data->chain_noise_b); 10737ac9a364SKalle Valo pos += 10747ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n", 10757ac9a364SKalle Valo data->chain_noise_c); 10767ac9a364SKalle Valo pos += 10777ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n", 10787ac9a364SKalle Valo data->chain_signal_a); 10797ac9a364SKalle Valo pos += 10807ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n", 10817ac9a364SKalle Valo data->chain_signal_b); 10827ac9a364SKalle Valo pos += 10837ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n", 10847ac9a364SKalle Valo data->chain_signal_c); 10857ac9a364SKalle Valo pos += 10867ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n", 10877ac9a364SKalle Valo data->beacon_count); 10887ac9a364SKalle Valo 10897ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t"); 10907ac9a364SKalle Valo for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 10917ac9a364SKalle Valo pos += 10927ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, " %u", 10937ac9a364SKalle Valo data->disconn_array[cnt]); 10947ac9a364SKalle Valo } 10957ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 10967ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t"); 10977ac9a364SKalle Valo for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 10987ac9a364SKalle Valo pos += 10997ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, " %u", 11007ac9a364SKalle Valo data->delta_gain_code[cnt]); 11017ac9a364SKalle Valo } 11027ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 11037ac9a364SKalle Valo pos += 11047ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n", 11057ac9a364SKalle Valo data->radio_write); 11067ac9a364SKalle Valo pos += 11077ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n", 11087ac9a364SKalle Valo data->state); 11097ac9a364SKalle Valo 11107ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 11117ac9a364SKalle Valo kfree(buf); 11127ac9a364SKalle Valo return ret; 11137ac9a364SKalle Valo } 11147ac9a364SKalle Valo 11157ac9a364SKalle Valo static ssize_t 11167ac9a364SKalle Valo il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf, 11177ac9a364SKalle Valo size_t count, loff_t *ppos) 11187ac9a364SKalle Valo { 11197ac9a364SKalle Valo struct il_priv *il = file->private_data; 11207ac9a364SKalle Valo char buf[60]; 11217ac9a364SKalle Valo int pos = 0; 11227ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 11237ac9a364SKalle Valo u32 pwrsave_status; 11247ac9a364SKalle Valo 11257ac9a364SKalle Valo pwrsave_status = 11267ac9a364SKalle Valo _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK; 11277ac9a364SKalle Valo 11287ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); 11297ac9a364SKalle Valo pos += 11307ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "%s\n", 11317ac9a364SKalle Valo (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" : 11327ac9a364SKalle Valo (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" : 11337ac9a364SKalle Valo (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : 11347ac9a364SKalle Valo "error"); 11357ac9a364SKalle Valo 11367ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 11377ac9a364SKalle Valo } 11387ac9a364SKalle Valo 11397ac9a364SKalle Valo static ssize_t 11407ac9a364SKalle Valo il_dbgfs_clear_ucode_stats_write(struct file *file, 11417ac9a364SKalle Valo const char __user *user_buf, size_t count, 11427ac9a364SKalle Valo loff_t *ppos) 11437ac9a364SKalle Valo { 11447ac9a364SKalle Valo struct il_priv *il = file->private_data; 11457ac9a364SKalle Valo char buf[8]; 11467ac9a364SKalle Valo int buf_size; 11477ac9a364SKalle Valo int clear; 11487ac9a364SKalle Valo 11497ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 11507ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 11517ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 11527ac9a364SKalle Valo return -EFAULT; 11537ac9a364SKalle Valo if (sscanf(buf, "%d", &clear) != 1) 11547ac9a364SKalle Valo return -EFAULT; 11557ac9a364SKalle Valo 11567ac9a364SKalle Valo /* make request to uCode to retrieve stats information */ 11577ac9a364SKalle Valo mutex_lock(&il->mutex); 11587ac9a364SKalle Valo il_send_stats_request(il, CMD_SYNC, true); 11597ac9a364SKalle Valo mutex_unlock(&il->mutex); 11607ac9a364SKalle Valo 11617ac9a364SKalle Valo return count; 11627ac9a364SKalle Valo } 11637ac9a364SKalle Valo 11647ac9a364SKalle Valo static ssize_t 11657ac9a364SKalle Valo il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf, 11667ac9a364SKalle Valo size_t count, loff_t *ppos) 11677ac9a364SKalle Valo { 11687ac9a364SKalle Valo 11697ac9a364SKalle Valo struct il_priv *il = file->private_data; 11707ac9a364SKalle Valo int len = 0; 11717ac9a364SKalle Valo char buf[20]; 11727ac9a364SKalle Valo 11737ac9a364SKalle Valo len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags)); 11747ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, len); 11757ac9a364SKalle Valo } 11767ac9a364SKalle Valo 11777ac9a364SKalle Valo static ssize_t 11787ac9a364SKalle Valo il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf, 11797ac9a364SKalle Valo size_t count, loff_t *ppos) 11807ac9a364SKalle Valo { 11817ac9a364SKalle Valo 11827ac9a364SKalle Valo struct il_priv *il = file->private_data; 11837ac9a364SKalle Valo int len = 0; 11847ac9a364SKalle Valo char buf[20]; 11857ac9a364SKalle Valo 11867ac9a364SKalle Valo len = 11877ac9a364SKalle Valo sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags)); 11887ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, len); 11897ac9a364SKalle Valo } 11907ac9a364SKalle Valo 11917ac9a364SKalle Valo static ssize_t 11927ac9a364SKalle Valo il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count, 11937ac9a364SKalle Valo loff_t *ppos) 11947ac9a364SKalle Valo { 11957ac9a364SKalle Valo struct il_priv *il = file->private_data; 11967ac9a364SKalle Valo char *buf; 11977ac9a364SKalle Valo int pos = 0; 11987ac9a364SKalle Valo ssize_t ret = -EFAULT; 11997ac9a364SKalle Valo 12007ac9a364SKalle Valo if (il->ops->dump_fh) { 12017ac9a364SKalle Valo ret = pos = il->ops->dump_fh(il, &buf, true); 12027ac9a364SKalle Valo if (buf) { 12037ac9a364SKalle Valo ret = 12047ac9a364SKalle Valo simple_read_from_buffer(user_buf, count, ppos, buf, 12057ac9a364SKalle Valo pos); 12067ac9a364SKalle Valo kfree(buf); 12077ac9a364SKalle Valo } 12087ac9a364SKalle Valo } 12097ac9a364SKalle Valo 12107ac9a364SKalle Valo return ret; 12117ac9a364SKalle Valo } 12127ac9a364SKalle Valo 12137ac9a364SKalle Valo static ssize_t 12147ac9a364SKalle Valo il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf, 12157ac9a364SKalle Valo size_t count, loff_t *ppos) 12167ac9a364SKalle Valo { 12177ac9a364SKalle Valo 12187ac9a364SKalle Valo struct il_priv *il = file->private_data; 12197ac9a364SKalle Valo int pos = 0; 12207ac9a364SKalle Valo char buf[12]; 12217ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 12227ac9a364SKalle Valo 12237ac9a364SKalle Valo pos += 12247ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "%d\n", 12257ac9a364SKalle Valo il->missed_beacon_threshold); 12267ac9a364SKalle Valo 12277ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 12287ac9a364SKalle Valo } 12297ac9a364SKalle Valo 12307ac9a364SKalle Valo static ssize_t 12317ac9a364SKalle Valo il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf, 12327ac9a364SKalle Valo size_t count, loff_t *ppos) 12337ac9a364SKalle Valo { 12347ac9a364SKalle Valo struct il_priv *il = file->private_data; 12357ac9a364SKalle Valo char buf[8]; 12367ac9a364SKalle Valo int buf_size; 12377ac9a364SKalle Valo int missed; 12387ac9a364SKalle Valo 12397ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 12407ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 12417ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 12427ac9a364SKalle Valo return -EFAULT; 12437ac9a364SKalle Valo if (sscanf(buf, "%d", &missed) != 1) 12447ac9a364SKalle Valo return -EINVAL; 12457ac9a364SKalle Valo 12467ac9a364SKalle Valo if (missed < IL_MISSED_BEACON_THRESHOLD_MIN || 12477ac9a364SKalle Valo missed > IL_MISSED_BEACON_THRESHOLD_MAX) 12487ac9a364SKalle Valo il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF; 12497ac9a364SKalle Valo else 12507ac9a364SKalle Valo il->missed_beacon_threshold = missed; 12517ac9a364SKalle Valo 12527ac9a364SKalle Valo return count; 12537ac9a364SKalle Valo } 12547ac9a364SKalle Valo 12557ac9a364SKalle Valo static ssize_t 12567ac9a364SKalle Valo il_dbgfs_force_reset_read(struct file *file, char __user *user_buf, 12577ac9a364SKalle Valo size_t count, loff_t *ppos) 12587ac9a364SKalle Valo { 12597ac9a364SKalle Valo 12607ac9a364SKalle Valo struct il_priv *il = file->private_data; 12617ac9a364SKalle Valo int pos = 0; 12627ac9a364SKalle Valo char buf[300]; 12637ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 12647ac9a364SKalle Valo struct il_force_reset *force_reset; 12657ac9a364SKalle Valo 12667ac9a364SKalle Valo force_reset = &il->force_reset; 12677ac9a364SKalle Valo 12687ac9a364SKalle Valo pos += 12697ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n", 12707ac9a364SKalle Valo force_reset->reset_request_count); 12717ac9a364SKalle Valo pos += 12727ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 12737ac9a364SKalle Valo "\tnumber of reset request success: %d\n", 12747ac9a364SKalle Valo force_reset->reset_success_count); 12757ac9a364SKalle Valo pos += 12767ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 12777ac9a364SKalle Valo "\tnumber of reset request reject: %d\n", 12787ac9a364SKalle Valo force_reset->reset_reject_count); 12797ac9a364SKalle Valo pos += 12807ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n", 12817ac9a364SKalle Valo force_reset->reset_duration); 12827ac9a364SKalle Valo 12837ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 12847ac9a364SKalle Valo } 12857ac9a364SKalle Valo 12867ac9a364SKalle Valo static ssize_t 12877ac9a364SKalle Valo il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf, 12887ac9a364SKalle Valo size_t count, loff_t *ppos) 12897ac9a364SKalle Valo { 12907ac9a364SKalle Valo 12917ac9a364SKalle Valo int ret; 12927ac9a364SKalle Valo struct il_priv *il = file->private_data; 12937ac9a364SKalle Valo 12947ac9a364SKalle Valo ret = il_force_reset(il, true); 12957ac9a364SKalle Valo 12967ac9a364SKalle Valo return ret ? ret : count; 12977ac9a364SKalle Valo } 12987ac9a364SKalle Valo 12997ac9a364SKalle Valo static ssize_t 13007ac9a364SKalle Valo il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf, 13017ac9a364SKalle Valo size_t count, loff_t *ppos) 13027ac9a364SKalle Valo { 13037ac9a364SKalle Valo 13047ac9a364SKalle Valo struct il_priv *il = file->private_data; 13057ac9a364SKalle Valo char buf[8]; 13067ac9a364SKalle Valo int buf_size; 13077ac9a364SKalle Valo int timeout; 13087ac9a364SKalle Valo 13097ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 13107ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 13117ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 13127ac9a364SKalle Valo return -EFAULT; 13137ac9a364SKalle Valo if (sscanf(buf, "%d", &timeout) != 1) 13147ac9a364SKalle Valo return -EINVAL; 13157ac9a364SKalle Valo if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT) 13167ac9a364SKalle Valo timeout = IL_DEF_WD_TIMEOUT; 13177ac9a364SKalle Valo 13187ac9a364SKalle Valo il->cfg->wd_timeout = timeout; 13197ac9a364SKalle Valo il_setup_watchdog(il); 13207ac9a364SKalle Valo return count; 13217ac9a364SKalle Valo } 13227ac9a364SKalle Valo 13237ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rx_stats); 13247ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(tx_stats); 13257ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rx_queue); 13267ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(tx_queue); 13277ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(ucode_rx_stats); 13287ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(ucode_tx_stats); 13297ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(ucode_general_stats); 13307ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(sensitivity); 13317ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(chain_noise); 13327ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(power_save_status); 13337ac9a364SKalle Valo DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats); 13347ac9a364SKalle Valo DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats); 13357ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(fh_reg); 13367ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); 13377ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(force_reset); 13387ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rxon_flags); 13397ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rxon_filter_flags); 13407ac9a364SKalle Valo DEBUGFS_WRITE_FILE_OPS(wd_timeout); 13417ac9a364SKalle Valo 13427ac9a364SKalle Valo /* 13437ac9a364SKalle Valo * Create the debugfs files and directories 13447ac9a364SKalle Valo * 13457ac9a364SKalle Valo */ 13467ac9a364SKalle Valo int 13477ac9a364SKalle Valo il_dbgfs_register(struct il_priv *il, const char *name) 13487ac9a364SKalle Valo { 13497ac9a364SKalle Valo struct dentry *phyd = il->hw->wiphy->debugfsdir; 13507ac9a364SKalle Valo struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; 13517ac9a364SKalle Valo 13527ac9a364SKalle Valo dir_drv = debugfs_create_dir(name, phyd); 13537ac9a364SKalle Valo if (!dir_drv) 13547ac9a364SKalle Valo return -ENOMEM; 13557ac9a364SKalle Valo 13567ac9a364SKalle Valo il->debugfs_dir = dir_drv; 13577ac9a364SKalle Valo 13587ac9a364SKalle Valo dir_data = debugfs_create_dir("data", dir_drv); 13597ac9a364SKalle Valo if (!dir_data) 13607ac9a364SKalle Valo goto err; 13617ac9a364SKalle Valo dir_rf = debugfs_create_dir("rf", dir_drv); 13627ac9a364SKalle Valo if (!dir_rf) 13637ac9a364SKalle Valo goto err; 13647ac9a364SKalle Valo dir_debug = debugfs_create_dir("debug", dir_drv); 13657ac9a364SKalle Valo if (!dir_debug) 13667ac9a364SKalle Valo goto err; 13677ac9a364SKalle Valo 13687ac9a364SKalle Valo DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); 13697ac9a364SKalle Valo DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); 13707ac9a364SKalle Valo DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); 13717ac9a364SKalle Valo DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); 13727ac9a364SKalle Valo DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); 13737ac9a364SKalle Valo DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); 13747ac9a364SKalle Valo DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); 13757ac9a364SKalle Valo DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); 13767ac9a364SKalle Valo DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR); 13777ac9a364SKalle Valo DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR); 13787ac9a364SKalle Valo DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); 13797ac9a364SKalle Valo DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); 13807ac9a364SKalle Valo DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); 13817ac9a364SKalle Valo DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, S_IWUSR); 13827ac9a364SKalle Valo DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, S_IWUSR); 13837ac9a364SKalle Valo DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); 13847ac9a364SKalle Valo DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); 13857ac9a364SKalle Valo DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); 13867ac9a364SKalle Valo DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); 13877ac9a364SKalle Valo DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); 13887ac9a364SKalle Valo DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); 13897ac9a364SKalle Valo 13907ac9a364SKalle Valo if (il->cfg->sensitivity_calib_by_driver) 13917ac9a364SKalle Valo DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); 13927ac9a364SKalle Valo if (il->cfg->chain_noise_calib_by_driver) 13937ac9a364SKalle Valo DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); 13947ac9a364SKalle Valo DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); 13957ac9a364SKalle Valo DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); 13967ac9a364SKalle Valo DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); 13977ac9a364SKalle Valo if (il->cfg->sensitivity_calib_by_driver) 13987ac9a364SKalle Valo DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, 13997ac9a364SKalle Valo &il->disable_sens_cal); 14007ac9a364SKalle Valo if (il->cfg->chain_noise_calib_by_driver) 14017ac9a364SKalle Valo DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, 14027ac9a364SKalle Valo &il->disable_chain_noise_cal); 14037ac9a364SKalle Valo DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal); 14047ac9a364SKalle Valo return 0; 14057ac9a364SKalle Valo 14067ac9a364SKalle Valo err: 14077ac9a364SKalle Valo IL_ERR("Can't create the debugfs directory\n"); 14087ac9a364SKalle Valo il_dbgfs_unregister(il); 14097ac9a364SKalle Valo return -ENOMEM; 14107ac9a364SKalle Valo } 14117ac9a364SKalle Valo EXPORT_SYMBOL(il_dbgfs_register); 14127ac9a364SKalle Valo 14137ac9a364SKalle Valo /** 14147ac9a364SKalle Valo * Remove the debugfs files and directories 14157ac9a364SKalle Valo * 14167ac9a364SKalle Valo */ 14177ac9a364SKalle Valo void 14187ac9a364SKalle Valo il_dbgfs_unregister(struct il_priv *il) 14197ac9a364SKalle Valo { 14207ac9a364SKalle Valo if (!il->debugfs_dir) 14217ac9a364SKalle Valo return; 14227ac9a364SKalle Valo 14237ac9a364SKalle Valo debugfs_remove_recursive(il->debugfs_dir); 14247ac9a364SKalle Valo il->debugfs_dir = NULL; 14257ac9a364SKalle Valo } 14267ac9a364SKalle Valo EXPORT_SYMBOL(il_dbgfs_unregister); 1427