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