2382 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/******************************************************************************3 *4 * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.5 * Copyright (C) 2018 Intel Corporation6 *****************************************************************************/7 8#include <linux/slab.h>9#include <linux/kernel.h>10#include <linux/module.h>11#include <linux/debugfs.h>12#include <linux/ieee80211.h>13#include <net/mac80211.h>14 15#include "iwl-debug.h"16#include "iwl-trans.h"17#include "iwl-io.h"18#include "dev.h"19#include "agn.h"20 21/* create and remove of files */22#define DEBUGFS_ADD_FILE(name, parent, mode) do { \23 debugfs_create_file(#name, mode, parent, priv, \24 &iwl_dbgfs_##name##_ops); \25} while (0)26 27/* file operation */28#define DEBUGFS_READ_FILE_OPS(name) \29static const struct file_operations iwl_dbgfs_##name##_ops = { \30 .read = iwl_dbgfs_##name##_read, \31 .open = simple_open, \32 .llseek = generic_file_llseek, \33};34 35#define DEBUGFS_WRITE_FILE_OPS(name) \36static const struct file_operations iwl_dbgfs_##name##_ops = { \37 .write = iwl_dbgfs_##name##_write, \38 .open = simple_open, \39 .llseek = generic_file_llseek, \40};41 42 43#define DEBUGFS_READ_WRITE_FILE_OPS(name) \44static const struct file_operations iwl_dbgfs_##name##_ops = { \45 .write = iwl_dbgfs_##name##_write, \46 .read = iwl_dbgfs_##name##_read, \47 .open = simple_open, \48 .llseek = generic_file_llseek, \49};50 51static ssize_t iwl_dbgfs_sram_read(struct file *file,52 char __user *user_buf,53 size_t count, loff_t *ppos)54{55 u32 val = 0;56 char *buf;57 ssize_t ret;58 int i = 0;59 bool device_format = false;60 int offset = 0;61 int len = 0;62 int pos = 0;63 int sram;64 struct iwl_priv *priv = file->private_data;65 const struct fw_img *img;66 size_t bufsz;67 68 if (!iwl_is_ready_rf(priv))69 return -EAGAIN;70 71 /* default is to dump the entire data segment */72 if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {73 priv->dbgfs_sram_offset = 0x800000;74 if (!priv->ucode_loaded)75 return -EINVAL;76 img = &priv->fw->img[priv->cur_ucode];77 priv->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;78 }79 len = priv->dbgfs_sram_len;80 81 if (len == -4) {82 device_format = true;83 len = 4;84 }85 86 bufsz = 50 + len * 4;87 buf = kmalloc(bufsz, GFP_KERNEL);88 if (!buf)89 return -ENOMEM;90 91 pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",92 len);93 pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",94 priv->dbgfs_sram_offset);95 96 /* adjust sram address since reads are only on even u32 boundaries */97 offset = priv->dbgfs_sram_offset & 0x3;98 sram = priv->dbgfs_sram_offset & ~0x3;99 100 /* read the first u32 from sram */101 val = iwl_trans_read_mem32(priv->trans, sram);102 103 for (; len; len--) {104 /* put the address at the start of every line */105 if (i == 0)106 pos += scnprintf(buf + pos, bufsz - pos,107 "%08X: ", sram + offset);108 109 if (device_format)110 pos += scnprintf(buf + pos, bufsz - pos,111 "%02x", (val >> (8 * (3 - offset))) & 0xff);112 else113 pos += scnprintf(buf + pos, bufsz - pos,114 "%02x ", (val >> (8 * offset)) & 0xff);115 116 /* if all bytes processed, read the next u32 from sram */117 if (++offset == 4) {118 sram += 4;119 offset = 0;120 val = iwl_trans_read_mem32(priv->trans, sram);121 }122 123 /* put in extra spaces and split lines for human readability */124 if (++i == 16) {125 i = 0;126 pos += scnprintf(buf + pos, bufsz - pos, "\n");127 } else if (!(i & 7)) {128 pos += scnprintf(buf + pos, bufsz - pos, " ");129 } else if (!(i & 3)) {130 pos += scnprintf(buf + pos, bufsz - pos, " ");131 }132 }133 if (i)134 pos += scnprintf(buf + pos, bufsz - pos, "\n");135 136 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);137 kfree(buf);138 return ret;139}140 141static ssize_t iwl_dbgfs_sram_write(struct file *file,142 const char __user *user_buf,143 size_t count, loff_t *ppos)144{145 struct iwl_priv *priv = file->private_data;146 char buf[64];147 int buf_size;148 u32 offset, len;149 150 memset(buf, 0, sizeof(buf));151 buf_size = min(count, sizeof(buf) - 1);152 if (copy_from_user(buf, user_buf, buf_size))153 return -EFAULT;154 155 if (sscanf(buf, "%x,%x", &offset, &len) == 2) {156 priv->dbgfs_sram_offset = offset;157 priv->dbgfs_sram_len = len;158 } else if (sscanf(buf, "%x", &offset) == 1) {159 priv->dbgfs_sram_offset = offset;160 priv->dbgfs_sram_len = -4;161 } else {162 priv->dbgfs_sram_offset = 0;163 priv->dbgfs_sram_len = 0;164 }165 166 return count;167}168 169static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file,170 char __user *user_buf,171 size_t count, loff_t *ppos)172{173 struct iwl_priv *priv = file->private_data;174 const struct fw_img *img = &priv->fw->img[IWL_UCODE_WOWLAN];175 176 if (!priv->wowlan_sram)177 return -ENODATA;178 179 return simple_read_from_buffer(user_buf, count, ppos,180 priv->wowlan_sram,181 img->sec[IWL_UCODE_SECTION_DATA].len);182}183static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,184 size_t count, loff_t *ppos)185{186 struct iwl_priv *priv = file->private_data;187 struct iwl_station_entry *station;188 struct iwl_tid_data *tid_data;189 char *buf;190 int i, j, pos = 0;191 ssize_t ret;192 /* Add 30 for initial string */193 const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);194 195 buf = kmalloc(bufsz, GFP_KERNEL);196 if (!buf)197 return -ENOMEM;198 199 pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",200 priv->num_stations);201 202 for (i = 0; i < IWLAGN_STATION_COUNT; i++) {203 station = &priv->stations[i];204 if (!station->used)205 continue;206 pos += scnprintf(buf + pos, bufsz - pos,207 "station %d - addr: %pM, flags: %#x\n",208 i, station->sta.sta.addr,209 station->sta.station_flags_msk);210 pos += scnprintf(buf + pos, bufsz - pos,211 "TID seqno next_rclmd "212 "rate_n_flags state txq\n");213 214 for (j = 0; j < IWL_MAX_TID_COUNT; j++) {215 tid_data = &priv->tid_data[i][j];216 pos += scnprintf(buf + pos, bufsz - pos,217 "%d: 0x%.4x 0x%.4x 0x%.8x "218 "%d %.2d",219 j, tid_data->seq_number,220 tid_data->next_reclaimed,221 tid_data->agg.rate_n_flags,222 tid_data->agg.state,223 tid_data->agg.txq_id);224 225 if (tid_data->agg.wait_for_ba)226 pos += scnprintf(buf + pos, bufsz - pos,227 " - waitforba");228 pos += scnprintf(buf + pos, bufsz - pos, "\n");229 }230 231 pos += scnprintf(buf + pos, bufsz - pos, "\n");232 }233 234 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);235 kfree(buf);236 return ret;237}238 239static ssize_t iwl_dbgfs_nvm_read(struct file *file,240 char __user *user_buf,241 size_t count,242 loff_t *ppos)243{244 ssize_t ret;245 struct iwl_priv *priv = file->private_data;246 int pos = 0, ofs = 0, buf_size = 0;247 const u8 *ptr;248 char *buf;249 u16 nvm_ver;250 size_t eeprom_len = priv->eeprom_blob_size;251 buf_size = 4 * eeprom_len + 256;252 253 if (eeprom_len % 16)254 return -ENODATA;255 256 ptr = priv->eeprom_blob;257 if (!ptr)258 return -ENOMEM;259 260 /* 4 characters for byte 0xYY */261 buf = kzalloc(buf_size, GFP_KERNEL);262 if (!buf)263 return -ENOMEM;264 265 nvm_ver = priv->nvm_data->nvm_version;266 pos += scnprintf(buf + pos, buf_size - pos,267 "NVM version: 0x%x\n", nvm_ver);268 for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {269 pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n",270 ofs, ptr + ofs);271 }272 273 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);274 kfree(buf);275 return ret;276}277 278static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,279 size_t count, loff_t *ppos)280{281 struct iwl_priv *priv = file->private_data;282 struct ieee80211_channel *channels = NULL;283 const struct ieee80211_supported_band *supp_band = NULL;284 int pos = 0, i, bufsz = PAGE_SIZE;285 char *buf;286 ssize_t ret;287 288 buf = kzalloc(bufsz, GFP_KERNEL);289 if (!buf)290 return -ENOMEM;291 292 supp_band = iwl_get_hw_mode(priv, NL80211_BAND_2GHZ);293 if (supp_band) {294 channels = supp_band->channels;295 296 pos += scnprintf(buf + pos, bufsz - pos,297 "Displaying %d channels in 2.4GHz band 802.11bg):\n",298 supp_band->n_channels);299 300 for (i = 0; i < supp_band->n_channels; i++)301 pos += scnprintf(buf + pos, bufsz - pos,302 "%d: %ddBm: BSS%s%s, %s.\n",303 channels[i].hw_value,304 channels[i].max_power,305 channels[i].flags & IEEE80211_CHAN_RADAR ?306 " (IEEE 802.11h required)" : "",307 ((channels[i].flags & IEEE80211_CHAN_NO_IR)308 || (channels[i].flags &309 IEEE80211_CHAN_RADAR)) ? "" :310 ", IBSS",311 channels[i].flags &312 IEEE80211_CHAN_NO_IR ?313 "passive only" : "active/passive");314 }315 supp_band = iwl_get_hw_mode(priv, NL80211_BAND_5GHZ);316 if (supp_band) {317 channels = supp_band->channels;318 319 pos += scnprintf(buf + pos, bufsz - pos,320 "Displaying %d channels in 5.2GHz band (802.11a)\n",321 supp_band->n_channels);322 323 for (i = 0; i < supp_band->n_channels; i++)324 pos += scnprintf(buf + pos, bufsz - pos,325 "%d: %ddBm: BSS%s%s, %s.\n",326 channels[i].hw_value,327 channels[i].max_power,328 channels[i].flags & IEEE80211_CHAN_RADAR ?329 " (IEEE 802.11h required)" : "",330 ((channels[i].flags & IEEE80211_CHAN_NO_IR)331 || (channels[i].flags &332 IEEE80211_CHAN_RADAR)) ? "" :333 ", IBSS",334 channels[i].flags &335 IEEE80211_CHAN_NO_IR ?336 "passive only" : "active/passive");337 }338 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);339 kfree(buf);340 return ret;341}342 343static ssize_t iwl_dbgfs_status_read(struct file *file,344 char __user *user_buf,345 size_t count, loff_t *ppos) {346 347 struct iwl_priv *priv = file->private_data;348 char buf[512];349 int pos = 0;350 const size_t bufsz = sizeof(buf);351 352 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",353 test_bit(STATUS_RF_KILL_HW, &priv->status));354 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",355 test_bit(STATUS_CT_KILL, &priv->status));356 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",357 test_bit(STATUS_ALIVE, &priv->status));358 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",359 test_bit(STATUS_READY, &priv->status));360 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",361 test_bit(STATUS_EXIT_PENDING, &priv->status));362 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",363 test_bit(STATUS_STATISTICS, &priv->status));364 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",365 test_bit(STATUS_SCANNING, &priv->status));366 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",367 test_bit(STATUS_SCAN_ABORTING, &priv->status));368 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",369 test_bit(STATUS_SCAN_HW, &priv->status));370 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",371 test_bit(STATUS_POWER_PMI, &priv->status));372 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",373 test_bit(STATUS_FW_ERROR, &priv->status));374 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);375}376 377static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file,378 char __user *user_buf,379 size_t count, loff_t *ppos) {380 381 struct iwl_priv *priv = file->private_data;382 383 int pos = 0;384 int cnt = 0;385 char *buf;386 int bufsz = 24 * 64; /* 24 items * 64 char per item */387 ssize_t ret;388 389 buf = kzalloc(bufsz, GFP_KERNEL);390 if (!buf)391 return -ENOMEM;392 393 for (cnt = 0; cnt < REPLY_MAX; cnt++) {394 if (priv->rx_handlers_stats[cnt] > 0)395 pos += scnprintf(buf + pos, bufsz - pos,396 "\tRx handler[%36s]:\t\t %u\n",397 iwl_get_cmd_string(priv->trans, (u32)cnt),398 priv->rx_handlers_stats[cnt]);399 }400 401 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);402 kfree(buf);403 return ret;404}405 406static ssize_t iwl_dbgfs_rx_handlers_write(struct file *file,407 const char __user *user_buf,408 size_t count, loff_t *ppos)409{410 struct iwl_priv *priv = file->private_data;411 412 char buf[8];413 int buf_size;414 u32 reset_flag;415 416 memset(buf, 0, sizeof(buf));417 buf_size = min(count, sizeof(buf) - 1);418 if (copy_from_user(buf, user_buf, buf_size))419 return -EFAULT;420 if (sscanf(buf, "%x", &reset_flag) != 1)421 return -EFAULT;422 if (reset_flag == 0)423 memset(&priv->rx_handlers_stats[0], 0,424 sizeof(priv->rx_handlers_stats));425 426 return count;427}428 429static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,430 size_t count, loff_t *ppos)431{432 struct iwl_priv *priv = file->private_data;433 struct iwl_rxon_context *ctx;434 int pos = 0, i;435 char buf[256 * NUM_IWL_RXON_CTX];436 const size_t bufsz = sizeof(buf);437 438 for_each_context(priv, ctx) {439 pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",440 ctx->ctxid);441 for (i = 0; i < AC_NUM; i++) {442 pos += scnprintf(buf + pos, bufsz - pos,443 "\tcw_min\tcw_max\taifsn\ttxop\n");444 pos += scnprintf(buf + pos, bufsz - pos,445 "AC[%d]\t%u\t%u\t%u\t%u\n", i,446 ctx->qos_data.def_qos_parm.ac[i].cw_min,447 ctx->qos_data.def_qos_parm.ac[i].cw_max,448 ctx->qos_data.def_qos_parm.ac[i].aifsn,449 ctx->qos_data.def_qos_parm.ac[i].edca_txop);450 }451 pos += scnprintf(buf + pos, bufsz - pos, "\n");452 }453 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);454}455 456static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,457 char __user *user_buf,458 size_t count, loff_t *ppos)459{460 struct iwl_priv *priv = file->private_data;461 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;462 struct iwl_tt_restriction *restriction;463 char buf[100];464 int pos = 0;465 const size_t bufsz = sizeof(buf);466 467 pos += scnprintf(buf + pos, bufsz - pos,468 "Thermal Throttling Mode: %s\n",469 tt->advanced_tt ? "Advance" : "Legacy");470 pos += scnprintf(buf + pos, bufsz - pos,471 "Thermal Throttling State: %d\n",472 tt->state);473 if (tt->advanced_tt) {474 restriction = tt->restriction + tt->state;475 pos += scnprintf(buf + pos, bufsz - pos,476 "Tx mode: %d\n",477 restriction->tx_stream);478 pos += scnprintf(buf + pos, bufsz - pos,479 "Rx mode: %d\n",480 restriction->rx_stream);481 pos += scnprintf(buf + pos, bufsz - pos,482 "HT mode: %d\n",483 restriction->is_ht);484 }485 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);486}487 488static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,489 const char __user *user_buf,490 size_t count, loff_t *ppos)491{492 struct iwl_priv *priv = file->private_data;493 char buf[8];494 int buf_size;495 int ht40;496 497 memset(buf, 0, sizeof(buf));498 buf_size = min(count, sizeof(buf) - 1);499 if (copy_from_user(buf, user_buf, buf_size))500 return -EFAULT;501 if (sscanf(buf, "%d", &ht40) != 1)502 return -EFAULT;503 if (!iwl_is_any_associated(priv))504 priv->disable_ht40 = ht40 ? true : false;505 else506 return -EINVAL;507 508 return count;509}510 511static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,512 char __user *user_buf,513 size_t count, loff_t *ppos)514{515 struct iwl_priv *priv = file->private_data;516 char buf[100];517 int pos = 0;518 const size_t bufsz = sizeof(buf);519 520 pos += scnprintf(buf + pos, bufsz - pos,521 "11n 40MHz Mode: %s\n",522 priv->disable_ht40 ? "Disabled" : "Enabled");523 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);524}525 526static ssize_t iwl_dbgfs_temperature_read(struct file *file,527 char __user *user_buf,528 size_t count, loff_t *ppos)529{530 struct iwl_priv *priv = file->private_data;531 char buf[8];532 int pos = 0;533 const size_t bufsz = sizeof(buf);534 535 pos += scnprintf(buf + pos, bufsz - pos, "%d\n", priv->temperature);536 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);537}538 539 540static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,541 const char __user *user_buf,542 size_t count, loff_t *ppos)543{544 struct iwl_priv *priv = file->private_data;545 char buf[8];546 int buf_size;547 int value;548 549 memset(buf, 0, sizeof(buf));550 buf_size = min(count, sizeof(buf) - 1);551 if (copy_from_user(buf, user_buf, buf_size))552 return -EFAULT;553 554 if (sscanf(buf, "%d", &value) != 1)555 return -EINVAL;556 557 /*558 * Our users expect 0 to be "CAM", but 0 isn't actually559 * valid here. However, let's not confuse them and present560 * IWL_POWER_INDEX_1 as "1", not "0".561 */562 if (value == 0)563 return -EINVAL;564 else if (value > 0)565 value -= 1;566 567 if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))568 return -EINVAL;569 570 if (!iwl_is_ready_rf(priv))571 return -EAGAIN;572 573 priv->power_data.debug_sleep_level_override = value;574 575 mutex_lock(&priv->mutex);576 iwl_power_update_mode(priv, true);577 mutex_unlock(&priv->mutex);578 579 return count;580}581 582static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file,583 char __user *user_buf,584 size_t count, loff_t *ppos)585{586 struct iwl_priv *priv = file->private_data;587 char buf[10];588 int pos, value;589 const size_t bufsz = sizeof(buf);590 591 /* see the write function */592 value = priv->power_data.debug_sleep_level_override;593 if (value >= 0)594 value += 1;595 596 pos = scnprintf(buf, bufsz, "%d\n", value);597 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);598}599 600static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,601 char __user *user_buf,602 size_t count, loff_t *ppos)603{604 struct iwl_priv *priv = file->private_data;605 char buf[200];606 int pos = 0, i;607 const size_t bufsz = sizeof(buf);608 struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd;609 610 pos += scnprintf(buf + pos, bufsz - pos,611 "flags: %#.2x\n", le16_to_cpu(cmd->flags));612 pos += scnprintf(buf + pos, bufsz - pos,613 "RX/TX timeout: %d/%d usec\n",614 le32_to_cpu(cmd->rx_data_timeout),615 le32_to_cpu(cmd->tx_data_timeout));616 for (i = 0; i < IWL_POWER_VEC_SIZE; i++)617 pos += scnprintf(buf + pos, bufsz - pos,618 "sleep_interval[%d]: %d\n", i,619 le32_to_cpu(cmd->sleep_interval[i]));620 621 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);622}623 624DEBUGFS_READ_WRITE_FILE_OPS(sram);625DEBUGFS_READ_FILE_OPS(wowlan_sram);626DEBUGFS_READ_FILE_OPS(nvm);627DEBUGFS_READ_FILE_OPS(stations);628DEBUGFS_READ_FILE_OPS(channels);629DEBUGFS_READ_FILE_OPS(status);630DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers);631DEBUGFS_READ_FILE_OPS(qos);632DEBUGFS_READ_FILE_OPS(thermal_throttling);633DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);634DEBUGFS_READ_FILE_OPS(temperature);635DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);636DEBUGFS_READ_FILE_OPS(current_sleep_command);637 638#define fmt_value " %-30s %10u\n"639#define fmt_hex " %-30s 0x%02X\n"640#define fmt_table " %-30s %10u %10u %10u %10u\n"641#define fmt_header "%-32s current cumulative delta max\n"642 643static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)644{645 int p = 0;646 u32 flag;647 648 lockdep_assert_held(&priv->statistics.lock);649 650 flag = le32_to_cpu(priv->statistics.flag);651 652 p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);653 if (flag & UCODE_STATISTICS_CLEAR_MSK)654 p += scnprintf(buf + p, bufsz - p,655 "\tStatistics have been cleared\n");656 p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",657 (flag & UCODE_STATISTICS_FREQUENCY_MSK)658 ? "2.4 GHz" : "5.2 GHz");659 p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",660 (flag & UCODE_STATISTICS_NARROW_BAND_MSK)661 ? "enabled" : "disabled");662 663 return p;664}665 666static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,667 char __user *user_buf,668 size_t count, loff_t *ppos)669{670 struct iwl_priv *priv = file->private_data;671 int pos = 0;672 char *buf;673 int bufsz = sizeof(struct statistics_rx_phy) * 40 +674 sizeof(struct statistics_rx_non_phy) * 40 +675 sizeof(struct statistics_rx_ht_phy) * 40 + 400;676 ssize_t ret;677 struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;678 struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;679 struct statistics_rx_non_phy *general, *accum_general;680 struct statistics_rx_non_phy *delta_general, *max_general;681 struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;682 683 if (!iwl_is_alive(priv))684 return -EAGAIN;685 686 buf = kzalloc(bufsz, GFP_KERNEL);687 if (!buf)688 return -ENOMEM;689 690 /*691 * the statistic information display here is based on692 * the last statistics notification from uCode693 * might not reflect the current uCode activity694 */695 spin_lock_bh(&priv->statistics.lock);696 ofdm = &priv->statistics.rx_ofdm;697 cck = &priv->statistics.rx_cck;698 general = &priv->statistics.rx_non_phy;699 ht = &priv->statistics.rx_ofdm_ht;700 accum_ofdm = &priv->accum_stats.rx_ofdm;701 accum_cck = &priv->accum_stats.rx_cck;702 accum_general = &priv->accum_stats.rx_non_phy;703 accum_ht = &priv->accum_stats.rx_ofdm_ht;704 delta_ofdm = &priv->delta_stats.rx_ofdm;705 delta_cck = &priv->delta_stats.rx_cck;706 delta_general = &priv->delta_stats.rx_non_phy;707 delta_ht = &priv->delta_stats.rx_ofdm_ht;708 max_ofdm = &priv->max_delta_stats.rx_ofdm;709 max_cck = &priv->max_delta_stats.rx_cck;710 max_general = &priv->max_delta_stats.rx_non_phy;711 max_ht = &priv->max_delta_stats.rx_ofdm_ht;712 713 pos += iwl_statistics_flag(priv, buf, bufsz);714 pos += scnprintf(buf + pos, bufsz - pos,715 fmt_header, "Statistics_Rx - OFDM:");716 pos += scnprintf(buf + pos, bufsz - pos,717 fmt_table, "ina_cnt:",718 le32_to_cpu(ofdm->ina_cnt),719 accum_ofdm->ina_cnt,720 delta_ofdm->ina_cnt, max_ofdm->ina_cnt);721 pos += scnprintf(buf + pos, bufsz - pos,722 fmt_table, "fina_cnt:",723 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,724 delta_ofdm->fina_cnt, max_ofdm->fina_cnt);725 pos += scnprintf(buf + pos, bufsz - pos,726 fmt_table, "plcp_err:",727 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,728 delta_ofdm->plcp_err, max_ofdm->plcp_err);729 pos += scnprintf(buf + pos, bufsz - pos,730 fmt_table, "crc32_err:",731 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,732 delta_ofdm->crc32_err, max_ofdm->crc32_err);733 pos += scnprintf(buf + pos, bufsz - pos,734 fmt_table, "overrun_err:",735 le32_to_cpu(ofdm->overrun_err),736 accum_ofdm->overrun_err, delta_ofdm->overrun_err,737 max_ofdm->overrun_err);738 pos += scnprintf(buf + pos, bufsz - pos,739 fmt_table, "early_overrun_err:",740 le32_to_cpu(ofdm->early_overrun_err),741 accum_ofdm->early_overrun_err,742 delta_ofdm->early_overrun_err,743 max_ofdm->early_overrun_err);744 pos += scnprintf(buf + pos, bufsz - pos,745 fmt_table, "crc32_good:",746 le32_to_cpu(ofdm->crc32_good),747 accum_ofdm->crc32_good, delta_ofdm->crc32_good,748 max_ofdm->crc32_good);749 pos += scnprintf(buf + pos, bufsz - pos,750 fmt_table, "false_alarm_cnt:",751 le32_to_cpu(ofdm->false_alarm_cnt),752 accum_ofdm->false_alarm_cnt,753 delta_ofdm->false_alarm_cnt,754 max_ofdm->false_alarm_cnt);755 pos += scnprintf(buf + pos, bufsz - pos,756 fmt_table, "fina_sync_err_cnt:",757 le32_to_cpu(ofdm->fina_sync_err_cnt),758 accum_ofdm->fina_sync_err_cnt,759 delta_ofdm->fina_sync_err_cnt,760 max_ofdm->fina_sync_err_cnt);761 pos += scnprintf(buf + pos, bufsz - pos,762 fmt_table, "sfd_timeout:",763 le32_to_cpu(ofdm->sfd_timeout),764 accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout,765 max_ofdm->sfd_timeout);766 pos += scnprintf(buf + pos, bufsz - pos,767 fmt_table, "fina_timeout:",768 le32_to_cpu(ofdm->fina_timeout),769 accum_ofdm->fina_timeout, delta_ofdm->fina_timeout,770 max_ofdm->fina_timeout);771 pos += scnprintf(buf + pos, bufsz - pos,772 fmt_table, "unresponded_rts:",773 le32_to_cpu(ofdm->unresponded_rts),774 accum_ofdm->unresponded_rts,775 delta_ofdm->unresponded_rts,776 max_ofdm->unresponded_rts);777 pos += scnprintf(buf + pos, bufsz - pos,778 fmt_table, "rxe_frame_lmt_ovrun:",779 le32_to_cpu(ofdm->rxe_frame_limit_overrun),780 accum_ofdm->rxe_frame_limit_overrun,781 delta_ofdm->rxe_frame_limit_overrun,782 max_ofdm->rxe_frame_limit_overrun);783 pos += scnprintf(buf + pos, bufsz - pos,784 fmt_table, "sent_ack_cnt:",785 le32_to_cpu(ofdm->sent_ack_cnt),786 accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt,787 max_ofdm->sent_ack_cnt);788 pos += scnprintf(buf + pos, bufsz - pos,789 fmt_table, "sent_cts_cnt:",790 le32_to_cpu(ofdm->sent_cts_cnt),791 accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt,792 max_ofdm->sent_cts_cnt);793 pos += scnprintf(buf + pos, bufsz - pos,794 fmt_table, "sent_ba_rsp_cnt:",795 le32_to_cpu(ofdm->sent_ba_rsp_cnt),796 accum_ofdm->sent_ba_rsp_cnt,797 delta_ofdm->sent_ba_rsp_cnt,798 max_ofdm->sent_ba_rsp_cnt);799 pos += scnprintf(buf + pos, bufsz - pos,800 fmt_table, "dsp_self_kill:",801 le32_to_cpu(ofdm->dsp_self_kill),802 accum_ofdm->dsp_self_kill,803 delta_ofdm->dsp_self_kill,804 max_ofdm->dsp_self_kill);805 pos += scnprintf(buf + pos, bufsz - pos,806 fmt_table, "mh_format_err:",807 le32_to_cpu(ofdm->mh_format_err),808 accum_ofdm->mh_format_err,809 delta_ofdm->mh_format_err,810 max_ofdm->mh_format_err);811 pos += scnprintf(buf + pos, bufsz - pos,812 fmt_table, "re_acq_main_rssi_sum:",813 le32_to_cpu(ofdm->re_acq_main_rssi_sum),814 accum_ofdm->re_acq_main_rssi_sum,815 delta_ofdm->re_acq_main_rssi_sum,816 max_ofdm->re_acq_main_rssi_sum);817 818 pos += scnprintf(buf + pos, bufsz - pos,819 fmt_header, "Statistics_Rx - CCK:");820 pos += scnprintf(buf + pos, bufsz - pos,821 fmt_table, "ina_cnt:",822 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,823 delta_cck->ina_cnt, max_cck->ina_cnt);824 pos += scnprintf(buf + pos, bufsz - pos,825 fmt_table, "fina_cnt:",826 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,827 delta_cck->fina_cnt, max_cck->fina_cnt);828 pos += scnprintf(buf + pos, bufsz - pos,829 fmt_table, "plcp_err:",830 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,831 delta_cck->plcp_err, max_cck->plcp_err);832 pos += scnprintf(buf + pos, bufsz - pos,833 fmt_table, "crc32_err:",834 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,835 delta_cck->crc32_err, max_cck->crc32_err);836 pos += scnprintf(buf + pos, bufsz - pos,837 fmt_table, "overrun_err:",838 le32_to_cpu(cck->overrun_err),839 accum_cck->overrun_err, delta_cck->overrun_err,840 max_cck->overrun_err);841 pos += scnprintf(buf + pos, bufsz - pos,842 fmt_table, "early_overrun_err:",843 le32_to_cpu(cck->early_overrun_err),844 accum_cck->early_overrun_err,845 delta_cck->early_overrun_err,846 max_cck->early_overrun_err);847 pos += scnprintf(buf + pos, bufsz - pos,848 fmt_table, "crc32_good:",849 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,850 delta_cck->crc32_good, max_cck->crc32_good);851 pos += scnprintf(buf + pos, bufsz - pos,852 fmt_table, "false_alarm_cnt:",853 le32_to_cpu(cck->false_alarm_cnt),854 accum_cck->false_alarm_cnt,855 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);856 pos += scnprintf(buf + pos, bufsz - pos,857 fmt_table, "fina_sync_err_cnt:",858 le32_to_cpu(cck->fina_sync_err_cnt),859 accum_cck->fina_sync_err_cnt,860 delta_cck->fina_sync_err_cnt,861 max_cck->fina_sync_err_cnt);862 pos += scnprintf(buf + pos, bufsz - pos,863 fmt_table, "sfd_timeout:",864 le32_to_cpu(cck->sfd_timeout),865 accum_cck->sfd_timeout, delta_cck->sfd_timeout,866 max_cck->sfd_timeout);867 pos += scnprintf(buf + pos, bufsz - pos,868 fmt_table, "fina_timeout:",869 le32_to_cpu(cck->fina_timeout),870 accum_cck->fina_timeout, delta_cck->fina_timeout,871 max_cck->fina_timeout);872 pos += scnprintf(buf + pos, bufsz - pos,873 fmt_table, "unresponded_rts:",874 le32_to_cpu(cck->unresponded_rts),875 accum_cck->unresponded_rts, delta_cck->unresponded_rts,876 max_cck->unresponded_rts);877 pos += scnprintf(buf + pos, bufsz - pos,878 fmt_table, "rxe_frame_lmt_ovrun:",879 le32_to_cpu(cck->rxe_frame_limit_overrun),880 accum_cck->rxe_frame_limit_overrun,881 delta_cck->rxe_frame_limit_overrun,882 max_cck->rxe_frame_limit_overrun);883 pos += scnprintf(buf + pos, bufsz - pos,884 fmt_table, "sent_ack_cnt:",885 le32_to_cpu(cck->sent_ack_cnt),886 accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt,887 max_cck->sent_ack_cnt);888 pos += scnprintf(buf + pos, bufsz - pos,889 fmt_table, "sent_cts_cnt:",890 le32_to_cpu(cck->sent_cts_cnt),891 accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt,892 max_cck->sent_cts_cnt);893 pos += scnprintf(buf + pos, bufsz - pos,894 fmt_table, "sent_ba_rsp_cnt:",895 le32_to_cpu(cck->sent_ba_rsp_cnt),896 accum_cck->sent_ba_rsp_cnt,897 delta_cck->sent_ba_rsp_cnt,898 max_cck->sent_ba_rsp_cnt);899 pos += scnprintf(buf + pos, bufsz - pos,900 fmt_table, "dsp_self_kill:",901 le32_to_cpu(cck->dsp_self_kill),902 accum_cck->dsp_self_kill, delta_cck->dsp_self_kill,903 max_cck->dsp_self_kill);904 pos += scnprintf(buf + pos, bufsz - pos,905 fmt_table, "mh_format_err:",906 le32_to_cpu(cck->mh_format_err),907 accum_cck->mh_format_err, delta_cck->mh_format_err,908 max_cck->mh_format_err);909 pos += scnprintf(buf + pos, bufsz - pos,910 fmt_table, "re_acq_main_rssi_sum:",911 le32_to_cpu(cck->re_acq_main_rssi_sum),912 accum_cck->re_acq_main_rssi_sum,913 delta_cck->re_acq_main_rssi_sum,914 max_cck->re_acq_main_rssi_sum);915 916 pos += scnprintf(buf + pos, bufsz - pos,917 fmt_header, "Statistics_Rx - GENERAL:");918 pos += scnprintf(buf + pos, bufsz - pos,919 fmt_table, "bogus_cts:",920 le32_to_cpu(general->bogus_cts),921 accum_general->bogus_cts, delta_general->bogus_cts,922 max_general->bogus_cts);923 pos += scnprintf(buf + pos, bufsz - pos,924 fmt_table, "bogus_ack:",925 le32_to_cpu(general->bogus_ack),926 accum_general->bogus_ack, delta_general->bogus_ack,927 max_general->bogus_ack);928 pos += scnprintf(buf + pos, bufsz - pos,929 fmt_table, "non_bssid_frames:",930 le32_to_cpu(general->non_bssid_frames),931 accum_general->non_bssid_frames,932 delta_general->non_bssid_frames,933 max_general->non_bssid_frames);934 pos += scnprintf(buf + pos, bufsz - pos,935 fmt_table, "filtered_frames:",936 le32_to_cpu(general->filtered_frames),937 accum_general->filtered_frames,938 delta_general->filtered_frames,939 max_general->filtered_frames);940 pos += scnprintf(buf + pos, bufsz - pos,941 fmt_table, "non_channel_beacons:",942 le32_to_cpu(general->non_channel_beacons),943 accum_general->non_channel_beacons,944 delta_general->non_channel_beacons,945 max_general->non_channel_beacons);946 pos += scnprintf(buf + pos, bufsz - pos,947 fmt_table, "channel_beacons:",948 le32_to_cpu(general->channel_beacons),949 accum_general->channel_beacons,950 delta_general->channel_beacons,951 max_general->channel_beacons);952 pos += scnprintf(buf + pos, bufsz - pos,953 fmt_table, "num_missed_bcon:",954 le32_to_cpu(general->num_missed_bcon),955 accum_general->num_missed_bcon,956 delta_general->num_missed_bcon,957 max_general->num_missed_bcon);958 pos += scnprintf(buf + pos, bufsz - pos,959 fmt_table, "adc_rx_saturation_time:",960 le32_to_cpu(general->adc_rx_saturation_time),961 accum_general->adc_rx_saturation_time,962 delta_general->adc_rx_saturation_time,963 max_general->adc_rx_saturation_time);964 pos += scnprintf(buf + pos, bufsz - pos,965 fmt_table, "ina_detect_search_tm:",966 le32_to_cpu(general->ina_detection_search_time),967 accum_general->ina_detection_search_time,968 delta_general->ina_detection_search_time,969 max_general->ina_detection_search_time);970 pos += scnprintf(buf + pos, bufsz - pos,971 fmt_table, "beacon_silence_rssi_a:",972 le32_to_cpu(general->beacon_silence_rssi_a),973 accum_general->beacon_silence_rssi_a,974 delta_general->beacon_silence_rssi_a,975 max_general->beacon_silence_rssi_a);976 pos += scnprintf(buf + pos, bufsz - pos,977 fmt_table, "beacon_silence_rssi_b:",978 le32_to_cpu(general->beacon_silence_rssi_b),979 accum_general->beacon_silence_rssi_b,980 delta_general->beacon_silence_rssi_b,981 max_general->beacon_silence_rssi_b);982 pos += scnprintf(buf + pos, bufsz - pos,983 fmt_table, "beacon_silence_rssi_c:",984 le32_to_cpu(general->beacon_silence_rssi_c),985 accum_general->beacon_silence_rssi_c,986 delta_general->beacon_silence_rssi_c,987 max_general->beacon_silence_rssi_c);988 pos += scnprintf(buf + pos, bufsz - pos,989 fmt_table, "interference_data_flag:",990 le32_to_cpu(general->interference_data_flag),991 accum_general->interference_data_flag,992 delta_general->interference_data_flag,993 max_general->interference_data_flag);994 pos += scnprintf(buf + pos, bufsz - pos,995 fmt_table, "channel_load:",996 le32_to_cpu(general->channel_load),997 accum_general->channel_load,998 delta_general->channel_load,999 max_general->channel_load);1000 pos += scnprintf(buf + pos, bufsz - pos,1001 fmt_table, "dsp_false_alarms:",1002 le32_to_cpu(general->dsp_false_alarms),1003 accum_general->dsp_false_alarms,1004 delta_general->dsp_false_alarms,1005 max_general->dsp_false_alarms);1006 pos += scnprintf(buf + pos, bufsz - pos,1007 fmt_table, "beacon_rssi_a:",1008 le32_to_cpu(general->beacon_rssi_a),1009 accum_general->beacon_rssi_a,1010 delta_general->beacon_rssi_a,1011 max_general->beacon_rssi_a);1012 pos += scnprintf(buf + pos, bufsz - pos,1013 fmt_table, "beacon_rssi_b:",1014 le32_to_cpu(general->beacon_rssi_b),1015 accum_general->beacon_rssi_b,1016 delta_general->beacon_rssi_b,1017 max_general->beacon_rssi_b);1018 pos += scnprintf(buf + pos, bufsz - pos,1019 fmt_table, "beacon_rssi_c:",1020 le32_to_cpu(general->beacon_rssi_c),1021 accum_general->beacon_rssi_c,1022 delta_general->beacon_rssi_c,1023 max_general->beacon_rssi_c);1024 pos += scnprintf(buf + pos, bufsz - pos,1025 fmt_table, "beacon_energy_a:",1026 le32_to_cpu(general->beacon_energy_a),1027 accum_general->beacon_energy_a,1028 delta_general->beacon_energy_a,1029 max_general->beacon_energy_a);1030 pos += scnprintf(buf + pos, bufsz - pos,1031 fmt_table, "beacon_energy_b:",1032 le32_to_cpu(general->beacon_energy_b),1033 accum_general->beacon_energy_b,1034 delta_general->beacon_energy_b,1035 max_general->beacon_energy_b);1036 pos += scnprintf(buf + pos, bufsz - pos,1037 fmt_table, "beacon_energy_c:",1038 le32_to_cpu(general->beacon_energy_c),1039 accum_general->beacon_energy_c,1040 delta_general->beacon_energy_c,1041 max_general->beacon_energy_c);1042 1043 pos += scnprintf(buf + pos, bufsz - pos,1044 fmt_header, "Statistics_Rx - OFDM_HT:");1045 pos += scnprintf(buf + pos, bufsz - pos,1046 fmt_table, "plcp_err:",1047 le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,1048 delta_ht->plcp_err, max_ht->plcp_err);1049 pos += scnprintf(buf + pos, bufsz - pos,1050 fmt_table, "overrun_err:",1051 le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,1052 delta_ht->overrun_err, max_ht->overrun_err);1053 pos += scnprintf(buf + pos, bufsz - pos,1054 fmt_table, "early_overrun_err:",1055 le32_to_cpu(ht->early_overrun_err),1056 accum_ht->early_overrun_err,1057 delta_ht->early_overrun_err,1058 max_ht->early_overrun_err);1059 pos += scnprintf(buf + pos, bufsz - pos,1060 fmt_table, "crc32_good:",1061 le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,1062 delta_ht->crc32_good, max_ht->crc32_good);1063 pos += scnprintf(buf + pos, bufsz - pos,1064 fmt_table, "crc32_err:",1065 le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,1066 delta_ht->crc32_err, max_ht->crc32_err);1067 pos += scnprintf(buf + pos, bufsz - pos,1068 fmt_table, "mh_format_err:",1069 le32_to_cpu(ht->mh_format_err),1070 accum_ht->mh_format_err,1071 delta_ht->mh_format_err, max_ht->mh_format_err);1072 pos += scnprintf(buf + pos, bufsz - pos,1073 fmt_table, "agg_crc32_good:",1074 le32_to_cpu(ht->agg_crc32_good),1075 accum_ht->agg_crc32_good,1076 delta_ht->agg_crc32_good, max_ht->agg_crc32_good);1077 pos += scnprintf(buf + pos, bufsz - pos,1078 fmt_table, "agg_mpdu_cnt:",1079 le32_to_cpu(ht->agg_mpdu_cnt),1080 accum_ht->agg_mpdu_cnt,1081 delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);1082 pos += scnprintf(buf + pos, bufsz - pos,1083 fmt_table, "agg_cnt:",1084 le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,1085 delta_ht->agg_cnt, max_ht->agg_cnt);1086 pos += scnprintf(buf + pos, bufsz - pos,1087 fmt_table, "unsupport_mcs:",1088 le32_to_cpu(ht->unsupport_mcs),1089 accum_ht->unsupport_mcs,1090 delta_ht->unsupport_mcs, max_ht->unsupport_mcs);1091 1092 spin_unlock_bh(&priv->statistics.lock);1093 1094 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);1095 kfree(buf);1096 return ret;1097}1098 1099static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,1100 char __user *user_buf,1101 size_t count, loff_t *ppos)1102{1103 struct iwl_priv *priv = file->private_data;1104 int pos = 0;1105 char *buf;1106 int bufsz = (sizeof(struct statistics_tx) * 48) + 250;1107 ssize_t ret;1108 struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;1109 1110 if (!iwl_is_alive(priv))1111 return -EAGAIN;1112 1113 buf = kzalloc(bufsz, GFP_KERNEL);1114 if (!buf)1115 return -ENOMEM;1116 1117 /* the statistic information display here is based on1118 * the last statistics notification from uCode1119 * might not reflect the current uCode activity1120 */1121 spin_lock_bh(&priv->statistics.lock);1122 1123 tx = &priv->statistics.tx;1124 accum_tx = &priv->accum_stats.tx;1125 delta_tx = &priv->delta_stats.tx;1126 max_tx = &priv->max_delta_stats.tx;1127 1128 pos += iwl_statistics_flag(priv, buf, bufsz);1129 pos += scnprintf(buf + pos, bufsz - pos,1130 fmt_header, "Statistics_Tx:");1131 pos += scnprintf(buf + pos, bufsz - pos,1132 fmt_table, "preamble:",1133 le32_to_cpu(tx->preamble_cnt),1134 accum_tx->preamble_cnt,1135 delta_tx->preamble_cnt, max_tx->preamble_cnt);1136 pos += scnprintf(buf + pos, bufsz - pos,1137 fmt_table, "rx_detected_cnt:",1138 le32_to_cpu(tx->rx_detected_cnt),1139 accum_tx->rx_detected_cnt,1140 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);1141 pos += scnprintf(buf + pos, bufsz - pos,1142 fmt_table, "bt_prio_defer_cnt:",1143 le32_to_cpu(tx->bt_prio_defer_cnt),1144 accum_tx->bt_prio_defer_cnt,1145 delta_tx->bt_prio_defer_cnt,1146 max_tx->bt_prio_defer_cnt);1147 pos += scnprintf(buf + pos, bufsz - pos,1148 fmt_table, "bt_prio_kill_cnt:",1149 le32_to_cpu(tx->bt_prio_kill_cnt),1150 accum_tx->bt_prio_kill_cnt,1151 delta_tx->bt_prio_kill_cnt,1152 max_tx->bt_prio_kill_cnt);1153 pos += scnprintf(buf + pos, bufsz - pos,1154 fmt_table, "few_bytes_cnt:",1155 le32_to_cpu(tx->few_bytes_cnt),1156 accum_tx->few_bytes_cnt,1157 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);1158 pos += scnprintf(buf + pos, bufsz - pos,1159 fmt_table, "cts_timeout:",1160 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,1161 delta_tx->cts_timeout, max_tx->cts_timeout);1162 pos += scnprintf(buf + pos, bufsz - pos,1163 fmt_table, "ack_timeout:",1164 le32_to_cpu(tx->ack_timeout),1165 accum_tx->ack_timeout,1166 delta_tx->ack_timeout, max_tx->ack_timeout);1167 pos += scnprintf(buf + pos, bufsz - pos,1168 fmt_table, "expected_ack_cnt:",1169 le32_to_cpu(tx->expected_ack_cnt),1170 accum_tx->expected_ack_cnt,1171 delta_tx->expected_ack_cnt,1172 max_tx->expected_ack_cnt);1173 pos += scnprintf(buf + pos, bufsz - pos,1174 fmt_table, "actual_ack_cnt:",1175 le32_to_cpu(tx->actual_ack_cnt),1176 accum_tx->actual_ack_cnt,1177 delta_tx->actual_ack_cnt,1178 max_tx->actual_ack_cnt);1179 pos += scnprintf(buf + pos, bufsz - pos,1180 fmt_table, "dump_msdu_cnt:",1181 le32_to_cpu(tx->dump_msdu_cnt),1182 accum_tx->dump_msdu_cnt,1183 delta_tx->dump_msdu_cnt,1184 max_tx->dump_msdu_cnt);1185 pos += scnprintf(buf + pos, bufsz - pos,1186 fmt_table, "abort_nxt_frame_mismatch:",1187 le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),1188 accum_tx->burst_abort_next_frame_mismatch_cnt,1189 delta_tx->burst_abort_next_frame_mismatch_cnt,1190 max_tx->burst_abort_next_frame_mismatch_cnt);1191 pos += scnprintf(buf + pos, bufsz - pos,1192 fmt_table, "abort_missing_nxt_frame:",1193 le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),1194 accum_tx->burst_abort_missing_next_frame_cnt,1195 delta_tx->burst_abort_missing_next_frame_cnt,1196 max_tx->burst_abort_missing_next_frame_cnt);1197 pos += scnprintf(buf + pos, bufsz - pos,1198 fmt_table, "cts_timeout_collision:",1199 le32_to_cpu(tx->cts_timeout_collision),1200 accum_tx->cts_timeout_collision,1201 delta_tx->cts_timeout_collision,1202 max_tx->cts_timeout_collision);1203 pos += scnprintf(buf + pos, bufsz - pos,1204 fmt_table, "ack_ba_timeout_collision:",1205 le32_to_cpu(tx->ack_or_ba_timeout_collision),1206 accum_tx->ack_or_ba_timeout_collision,1207 delta_tx->ack_or_ba_timeout_collision,1208 max_tx->ack_or_ba_timeout_collision);1209 pos += scnprintf(buf + pos, bufsz - pos,1210 fmt_table, "agg ba_timeout:",1211 le32_to_cpu(tx->agg.ba_timeout),1212 accum_tx->agg.ba_timeout,1213 delta_tx->agg.ba_timeout,1214 max_tx->agg.ba_timeout);1215 pos += scnprintf(buf + pos, bufsz - pos,1216 fmt_table, "agg ba_resched_frames:",1217 le32_to_cpu(tx->agg.ba_reschedule_frames),1218 accum_tx->agg.ba_reschedule_frames,1219 delta_tx->agg.ba_reschedule_frames,1220 max_tx->agg.ba_reschedule_frames);1221 pos += scnprintf(buf + pos, bufsz - pos,1222 fmt_table, "agg scd_query_agg_frame:",1223 le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),1224 accum_tx->agg.scd_query_agg_frame_cnt,1225 delta_tx->agg.scd_query_agg_frame_cnt,1226 max_tx->agg.scd_query_agg_frame_cnt);1227 pos += scnprintf(buf + pos, bufsz - pos,1228 fmt_table, "agg scd_query_no_agg:",1229 le32_to_cpu(tx->agg.scd_query_no_agg),1230 accum_tx->agg.scd_query_no_agg,1231 delta_tx->agg.scd_query_no_agg,1232 max_tx->agg.scd_query_no_agg);1233 pos += scnprintf(buf + pos, bufsz - pos,1234 fmt_table, "agg scd_query_agg:",1235 le32_to_cpu(tx->agg.scd_query_agg),1236 accum_tx->agg.scd_query_agg,1237 delta_tx->agg.scd_query_agg,1238 max_tx->agg.scd_query_agg);1239 pos += scnprintf(buf + pos, bufsz - pos,1240 fmt_table, "agg scd_query_mismatch:",1241 le32_to_cpu(tx->agg.scd_query_mismatch),1242 accum_tx->agg.scd_query_mismatch,1243 delta_tx->agg.scd_query_mismatch,1244 max_tx->agg.scd_query_mismatch);1245 pos += scnprintf(buf + pos, bufsz - pos,1246 fmt_table, "agg frame_not_ready:",1247 le32_to_cpu(tx->agg.frame_not_ready),1248 accum_tx->agg.frame_not_ready,1249 delta_tx->agg.frame_not_ready,1250 max_tx->agg.frame_not_ready);1251 pos += scnprintf(buf + pos, bufsz - pos,1252 fmt_table, "agg underrun:",1253 le32_to_cpu(tx->agg.underrun),1254 accum_tx->agg.underrun,1255 delta_tx->agg.underrun, max_tx->agg.underrun);1256 pos += scnprintf(buf + pos, bufsz - pos,1257 fmt_table, "agg bt_prio_kill:",1258 le32_to_cpu(tx->agg.bt_prio_kill),1259 accum_tx->agg.bt_prio_kill,1260 delta_tx->agg.bt_prio_kill,1261 max_tx->agg.bt_prio_kill);1262 pos += scnprintf(buf + pos, bufsz - pos,1263 fmt_table, "agg rx_ba_rsp_cnt:",1264 le32_to_cpu(tx->agg.rx_ba_rsp_cnt),1265 accum_tx->agg.rx_ba_rsp_cnt,1266 delta_tx->agg.rx_ba_rsp_cnt,1267 max_tx->agg.rx_ba_rsp_cnt);1268 1269 if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {1270 pos += scnprintf(buf + pos, bufsz - pos,1271 "tx power: (1/2 dB step)\n");1272 if ((priv->nvm_data->valid_tx_ant & ANT_A) &&1273 tx->tx_power.ant_a)1274 pos += scnprintf(buf + pos, bufsz - pos,1275 fmt_hex, "antenna A:",1276 tx->tx_power.ant_a);1277 if ((priv->nvm_data->valid_tx_ant & ANT_B) &&1278 tx->tx_power.ant_b)1279 pos += scnprintf(buf + pos, bufsz - pos,1280 fmt_hex, "antenna B:",1281 tx->tx_power.ant_b);1282 if ((priv->nvm_data->valid_tx_ant & ANT_C) &&1283 tx->tx_power.ant_c)1284 pos += scnprintf(buf + pos, bufsz - pos,1285 fmt_hex, "antenna C:",1286 tx->tx_power.ant_c);1287 }1288 1289 spin_unlock_bh(&priv->statistics.lock);1290 1291 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);1292 kfree(buf);1293 return ret;1294}1295 1296static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,1297 char __user *user_buf,1298 size_t count, loff_t *ppos)1299{1300 struct iwl_priv *priv = file->private_data;1301 int pos = 0;1302 char *buf;1303 int bufsz = sizeof(struct statistics_general) * 10 + 300;1304 ssize_t ret;1305 struct statistics_general_common *general, *accum_general;1306 struct statistics_general_common *delta_general, *max_general;1307 struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;1308 struct statistics_div *div, *accum_div, *delta_div, *max_div;1309 1310 if (!iwl_is_alive(priv))1311 return -EAGAIN;1312 1313 buf = kzalloc(bufsz, GFP_KERNEL);1314 if (!buf)1315 return -ENOMEM;1316 1317 /* the statistic information display here is based on1318 * the last statistics notification from uCode1319 * might not reflect the current uCode activity1320 */1321 1322 spin_lock_bh(&priv->statistics.lock);1323 1324 general = &priv->statistics.common;1325 dbg = &priv->statistics.common.dbg;1326 div = &priv->statistics.common.div;1327 accum_general = &priv->accum_stats.common;1328 accum_dbg = &priv->accum_stats.common.dbg;1329 accum_div = &priv->accum_stats.common.div;1330 delta_general = &priv->delta_stats.common;1331 max_general = &priv->max_delta_stats.common;1332 delta_dbg = &priv->delta_stats.common.dbg;1333 max_dbg = &priv->max_delta_stats.common.dbg;1334 delta_div = &priv->delta_stats.common.div;1335 max_div = &priv->max_delta_stats.common.div;1336 1337 pos += iwl_statistics_flag(priv, buf, bufsz);1338 pos += scnprintf(buf + pos, bufsz - pos,1339 fmt_header, "Statistics_General:");1340 pos += scnprintf(buf + pos, bufsz - pos,1341 fmt_value, "temperature:",1342 le32_to_cpu(general->temperature));1343 pos += scnprintf(buf + pos, bufsz - pos,1344 fmt_value, "temperature_m:",1345 le32_to_cpu(general->temperature_m));1346 pos += scnprintf(buf + pos, bufsz - pos,1347 fmt_value, "ttl_timestamp:",1348 le32_to_cpu(general->ttl_timestamp));1349 pos += scnprintf(buf + pos, bufsz - pos,1350 fmt_table, "burst_check:",1351 le32_to_cpu(dbg->burst_check),1352 accum_dbg->burst_check,1353 delta_dbg->burst_check, max_dbg->burst_check);1354 pos += scnprintf(buf + pos, bufsz - pos,1355 fmt_table, "burst_count:",1356 le32_to_cpu(dbg->burst_count),1357 accum_dbg->burst_count,1358 delta_dbg->burst_count, max_dbg->burst_count);1359 pos += scnprintf(buf + pos, bufsz - pos,1360 fmt_table, "wait_for_silence_timeout_count:",1361 le32_to_cpu(dbg->wait_for_silence_timeout_cnt),1362 accum_dbg->wait_for_silence_timeout_cnt,1363 delta_dbg->wait_for_silence_timeout_cnt,1364 max_dbg->wait_for_silence_timeout_cnt);1365 pos += scnprintf(buf + pos, bufsz - pos,1366 fmt_table, "sleep_time:",1367 le32_to_cpu(general->sleep_time),1368 accum_general->sleep_time,1369 delta_general->sleep_time, max_general->sleep_time);1370 pos += scnprintf(buf + pos, bufsz - pos,1371 fmt_table, "slots_out:",1372 le32_to_cpu(general->slots_out),1373 accum_general->slots_out,1374 delta_general->slots_out, max_general->slots_out);1375 pos += scnprintf(buf + pos, bufsz - pos,1376 fmt_table, "slots_idle:",1377 le32_to_cpu(general->slots_idle),1378 accum_general->slots_idle,1379 delta_general->slots_idle, max_general->slots_idle);1380 pos += scnprintf(buf + pos, bufsz - pos,1381 fmt_table, "tx_on_a:",1382 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,1383 delta_div->tx_on_a, max_div->tx_on_a);1384 pos += scnprintf(buf + pos, bufsz - pos,1385 fmt_table, "tx_on_b:",1386 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,1387 delta_div->tx_on_b, max_div->tx_on_b);1388 pos += scnprintf(buf + pos, bufsz - pos,1389 fmt_table, "exec_time:",1390 le32_to_cpu(div->exec_time), accum_div->exec_time,1391 delta_div->exec_time, max_div->exec_time);1392 pos += scnprintf(buf + pos, bufsz - pos,1393 fmt_table, "probe_time:",1394 le32_to_cpu(div->probe_time), accum_div->probe_time,1395 delta_div->probe_time, max_div->probe_time);1396 pos += scnprintf(buf + pos, bufsz - pos,1397 fmt_table, "rx_enable_counter:",1398 le32_to_cpu(general->rx_enable_counter),1399 accum_general->rx_enable_counter,1400 delta_general->rx_enable_counter,1401 max_general->rx_enable_counter);1402 pos += scnprintf(buf + pos, bufsz - pos,1403 fmt_table, "num_of_sos_states:",1404 le32_to_cpu(general->num_of_sos_states),1405 accum_general->num_of_sos_states,1406 delta_general->num_of_sos_states,1407 max_general->num_of_sos_states);1408 1409 spin_unlock_bh(&priv->statistics.lock);1410 1411 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);1412 kfree(buf);1413 return ret;1414}1415 1416static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,1417 char __user *user_buf,1418 size_t count, loff_t *ppos)1419{1420 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;1421 int pos = 0;1422 char *buf;1423 int bufsz = (sizeof(struct statistics_bt_activity) * 24) + 200;1424 ssize_t ret;1425 struct statistics_bt_activity *bt, *accum_bt;1426 1427 if (!iwl_is_alive(priv))1428 return -EAGAIN;1429 1430 if (!priv->bt_enable_flag)1431 return -EINVAL;1432 1433 /* make request to uCode to retrieve statistics information */1434 mutex_lock(&priv->mutex);1435 ret = iwl_send_statistics_request(priv, 0, false);1436 mutex_unlock(&priv->mutex);1437 1438 if (ret)1439 return -EAGAIN;1440 buf = kzalloc(bufsz, GFP_KERNEL);1441 if (!buf)1442 return -ENOMEM;1443 1444 /*1445 * the statistic information display here is based on1446 * the last statistics notification from uCode1447 * might not reflect the current uCode activity1448 */1449 1450 spin_lock_bh(&priv->statistics.lock);1451 1452 bt = &priv->statistics.bt_activity;1453 accum_bt = &priv->accum_stats.bt_activity;1454 1455 pos += iwl_statistics_flag(priv, buf, bufsz);1456 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n");1457 pos += scnprintf(buf + pos, bufsz - pos,1458 "\t\t\tcurrent\t\t\taccumulative\n");1459 pos += scnprintf(buf + pos, bufsz - pos,1460 "hi_priority_tx_req_cnt:\t\t%u\t\t\t%u\n",1461 le32_to_cpu(bt->hi_priority_tx_req_cnt),1462 accum_bt->hi_priority_tx_req_cnt);1463 pos += scnprintf(buf + pos, bufsz - pos,1464 "hi_priority_tx_denied_cnt:\t%u\t\t\t%u\n",1465 le32_to_cpu(bt->hi_priority_tx_denied_cnt),1466 accum_bt->hi_priority_tx_denied_cnt);1467 pos += scnprintf(buf + pos, bufsz - pos,1468 "lo_priority_tx_req_cnt:\t\t%u\t\t\t%u\n",1469 le32_to_cpu(bt->lo_priority_tx_req_cnt),1470 accum_bt->lo_priority_tx_req_cnt);1471 pos += scnprintf(buf + pos, bufsz - pos,1472 "lo_priority_tx_denied_cnt:\t%u\t\t\t%u\n",1473 le32_to_cpu(bt->lo_priority_tx_denied_cnt),1474 accum_bt->lo_priority_tx_denied_cnt);1475 pos += scnprintf(buf + pos, bufsz - pos,1476 "hi_priority_rx_req_cnt:\t\t%u\t\t\t%u\n",1477 le32_to_cpu(bt->hi_priority_rx_req_cnt),1478 accum_bt->hi_priority_rx_req_cnt);1479 pos += scnprintf(buf + pos, bufsz - pos,1480 "hi_priority_rx_denied_cnt:\t%u\t\t\t%u\n",1481 le32_to_cpu(bt->hi_priority_rx_denied_cnt),1482 accum_bt->hi_priority_rx_denied_cnt);1483 pos += scnprintf(buf + pos, bufsz - pos,1484 "lo_priority_rx_req_cnt:\t\t%u\t\t\t%u\n",1485 le32_to_cpu(bt->lo_priority_rx_req_cnt),1486 accum_bt->lo_priority_rx_req_cnt);1487 pos += scnprintf(buf + pos, bufsz - pos,1488 "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n",1489 le32_to_cpu(bt->lo_priority_rx_denied_cnt),1490 accum_bt->lo_priority_rx_denied_cnt);1491 1492 pos += scnprintf(buf + pos, bufsz - pos,1493 "(rx)num_bt_kills:\t\t%u\t\t\t%u\n",1494 le32_to_cpu(priv->statistics.num_bt_kills),1495 priv->statistics.accum_num_bt_kills);1496 1497 spin_unlock_bh(&priv->statistics.lock);1498 1499 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);1500 kfree(buf);1501 return ret;1502}1503 1504static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,1505 char __user *user_buf,1506 size_t count, loff_t *ppos)1507{1508 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;1509 int pos = 0;1510 char *buf;1511 int bufsz = (sizeof(struct reply_tx_error_statistics) * 24) +1512 (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200;1513 ssize_t ret;1514 1515 if (!iwl_is_alive(priv))1516 return -EAGAIN;1517 1518 buf = kzalloc(bufsz, GFP_KERNEL);1519 if (!buf)1520 return -ENOMEM;1521 1522 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n");1523 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n",1524 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY),1525 priv->reply_tx_stats.pp_delay);1526 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1527 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES),1528 priv->reply_tx_stats.pp_few_bytes);1529 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1530 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO),1531 priv->reply_tx_stats.pp_bt_prio);1532 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1533 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD),1534 priv->reply_tx_stats.pp_quiet_period);1535 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1536 iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK),1537 priv->reply_tx_stats.pp_calc_ttak);1538 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",1539 iwl_get_tx_fail_reason(1540 TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY),1541 priv->reply_tx_stats.int_crossed_retry);1542 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1543 iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT),1544 priv->reply_tx_stats.short_limit);1545 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1546 iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT),1547 priv->reply_tx_stats.long_limit);1548 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1549 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN),1550 priv->reply_tx_stats.fifo_underrun);1551 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1552 iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW),1553 priv->reply_tx_stats.drain_flow);1554 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1555 iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH),1556 priv->reply_tx_stats.rfkill_flush);1557 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1558 iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE),1559 priv->reply_tx_stats.life_expire);1560 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1561 iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS),1562 priv->reply_tx_stats.dest_ps);1563 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1564 iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED),1565 priv->reply_tx_stats.host_abort);1566 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1567 iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY),1568 priv->reply_tx_stats.pp_delay);1569 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1570 iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID),1571 priv->reply_tx_stats.sta_invalid);1572 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1573 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED),1574 priv->reply_tx_stats.frag_drop);1575 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1576 iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE),1577 priv->reply_tx_stats.tid_disable);1578 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1579 iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED),1580 priv->reply_tx_stats.fifo_flush);1581 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",1582 iwl_get_tx_fail_reason(1583 TX_STATUS_FAIL_INSUFFICIENT_CF_POLL),1584 priv->reply_tx_stats.insuff_cf_poll);1585 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1586 iwl_get_tx_fail_reason(TX_STATUS_FAIL_PASSIVE_NO_RX),1587 priv->reply_tx_stats.fail_hw_drop);1588 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",1589 iwl_get_tx_fail_reason(1590 TX_STATUS_FAIL_NO_BEACON_ON_RADAR),1591 priv->reply_tx_stats.sta_color_mismatch);1592 pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",1593 priv->reply_tx_stats.unknown);1594 1595 pos += scnprintf(buf + pos, bufsz - pos,1596 "\nStatistics_Agg_TX_Error:\n");1597 1598 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1599 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_UNDERRUN_MSK),1600 priv->reply_agg_tx_stats.underrun);1601 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1602 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_BT_PRIO_MSK),1603 priv->reply_agg_tx_stats.bt_prio);1604 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1605 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_FEW_BYTES_MSK),1606 priv->reply_agg_tx_stats.few_bytes);1607 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1608 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_ABORT_MSK),1609 priv->reply_agg_tx_stats.abort);1610 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",1611 iwl_get_agg_tx_fail_reason(1612 AGG_TX_STATE_LAST_SENT_TTL_MSK),1613 priv->reply_agg_tx_stats.last_sent_ttl);1614 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",1615 iwl_get_agg_tx_fail_reason(1616 AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK),1617 priv->reply_agg_tx_stats.last_sent_try);1618 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",1619 iwl_get_agg_tx_fail_reason(1620 AGG_TX_STATE_LAST_SENT_BT_KILL_MSK),1621 priv->reply_agg_tx_stats.last_sent_bt_kill);1622 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1623 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_SCD_QUERY_MSK),1624 priv->reply_agg_tx_stats.scd_query);1625 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",1626 iwl_get_agg_tx_fail_reason(1627 AGG_TX_STATE_TEST_BAD_CRC32_MSK),1628 priv->reply_agg_tx_stats.bad_crc32);1629 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1630 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_RESPONSE_MSK),1631 priv->reply_agg_tx_stats.response);1632 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1633 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DUMP_TX_MSK),1634 priv->reply_agg_tx_stats.dump_tx);1635 pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",1636 iwl_get_agg_tx_fail_reason(AGG_TX_STATE_DELAY_TX_MSK),1637 priv->reply_agg_tx_stats.delay_tx);1638 pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",1639 priv->reply_agg_tx_stats.unknown);1640 1641 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);1642 kfree(buf);1643 return ret;1644}1645 1646static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,1647 char __user *user_buf,1648 size_t count, loff_t *ppos) {1649 1650 struct iwl_priv *priv = file->private_data;1651 int pos = 0;1652 int cnt = 0;1653 char *buf;1654 int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;1655 ssize_t ret;1656 struct iwl_sensitivity_data *data;1657 1658 data = &priv->sensitivity_data;1659 buf = kzalloc(bufsz, GFP_KERNEL);1660 if (!buf)1661 return -ENOMEM;1662 1663 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",1664 data->auto_corr_ofdm);1665 pos += scnprintf(buf + pos, bufsz - pos,1666 "auto_corr_ofdm_mrc:\t\t %u\n",1667 data->auto_corr_ofdm_mrc);1668 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",1669 data->auto_corr_ofdm_x1);1670 pos += scnprintf(buf + pos, bufsz - pos,1671 "auto_corr_ofdm_mrc_x1:\t\t %u\n",1672 data->auto_corr_ofdm_mrc_x1);1673 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",1674 data->auto_corr_cck);1675 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",1676 data->auto_corr_cck_mrc);1677 pos += scnprintf(buf + pos, bufsz - pos,1678 "last_bad_plcp_cnt_ofdm:\t\t %u\n",1679 data->last_bad_plcp_cnt_ofdm);1680 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",1681 data->last_fa_cnt_ofdm);1682 pos += scnprintf(buf + pos, bufsz - pos,1683 "last_bad_plcp_cnt_cck:\t\t %u\n",1684 data->last_bad_plcp_cnt_cck);1685 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",1686 data->last_fa_cnt_cck);1687 pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",1688 data->nrg_curr_state);1689 pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",1690 data->nrg_prev_state);1691 pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");1692 for (cnt = 0; cnt < 10; cnt++) {1693 pos += scnprintf(buf + pos, bufsz - pos, " %u",1694 data->nrg_value[cnt]);1695 }1696 pos += scnprintf(buf + pos, bufsz - pos, "\n");1697 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");1698 for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {1699 pos += scnprintf(buf + pos, bufsz - pos, " %u",1700 data->nrg_silence_rssi[cnt]);1701 }1702 pos += scnprintf(buf + pos, bufsz - pos, "\n");1703 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",1704 data->nrg_silence_ref);1705 pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",1706 data->nrg_energy_idx);1707 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",1708 data->nrg_silence_idx);1709 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",1710 data->nrg_th_cck);1711 pos += scnprintf(buf + pos, bufsz - pos,1712 "nrg_auto_corr_silence_diff:\t %u\n",1713 data->nrg_auto_corr_silence_diff);1714 pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",1715 data->num_in_cck_no_fa);1716 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",1717 data->nrg_th_ofdm);1718 1719 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);1720 kfree(buf);1721 return ret;1722}1723 1724 1725static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,1726 char __user *user_buf,1727 size_t count, loff_t *ppos) {1728 1729 struct iwl_priv *priv = file->private_data;1730 int pos = 0;1731 int cnt = 0;1732 char *buf;1733 int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;1734 ssize_t ret;1735 struct iwl_chain_noise_data *data;1736 1737 data = &priv->chain_noise_data;1738 buf = kzalloc(bufsz, GFP_KERNEL);1739 if (!buf)1740 return -ENOMEM;1741 1742 pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",1743 data->active_chains);1744 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",1745 data->chain_noise_a);1746 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",1747 data->chain_noise_b);1748 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",1749 data->chain_noise_c);1750 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",1751 data->chain_signal_a);1752 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",1753 data->chain_signal_b);1754 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",1755 data->chain_signal_c);1756 pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",1757 data->beacon_count);1758 1759 pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");1760 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {1761 pos += scnprintf(buf + pos, bufsz - pos, " %u",1762 data->disconn_array[cnt]);1763 }1764 pos += scnprintf(buf + pos, bufsz - pos, "\n");1765 pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");1766 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {1767 pos += scnprintf(buf + pos, bufsz - pos, " %u",1768 data->delta_gain_code[cnt]);1769 }1770 pos += scnprintf(buf + pos, bufsz - pos, "\n");1771 pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",1772 data->radio_write);1773 pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",1774 data->state);1775 1776 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);1777 kfree(buf);1778 return ret;1779}1780 1781static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,1782 char __user *user_buf,1783 size_t count, loff_t *ppos)1784{1785 struct iwl_priv *priv = file->private_data;1786 char buf[60];1787 int pos = 0;1788 const size_t bufsz = sizeof(buf);1789 u32 pwrsave_status;1790 1791 pwrsave_status = iwl_read32(priv->trans, CSR_GP_CNTRL) &1792 CSR_GP_REG_POWER_SAVE_STATUS_MSK;1793 1794 pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");1795 pos += scnprintf(buf + pos, bufsz - pos, "%s\n",1796 (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :1797 (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :1798 (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :1799 "error");1800 1801 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);1802}1803 1804static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,1805 const char __user *user_buf,1806 size_t count, loff_t *ppos)1807{1808 struct iwl_priv *priv = file->private_data;1809 char buf[8];1810 int buf_size;1811 int clear;1812 1813 memset(buf, 0, sizeof(buf));1814 buf_size = min(count, sizeof(buf) - 1);1815 if (copy_from_user(buf, user_buf, buf_size))1816 return -EFAULT;1817 if (sscanf(buf, "%d", &clear) != 1)1818 return -EFAULT;1819 1820 /* make request to uCode to retrieve statistics information */1821 mutex_lock(&priv->mutex);1822 iwl_send_statistics_request(priv, 0, true);1823 mutex_unlock(&priv->mutex);1824 1825 return count;1826}1827 1828static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file,1829 char __user *user_buf,1830 size_t count, loff_t *ppos) {1831 1832 struct iwl_priv *priv = file->private_data;1833 int pos = 0;1834 char buf[128];1835 const size_t bufsz = sizeof(buf);1836 1837 pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",1838 priv->event_log.ucode_trace ? "On" : "Off");1839 pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",1840 priv->event_log.non_wraps_count);1841 pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",1842 priv->event_log.wraps_once_count);1843 pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",1844 priv->event_log.wraps_more_count);1845 1846 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);1847}1848 1849static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,1850 const char __user *user_buf,1851 size_t count, loff_t *ppos)1852{1853 struct iwl_priv *priv = file->private_data;1854 char buf[8];1855 int buf_size;1856 int trace;1857 1858 memset(buf, 0, sizeof(buf));1859 buf_size = min(count, sizeof(buf) - 1);1860 if (copy_from_user(buf, user_buf, buf_size))1861 return -EFAULT;1862 if (sscanf(buf, "%d", &trace) != 1)1863 return -EFAULT;1864 1865 if (trace) {1866 priv->event_log.ucode_trace = true;1867 if (iwl_is_alive(priv)) {1868 /* start collecting data now */1869 mod_timer(&priv->ucode_trace, jiffies);1870 }1871 } else {1872 priv->event_log.ucode_trace = false;1873 del_timer_sync(&priv->ucode_trace);1874 }1875 1876 return count;1877}1878 1879static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file,1880 char __user *user_buf,1881 size_t count, loff_t *ppos) {1882 1883 struct iwl_priv *priv = file->private_data;1884 int len = 0;1885 char buf[20];1886 1887 len = sprintf(buf, "0x%04X\n",1888 le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags));1889 return simple_read_from_buffer(user_buf, count, ppos, buf, len);1890}1891 1892static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file,1893 char __user *user_buf,1894 size_t count, loff_t *ppos) {1895 1896 struct iwl_priv *priv = file->private_data;1897 int len = 0;1898 char buf[20];1899 1900 len = sprintf(buf, "0x%04X\n",1901 le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags));1902 return simple_read_from_buffer(user_buf, count, ppos, buf, len);1903}1904 1905static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file,1906 char __user *user_buf,1907 size_t count, loff_t *ppos) {1908 1909 struct iwl_priv *priv = file->private_data;1910 int pos = 0;1911 char buf[12];1912 const size_t bufsz = sizeof(buf);1913 1914 pos += scnprintf(buf + pos, bufsz - pos, "%d\n",1915 priv->missed_beacon_threshold);1916 1917 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);1918}1919 1920static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file,1921 const char __user *user_buf,1922 size_t count, loff_t *ppos)1923{1924 struct iwl_priv *priv = file->private_data;1925 char buf[8];1926 int buf_size;1927 int missed;1928 1929 memset(buf, 0, sizeof(buf));1930 buf_size = min(count, sizeof(buf) - 1);1931 if (copy_from_user(buf, user_buf, buf_size))1932 return -EFAULT;1933 if (sscanf(buf, "%d", &missed) != 1)1934 return -EINVAL;1935 1936 if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN ||1937 missed > IWL_MISSED_BEACON_THRESHOLD_MAX)1938 priv->missed_beacon_threshold =1939 IWL_MISSED_BEACON_THRESHOLD_DEF;1940 else1941 priv->missed_beacon_threshold = missed;1942 1943 return count;1944}1945 1946static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,1947 char __user *user_buf,1948 size_t count, loff_t *ppos) {1949 1950 struct iwl_priv *priv = file->private_data;1951 int pos = 0;1952 char buf[12];1953 const size_t bufsz = sizeof(buf);1954 1955 pos += scnprintf(buf + pos, bufsz - pos, "%u\n",1956 priv->plcp_delta_threshold);1957 1958 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);1959}1960 1961static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,1962 const char __user *user_buf,1963 size_t count, loff_t *ppos) {1964 1965 struct iwl_priv *priv = file->private_data;1966 char buf[8];1967 int buf_size;1968 int plcp;1969 1970 memset(buf, 0, sizeof(buf));1971 buf_size = min(count, sizeof(buf) - 1);1972 if (copy_from_user(buf, user_buf, buf_size))1973 return -EFAULT;1974 if (sscanf(buf, "%d", &plcp) != 1)1975 return -EINVAL;1976 if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||1977 (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))1978 priv->plcp_delta_threshold =1979 IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;1980 else1981 priv->plcp_delta_threshold = plcp;1982 return count;1983}1984 1985static ssize_t iwl_dbgfs_rf_reset_read(struct file *file,1986 char __user *user_buf,1987 size_t count, loff_t *ppos)1988{1989 struct iwl_priv *priv = file->private_data;1990 int pos = 0;1991 char buf[300];1992 const size_t bufsz = sizeof(buf);1993 struct iwl_rf_reset *rf_reset = &priv->rf_reset;1994 1995 pos += scnprintf(buf + pos, bufsz - pos,1996 "RF reset statistics\n");1997 pos += scnprintf(buf + pos, bufsz - pos,1998 "\tnumber of reset request: %d\n",1999 rf_reset->reset_request_count);2000 pos += scnprintf(buf + pos, bufsz - pos,2001 "\tnumber of reset request success: %d\n",2002 rf_reset->reset_success_count);2003 pos += scnprintf(buf + pos, bufsz - pos,2004 "\tnumber of reset request reject: %d\n",2005 rf_reset->reset_reject_count);2006 2007 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);2008}2009 2010static ssize_t iwl_dbgfs_rf_reset_write(struct file *file,2011 const char __user *user_buf,2012 size_t count, loff_t *ppos) {2013 2014 struct iwl_priv *priv = file->private_data;2015 int ret;2016 2017 ret = iwl_force_rf_reset(priv, true);2018 return ret ? ret : count;2019}2020 2021static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,2022 const char __user *user_buf,2023 size_t count, loff_t *ppos) {2024 2025 struct iwl_priv *priv = file->private_data;2026 char buf[8];2027 int buf_size;2028 int flush;2029 2030 memset(buf, 0, sizeof(buf));2031 buf_size = min(count, sizeof(buf) - 1);2032 if (copy_from_user(buf, user_buf, buf_size))2033 return -EFAULT;2034 if (sscanf(buf, "%d", &flush) != 1)2035 return -EINVAL;2036 2037 if (iwl_is_rfkill(priv))2038 return -EFAULT;2039 2040 iwlagn_dev_txfifo_flush(priv);2041 2042 return count;2043}2044 2045static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file,2046 char __user *user_buf,2047 size_t count, loff_t *ppos) {2048 2049 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;2050 int pos = 0;2051 char buf[200];2052 const size_t bufsz = sizeof(buf);2053 2054 if (!priv->bt_enable_flag) {2055 pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n");2056 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);2057 }2058 pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n",2059 priv->bt_enable_flag);2060 pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n",2061 priv->bt_full_concurrent ? "full concurrency" : "3-wire");2062 pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, "2063 "last traffic notif: %d\n",2064 priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load);2065 pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, "2066 "kill_ack_mask: %x, kill_cts_mask: %x\n",2067 priv->bt_ch_announce, priv->kill_ack_mask,2068 priv->kill_cts_mask);2069 2070 pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: ");2071 switch (priv->bt_traffic_load) {2072 case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:2073 pos += scnprintf(buf + pos, bufsz - pos, "Continuous\n");2074 break;2075 case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:2076 pos += scnprintf(buf + pos, bufsz - pos, "High\n");2077 break;2078 case IWL_BT_COEX_TRAFFIC_LOAD_LOW:2079 pos += scnprintf(buf + pos, bufsz - pos, "Low\n");2080 break;2081 case IWL_BT_COEX_TRAFFIC_LOAD_NONE:2082 default:2083 pos += scnprintf(buf + pos, bufsz - pos, "None\n");2084 break;2085 }2086 2087 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);2088}2089 2090static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,2091 char __user *user_buf,2092 size_t count, loff_t *ppos)2093{2094 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;2095 2096 int pos = 0;2097 char buf[40];2098 const size_t bufsz = sizeof(buf);2099 2100 if (priv->cfg->ht_params)2101 pos += scnprintf(buf + pos, bufsz - pos,2102 "use %s for aggregation\n",2103 (priv->hw_params.use_rts_for_aggregation) ?2104 "rts/cts" : "cts-to-self");2105 else2106 pos += scnprintf(buf + pos, bufsz - pos, "N/A");2107 2108 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);2109}2110 2111static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,2112 const char __user *user_buf,2113 size_t count, loff_t *ppos) {2114 2115 struct iwl_priv *priv = file->private_data;2116 char buf[8];2117 int buf_size;2118 int rts;2119 2120 if (!priv->cfg->ht_params)2121 return -EINVAL;2122 2123 memset(buf, 0, sizeof(buf));2124 buf_size = min(count, sizeof(buf) - 1);2125 if (copy_from_user(buf, user_buf, buf_size))2126 return -EFAULT;2127 if (sscanf(buf, "%d", &rts) != 1)2128 return -EINVAL;2129 if (rts)2130 priv->hw_params.use_rts_for_aggregation = true;2131 else2132 priv->hw_params.use_rts_for_aggregation = false;2133 return count;2134}2135 2136static int iwl_cmd_echo_test(struct iwl_priv *priv)2137{2138 int ret;2139 struct iwl_host_cmd cmd = {2140 .id = REPLY_ECHO,2141 .len = { 0 },2142 };2143 2144 ret = iwl_dvm_send_cmd(priv, &cmd);2145 if (ret)2146 IWL_ERR(priv, "echo testing fail: 0X%x\n", ret);2147 else2148 IWL_DEBUG_INFO(priv, "echo testing pass\n");2149 return ret;2150}2151 2152static ssize_t iwl_dbgfs_echo_test_write(struct file *file,2153 const char __user *user_buf,2154 size_t count, loff_t *ppos)2155{2156 struct iwl_priv *priv = file->private_data;2157 char buf[8];2158 int buf_size;2159 2160 memset(buf, 0, sizeof(buf));2161 buf_size = min(count, sizeof(buf) - 1);2162 if (copy_from_user(buf, user_buf, buf_size))2163 return -EFAULT;2164 2165 iwl_cmd_echo_test(priv);2166 return count;2167}2168 2169#ifdef CONFIG_IWLWIFI_DEBUG2170static ssize_t iwl_dbgfs_log_event_read(struct file *file,2171 char __user *user_buf,2172 size_t count, loff_t *ppos)2173{2174 struct iwl_priv *priv = file->private_data;2175 char *buf = NULL;2176 ssize_t ret;2177 2178 ret = iwl_dump_nic_event_log(priv, true, &buf);2179 if (ret > 0)2180 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);2181 kfree(buf);2182 return ret;2183}2184 2185static ssize_t iwl_dbgfs_log_event_write(struct file *file,2186 const char __user *user_buf,2187 size_t count, loff_t *ppos)2188{2189 struct iwl_priv *priv = file->private_data;2190 u32 event_log_flag;2191 char buf[8];2192 int buf_size;2193 2194 /* check that the interface is up */2195 if (!iwl_is_ready(priv))2196 return -EAGAIN;2197 2198 memset(buf, 0, sizeof(buf));2199 buf_size = min(count, sizeof(buf) - 1);2200 if (copy_from_user(buf, user_buf, buf_size))2201 return -EFAULT;2202 if (sscanf(buf, "%u", &event_log_flag) != 1)2203 return -EFAULT;2204 if (event_log_flag == 1)2205 iwl_dump_nic_event_log(priv, true, NULL);2206 2207 return count;2208}2209#endif2210 2211static ssize_t iwl_dbgfs_calib_disabled_read(struct file *file,2212 char __user *user_buf,2213 size_t count, loff_t *ppos)2214{2215 struct iwl_priv *priv = file->private_data;2216 char buf[120];2217 int pos = 0;2218 const size_t bufsz = sizeof(buf);2219 2220 pos += scnprintf(buf + pos, bufsz - pos,2221 "Sensitivity calibrations %s\n",2222 (priv->calib_disabled &2223 IWL_SENSITIVITY_CALIB_DISABLED) ?2224 "DISABLED" : "ENABLED");2225 pos += scnprintf(buf + pos, bufsz - pos,2226 "Chain noise calibrations %s\n",2227 (priv->calib_disabled &2228 IWL_CHAIN_NOISE_CALIB_DISABLED) ?2229 "DISABLED" : "ENABLED");2230 pos += scnprintf(buf + pos, bufsz - pos,2231 "Tx power calibrations %s\n",2232 (priv->calib_disabled &2233 IWL_TX_POWER_CALIB_DISABLED) ?2234 "DISABLED" : "ENABLED");2235 2236 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);2237}2238 2239static ssize_t iwl_dbgfs_calib_disabled_write(struct file *file,2240 const char __user *user_buf,2241 size_t count, loff_t *ppos)2242{2243 struct iwl_priv *priv = file->private_data;2244 char buf[8];2245 u32 calib_disabled;2246 int buf_size;2247 2248 memset(buf, 0, sizeof(buf));2249 buf_size = min(count, sizeof(buf) - 1);2250 if (copy_from_user(buf, user_buf, buf_size))2251 return -EFAULT;2252 if (sscanf(buf, "%x", &calib_disabled) != 1)2253 return -EFAULT;2254 2255 priv->calib_disabled = calib_disabled;2256 2257 return count;2258}2259 2260static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,2261 const char __user *user_buf,2262 size_t count, loff_t *ppos)2263{2264 struct iwl_priv *priv = file->private_data;2265 bool fw_restart = iwlwifi_mod_params.fw_restart;2266 int __maybe_unused ret;2267 2268 iwlwifi_mod_params.fw_restart = true;2269 2270 mutex_lock(&priv->mutex);2271 2272 /* take the return value to make compiler happy - it will fail anyway */2273 ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, 0, 0, NULL);2274 2275 mutex_unlock(&priv->mutex);2276 2277 iwlwifi_mod_params.fw_restart = fw_restart;2278 2279 return count;2280}2281 2282DEBUGFS_READ_FILE_OPS(ucode_rx_stats);2283DEBUGFS_READ_FILE_OPS(ucode_tx_stats);2284DEBUGFS_READ_FILE_OPS(ucode_general_stats);2285DEBUGFS_READ_FILE_OPS(sensitivity);2286DEBUGFS_READ_FILE_OPS(chain_noise);2287DEBUGFS_READ_FILE_OPS(power_save_status);2288DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);2289DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);2290DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);2291DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);2292DEBUGFS_READ_WRITE_FILE_OPS(rf_reset);2293DEBUGFS_READ_FILE_OPS(rxon_flags);2294DEBUGFS_READ_FILE_OPS(rxon_filter_flags);2295DEBUGFS_WRITE_FILE_OPS(txfifo_flush);2296DEBUGFS_READ_FILE_OPS(ucode_bt_stats);2297DEBUGFS_READ_FILE_OPS(bt_traffic);2298DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);2299DEBUGFS_READ_FILE_OPS(reply_tx_error);2300DEBUGFS_WRITE_FILE_OPS(echo_test);2301DEBUGFS_WRITE_FILE_OPS(fw_restart);2302#ifdef CONFIG_IWLWIFI_DEBUG2303DEBUGFS_READ_WRITE_FILE_OPS(log_event);2304#endif2305DEBUGFS_READ_WRITE_FILE_OPS(calib_disabled);2306 2307/*2308 * Create the debugfs files and directories2309 *2310 */2311void iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir)2312{2313 struct dentry *dir_data, *dir_rf, *dir_debug;2314 2315 priv->debugfs_dir = dbgfs_dir;2316 2317 dir_data = debugfs_create_dir("data", dbgfs_dir);2318 dir_rf = debugfs_create_dir("rf", dbgfs_dir);2319 dir_debug = debugfs_create_dir("debug", dbgfs_dir);2320 2321 DEBUGFS_ADD_FILE(nvm, dir_data, 0400);2322 DEBUGFS_ADD_FILE(sram, dir_data, 0600);2323 DEBUGFS_ADD_FILE(wowlan_sram, dir_data, 0400);2324 DEBUGFS_ADD_FILE(stations, dir_data, 0400);2325 DEBUGFS_ADD_FILE(channels, dir_data, 0400);2326 DEBUGFS_ADD_FILE(status, dir_data, 0400);2327 DEBUGFS_ADD_FILE(rx_handlers, dir_data, 0600);2328 DEBUGFS_ADD_FILE(qos, dir_data, 0400);2329 DEBUGFS_ADD_FILE(sleep_level_override, dir_data, 0600);2330 DEBUGFS_ADD_FILE(current_sleep_command, dir_data, 0400);2331 DEBUGFS_ADD_FILE(thermal_throttling, dir_data, 0400);2332 DEBUGFS_ADD_FILE(disable_ht40, dir_data, 0600);2333 DEBUGFS_ADD_FILE(temperature, dir_data, 0400);2334 2335 DEBUGFS_ADD_FILE(power_save_status, dir_debug, 0400);2336 DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, 0200);2337 DEBUGFS_ADD_FILE(missed_beacon, dir_debug, 0200);2338 DEBUGFS_ADD_FILE(plcp_delta, dir_debug, 0600);2339 DEBUGFS_ADD_FILE(rf_reset, dir_debug, 0600);2340 DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, 0400);2341 DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, 0400);2342 DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, 0400);2343 DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, 0200);2344 DEBUGFS_ADD_FILE(protection_mode, dir_debug, 0600);2345 DEBUGFS_ADD_FILE(sensitivity, dir_debug, 0400);2346 DEBUGFS_ADD_FILE(chain_noise, dir_debug, 0400);2347 DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, 0600);2348 DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, 0400);2349 DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, 0400);2350 DEBUGFS_ADD_FILE(rxon_flags, dir_debug, 0200);2351 DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, 0200);2352 DEBUGFS_ADD_FILE(echo_test, dir_debug, 0200);2353 DEBUGFS_ADD_FILE(fw_restart, dir_debug, 0200);2354#ifdef CONFIG_IWLWIFI_DEBUG2355 DEBUGFS_ADD_FILE(log_event, dir_debug, 0600);2356#endif2357 2358 if (iwl_advanced_bt_coexist(priv))2359 DEBUGFS_ADD_FILE(bt_traffic, dir_debug, 0400);2360 2361 /* Calibrations disabled/enabled status*/2362 DEBUGFS_ADD_FILE(calib_disabled, dir_rf, 0600);2363 2364 /*2365 * Create a symlink with mac80211. This is not very robust, as it does2366 * not remove the symlink created. The implicit assumption is that2367 * when the opmode exits, mac80211 will also exit, and will remove2368 * this symlink as part of its cleanup.2369 */2370 if (priv->mac80211_registered) {2371 char buf[100];2372 struct dentry *mac80211_dir, *dev_dir;2373 2374 dev_dir = dbgfs_dir->d_parent;2375 mac80211_dir = priv->hw->wiphy->debugfsdir;2376 2377 snprintf(buf, 100, "../../%pd2", dev_dir);2378 2379 debugfs_create_symlink("iwlwifi", mac80211_dir, buf);2380 }2381}2382