1*7ac9a364SKalle Valo /****************************************************************************** 2*7ac9a364SKalle Valo * 3*7ac9a364SKalle Valo * GPL LICENSE SUMMARY 4*7ac9a364SKalle Valo * 5*7ac9a364SKalle Valo * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 6*7ac9a364SKalle Valo * 7*7ac9a364SKalle Valo * This program is free software; you can redistribute it and/or modify 8*7ac9a364SKalle Valo * it under the terms of version 2 of the GNU General Public License as 9*7ac9a364SKalle Valo * published by the Free Software Foundation. 10*7ac9a364SKalle Valo * 11*7ac9a364SKalle Valo * This program is distributed in the hope that it will be useful, but 12*7ac9a364SKalle Valo * WITHOUT ANY WARRANTY; without even the implied warranty of 13*7ac9a364SKalle Valo * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*7ac9a364SKalle Valo * General Public License for more details. 15*7ac9a364SKalle Valo * 16*7ac9a364SKalle Valo * You should have received a copy of the GNU General Public License 17*7ac9a364SKalle Valo * along with this program; if not, write to the Free Software 18*7ac9a364SKalle Valo * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, 19*7ac9a364SKalle Valo * USA 20*7ac9a364SKalle Valo * 21*7ac9a364SKalle Valo * The full GNU General Public License is included in this distribution 22*7ac9a364SKalle Valo * in the file called LICENSE.GPL. 23*7ac9a364SKalle Valo * 24*7ac9a364SKalle Valo * Contact Information: 25*7ac9a364SKalle Valo * Intel Linux Wireless <ilw@linux.intel.com> 26*7ac9a364SKalle Valo * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 27*7ac9a364SKalle Valo *****************************************************************************/ 28*7ac9a364SKalle Valo #include <linux/ieee80211.h> 29*7ac9a364SKalle Valo #include <linux/export.h> 30*7ac9a364SKalle Valo #include <net/mac80211.h> 31*7ac9a364SKalle Valo 32*7ac9a364SKalle Valo #include "common.h" 33*7ac9a364SKalle Valo 34*7ac9a364SKalle Valo static void 35*7ac9a364SKalle Valo il_clear_traffic_stats(struct il_priv *il) 36*7ac9a364SKalle Valo { 37*7ac9a364SKalle Valo memset(&il->tx_stats, 0, sizeof(struct traffic_stats)); 38*7ac9a364SKalle Valo memset(&il->rx_stats, 0, sizeof(struct traffic_stats)); 39*7ac9a364SKalle Valo } 40*7ac9a364SKalle Valo 41*7ac9a364SKalle Valo /* 42*7ac9a364SKalle Valo * il_update_stats function record all the MGMT, CTRL and DATA pkt for 43*7ac9a364SKalle Valo * both TX and Rx . Use debugfs to display the rx/rx_stats 44*7ac9a364SKalle Valo */ 45*7ac9a364SKalle Valo void 46*7ac9a364SKalle Valo il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len) 47*7ac9a364SKalle Valo { 48*7ac9a364SKalle Valo struct traffic_stats *stats; 49*7ac9a364SKalle Valo 50*7ac9a364SKalle Valo if (is_tx) 51*7ac9a364SKalle Valo stats = &il->tx_stats; 52*7ac9a364SKalle Valo else 53*7ac9a364SKalle Valo stats = &il->rx_stats; 54*7ac9a364SKalle Valo 55*7ac9a364SKalle Valo if (ieee80211_is_mgmt(fc)) { 56*7ac9a364SKalle Valo switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { 57*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): 58*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_ASSOC_REQ]++; 59*7ac9a364SKalle Valo break; 60*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): 61*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_ASSOC_RESP]++; 62*7ac9a364SKalle Valo break; 63*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): 64*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_REASSOC_REQ]++; 65*7ac9a364SKalle Valo break; 66*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): 67*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_REASSOC_RESP]++; 68*7ac9a364SKalle Valo break; 69*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): 70*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_PROBE_REQ]++; 71*7ac9a364SKalle Valo break; 72*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): 73*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_PROBE_RESP]++; 74*7ac9a364SKalle Valo break; 75*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_BEACON): 76*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_BEACON]++; 77*7ac9a364SKalle Valo break; 78*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_ATIM): 79*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_ATIM]++; 80*7ac9a364SKalle Valo break; 81*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_DISASSOC): 82*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_DISASSOC]++; 83*7ac9a364SKalle Valo break; 84*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_AUTH): 85*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_AUTH]++; 86*7ac9a364SKalle Valo break; 87*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_DEAUTH): 88*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_DEAUTH]++; 89*7ac9a364SKalle Valo break; 90*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_ACTION): 91*7ac9a364SKalle Valo stats->mgmt[MANAGEMENT_ACTION]++; 92*7ac9a364SKalle Valo break; 93*7ac9a364SKalle Valo } 94*7ac9a364SKalle Valo } else if (ieee80211_is_ctl(fc)) { 95*7ac9a364SKalle Valo switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { 96*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_BACK_REQ): 97*7ac9a364SKalle Valo stats->ctrl[CONTROL_BACK_REQ]++; 98*7ac9a364SKalle Valo break; 99*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_BACK): 100*7ac9a364SKalle Valo stats->ctrl[CONTROL_BACK]++; 101*7ac9a364SKalle Valo break; 102*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_PSPOLL): 103*7ac9a364SKalle Valo stats->ctrl[CONTROL_PSPOLL]++; 104*7ac9a364SKalle Valo break; 105*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_RTS): 106*7ac9a364SKalle Valo stats->ctrl[CONTROL_RTS]++; 107*7ac9a364SKalle Valo break; 108*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_CTS): 109*7ac9a364SKalle Valo stats->ctrl[CONTROL_CTS]++; 110*7ac9a364SKalle Valo break; 111*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_ACK): 112*7ac9a364SKalle Valo stats->ctrl[CONTROL_ACK]++; 113*7ac9a364SKalle Valo break; 114*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_CFEND): 115*7ac9a364SKalle Valo stats->ctrl[CONTROL_CFEND]++; 116*7ac9a364SKalle Valo break; 117*7ac9a364SKalle Valo case cpu_to_le16(IEEE80211_STYPE_CFENDACK): 118*7ac9a364SKalle Valo stats->ctrl[CONTROL_CFENDACK]++; 119*7ac9a364SKalle Valo break; 120*7ac9a364SKalle Valo } 121*7ac9a364SKalle Valo } else { 122*7ac9a364SKalle Valo /* data */ 123*7ac9a364SKalle Valo stats->data_cnt++; 124*7ac9a364SKalle Valo stats->data_bytes += len; 125*7ac9a364SKalle Valo } 126*7ac9a364SKalle Valo } 127*7ac9a364SKalle Valo EXPORT_SYMBOL(il_update_stats); 128*7ac9a364SKalle Valo 129*7ac9a364SKalle Valo /* create and remove of files */ 130*7ac9a364SKalle Valo #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ 131*7ac9a364SKalle Valo if (!debugfs_create_file(#name, mode, parent, il, \ 132*7ac9a364SKalle Valo &il_dbgfs_##name##_ops)) \ 133*7ac9a364SKalle Valo goto err; \ 134*7ac9a364SKalle Valo } while (0) 135*7ac9a364SKalle Valo 136*7ac9a364SKalle Valo #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ 137*7ac9a364SKalle Valo struct dentry *__tmp; \ 138*7ac9a364SKalle Valo __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ 139*7ac9a364SKalle Valo parent, ptr); \ 140*7ac9a364SKalle Valo if (IS_ERR(__tmp) || !__tmp) \ 141*7ac9a364SKalle Valo goto err; \ 142*7ac9a364SKalle Valo } while (0) 143*7ac9a364SKalle Valo 144*7ac9a364SKalle Valo #define DEBUGFS_ADD_X32(name, parent, ptr) do { \ 145*7ac9a364SKalle Valo struct dentry *__tmp; \ 146*7ac9a364SKalle Valo __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \ 147*7ac9a364SKalle Valo parent, ptr); \ 148*7ac9a364SKalle Valo if (IS_ERR(__tmp) || !__tmp) \ 149*7ac9a364SKalle Valo goto err; \ 150*7ac9a364SKalle Valo } while (0) 151*7ac9a364SKalle Valo 152*7ac9a364SKalle Valo /* file operation */ 153*7ac9a364SKalle Valo #define DEBUGFS_READ_FUNC(name) \ 154*7ac9a364SKalle Valo static ssize_t il_dbgfs_##name##_read(struct file *file, \ 155*7ac9a364SKalle Valo char __user *user_buf, \ 156*7ac9a364SKalle Valo size_t count, loff_t *ppos); 157*7ac9a364SKalle Valo 158*7ac9a364SKalle Valo #define DEBUGFS_WRITE_FUNC(name) \ 159*7ac9a364SKalle Valo static ssize_t il_dbgfs_##name##_write(struct file *file, \ 160*7ac9a364SKalle Valo const char __user *user_buf, \ 161*7ac9a364SKalle Valo size_t count, loff_t *ppos); 162*7ac9a364SKalle Valo 163*7ac9a364SKalle Valo 164*7ac9a364SKalle Valo #define DEBUGFS_READ_FILE_OPS(name) \ 165*7ac9a364SKalle Valo DEBUGFS_READ_FUNC(name); \ 166*7ac9a364SKalle Valo static const struct file_operations il_dbgfs_##name##_ops = { \ 167*7ac9a364SKalle Valo .read = il_dbgfs_##name##_read, \ 168*7ac9a364SKalle Valo .open = simple_open, \ 169*7ac9a364SKalle Valo .llseek = generic_file_llseek, \ 170*7ac9a364SKalle Valo }; 171*7ac9a364SKalle Valo 172*7ac9a364SKalle Valo #define DEBUGFS_WRITE_FILE_OPS(name) \ 173*7ac9a364SKalle Valo DEBUGFS_WRITE_FUNC(name); \ 174*7ac9a364SKalle Valo static const struct file_operations il_dbgfs_##name##_ops = { \ 175*7ac9a364SKalle Valo .write = il_dbgfs_##name##_write, \ 176*7ac9a364SKalle Valo .open = simple_open, \ 177*7ac9a364SKalle Valo .llseek = generic_file_llseek, \ 178*7ac9a364SKalle Valo }; 179*7ac9a364SKalle Valo 180*7ac9a364SKalle Valo #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ 181*7ac9a364SKalle Valo DEBUGFS_READ_FUNC(name); \ 182*7ac9a364SKalle Valo DEBUGFS_WRITE_FUNC(name); \ 183*7ac9a364SKalle Valo static const struct file_operations il_dbgfs_##name##_ops = { \ 184*7ac9a364SKalle Valo .write = il_dbgfs_##name##_write, \ 185*7ac9a364SKalle Valo .read = il_dbgfs_##name##_read, \ 186*7ac9a364SKalle Valo .open = simple_open, \ 187*7ac9a364SKalle Valo .llseek = generic_file_llseek, \ 188*7ac9a364SKalle Valo }; 189*7ac9a364SKalle Valo 190*7ac9a364SKalle Valo static const char * 191*7ac9a364SKalle Valo il_get_mgmt_string(int cmd) 192*7ac9a364SKalle Valo { 193*7ac9a364SKalle Valo switch (cmd) { 194*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_ASSOC_REQ); 195*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_ASSOC_RESP); 196*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_REASSOC_REQ); 197*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_REASSOC_RESP); 198*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_PROBE_REQ); 199*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_PROBE_RESP); 200*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_BEACON); 201*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_ATIM); 202*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_DISASSOC); 203*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_AUTH); 204*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_DEAUTH); 205*7ac9a364SKalle Valo IL_CMD(MANAGEMENT_ACTION); 206*7ac9a364SKalle Valo default: 207*7ac9a364SKalle Valo return "UNKNOWN"; 208*7ac9a364SKalle Valo 209*7ac9a364SKalle Valo } 210*7ac9a364SKalle Valo } 211*7ac9a364SKalle Valo 212*7ac9a364SKalle Valo static const char * 213*7ac9a364SKalle Valo il_get_ctrl_string(int cmd) 214*7ac9a364SKalle Valo { 215*7ac9a364SKalle Valo switch (cmd) { 216*7ac9a364SKalle Valo IL_CMD(CONTROL_BACK_REQ); 217*7ac9a364SKalle Valo IL_CMD(CONTROL_BACK); 218*7ac9a364SKalle Valo IL_CMD(CONTROL_PSPOLL); 219*7ac9a364SKalle Valo IL_CMD(CONTROL_RTS); 220*7ac9a364SKalle Valo IL_CMD(CONTROL_CTS); 221*7ac9a364SKalle Valo IL_CMD(CONTROL_ACK); 222*7ac9a364SKalle Valo IL_CMD(CONTROL_CFEND); 223*7ac9a364SKalle Valo IL_CMD(CONTROL_CFENDACK); 224*7ac9a364SKalle Valo default: 225*7ac9a364SKalle Valo return "UNKNOWN"; 226*7ac9a364SKalle Valo 227*7ac9a364SKalle Valo } 228*7ac9a364SKalle Valo } 229*7ac9a364SKalle Valo 230*7ac9a364SKalle Valo static ssize_t 231*7ac9a364SKalle Valo il_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count, 232*7ac9a364SKalle Valo loff_t *ppos) 233*7ac9a364SKalle Valo { 234*7ac9a364SKalle Valo 235*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 236*7ac9a364SKalle Valo char *buf; 237*7ac9a364SKalle Valo int pos = 0; 238*7ac9a364SKalle Valo 239*7ac9a364SKalle Valo int cnt; 240*7ac9a364SKalle Valo ssize_t ret; 241*7ac9a364SKalle Valo const size_t bufsz = 242*7ac9a364SKalle Valo 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); 243*7ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 244*7ac9a364SKalle Valo if (!buf) 245*7ac9a364SKalle Valo return -ENOMEM; 246*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); 247*7ac9a364SKalle Valo for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { 248*7ac9a364SKalle Valo pos += 249*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 250*7ac9a364SKalle Valo il_get_mgmt_string(cnt), il->tx_stats.mgmt[cnt]); 251*7ac9a364SKalle Valo } 252*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); 253*7ac9a364SKalle Valo for (cnt = 0; cnt < CONTROL_MAX; cnt++) { 254*7ac9a364SKalle Valo pos += 255*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 256*7ac9a364SKalle Valo il_get_ctrl_string(cnt), il->tx_stats.ctrl[cnt]); 257*7ac9a364SKalle Valo } 258*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); 259*7ac9a364SKalle Valo pos += 260*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", 261*7ac9a364SKalle Valo il->tx_stats.data_cnt); 262*7ac9a364SKalle Valo pos += 263*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", 264*7ac9a364SKalle Valo il->tx_stats.data_bytes); 265*7ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 266*7ac9a364SKalle Valo kfree(buf); 267*7ac9a364SKalle Valo return ret; 268*7ac9a364SKalle Valo } 269*7ac9a364SKalle Valo 270*7ac9a364SKalle Valo static ssize_t 271*7ac9a364SKalle Valo il_dbgfs_clear_traffic_stats_write(struct file *file, 272*7ac9a364SKalle Valo const char __user *user_buf, size_t count, 273*7ac9a364SKalle Valo loff_t *ppos) 274*7ac9a364SKalle Valo { 275*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 276*7ac9a364SKalle Valo u32 clear_flag; 277*7ac9a364SKalle Valo char buf[8]; 278*7ac9a364SKalle Valo int buf_size; 279*7ac9a364SKalle Valo 280*7ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 281*7ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 282*7ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 283*7ac9a364SKalle Valo return -EFAULT; 284*7ac9a364SKalle Valo if (sscanf(buf, "%x", &clear_flag) != 1) 285*7ac9a364SKalle Valo return -EFAULT; 286*7ac9a364SKalle Valo il_clear_traffic_stats(il); 287*7ac9a364SKalle Valo 288*7ac9a364SKalle Valo return count; 289*7ac9a364SKalle Valo } 290*7ac9a364SKalle Valo 291*7ac9a364SKalle Valo static ssize_t 292*7ac9a364SKalle Valo il_dbgfs_rx_stats_read(struct file *file, char __user *user_buf, size_t count, 293*7ac9a364SKalle Valo loff_t *ppos) 294*7ac9a364SKalle Valo { 295*7ac9a364SKalle Valo 296*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 297*7ac9a364SKalle Valo char *buf; 298*7ac9a364SKalle Valo int pos = 0; 299*7ac9a364SKalle Valo int cnt; 300*7ac9a364SKalle Valo ssize_t ret; 301*7ac9a364SKalle Valo const size_t bufsz = 302*7ac9a364SKalle Valo 100 + sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); 303*7ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 304*7ac9a364SKalle Valo if (!buf) 305*7ac9a364SKalle Valo return -ENOMEM; 306*7ac9a364SKalle Valo 307*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); 308*7ac9a364SKalle Valo for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { 309*7ac9a364SKalle Valo pos += 310*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 311*7ac9a364SKalle Valo il_get_mgmt_string(cnt), il->rx_stats.mgmt[cnt]); 312*7ac9a364SKalle Valo } 313*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); 314*7ac9a364SKalle Valo for (cnt = 0; cnt < CONTROL_MAX; cnt++) { 315*7ac9a364SKalle Valo pos += 316*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\t%25s\t\t: %u\n", 317*7ac9a364SKalle Valo il_get_ctrl_string(cnt), il->rx_stats.ctrl[cnt]); 318*7ac9a364SKalle Valo } 319*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); 320*7ac9a364SKalle Valo pos += 321*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", 322*7ac9a364SKalle Valo il->rx_stats.data_cnt); 323*7ac9a364SKalle Valo pos += 324*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", 325*7ac9a364SKalle Valo il->rx_stats.data_bytes); 326*7ac9a364SKalle Valo 327*7ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 328*7ac9a364SKalle Valo kfree(buf); 329*7ac9a364SKalle Valo return ret; 330*7ac9a364SKalle Valo } 331*7ac9a364SKalle Valo 332*7ac9a364SKalle Valo #define BYTE1_MASK 0x000000ff; 333*7ac9a364SKalle Valo #define BYTE2_MASK 0x0000ffff; 334*7ac9a364SKalle Valo #define BYTE3_MASK 0x00ffffff; 335*7ac9a364SKalle Valo static ssize_t 336*7ac9a364SKalle Valo il_dbgfs_sram_read(struct file *file, char __user *user_buf, size_t count, 337*7ac9a364SKalle Valo loff_t *ppos) 338*7ac9a364SKalle Valo { 339*7ac9a364SKalle Valo u32 val; 340*7ac9a364SKalle Valo char *buf; 341*7ac9a364SKalle Valo ssize_t ret; 342*7ac9a364SKalle Valo int i; 343*7ac9a364SKalle Valo int pos = 0; 344*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 345*7ac9a364SKalle Valo size_t bufsz; 346*7ac9a364SKalle Valo 347*7ac9a364SKalle Valo /* default is to dump the entire data segment */ 348*7ac9a364SKalle Valo if (!il->dbgfs_sram_offset && !il->dbgfs_sram_len) { 349*7ac9a364SKalle Valo il->dbgfs_sram_offset = 0x800000; 350*7ac9a364SKalle Valo if (il->ucode_type == UCODE_INIT) 351*7ac9a364SKalle Valo il->dbgfs_sram_len = il->ucode_init_data.len; 352*7ac9a364SKalle Valo else 353*7ac9a364SKalle Valo il->dbgfs_sram_len = il->ucode_data.len; 354*7ac9a364SKalle Valo } 355*7ac9a364SKalle Valo bufsz = 30 + il->dbgfs_sram_len * sizeof(char) * 10; 356*7ac9a364SKalle Valo buf = kmalloc(bufsz, GFP_KERNEL); 357*7ac9a364SKalle Valo if (!buf) 358*7ac9a364SKalle Valo return -ENOMEM; 359*7ac9a364SKalle Valo pos += 360*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", 361*7ac9a364SKalle Valo il->dbgfs_sram_len); 362*7ac9a364SKalle Valo pos += 363*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", 364*7ac9a364SKalle Valo il->dbgfs_sram_offset); 365*7ac9a364SKalle Valo for (i = il->dbgfs_sram_len; i > 0; i -= 4) { 366*7ac9a364SKalle Valo val = 367*7ac9a364SKalle Valo il_read_targ_mem(il, 368*7ac9a364SKalle Valo il->dbgfs_sram_offset + 369*7ac9a364SKalle Valo il->dbgfs_sram_len - i); 370*7ac9a364SKalle Valo if (i < 4) { 371*7ac9a364SKalle Valo switch (i) { 372*7ac9a364SKalle Valo case 1: 373*7ac9a364SKalle Valo val &= BYTE1_MASK; 374*7ac9a364SKalle Valo break; 375*7ac9a364SKalle Valo case 2: 376*7ac9a364SKalle Valo val &= BYTE2_MASK; 377*7ac9a364SKalle Valo break; 378*7ac9a364SKalle Valo case 3: 379*7ac9a364SKalle Valo val &= BYTE3_MASK; 380*7ac9a364SKalle Valo break; 381*7ac9a364SKalle Valo } 382*7ac9a364SKalle Valo } 383*7ac9a364SKalle Valo if (!(i % 16)) 384*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 385*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); 386*7ac9a364SKalle Valo } 387*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 388*7ac9a364SKalle Valo 389*7ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 390*7ac9a364SKalle Valo kfree(buf); 391*7ac9a364SKalle Valo return ret; 392*7ac9a364SKalle Valo } 393*7ac9a364SKalle Valo 394*7ac9a364SKalle Valo static ssize_t 395*7ac9a364SKalle Valo il_dbgfs_sram_write(struct file *file, const char __user *user_buf, 396*7ac9a364SKalle Valo size_t count, loff_t *ppos) 397*7ac9a364SKalle Valo { 398*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 399*7ac9a364SKalle Valo char buf[64]; 400*7ac9a364SKalle Valo int buf_size; 401*7ac9a364SKalle Valo u32 offset, len; 402*7ac9a364SKalle Valo 403*7ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 404*7ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 405*7ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 406*7ac9a364SKalle Valo return -EFAULT; 407*7ac9a364SKalle Valo 408*7ac9a364SKalle Valo if (sscanf(buf, "%x,%x", &offset, &len) == 2) { 409*7ac9a364SKalle Valo il->dbgfs_sram_offset = offset; 410*7ac9a364SKalle Valo il->dbgfs_sram_len = len; 411*7ac9a364SKalle Valo } else { 412*7ac9a364SKalle Valo il->dbgfs_sram_offset = 0; 413*7ac9a364SKalle Valo il->dbgfs_sram_len = 0; 414*7ac9a364SKalle Valo } 415*7ac9a364SKalle Valo 416*7ac9a364SKalle Valo return count; 417*7ac9a364SKalle Valo } 418*7ac9a364SKalle Valo 419*7ac9a364SKalle Valo static ssize_t 420*7ac9a364SKalle Valo il_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count, 421*7ac9a364SKalle Valo loff_t *ppos) 422*7ac9a364SKalle Valo { 423*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 424*7ac9a364SKalle Valo struct il_station_entry *station; 425*7ac9a364SKalle Valo int max_sta = il->hw_params.max_stations; 426*7ac9a364SKalle Valo char *buf; 427*7ac9a364SKalle Valo int i, j, pos = 0; 428*7ac9a364SKalle Valo ssize_t ret; 429*7ac9a364SKalle Valo /* Add 30 for initial string */ 430*7ac9a364SKalle Valo const size_t bufsz = 30 + sizeof(char) * 500 * (il->num_stations); 431*7ac9a364SKalle Valo 432*7ac9a364SKalle Valo buf = kmalloc(bufsz, GFP_KERNEL); 433*7ac9a364SKalle Valo if (!buf) 434*7ac9a364SKalle Valo return -ENOMEM; 435*7ac9a364SKalle Valo 436*7ac9a364SKalle Valo pos += 437*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", 438*7ac9a364SKalle Valo il->num_stations); 439*7ac9a364SKalle Valo 440*7ac9a364SKalle Valo for (i = 0; i < max_sta; i++) { 441*7ac9a364SKalle Valo station = &il->stations[i]; 442*7ac9a364SKalle Valo if (!station->used) 443*7ac9a364SKalle Valo continue; 444*7ac9a364SKalle Valo pos += 445*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 446*7ac9a364SKalle Valo "station %d - addr: %pM, flags: %#x\n", i, 447*7ac9a364SKalle Valo station->sta.sta.addr, 448*7ac9a364SKalle Valo station->sta.station_flags_msk); 449*7ac9a364SKalle Valo pos += 450*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 451*7ac9a364SKalle Valo "TID\tseq_num\ttxq_id\tframes\ttfds\t"); 452*7ac9a364SKalle Valo pos += 453*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 454*7ac9a364SKalle Valo "start_idx\tbitmap\t\t\trate_n_flags\n"); 455*7ac9a364SKalle Valo 456*7ac9a364SKalle Valo for (j = 0; j < MAX_TID_COUNT; j++) { 457*7ac9a364SKalle Valo pos += 458*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 459*7ac9a364SKalle Valo "%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x", 460*7ac9a364SKalle Valo j, station->tid[j].seq_number, 461*7ac9a364SKalle Valo station->tid[j].agg.txq_id, 462*7ac9a364SKalle Valo station->tid[j].agg.frame_count, 463*7ac9a364SKalle Valo station->tid[j].tfds_in_queue, 464*7ac9a364SKalle Valo station->tid[j].agg.start_idx, 465*7ac9a364SKalle Valo station->tid[j].agg.bitmap, 466*7ac9a364SKalle Valo station->tid[j].agg.rate_n_flags); 467*7ac9a364SKalle Valo 468*7ac9a364SKalle Valo if (station->tid[j].agg.wait_for_ba) 469*7ac9a364SKalle Valo pos += 470*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 471*7ac9a364SKalle Valo " - waitforba"); 472*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 473*7ac9a364SKalle Valo } 474*7ac9a364SKalle Valo 475*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 476*7ac9a364SKalle Valo } 477*7ac9a364SKalle Valo 478*7ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 479*7ac9a364SKalle Valo kfree(buf); 480*7ac9a364SKalle Valo return ret; 481*7ac9a364SKalle Valo } 482*7ac9a364SKalle Valo 483*7ac9a364SKalle Valo static ssize_t 484*7ac9a364SKalle Valo il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count, 485*7ac9a364SKalle Valo loff_t *ppos) 486*7ac9a364SKalle Valo { 487*7ac9a364SKalle Valo ssize_t ret; 488*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 489*7ac9a364SKalle Valo int pos = 0, ofs = 0, buf_size = 0; 490*7ac9a364SKalle Valo const u8 *ptr; 491*7ac9a364SKalle Valo char *buf; 492*7ac9a364SKalle Valo u16 eeprom_ver; 493*7ac9a364SKalle Valo size_t eeprom_len = il->cfg->eeprom_size; 494*7ac9a364SKalle Valo buf_size = 4 * eeprom_len + 256; 495*7ac9a364SKalle Valo 496*7ac9a364SKalle Valo if (eeprom_len % 16) { 497*7ac9a364SKalle Valo IL_ERR("NVM size is not multiple of 16.\n"); 498*7ac9a364SKalle Valo return -ENODATA; 499*7ac9a364SKalle Valo } 500*7ac9a364SKalle Valo 501*7ac9a364SKalle Valo ptr = il->eeprom; 502*7ac9a364SKalle Valo if (!ptr) { 503*7ac9a364SKalle Valo IL_ERR("Invalid EEPROM memory\n"); 504*7ac9a364SKalle Valo return -ENOMEM; 505*7ac9a364SKalle Valo } 506*7ac9a364SKalle Valo 507*7ac9a364SKalle Valo /* 4 characters for byte 0xYY */ 508*7ac9a364SKalle Valo buf = kzalloc(buf_size, GFP_KERNEL); 509*7ac9a364SKalle Valo if (!buf) { 510*7ac9a364SKalle Valo IL_ERR("Can not allocate Buffer\n"); 511*7ac9a364SKalle Valo return -ENOMEM; 512*7ac9a364SKalle Valo } 513*7ac9a364SKalle Valo eeprom_ver = il_eeprom_query16(il, EEPROM_VERSION); 514*7ac9a364SKalle Valo pos += 515*7ac9a364SKalle Valo scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n", 516*7ac9a364SKalle Valo eeprom_ver); 517*7ac9a364SKalle Valo for (ofs = 0; ofs < eeprom_len; ofs += 16) { 518*7ac9a364SKalle Valo pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n", 519*7ac9a364SKalle Valo ofs, ptr + ofs); 520*7ac9a364SKalle Valo } 521*7ac9a364SKalle Valo 522*7ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 523*7ac9a364SKalle Valo kfree(buf); 524*7ac9a364SKalle Valo return ret; 525*7ac9a364SKalle Valo } 526*7ac9a364SKalle Valo 527*7ac9a364SKalle Valo static ssize_t 528*7ac9a364SKalle Valo il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, 529*7ac9a364SKalle Valo loff_t *ppos) 530*7ac9a364SKalle Valo { 531*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 532*7ac9a364SKalle Valo struct ieee80211_channel *channels = NULL; 533*7ac9a364SKalle Valo const struct ieee80211_supported_band *supp_band = NULL; 534*7ac9a364SKalle Valo int pos = 0, i, bufsz = PAGE_SIZE; 535*7ac9a364SKalle Valo char *buf; 536*7ac9a364SKalle Valo ssize_t ret; 537*7ac9a364SKalle Valo 538*7ac9a364SKalle Valo if (!test_bit(S_GEO_CONFIGURED, &il->status)) 539*7ac9a364SKalle Valo return -EAGAIN; 540*7ac9a364SKalle Valo 541*7ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 542*7ac9a364SKalle Valo if (!buf) { 543*7ac9a364SKalle Valo IL_ERR("Can not allocate Buffer\n"); 544*7ac9a364SKalle Valo return -ENOMEM; 545*7ac9a364SKalle Valo } 546*7ac9a364SKalle Valo 547*7ac9a364SKalle Valo supp_band = il_get_hw_mode(il, IEEE80211_BAND_2GHZ); 548*7ac9a364SKalle Valo if (supp_band) { 549*7ac9a364SKalle Valo channels = supp_band->channels; 550*7ac9a364SKalle Valo 551*7ac9a364SKalle Valo pos += 552*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 553*7ac9a364SKalle Valo "Displaying %d channels in 2.4GHz band 802.11bg):\n", 554*7ac9a364SKalle Valo supp_band->n_channels); 555*7ac9a364SKalle Valo 556*7ac9a364SKalle Valo for (i = 0; i < supp_band->n_channels; i++) 557*7ac9a364SKalle Valo pos += 558*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 559*7ac9a364SKalle Valo "%d: %ddBm: BSS%s%s, %s.\n", 560*7ac9a364SKalle Valo channels[i].hw_value, 561*7ac9a364SKalle Valo channels[i].max_power, 562*7ac9a364SKalle Valo channels[i]. 563*7ac9a364SKalle Valo flags & IEEE80211_CHAN_RADAR ? 564*7ac9a364SKalle Valo " (IEEE 802.11h required)" : "", 565*7ac9a364SKalle Valo ((channels[i]. 566*7ac9a364SKalle Valo flags & IEEE80211_CHAN_NO_IR) || 567*7ac9a364SKalle Valo (channels[i]. 568*7ac9a364SKalle Valo flags & IEEE80211_CHAN_RADAR)) ? "" : 569*7ac9a364SKalle Valo ", IBSS", 570*7ac9a364SKalle Valo channels[i]. 571*7ac9a364SKalle Valo flags & IEEE80211_CHAN_NO_IR ? 572*7ac9a364SKalle Valo "passive only" : "active/passive"); 573*7ac9a364SKalle Valo } 574*7ac9a364SKalle Valo supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ); 575*7ac9a364SKalle Valo if (supp_band) { 576*7ac9a364SKalle Valo channels = supp_band->channels; 577*7ac9a364SKalle Valo 578*7ac9a364SKalle Valo pos += 579*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 580*7ac9a364SKalle Valo "Displaying %d channels in 5.2GHz band (802.11a)\n", 581*7ac9a364SKalle Valo supp_band->n_channels); 582*7ac9a364SKalle Valo 583*7ac9a364SKalle Valo for (i = 0; i < supp_band->n_channels; i++) 584*7ac9a364SKalle Valo pos += 585*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 586*7ac9a364SKalle Valo "%d: %ddBm: BSS%s%s, %s.\n", 587*7ac9a364SKalle Valo channels[i].hw_value, 588*7ac9a364SKalle Valo channels[i].max_power, 589*7ac9a364SKalle Valo channels[i]. 590*7ac9a364SKalle Valo flags & IEEE80211_CHAN_RADAR ? 591*7ac9a364SKalle Valo " (IEEE 802.11h required)" : "", 592*7ac9a364SKalle Valo ((channels[i]. 593*7ac9a364SKalle Valo flags & IEEE80211_CHAN_NO_IR) || 594*7ac9a364SKalle Valo (channels[i]. 595*7ac9a364SKalle Valo flags & IEEE80211_CHAN_RADAR)) ? "" : 596*7ac9a364SKalle Valo ", IBSS", 597*7ac9a364SKalle Valo channels[i]. 598*7ac9a364SKalle Valo flags & IEEE80211_CHAN_NO_IR ? 599*7ac9a364SKalle Valo "passive only" : "active/passive"); 600*7ac9a364SKalle Valo } 601*7ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 602*7ac9a364SKalle Valo kfree(buf); 603*7ac9a364SKalle Valo return ret; 604*7ac9a364SKalle Valo } 605*7ac9a364SKalle Valo 606*7ac9a364SKalle Valo static ssize_t 607*7ac9a364SKalle Valo il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count, 608*7ac9a364SKalle Valo loff_t *ppos) 609*7ac9a364SKalle Valo { 610*7ac9a364SKalle Valo 611*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 612*7ac9a364SKalle Valo char buf[512]; 613*7ac9a364SKalle Valo int pos = 0; 614*7ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 615*7ac9a364SKalle Valo 616*7ac9a364SKalle Valo pos += 617*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_HCMD_ACTIVE:\t %d\n", 618*7ac9a364SKalle Valo test_bit(S_HCMD_ACTIVE, &il->status)); 619*7ac9a364SKalle Valo pos += 620*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n", 621*7ac9a364SKalle Valo test_bit(S_INT_ENABLED, &il->status)); 622*7ac9a364SKalle Valo pos += 623*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_RFKILL:\t %d\n", 624*7ac9a364SKalle Valo test_bit(S_RFKILL, &il->status)); 625*7ac9a364SKalle Valo pos += 626*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n", 627*7ac9a364SKalle Valo test_bit(S_CT_KILL, &il->status)); 628*7ac9a364SKalle Valo pos += 629*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_INIT:\t\t %d\n", 630*7ac9a364SKalle Valo test_bit(S_INIT, &il->status)); 631*7ac9a364SKalle Valo pos += 632*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_ALIVE:\t\t %d\n", 633*7ac9a364SKalle Valo test_bit(S_ALIVE, &il->status)); 634*7ac9a364SKalle Valo pos += 635*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_READY:\t\t %d\n", 636*7ac9a364SKalle Valo test_bit(S_READY, &il->status)); 637*7ac9a364SKalle Valo pos += 638*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_TEMPERATURE:\t %d\n", 639*7ac9a364SKalle Valo test_bit(S_TEMPERATURE, &il->status)); 640*7ac9a364SKalle Valo pos += 641*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_GEO_CONFIGURED:\t %d\n", 642*7ac9a364SKalle Valo test_bit(S_GEO_CONFIGURED, &il->status)); 643*7ac9a364SKalle Valo pos += 644*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_EXIT_PENDING:\t %d\n", 645*7ac9a364SKalle Valo test_bit(S_EXIT_PENDING, &il->status)); 646*7ac9a364SKalle Valo pos += 647*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_STATS:\t %d\n", 648*7ac9a364SKalle Valo test_bit(S_STATS, &il->status)); 649*7ac9a364SKalle Valo pos += 650*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_SCANNING:\t %d\n", 651*7ac9a364SKalle Valo test_bit(S_SCANNING, &il->status)); 652*7ac9a364SKalle Valo pos += 653*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_SCAN_ABORTING:\t %d\n", 654*7ac9a364SKalle Valo test_bit(S_SCAN_ABORTING, &il->status)); 655*7ac9a364SKalle Valo pos += 656*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_SCAN_HW:\t\t %d\n", 657*7ac9a364SKalle Valo test_bit(S_SCAN_HW, &il->status)); 658*7ac9a364SKalle Valo pos += 659*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_POWER_PMI:\t %d\n", 660*7ac9a364SKalle Valo test_bit(S_POWER_PMI, &il->status)); 661*7ac9a364SKalle Valo pos += 662*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "S_FW_ERROR:\t %d\n", 663*7ac9a364SKalle Valo test_bit(S_FW_ERROR, &il->status)); 664*7ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 665*7ac9a364SKalle Valo } 666*7ac9a364SKalle Valo 667*7ac9a364SKalle Valo static ssize_t 668*7ac9a364SKalle Valo il_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count, 669*7ac9a364SKalle Valo loff_t *ppos) 670*7ac9a364SKalle Valo { 671*7ac9a364SKalle Valo 672*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 673*7ac9a364SKalle Valo int pos = 0; 674*7ac9a364SKalle Valo int cnt = 0; 675*7ac9a364SKalle Valo char *buf; 676*7ac9a364SKalle Valo int bufsz = 24 * 64; /* 24 items * 64 char per item */ 677*7ac9a364SKalle Valo ssize_t ret; 678*7ac9a364SKalle Valo 679*7ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 680*7ac9a364SKalle Valo if (!buf) { 681*7ac9a364SKalle Valo IL_ERR("Can not allocate Buffer\n"); 682*7ac9a364SKalle Valo return -ENOMEM; 683*7ac9a364SKalle Valo } 684*7ac9a364SKalle Valo 685*7ac9a364SKalle Valo pos += 686*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Interrupt Statistics Report:\n"); 687*7ac9a364SKalle Valo 688*7ac9a364SKalle Valo pos += 689*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", 690*7ac9a364SKalle Valo il->isr_stats.hw); 691*7ac9a364SKalle Valo pos += 692*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", 693*7ac9a364SKalle Valo il->isr_stats.sw); 694*7ac9a364SKalle Valo if (il->isr_stats.sw || il->isr_stats.hw) { 695*7ac9a364SKalle Valo pos += 696*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 697*7ac9a364SKalle Valo "\tLast Restarting Code: 0x%X\n", 698*7ac9a364SKalle Valo il->isr_stats.err_code); 699*7ac9a364SKalle Valo } 700*7ac9a364SKalle Valo #ifdef CONFIG_IWLEGACY_DEBUG 701*7ac9a364SKalle Valo pos += 702*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", 703*7ac9a364SKalle Valo il->isr_stats.sch); 704*7ac9a364SKalle Valo pos += 705*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", 706*7ac9a364SKalle Valo il->isr_stats.alive); 707*7ac9a364SKalle Valo #endif 708*7ac9a364SKalle Valo pos += 709*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 710*7ac9a364SKalle Valo "HW RF KILL switch toggled:\t %u\n", 711*7ac9a364SKalle Valo il->isr_stats.rfkill); 712*7ac9a364SKalle Valo 713*7ac9a364SKalle Valo pos += 714*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", 715*7ac9a364SKalle Valo il->isr_stats.ctkill); 716*7ac9a364SKalle Valo 717*7ac9a364SKalle Valo pos += 718*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", 719*7ac9a364SKalle Valo il->isr_stats.wakeup); 720*7ac9a364SKalle Valo 721*7ac9a364SKalle Valo pos += 722*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Rx command responses:\t\t %u\n", 723*7ac9a364SKalle Valo il->isr_stats.rx); 724*7ac9a364SKalle Valo for (cnt = 0; cnt < IL_CN_MAX; cnt++) { 725*7ac9a364SKalle Valo if (il->isr_stats.handlers[cnt] > 0) 726*7ac9a364SKalle Valo pos += 727*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 728*7ac9a364SKalle Valo "\tRx handler[%36s]:\t\t %u\n", 729*7ac9a364SKalle Valo il_get_cmd_string(cnt), 730*7ac9a364SKalle Valo il->isr_stats.handlers[cnt]); 731*7ac9a364SKalle Valo } 732*7ac9a364SKalle Valo 733*7ac9a364SKalle Valo pos += 734*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", 735*7ac9a364SKalle Valo il->isr_stats.tx); 736*7ac9a364SKalle Valo 737*7ac9a364SKalle Valo pos += 738*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", 739*7ac9a364SKalle Valo il->isr_stats.unhandled); 740*7ac9a364SKalle Valo 741*7ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 742*7ac9a364SKalle Valo kfree(buf); 743*7ac9a364SKalle Valo return ret; 744*7ac9a364SKalle Valo } 745*7ac9a364SKalle Valo 746*7ac9a364SKalle Valo static ssize_t 747*7ac9a364SKalle Valo il_dbgfs_interrupt_write(struct file *file, const char __user *user_buf, 748*7ac9a364SKalle Valo size_t count, loff_t *ppos) 749*7ac9a364SKalle Valo { 750*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 751*7ac9a364SKalle Valo char buf[8]; 752*7ac9a364SKalle Valo int buf_size; 753*7ac9a364SKalle Valo u32 reset_flag; 754*7ac9a364SKalle Valo 755*7ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 756*7ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 757*7ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 758*7ac9a364SKalle Valo return -EFAULT; 759*7ac9a364SKalle Valo if (sscanf(buf, "%x", &reset_flag) != 1) 760*7ac9a364SKalle Valo return -EFAULT; 761*7ac9a364SKalle Valo if (reset_flag == 0) 762*7ac9a364SKalle Valo il_clear_isr_stats(il); 763*7ac9a364SKalle Valo 764*7ac9a364SKalle Valo return count; 765*7ac9a364SKalle Valo } 766*7ac9a364SKalle Valo 767*7ac9a364SKalle Valo static ssize_t 768*7ac9a364SKalle Valo il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count, 769*7ac9a364SKalle Valo loff_t *ppos) 770*7ac9a364SKalle Valo { 771*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 772*7ac9a364SKalle Valo int pos = 0, i; 773*7ac9a364SKalle Valo char buf[256]; 774*7ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 775*7ac9a364SKalle Valo 776*7ac9a364SKalle Valo for (i = 0; i < AC_NUM; i++) { 777*7ac9a364SKalle Valo pos += 778*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 779*7ac9a364SKalle Valo "\tcw_min\tcw_max\taifsn\ttxop\n"); 780*7ac9a364SKalle Valo pos += 781*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 782*7ac9a364SKalle Valo "AC[%d]\t%u\t%u\t%u\t%u\n", i, 783*7ac9a364SKalle Valo il->qos_data.def_qos_parm.ac[i].cw_min, 784*7ac9a364SKalle Valo il->qos_data.def_qos_parm.ac[i].cw_max, 785*7ac9a364SKalle Valo il->qos_data.def_qos_parm.ac[i].aifsn, 786*7ac9a364SKalle Valo il->qos_data.def_qos_parm.ac[i].edca_txop); 787*7ac9a364SKalle Valo } 788*7ac9a364SKalle Valo 789*7ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 790*7ac9a364SKalle Valo } 791*7ac9a364SKalle Valo 792*7ac9a364SKalle Valo static ssize_t 793*7ac9a364SKalle Valo il_dbgfs_disable_ht40_write(struct file *file, const char __user *user_buf, 794*7ac9a364SKalle Valo size_t count, loff_t *ppos) 795*7ac9a364SKalle Valo { 796*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 797*7ac9a364SKalle Valo char buf[8]; 798*7ac9a364SKalle Valo int buf_size; 799*7ac9a364SKalle Valo int ht40; 800*7ac9a364SKalle Valo 801*7ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 802*7ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 803*7ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 804*7ac9a364SKalle Valo return -EFAULT; 805*7ac9a364SKalle Valo if (sscanf(buf, "%d", &ht40) != 1) 806*7ac9a364SKalle Valo return -EFAULT; 807*7ac9a364SKalle Valo if (!il_is_any_associated(il)) 808*7ac9a364SKalle Valo il->disable_ht40 = ht40 ? true : false; 809*7ac9a364SKalle Valo else { 810*7ac9a364SKalle Valo IL_ERR("Sta associated with AP - " 811*7ac9a364SKalle Valo "Change to 40MHz channel support is not allowed\n"); 812*7ac9a364SKalle Valo return -EINVAL; 813*7ac9a364SKalle Valo } 814*7ac9a364SKalle Valo 815*7ac9a364SKalle Valo return count; 816*7ac9a364SKalle Valo } 817*7ac9a364SKalle Valo 818*7ac9a364SKalle Valo static ssize_t 819*7ac9a364SKalle Valo il_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf, 820*7ac9a364SKalle Valo size_t count, loff_t *ppos) 821*7ac9a364SKalle Valo { 822*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 823*7ac9a364SKalle Valo char buf[100]; 824*7ac9a364SKalle Valo int pos = 0; 825*7ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 826*7ac9a364SKalle Valo 827*7ac9a364SKalle Valo pos += 828*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "11n 40MHz Mode: %s\n", 829*7ac9a364SKalle Valo il->disable_ht40 ? "Disabled" : "Enabled"); 830*7ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 831*7ac9a364SKalle Valo } 832*7ac9a364SKalle Valo 833*7ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(sram); 834*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(nvm); 835*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(stations); 836*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(channels); 837*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(status); 838*7ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 839*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(qos); 840*7ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); 841*7ac9a364SKalle Valo 842*7ac9a364SKalle Valo static ssize_t 843*7ac9a364SKalle Valo il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count, 844*7ac9a364SKalle Valo loff_t *ppos) 845*7ac9a364SKalle Valo { 846*7ac9a364SKalle Valo 847*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 848*7ac9a364SKalle Valo struct il_tx_queue *txq; 849*7ac9a364SKalle Valo struct il_queue *q; 850*7ac9a364SKalle Valo char *buf; 851*7ac9a364SKalle Valo int pos = 0; 852*7ac9a364SKalle Valo int cnt; 853*7ac9a364SKalle Valo int ret; 854*7ac9a364SKalle Valo const size_t bufsz = 855*7ac9a364SKalle Valo sizeof(char) * 64 * il->cfg->num_of_queues; 856*7ac9a364SKalle Valo 857*7ac9a364SKalle Valo if (!il->txq) { 858*7ac9a364SKalle Valo IL_ERR("txq not ready\n"); 859*7ac9a364SKalle Valo return -EAGAIN; 860*7ac9a364SKalle Valo } 861*7ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 862*7ac9a364SKalle Valo if (!buf) 863*7ac9a364SKalle Valo return -ENOMEM; 864*7ac9a364SKalle Valo 865*7ac9a364SKalle Valo for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { 866*7ac9a364SKalle Valo txq = &il->txq[cnt]; 867*7ac9a364SKalle Valo q = &txq->q; 868*7ac9a364SKalle Valo pos += 869*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 870*7ac9a364SKalle Valo "hwq %.2d: read=%u write=%u stop=%d" 871*7ac9a364SKalle Valo " swq_id=%#.2x (ac %d/hwq %d)\n", cnt, 872*7ac9a364SKalle Valo q->read_ptr, q->write_ptr, 873*7ac9a364SKalle Valo !!test_bit(cnt, il->queue_stopped), 874*7ac9a364SKalle Valo txq->swq_id, txq->swq_id & 3, 875*7ac9a364SKalle Valo (txq->swq_id >> 2) & 0x1f); 876*7ac9a364SKalle Valo if (cnt >= 4) 877*7ac9a364SKalle Valo continue; 878*7ac9a364SKalle Valo /* for the ACs, display the stop count too */ 879*7ac9a364SKalle Valo pos += 880*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 881*7ac9a364SKalle Valo " stop-count: %d\n", 882*7ac9a364SKalle Valo atomic_read(&il->queue_stop_count[cnt])); 883*7ac9a364SKalle Valo } 884*7ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 885*7ac9a364SKalle Valo kfree(buf); 886*7ac9a364SKalle Valo return ret; 887*7ac9a364SKalle Valo } 888*7ac9a364SKalle Valo 889*7ac9a364SKalle Valo static ssize_t 890*7ac9a364SKalle Valo il_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count, 891*7ac9a364SKalle Valo loff_t *ppos) 892*7ac9a364SKalle Valo { 893*7ac9a364SKalle Valo 894*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 895*7ac9a364SKalle Valo struct il_rx_queue *rxq = &il->rxq; 896*7ac9a364SKalle Valo char buf[256]; 897*7ac9a364SKalle Valo int pos = 0; 898*7ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 899*7ac9a364SKalle Valo 900*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", rxq->read); 901*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", rxq->write); 902*7ac9a364SKalle Valo pos += 903*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", 904*7ac9a364SKalle Valo rxq->free_count); 905*7ac9a364SKalle Valo if (rxq->rb_stts) { 906*7ac9a364SKalle Valo pos += 907*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", 908*7ac9a364SKalle Valo le16_to_cpu(rxq->rb_stts-> 909*7ac9a364SKalle Valo closed_rb_num) & 0x0FFF); 910*7ac9a364SKalle Valo } else { 911*7ac9a364SKalle Valo pos += 912*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 913*7ac9a364SKalle Valo "closed_rb_num: Not Allocated\n"); 914*7ac9a364SKalle Valo } 915*7ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 916*7ac9a364SKalle Valo } 917*7ac9a364SKalle Valo 918*7ac9a364SKalle Valo static ssize_t 919*7ac9a364SKalle Valo il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf, 920*7ac9a364SKalle Valo size_t count, loff_t *ppos) 921*7ac9a364SKalle Valo { 922*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 923*7ac9a364SKalle Valo 924*7ac9a364SKalle Valo return il->debugfs_ops->rx_stats_read(file, user_buf, count, ppos); 925*7ac9a364SKalle Valo } 926*7ac9a364SKalle Valo 927*7ac9a364SKalle Valo static ssize_t 928*7ac9a364SKalle Valo il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf, 929*7ac9a364SKalle Valo size_t count, loff_t *ppos) 930*7ac9a364SKalle Valo { 931*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 932*7ac9a364SKalle Valo 933*7ac9a364SKalle Valo return il->debugfs_ops->tx_stats_read(file, user_buf, count, ppos); 934*7ac9a364SKalle Valo } 935*7ac9a364SKalle Valo 936*7ac9a364SKalle Valo static ssize_t 937*7ac9a364SKalle Valo il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf, 938*7ac9a364SKalle Valo size_t count, loff_t *ppos) 939*7ac9a364SKalle Valo { 940*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 941*7ac9a364SKalle Valo 942*7ac9a364SKalle Valo return il->debugfs_ops->general_stats_read(file, user_buf, count, ppos); 943*7ac9a364SKalle Valo } 944*7ac9a364SKalle Valo 945*7ac9a364SKalle Valo static ssize_t 946*7ac9a364SKalle Valo il_dbgfs_sensitivity_read(struct file *file, char __user *user_buf, 947*7ac9a364SKalle Valo size_t count, loff_t *ppos) 948*7ac9a364SKalle Valo { 949*7ac9a364SKalle Valo 950*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 951*7ac9a364SKalle Valo int pos = 0; 952*7ac9a364SKalle Valo int cnt = 0; 953*7ac9a364SKalle Valo char *buf; 954*7ac9a364SKalle Valo int bufsz = sizeof(struct il_sensitivity_data) * 4 + 100; 955*7ac9a364SKalle Valo ssize_t ret; 956*7ac9a364SKalle Valo struct il_sensitivity_data *data; 957*7ac9a364SKalle Valo 958*7ac9a364SKalle Valo data = &il->sensitivity_data; 959*7ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 960*7ac9a364SKalle Valo if (!buf) { 961*7ac9a364SKalle Valo IL_ERR("Can not allocate Buffer\n"); 962*7ac9a364SKalle Valo return -ENOMEM; 963*7ac9a364SKalle Valo } 964*7ac9a364SKalle Valo 965*7ac9a364SKalle Valo pos += 966*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n", 967*7ac9a364SKalle Valo data->auto_corr_ofdm); 968*7ac9a364SKalle Valo pos += 969*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc:\t\t %u\n", 970*7ac9a364SKalle Valo data->auto_corr_ofdm_mrc); 971*7ac9a364SKalle Valo pos += 972*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n", 973*7ac9a364SKalle Valo data->auto_corr_ofdm_x1); 974*7ac9a364SKalle Valo pos += 975*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_mrc_x1:\t\t %u\n", 976*7ac9a364SKalle Valo data->auto_corr_ofdm_mrc_x1); 977*7ac9a364SKalle Valo pos += 978*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n", 979*7ac9a364SKalle Valo data->auto_corr_cck); 980*7ac9a364SKalle Valo pos += 981*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n", 982*7ac9a364SKalle Valo data->auto_corr_cck_mrc); 983*7ac9a364SKalle Valo pos += 984*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 985*7ac9a364SKalle Valo "last_bad_plcp_cnt_ofdm:\t\t %u\n", 986*7ac9a364SKalle Valo data->last_bad_plcp_cnt_ofdm); 987*7ac9a364SKalle Valo pos += 988*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n", 989*7ac9a364SKalle Valo data->last_fa_cnt_ofdm); 990*7ac9a364SKalle Valo pos += 991*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "last_bad_plcp_cnt_cck:\t\t %u\n", 992*7ac9a364SKalle Valo data->last_bad_plcp_cnt_cck); 993*7ac9a364SKalle Valo pos += 994*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n", 995*7ac9a364SKalle Valo data->last_fa_cnt_cck); 996*7ac9a364SKalle Valo pos += 997*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n", 998*7ac9a364SKalle Valo data->nrg_curr_state); 999*7ac9a364SKalle Valo pos += 1000*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n", 1001*7ac9a364SKalle Valo data->nrg_prev_state); 1002*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t"); 1003*7ac9a364SKalle Valo for (cnt = 0; cnt < 10; cnt++) { 1004*7ac9a364SKalle Valo pos += 1005*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, " %u", 1006*7ac9a364SKalle Valo data->nrg_value[cnt]); 1007*7ac9a364SKalle Valo } 1008*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1009*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t"); 1010*7ac9a364SKalle Valo for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) { 1011*7ac9a364SKalle Valo pos += 1012*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, " %u", 1013*7ac9a364SKalle Valo data->nrg_silence_rssi[cnt]); 1014*7ac9a364SKalle Valo } 1015*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1016*7ac9a364SKalle Valo pos += 1017*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n", 1018*7ac9a364SKalle Valo data->nrg_silence_ref); 1019*7ac9a364SKalle Valo pos += 1020*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n", 1021*7ac9a364SKalle Valo data->nrg_energy_idx); 1022*7ac9a364SKalle Valo pos += 1023*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n", 1024*7ac9a364SKalle Valo data->nrg_silence_idx); 1025*7ac9a364SKalle Valo pos += 1026*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n", 1027*7ac9a364SKalle Valo data->nrg_th_cck); 1028*7ac9a364SKalle Valo pos += 1029*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 1030*7ac9a364SKalle Valo "nrg_auto_corr_silence_diff:\t %u\n", 1031*7ac9a364SKalle Valo data->nrg_auto_corr_silence_diff); 1032*7ac9a364SKalle Valo pos += 1033*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n", 1034*7ac9a364SKalle Valo data->num_in_cck_no_fa); 1035*7ac9a364SKalle Valo pos += 1036*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n", 1037*7ac9a364SKalle Valo data->nrg_th_ofdm); 1038*7ac9a364SKalle Valo 1039*7ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1040*7ac9a364SKalle Valo kfree(buf); 1041*7ac9a364SKalle Valo return ret; 1042*7ac9a364SKalle Valo } 1043*7ac9a364SKalle Valo 1044*7ac9a364SKalle Valo static ssize_t 1045*7ac9a364SKalle Valo il_dbgfs_chain_noise_read(struct file *file, char __user *user_buf, 1046*7ac9a364SKalle Valo size_t count, loff_t *ppos) 1047*7ac9a364SKalle Valo { 1048*7ac9a364SKalle Valo 1049*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 1050*7ac9a364SKalle Valo int pos = 0; 1051*7ac9a364SKalle Valo int cnt = 0; 1052*7ac9a364SKalle Valo char *buf; 1053*7ac9a364SKalle Valo int bufsz = sizeof(struct il_chain_noise_data) * 4 + 100; 1054*7ac9a364SKalle Valo ssize_t ret; 1055*7ac9a364SKalle Valo struct il_chain_noise_data *data; 1056*7ac9a364SKalle Valo 1057*7ac9a364SKalle Valo data = &il->chain_noise_data; 1058*7ac9a364SKalle Valo buf = kzalloc(bufsz, GFP_KERNEL); 1059*7ac9a364SKalle Valo if (!buf) { 1060*7ac9a364SKalle Valo IL_ERR("Can not allocate Buffer\n"); 1061*7ac9a364SKalle Valo return -ENOMEM; 1062*7ac9a364SKalle Valo } 1063*7ac9a364SKalle Valo 1064*7ac9a364SKalle Valo pos += 1065*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n", 1066*7ac9a364SKalle Valo data->active_chains); 1067*7ac9a364SKalle Valo pos += 1068*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n", 1069*7ac9a364SKalle Valo data->chain_noise_a); 1070*7ac9a364SKalle Valo pos += 1071*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n", 1072*7ac9a364SKalle Valo data->chain_noise_b); 1073*7ac9a364SKalle Valo pos += 1074*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n", 1075*7ac9a364SKalle Valo data->chain_noise_c); 1076*7ac9a364SKalle Valo pos += 1077*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n", 1078*7ac9a364SKalle Valo data->chain_signal_a); 1079*7ac9a364SKalle Valo pos += 1080*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n", 1081*7ac9a364SKalle Valo data->chain_signal_b); 1082*7ac9a364SKalle Valo pos += 1083*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n", 1084*7ac9a364SKalle Valo data->chain_signal_c); 1085*7ac9a364SKalle Valo pos += 1086*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n", 1087*7ac9a364SKalle Valo data->beacon_count); 1088*7ac9a364SKalle Valo 1089*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t"); 1090*7ac9a364SKalle Valo for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 1091*7ac9a364SKalle Valo pos += 1092*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, " %u", 1093*7ac9a364SKalle Valo data->disconn_array[cnt]); 1094*7ac9a364SKalle Valo } 1095*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1096*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t"); 1097*7ac9a364SKalle Valo for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { 1098*7ac9a364SKalle Valo pos += 1099*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, " %u", 1100*7ac9a364SKalle Valo data->delta_gain_code[cnt]); 1101*7ac9a364SKalle Valo } 1102*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "\n"); 1103*7ac9a364SKalle Valo pos += 1104*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n", 1105*7ac9a364SKalle Valo data->radio_write); 1106*7ac9a364SKalle Valo pos += 1107*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n", 1108*7ac9a364SKalle Valo data->state); 1109*7ac9a364SKalle Valo 1110*7ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1111*7ac9a364SKalle Valo kfree(buf); 1112*7ac9a364SKalle Valo return ret; 1113*7ac9a364SKalle Valo } 1114*7ac9a364SKalle Valo 1115*7ac9a364SKalle Valo static ssize_t 1116*7ac9a364SKalle Valo il_dbgfs_power_save_status_read(struct file *file, char __user *user_buf, 1117*7ac9a364SKalle Valo size_t count, loff_t *ppos) 1118*7ac9a364SKalle Valo { 1119*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 1120*7ac9a364SKalle Valo char buf[60]; 1121*7ac9a364SKalle Valo int pos = 0; 1122*7ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 1123*7ac9a364SKalle Valo u32 pwrsave_status; 1124*7ac9a364SKalle Valo 1125*7ac9a364SKalle Valo pwrsave_status = 1126*7ac9a364SKalle Valo _il_rd(il, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK; 1127*7ac9a364SKalle Valo 1128*7ac9a364SKalle Valo pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); 1129*7ac9a364SKalle Valo pos += 1130*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "%s\n", 1131*7ac9a364SKalle Valo (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" : 1132*7ac9a364SKalle Valo (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" : 1133*7ac9a364SKalle Valo (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : 1134*7ac9a364SKalle Valo "error"); 1135*7ac9a364SKalle Valo 1136*7ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1137*7ac9a364SKalle Valo } 1138*7ac9a364SKalle Valo 1139*7ac9a364SKalle Valo static ssize_t 1140*7ac9a364SKalle Valo il_dbgfs_clear_ucode_stats_write(struct file *file, 1141*7ac9a364SKalle Valo const char __user *user_buf, size_t count, 1142*7ac9a364SKalle Valo loff_t *ppos) 1143*7ac9a364SKalle Valo { 1144*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 1145*7ac9a364SKalle Valo char buf[8]; 1146*7ac9a364SKalle Valo int buf_size; 1147*7ac9a364SKalle Valo int clear; 1148*7ac9a364SKalle Valo 1149*7ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 1150*7ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 1151*7ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 1152*7ac9a364SKalle Valo return -EFAULT; 1153*7ac9a364SKalle Valo if (sscanf(buf, "%d", &clear) != 1) 1154*7ac9a364SKalle Valo return -EFAULT; 1155*7ac9a364SKalle Valo 1156*7ac9a364SKalle Valo /* make request to uCode to retrieve stats information */ 1157*7ac9a364SKalle Valo mutex_lock(&il->mutex); 1158*7ac9a364SKalle Valo il_send_stats_request(il, CMD_SYNC, true); 1159*7ac9a364SKalle Valo mutex_unlock(&il->mutex); 1160*7ac9a364SKalle Valo 1161*7ac9a364SKalle Valo return count; 1162*7ac9a364SKalle Valo } 1163*7ac9a364SKalle Valo 1164*7ac9a364SKalle Valo static ssize_t 1165*7ac9a364SKalle Valo il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf, 1166*7ac9a364SKalle Valo size_t count, loff_t *ppos) 1167*7ac9a364SKalle Valo { 1168*7ac9a364SKalle Valo 1169*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 1170*7ac9a364SKalle Valo int len = 0; 1171*7ac9a364SKalle Valo char buf[20]; 1172*7ac9a364SKalle Valo 1173*7ac9a364SKalle Valo len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags)); 1174*7ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1175*7ac9a364SKalle Valo } 1176*7ac9a364SKalle Valo 1177*7ac9a364SKalle Valo static ssize_t 1178*7ac9a364SKalle Valo il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf, 1179*7ac9a364SKalle Valo size_t count, loff_t *ppos) 1180*7ac9a364SKalle Valo { 1181*7ac9a364SKalle Valo 1182*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 1183*7ac9a364SKalle Valo int len = 0; 1184*7ac9a364SKalle Valo char buf[20]; 1185*7ac9a364SKalle Valo 1186*7ac9a364SKalle Valo len = 1187*7ac9a364SKalle Valo sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags)); 1188*7ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1189*7ac9a364SKalle Valo } 1190*7ac9a364SKalle Valo 1191*7ac9a364SKalle Valo static ssize_t 1192*7ac9a364SKalle Valo il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count, 1193*7ac9a364SKalle Valo loff_t *ppos) 1194*7ac9a364SKalle Valo { 1195*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 1196*7ac9a364SKalle Valo char *buf; 1197*7ac9a364SKalle Valo int pos = 0; 1198*7ac9a364SKalle Valo ssize_t ret = -EFAULT; 1199*7ac9a364SKalle Valo 1200*7ac9a364SKalle Valo if (il->ops->dump_fh) { 1201*7ac9a364SKalle Valo ret = pos = il->ops->dump_fh(il, &buf, true); 1202*7ac9a364SKalle Valo if (buf) { 1203*7ac9a364SKalle Valo ret = 1204*7ac9a364SKalle Valo simple_read_from_buffer(user_buf, count, ppos, buf, 1205*7ac9a364SKalle Valo pos); 1206*7ac9a364SKalle Valo kfree(buf); 1207*7ac9a364SKalle Valo } 1208*7ac9a364SKalle Valo } 1209*7ac9a364SKalle Valo 1210*7ac9a364SKalle Valo return ret; 1211*7ac9a364SKalle Valo } 1212*7ac9a364SKalle Valo 1213*7ac9a364SKalle Valo static ssize_t 1214*7ac9a364SKalle Valo il_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf, 1215*7ac9a364SKalle Valo size_t count, loff_t *ppos) 1216*7ac9a364SKalle Valo { 1217*7ac9a364SKalle Valo 1218*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 1219*7ac9a364SKalle Valo int pos = 0; 1220*7ac9a364SKalle Valo char buf[12]; 1221*7ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 1222*7ac9a364SKalle Valo 1223*7ac9a364SKalle Valo pos += 1224*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "%d\n", 1225*7ac9a364SKalle Valo il->missed_beacon_threshold); 1226*7ac9a364SKalle Valo 1227*7ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1228*7ac9a364SKalle Valo } 1229*7ac9a364SKalle Valo 1230*7ac9a364SKalle Valo static ssize_t 1231*7ac9a364SKalle Valo il_dbgfs_missed_beacon_write(struct file *file, const char __user *user_buf, 1232*7ac9a364SKalle Valo size_t count, loff_t *ppos) 1233*7ac9a364SKalle Valo { 1234*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 1235*7ac9a364SKalle Valo char buf[8]; 1236*7ac9a364SKalle Valo int buf_size; 1237*7ac9a364SKalle Valo int missed; 1238*7ac9a364SKalle Valo 1239*7ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 1240*7ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 1241*7ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 1242*7ac9a364SKalle Valo return -EFAULT; 1243*7ac9a364SKalle Valo if (sscanf(buf, "%d", &missed) != 1) 1244*7ac9a364SKalle Valo return -EINVAL; 1245*7ac9a364SKalle Valo 1246*7ac9a364SKalle Valo if (missed < IL_MISSED_BEACON_THRESHOLD_MIN || 1247*7ac9a364SKalle Valo missed > IL_MISSED_BEACON_THRESHOLD_MAX) 1248*7ac9a364SKalle Valo il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF; 1249*7ac9a364SKalle Valo else 1250*7ac9a364SKalle Valo il->missed_beacon_threshold = missed; 1251*7ac9a364SKalle Valo 1252*7ac9a364SKalle Valo return count; 1253*7ac9a364SKalle Valo } 1254*7ac9a364SKalle Valo 1255*7ac9a364SKalle Valo static ssize_t 1256*7ac9a364SKalle Valo il_dbgfs_force_reset_read(struct file *file, char __user *user_buf, 1257*7ac9a364SKalle Valo size_t count, loff_t *ppos) 1258*7ac9a364SKalle Valo { 1259*7ac9a364SKalle Valo 1260*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 1261*7ac9a364SKalle Valo int pos = 0; 1262*7ac9a364SKalle Valo char buf[300]; 1263*7ac9a364SKalle Valo const size_t bufsz = sizeof(buf); 1264*7ac9a364SKalle Valo struct il_force_reset *force_reset; 1265*7ac9a364SKalle Valo 1266*7ac9a364SKalle Valo force_reset = &il->force_reset; 1267*7ac9a364SKalle Valo 1268*7ac9a364SKalle Valo pos += 1269*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\tnumber of reset request: %d\n", 1270*7ac9a364SKalle Valo force_reset->reset_request_count); 1271*7ac9a364SKalle Valo pos += 1272*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 1273*7ac9a364SKalle Valo "\tnumber of reset request success: %d\n", 1274*7ac9a364SKalle Valo force_reset->reset_success_count); 1275*7ac9a364SKalle Valo pos += 1276*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, 1277*7ac9a364SKalle Valo "\tnumber of reset request reject: %d\n", 1278*7ac9a364SKalle Valo force_reset->reset_reject_count); 1279*7ac9a364SKalle Valo pos += 1280*7ac9a364SKalle Valo scnprintf(buf + pos, bufsz - pos, "\treset duration: %lu\n", 1281*7ac9a364SKalle Valo force_reset->reset_duration); 1282*7ac9a364SKalle Valo 1283*7ac9a364SKalle Valo return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 1284*7ac9a364SKalle Valo } 1285*7ac9a364SKalle Valo 1286*7ac9a364SKalle Valo static ssize_t 1287*7ac9a364SKalle Valo il_dbgfs_force_reset_write(struct file *file, const char __user *user_buf, 1288*7ac9a364SKalle Valo size_t count, loff_t *ppos) 1289*7ac9a364SKalle Valo { 1290*7ac9a364SKalle Valo 1291*7ac9a364SKalle Valo int ret; 1292*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 1293*7ac9a364SKalle Valo 1294*7ac9a364SKalle Valo ret = il_force_reset(il, true); 1295*7ac9a364SKalle Valo 1296*7ac9a364SKalle Valo return ret ? ret : count; 1297*7ac9a364SKalle Valo } 1298*7ac9a364SKalle Valo 1299*7ac9a364SKalle Valo static ssize_t 1300*7ac9a364SKalle Valo il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf, 1301*7ac9a364SKalle Valo size_t count, loff_t *ppos) 1302*7ac9a364SKalle Valo { 1303*7ac9a364SKalle Valo 1304*7ac9a364SKalle Valo struct il_priv *il = file->private_data; 1305*7ac9a364SKalle Valo char buf[8]; 1306*7ac9a364SKalle Valo int buf_size; 1307*7ac9a364SKalle Valo int timeout; 1308*7ac9a364SKalle Valo 1309*7ac9a364SKalle Valo memset(buf, 0, sizeof(buf)); 1310*7ac9a364SKalle Valo buf_size = min(count, sizeof(buf) - 1); 1311*7ac9a364SKalle Valo if (copy_from_user(buf, user_buf, buf_size)) 1312*7ac9a364SKalle Valo return -EFAULT; 1313*7ac9a364SKalle Valo if (sscanf(buf, "%d", &timeout) != 1) 1314*7ac9a364SKalle Valo return -EINVAL; 1315*7ac9a364SKalle Valo if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT) 1316*7ac9a364SKalle Valo timeout = IL_DEF_WD_TIMEOUT; 1317*7ac9a364SKalle Valo 1318*7ac9a364SKalle Valo il->cfg->wd_timeout = timeout; 1319*7ac9a364SKalle Valo il_setup_watchdog(il); 1320*7ac9a364SKalle Valo return count; 1321*7ac9a364SKalle Valo } 1322*7ac9a364SKalle Valo 1323*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rx_stats); 1324*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(tx_stats); 1325*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rx_queue); 1326*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(tx_queue); 1327*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(ucode_rx_stats); 1328*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(ucode_tx_stats); 1329*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(ucode_general_stats); 1330*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(sensitivity); 1331*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(chain_noise); 1332*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(power_save_status); 1333*7ac9a364SKalle Valo DEBUGFS_WRITE_FILE_OPS(clear_ucode_stats); 1334*7ac9a364SKalle Valo DEBUGFS_WRITE_FILE_OPS(clear_traffic_stats); 1335*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(fh_reg); 1336*7ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); 1337*7ac9a364SKalle Valo DEBUGFS_READ_WRITE_FILE_OPS(force_reset); 1338*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rxon_flags); 1339*7ac9a364SKalle Valo DEBUGFS_READ_FILE_OPS(rxon_filter_flags); 1340*7ac9a364SKalle Valo DEBUGFS_WRITE_FILE_OPS(wd_timeout); 1341*7ac9a364SKalle Valo 1342*7ac9a364SKalle Valo /* 1343*7ac9a364SKalle Valo * Create the debugfs files and directories 1344*7ac9a364SKalle Valo * 1345*7ac9a364SKalle Valo */ 1346*7ac9a364SKalle Valo int 1347*7ac9a364SKalle Valo il_dbgfs_register(struct il_priv *il, const char *name) 1348*7ac9a364SKalle Valo { 1349*7ac9a364SKalle Valo struct dentry *phyd = il->hw->wiphy->debugfsdir; 1350*7ac9a364SKalle Valo struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; 1351*7ac9a364SKalle Valo 1352*7ac9a364SKalle Valo dir_drv = debugfs_create_dir(name, phyd); 1353*7ac9a364SKalle Valo if (!dir_drv) 1354*7ac9a364SKalle Valo return -ENOMEM; 1355*7ac9a364SKalle Valo 1356*7ac9a364SKalle Valo il->debugfs_dir = dir_drv; 1357*7ac9a364SKalle Valo 1358*7ac9a364SKalle Valo dir_data = debugfs_create_dir("data", dir_drv); 1359*7ac9a364SKalle Valo if (!dir_data) 1360*7ac9a364SKalle Valo goto err; 1361*7ac9a364SKalle Valo dir_rf = debugfs_create_dir("rf", dir_drv); 1362*7ac9a364SKalle Valo if (!dir_rf) 1363*7ac9a364SKalle Valo goto err; 1364*7ac9a364SKalle Valo dir_debug = debugfs_create_dir("debug", dir_drv); 1365*7ac9a364SKalle Valo if (!dir_debug) 1366*7ac9a364SKalle Valo goto err; 1367*7ac9a364SKalle Valo 1368*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); 1369*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); 1370*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); 1371*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); 1372*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); 1373*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); 1374*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); 1375*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); 1376*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR); 1377*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR); 1378*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); 1379*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); 1380*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); 1381*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(clear_ucode_stats, dir_debug, S_IWUSR); 1382*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(clear_traffic_stats, dir_debug, S_IWUSR); 1383*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); 1384*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); 1385*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); 1386*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); 1387*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); 1388*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); 1389*7ac9a364SKalle Valo 1390*7ac9a364SKalle Valo if (il->cfg->sensitivity_calib_by_driver) 1391*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); 1392*7ac9a364SKalle Valo if (il->cfg->chain_noise_calib_by_driver) 1393*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); 1394*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); 1395*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); 1396*7ac9a364SKalle Valo DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); 1397*7ac9a364SKalle Valo if (il->cfg->sensitivity_calib_by_driver) 1398*7ac9a364SKalle Valo DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, 1399*7ac9a364SKalle Valo &il->disable_sens_cal); 1400*7ac9a364SKalle Valo if (il->cfg->chain_noise_calib_by_driver) 1401*7ac9a364SKalle Valo DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, 1402*7ac9a364SKalle Valo &il->disable_chain_noise_cal); 1403*7ac9a364SKalle Valo DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal); 1404*7ac9a364SKalle Valo return 0; 1405*7ac9a364SKalle Valo 1406*7ac9a364SKalle Valo err: 1407*7ac9a364SKalle Valo IL_ERR("Can't create the debugfs directory\n"); 1408*7ac9a364SKalle Valo il_dbgfs_unregister(il); 1409*7ac9a364SKalle Valo return -ENOMEM; 1410*7ac9a364SKalle Valo } 1411*7ac9a364SKalle Valo EXPORT_SYMBOL(il_dbgfs_register); 1412*7ac9a364SKalle Valo 1413*7ac9a364SKalle Valo /** 1414*7ac9a364SKalle Valo * Remove the debugfs files and directories 1415*7ac9a364SKalle Valo * 1416*7ac9a364SKalle Valo */ 1417*7ac9a364SKalle Valo void 1418*7ac9a364SKalle Valo il_dbgfs_unregister(struct il_priv *il) 1419*7ac9a364SKalle Valo { 1420*7ac9a364SKalle Valo if (!il->debugfs_dir) 1421*7ac9a364SKalle Valo return; 1422*7ac9a364SKalle Valo 1423*7ac9a364SKalle Valo debugfs_remove_recursive(il->debugfs_dir); 1424*7ac9a364SKalle Valo il->debugfs_dir = NULL; 1425*7ac9a364SKalle Valo } 1426*7ac9a364SKalle Valo EXPORT_SYMBOL(il_dbgfs_unregister); 1427