linux/drivers/net/wireless/iwlwifi/iwl-debugfs.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * GPL LICENSE SUMMARY
   4 *
   5 * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved.
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of version 2 of the GNU General Public License as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful, but
  12 * WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  19 * USA
  20 *
  21 * The full GNU General Public License is included in this distribution
  22 * in the file called LICENSE.GPL.
  23 *
  24 * Contact Information:
  25 *  Intel Linux Wireless <ilw@linux.intel.com>
  26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  27 *****************************************************************************/
  28
  29#include <linux/kernel.h>
  30#include <linux/module.h>
  31#include <linux/debugfs.h>
  32
  33#include <linux/ieee80211.h>
  34#include <net/mac80211.h>
  35
  36
  37#include "iwl-dev.h"
  38#include "iwl-debug.h"
  39#include "iwl-core.h"
  40#include "iwl-io.h"
  41#include "iwl-calib.h"
  42
  43/* create and remove of files */
  44#define DEBUGFS_ADD_DIR(name, parent) do {                              \
  45        dbgfs->dir_##name = debugfs_create_dir(#name, parent);          \
  46        if (!(dbgfs->dir_##name))                                       \
  47                goto err;                                               \
  48} while (0)
  49
  50#define DEBUGFS_ADD_FILE(name, parent) do {                             \
  51        dbgfs->dbgfs_##parent##_files.file_##name =                     \
  52        debugfs_create_file(#name, S_IWUSR | S_IRUSR,                   \
  53                                dbgfs->dir_##parent, priv,              \
  54                                &iwl_dbgfs_##name##_ops);               \
  55        if (!(dbgfs->dbgfs_##parent##_files.file_##name))               \
  56                goto err;                                               \
  57} while (0)
  58
  59#define DEBUGFS_ADD_BOOL(name, parent, ptr) do {                        \
  60        dbgfs->dbgfs_##parent##_files.file_##name =                     \
  61        debugfs_create_bool(#name, S_IWUSR | S_IRUSR,                   \
  62                            dbgfs->dir_##parent, ptr);                  \
  63        if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name)           \
  64                        || !dbgfs->dbgfs_##parent##_files.file_##name)  \
  65                goto err;                                               \
  66} while (0)
  67
  68#define DEBUGFS_ADD_X32(name, parent, ptr) do {                        \
  69        dbgfs->dbgfs_##parent##_files.file_##name =                     \
  70        debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr);   \
  71        if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name)           \
  72                        || !dbgfs->dbgfs_##parent##_files.file_##name)  \
  73                goto err;                                               \
  74} while (0)
  75
  76#define DEBUGFS_REMOVE(name)  do {              \
  77        debugfs_remove(name);                   \
  78        name = NULL;                            \
  79} while (0);
  80
  81/* file operation */
  82#define DEBUGFS_READ_FUNC(name)                                         \
  83static ssize_t iwl_dbgfs_##name##_read(struct file *file,               \
  84                                        char __user *user_buf,          \
  85                                        size_t count, loff_t *ppos);
  86
  87#define DEBUGFS_WRITE_FUNC(name)                                        \
  88static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \
  89                                        const char __user *user_buf,    \
  90                                        size_t count, loff_t *ppos);
  91
  92
  93static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
  94{
  95        file->private_data = inode->i_private;
  96        return 0;
  97}
  98
  99#define DEBUGFS_READ_FILE_OPS(name)                                     \
 100        DEBUGFS_READ_FUNC(name);                                        \
 101static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 102        .read = iwl_dbgfs_##name##_read,                                \
 103        .open = iwl_dbgfs_open_file_generic,                            \
 104};
 105
 106#define DEBUGFS_WRITE_FILE_OPS(name)                                    \
 107        DEBUGFS_WRITE_FUNC(name);                                       \
 108static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 109        .write = iwl_dbgfs_##name##_write,                              \
 110        .open = iwl_dbgfs_open_file_generic,                            \
 111};
 112
 113
 114#define DEBUGFS_READ_WRITE_FILE_OPS(name)                               \
 115        DEBUGFS_READ_FUNC(name);                                        \
 116        DEBUGFS_WRITE_FUNC(name);                                       \
 117static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 118        .write = iwl_dbgfs_##name##_write,                              \
 119        .read = iwl_dbgfs_##name##_read,                                \
 120        .open = iwl_dbgfs_open_file_generic,                            \
 121};
 122
 123
 124static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
 125                                                char __user *user_buf,
 126                                                size_t count, loff_t *ppos) {
 127
 128        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 129        char *buf;
 130        int pos = 0;
 131
 132        int cnt;
 133        ssize_t ret;
 134        const size_t bufsz = 100 + sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX);
 135        buf = kzalloc(bufsz, GFP_KERNEL);
 136        if (!buf)
 137                return -ENOMEM;
 138        pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
 139        for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
 140                pos += scnprintf(buf + pos, bufsz - pos,
 141                                 "\t%s\t\t: %u\n",
 142                                 get_mgmt_string(cnt),
 143                                 priv->tx_stats.mgmt[cnt]);
 144        }
 145        pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
 146        for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
 147                pos += scnprintf(buf + pos, bufsz - pos,
 148                                 "\t%s\t\t: %u\n",
 149                                 get_ctrl_string(cnt),
 150                                 priv->tx_stats.ctrl[cnt]);
 151        }
 152        pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
 153        pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
 154                         priv->tx_stats.data_cnt);
 155        pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
 156                         priv->tx_stats.data_bytes);
 157        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 158        kfree(buf);
 159        return ret;
 160}
 161
 162static ssize_t iwl_dbgfs_tx_statistics_write(struct file *file,
 163                                        const char __user *user_buf,
 164                                        size_t count, loff_t *ppos)
 165{
 166        struct iwl_priv *priv = file->private_data;
 167        u32 clear_flag;
 168        char buf[8];
 169        int buf_size;
 170
 171        memset(buf, 0, sizeof(buf));
 172        buf_size = min(count, sizeof(buf) -  1);
 173        if (copy_from_user(buf, user_buf, buf_size))
 174                return -EFAULT;
 175        if (sscanf(buf, "%x", &clear_flag) != 1)
 176                return -EFAULT;
 177        if (clear_flag == 1)
 178                iwl_clear_tx_stats(priv);
 179
 180        return count;
 181}
 182
 183static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
 184                                                char __user *user_buf,
 185                                                size_t count, loff_t *ppos) {
 186
 187        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 188        char *buf;
 189        int pos = 0;
 190        int cnt;
 191        ssize_t ret;
 192        const size_t bufsz = 100 +
 193                sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX);
 194        buf = kzalloc(bufsz, GFP_KERNEL);
 195        if (!buf)
 196                return -ENOMEM;
 197
 198        pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
 199        for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
 200                pos += scnprintf(buf + pos, bufsz - pos,
 201                                 "\t%s\t\t: %u\n",
 202                                 get_mgmt_string(cnt),
 203                                 priv->rx_stats.mgmt[cnt]);
 204        }
 205        pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
 206        for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
 207                pos += scnprintf(buf + pos, bufsz - pos,
 208                                 "\t%s\t\t: %u\n",
 209                                 get_ctrl_string(cnt),
 210                                 priv->rx_stats.ctrl[cnt]);
 211        }
 212        pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
 213        pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
 214                         priv->rx_stats.data_cnt);
 215        pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
 216                         priv->rx_stats.data_bytes);
 217
 218        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 219        kfree(buf);
 220        return ret;
 221}
 222
 223static ssize_t iwl_dbgfs_rx_statistics_write(struct file *file,
 224                                        const char __user *user_buf,
 225                                        size_t count, loff_t *ppos)
 226{
 227        struct iwl_priv *priv = file->private_data;
 228        u32 clear_flag;
 229        char buf[8];
 230        int buf_size;
 231
 232        memset(buf, 0, sizeof(buf));
 233        buf_size = min(count, sizeof(buf) -  1);
 234        if (copy_from_user(buf, user_buf, buf_size))
 235                return -EFAULT;
 236        if (sscanf(buf, "%x", &clear_flag) != 1)
 237                return -EFAULT;
 238        if (clear_flag == 1)
 239                iwl_clear_rx_stats(priv);
 240        return count;
 241}
 242
 243#define BYTE1_MASK 0x000000ff;
 244#define BYTE2_MASK 0x0000ffff;
 245#define BYTE3_MASK 0x00ffffff;
 246static ssize_t iwl_dbgfs_sram_read(struct file *file,
 247                                        char __user *user_buf,
 248                                        size_t count, loff_t *ppos)
 249{
 250        u32 val;
 251        char buf[1024];
 252        ssize_t ret;
 253        int i;
 254        int pos = 0;
 255        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 256        const size_t bufsz = sizeof(buf);
 257
 258        for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
 259                val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
 260                                        priv->dbgfs->sram_len - i);
 261                if (i < 4) {
 262                        switch (i) {
 263                        case 1:
 264                                val &= BYTE1_MASK;
 265                                break;
 266                        case 2:
 267                                val &= BYTE2_MASK;
 268                                break;
 269                        case 3:
 270                                val &= BYTE3_MASK;
 271                                break;
 272                        }
 273                }
 274                pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
 275        }
 276        pos += scnprintf(buf + pos, bufsz - pos, "\n");
 277
 278        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 279        return ret;
 280}
 281
 282static ssize_t iwl_dbgfs_sram_write(struct file *file,
 283                                        const char __user *user_buf,
 284                                        size_t count, loff_t *ppos)
 285{
 286        struct iwl_priv *priv = file->private_data;
 287        char buf[64];
 288        int buf_size;
 289        u32 offset, len;
 290
 291        memset(buf, 0, sizeof(buf));
 292        buf_size = min(count, sizeof(buf) -  1);
 293        if (copy_from_user(buf, user_buf, buf_size))
 294                return -EFAULT;
 295
 296        if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
 297                priv->dbgfs->sram_offset = offset;
 298                priv->dbgfs->sram_len = len;
 299        } else {
 300                priv->dbgfs->sram_offset = 0;
 301                priv->dbgfs->sram_len = 0;
 302        }
 303
 304        return count;
 305}
 306
 307static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
 308                                        size_t count, loff_t *ppos)
 309{
 310        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 311        struct iwl_station_entry *station;
 312        int max_sta = priv->hw_params.max_stations;
 313        char *buf;
 314        int i, j, pos = 0;
 315        ssize_t ret;
 316        /* Add 30 for initial string */
 317        const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
 318
 319        buf = kmalloc(bufsz, GFP_KERNEL);
 320        if (!buf)
 321                return -ENOMEM;
 322
 323        pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
 324                        priv->num_stations);
 325
 326        for (i = 0; i < max_sta; i++) {
 327                station = &priv->stations[i];
 328                if (station->used) {
 329                        pos += scnprintf(buf + pos, bufsz - pos,
 330                                        "station %d:\ngeneral data:\n", i+1);
 331                        pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
 332                                        station->sta.sta.sta_id);
 333                        pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
 334                                        station->sta.mode);
 335                        pos += scnprintf(buf + pos, bufsz - pos,
 336                                        "flags: 0x%x\n",
 337                                        station->sta.station_flags_msk);
 338                        pos += scnprintf(buf + pos, bufsz - pos,
 339                                        "ps_status: %u\n", station->ps_status);
 340                        pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n");
 341                        pos += scnprintf(buf + pos, bufsz - pos,
 342                                        "seq_num\t\ttxq_id");
 343                        pos += scnprintf(buf + pos, bufsz - pos,
 344                                        "\tframe_count\twait_for_ba\t");
 345                        pos += scnprintf(buf + pos, bufsz - pos,
 346                                        "start_idx\tbitmap0\t");
 347                        pos += scnprintf(buf + pos, bufsz - pos,
 348                                        "bitmap1\trate_n_flags");
 349                        pos += scnprintf(buf + pos, bufsz - pos, "\n");
 350
 351                        for (j = 0; j < MAX_TID_COUNT; j++) {
 352                                pos += scnprintf(buf + pos, bufsz - pos,
 353                                                "[%d]:\t\t%u", j,
 354                                                station->tid[j].seq_number);
 355                                pos += scnprintf(buf + pos, bufsz - pos,
 356                                                "\t%u\t\t%u\t\t%u\t\t",
 357                                                station->tid[j].agg.txq_id,
 358                                                station->tid[j].agg.frame_count,
 359                                                station->tid[j].agg.wait_for_ba);
 360                                pos += scnprintf(buf + pos, bufsz - pos,
 361                                                "%u\t%llu\t%u",
 362                                                station->tid[j].agg.start_idx,
 363                                                (unsigned long long)station->tid[j].agg.bitmap,
 364                                                station->tid[j].agg.rate_n_flags);
 365                                pos += scnprintf(buf + pos, bufsz - pos, "\n");
 366                        }
 367                        pos += scnprintf(buf + pos, bufsz - pos, "\n");
 368                }
 369        }
 370
 371        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 372        kfree(buf);
 373        return ret;
 374}
 375
 376static ssize_t iwl_dbgfs_nvm_read(struct file *file,
 377                                       char __user *user_buf,
 378                                       size_t count,
 379                                       loff_t *ppos)
 380{
 381        ssize_t ret;
 382        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 383        int pos = 0, ofs = 0, buf_size = 0;
 384        const u8 *ptr;
 385        char *buf;
 386        size_t eeprom_len = priv->cfg->eeprom_size;
 387        buf_size = 4 * eeprom_len + 256;
 388
 389        if (eeprom_len % 16) {
 390                IWL_ERR(priv, "NVM size is not multiple of 16.\n");
 391                return -ENODATA;
 392        }
 393
 394        ptr = priv->eeprom;
 395        if (!ptr) {
 396                IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
 397                return -ENOMEM;
 398        }
 399
 400        /* 4 characters for byte 0xYY */
 401        buf = kzalloc(buf_size, GFP_KERNEL);
 402        if (!buf) {
 403                IWL_ERR(priv, "Can not allocate Buffer\n");
 404                return -ENOMEM;
 405        }
 406        pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n",
 407                        (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
 408                        ? "OTP" : "EEPROM");
 409        for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
 410                pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
 411                hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
 412                                   buf_size - pos, 0);
 413                pos += strlen(buf + pos);
 414                if (buf_size - pos > 0)
 415                        buf[pos++] = '\n';
 416        }
 417
 418        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 419        kfree(buf);
 420        return ret;
 421}
 422
 423static ssize_t iwl_dbgfs_log_event_write(struct file *file,
 424                                        const char __user *user_buf,
 425                                        size_t count, loff_t *ppos)
 426{
 427        struct iwl_priv *priv = file->private_data;
 428        u32 event_log_flag;
 429        char buf[8];
 430        int buf_size;
 431
 432        memset(buf, 0, sizeof(buf));
 433        buf_size = min(count, sizeof(buf) -  1);
 434        if (copy_from_user(buf, user_buf, buf_size))
 435                return -EFAULT;
 436        if (sscanf(buf, "%d", &event_log_flag) != 1)
 437                return -EFAULT;
 438        if (event_log_flag == 1)
 439                priv->cfg->ops->lib->dump_nic_event_log(priv);
 440
 441        return count;
 442}
 443
 444
 445
 446static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
 447                                       size_t count, loff_t *ppos)
 448{
 449        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 450        struct ieee80211_channel *channels = NULL;
 451        const struct ieee80211_supported_band *supp_band = NULL;
 452        int pos = 0, i, bufsz = PAGE_SIZE;
 453        char *buf;
 454        ssize_t ret;
 455
 456        if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
 457                return -EAGAIN;
 458
 459        buf = kzalloc(bufsz, GFP_KERNEL);
 460        if (!buf) {
 461                IWL_ERR(priv, "Can not allocate Buffer\n");
 462                return -ENOMEM;
 463        }
 464
 465        supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
 466        if (supp_band) {
 467                channels = supp_band->channels;
 468
 469                pos += scnprintf(buf + pos, bufsz - pos,
 470                                "Displaying %d channels in 2.4GHz band 802.11bg):\n",
 471                                supp_band->n_channels);
 472
 473                for (i = 0; i < supp_band->n_channels; i++)
 474                        pos += scnprintf(buf + pos, bufsz - pos,
 475                                        "%d: %ddBm: BSS%s%s, %s.\n",
 476                                        ieee80211_frequency_to_channel(
 477                                        channels[i].center_freq),
 478                                        channels[i].max_power,
 479                                        channels[i].flags & IEEE80211_CHAN_RADAR ?
 480                                        " (IEEE 802.11h required)" : "",
 481                                        ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
 482                                        || (channels[i].flags &
 483                                        IEEE80211_CHAN_RADAR)) ? "" :
 484                                        ", IBSS",
 485                                        channels[i].flags &
 486                                        IEEE80211_CHAN_PASSIVE_SCAN ?
 487                                        "passive only" : "active/passive");
 488        }
 489        supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
 490        if (supp_band) {
 491                channels = supp_band->channels;
 492
 493                pos += scnprintf(buf + pos, bufsz - pos,
 494                                "Displaying %d channels in 5.2GHz band (802.11a)\n",
 495                                supp_band->n_channels);
 496
 497                for (i = 0; i < supp_band->n_channels; i++)
 498                        pos += scnprintf(buf + pos, bufsz - pos,
 499                                        "%d: %ddBm: BSS%s%s, %s.\n",
 500                                        ieee80211_frequency_to_channel(
 501                                        channels[i].center_freq),
 502                                        channels[i].max_power,
 503                                        channels[i].flags & IEEE80211_CHAN_RADAR ?
 504                                        " (IEEE 802.11h required)" : "",
 505                                        ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
 506                                        || (channels[i].flags &
 507                                        IEEE80211_CHAN_RADAR)) ? "" :
 508                                        ", IBSS",
 509                                        channels[i].flags &
 510                                        IEEE80211_CHAN_PASSIVE_SCAN ?
 511                                        "passive only" : "active/passive");
 512        }
 513        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 514        kfree(buf);
 515        return ret;
 516}
 517
 518static ssize_t iwl_dbgfs_status_read(struct file *file,
 519                                                char __user *user_buf,
 520                                                size_t count, loff_t *ppos) {
 521
 522        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 523        char buf[512];
 524        int pos = 0;
 525        const size_t bufsz = sizeof(buf);
 526
 527        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
 528                test_bit(STATUS_HCMD_ACTIVE, &priv->status));
 529        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n",
 530                test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status));
 531        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
 532                test_bit(STATUS_INT_ENABLED, &priv->status));
 533        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
 534                test_bit(STATUS_RF_KILL_HW, &priv->status));
 535        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
 536                test_bit(STATUS_INIT, &priv->status));
 537        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
 538                test_bit(STATUS_ALIVE, &priv->status));
 539        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
 540                test_bit(STATUS_READY, &priv->status));
 541        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
 542                test_bit(STATUS_TEMPERATURE, &priv->status));
 543        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
 544                test_bit(STATUS_GEO_CONFIGURED, &priv->status));
 545        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
 546                test_bit(STATUS_EXIT_PENDING, &priv->status));
 547        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
 548                test_bit(STATUS_STATISTICS, &priv->status));
 549        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
 550                test_bit(STATUS_SCANNING, &priv->status));
 551        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
 552                test_bit(STATUS_SCAN_ABORTING, &priv->status));
 553        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
 554                test_bit(STATUS_SCAN_HW, &priv->status));
 555        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
 556                test_bit(STATUS_POWER_PMI, &priv->status));
 557        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
 558                test_bit(STATUS_FW_ERROR, &priv->status));
 559        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n",
 560                test_bit(STATUS_MODE_PENDING, &priv->status));
 561        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 562}
 563
 564static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
 565                                        char __user *user_buf,
 566                                        size_t count, loff_t *ppos) {
 567
 568        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 569        int pos = 0;
 570        int cnt = 0;
 571        char *buf;
 572        int bufsz = 24 * 64; /* 24 items * 64 char per item */
 573        ssize_t ret;
 574
 575        buf = kzalloc(bufsz, GFP_KERNEL);
 576        if (!buf) {
 577                IWL_ERR(priv, "Can not allocate Buffer\n");
 578                return -ENOMEM;
 579        }
 580
 581        pos += scnprintf(buf + pos, bufsz - pos,
 582                        "Interrupt Statistics Report:\n");
 583
 584        pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
 585                priv->isr_stats.hw);
 586        pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
 587                priv->isr_stats.sw);
 588        if (priv->isr_stats.sw > 0) {
 589                pos += scnprintf(buf + pos, bufsz - pos,
 590                        "\tLast Restarting Code:  0x%X\n",
 591                        priv->isr_stats.sw_err);
 592        }
 593#ifdef CONFIG_IWLWIFI_DEBUG
 594        pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
 595                priv->isr_stats.sch);
 596        pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
 597                priv->isr_stats.alive);
 598#endif
 599        pos += scnprintf(buf + pos, bufsz - pos,
 600                "HW RF KILL switch toggled:\t %u\n",
 601                priv->isr_stats.rfkill);
 602
 603        pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
 604                priv->isr_stats.ctkill);
 605
 606        pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
 607                priv->isr_stats.wakeup);
 608
 609        pos += scnprintf(buf + pos, bufsz - pos,
 610                "Rx command responses:\t\t %u\n",
 611                priv->isr_stats.rx);
 612        for (cnt = 0; cnt < REPLY_MAX; cnt++) {
 613                if (priv->isr_stats.rx_handlers[cnt] > 0)
 614                        pos += scnprintf(buf + pos, bufsz - pos,
 615                                "\tRx handler[%36s]:\t\t %u\n",
 616                                get_cmd_string(cnt),
 617                                priv->isr_stats.rx_handlers[cnt]);
 618        }
 619
 620        pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
 621                priv->isr_stats.tx);
 622
 623        pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
 624                priv->isr_stats.unhandled);
 625
 626        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 627        kfree(buf);
 628        return ret;
 629}
 630
 631static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
 632                                         const char __user *user_buf,
 633                                         size_t count, loff_t *ppos)
 634{
 635        struct iwl_priv *priv = file->private_data;
 636        char buf[8];
 637        int buf_size;
 638        u32 reset_flag;
 639
 640        memset(buf, 0, sizeof(buf));
 641        buf_size = min(count, sizeof(buf) -  1);
 642        if (copy_from_user(buf, user_buf, buf_size))
 643                return -EFAULT;
 644        if (sscanf(buf, "%x", &reset_flag) != 1)
 645                return -EFAULT;
 646        if (reset_flag == 0)
 647                iwl_clear_isr_stats(priv);
 648
 649        return count;
 650}
 651
 652static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
 653                                       size_t count, loff_t *ppos)
 654{
 655        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 656        int pos = 0, i;
 657        char buf[256];
 658        const size_t bufsz = sizeof(buf);
 659        ssize_t ret;
 660
 661        for (i = 0; i < AC_NUM; i++) {
 662                pos += scnprintf(buf + pos, bufsz - pos,
 663                        "\tcw_min\tcw_max\taifsn\ttxop\n");
 664                pos += scnprintf(buf + pos, bufsz - pos,
 665                                "AC[%d]\t%u\t%u\t%u\t%u\n", i,
 666                                priv->qos_data.def_qos_parm.ac[i].cw_min,
 667                                priv->qos_data.def_qos_parm.ac[i].cw_max,
 668                                priv->qos_data.def_qos_parm.ac[i].aifsn,
 669                                priv->qos_data.def_qos_parm.ac[i].edca_txop);
 670        }
 671        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 672        return ret;
 673}
 674
 675#ifdef CONFIG_IWLWIFI_LEDS
 676static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
 677                                  size_t count, loff_t *ppos)
 678{
 679        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 680        int pos = 0;
 681        char buf[256];
 682        const size_t bufsz = sizeof(buf);
 683        ssize_t ret;
 684
 685        pos += scnprintf(buf + pos, bufsz - pos,
 686                         "allow blinking: %s\n",
 687                         (priv->allow_blinking) ? "True" : "False");
 688        if (priv->allow_blinking) {
 689                pos += scnprintf(buf + pos, bufsz - pos,
 690                                 "Led blinking rate: %u\n",
 691                                 priv->last_blink_rate);
 692                pos += scnprintf(buf + pos, bufsz - pos,
 693                                 "Last blink time: %lu\n",
 694                                 priv->last_blink_time);
 695        }
 696
 697        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 698        return ret;
 699}
 700#endif
 701
 702static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
 703                                char __user *user_buf,
 704                                size_t count, loff_t *ppos)
 705{
 706        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 707        struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 708        struct iwl_tt_restriction *restriction;
 709        char buf[100];
 710        int pos = 0;
 711        const size_t bufsz = sizeof(buf);
 712        ssize_t ret;
 713
 714        pos += scnprintf(buf + pos, bufsz - pos,
 715                        "Thermal Throttling Mode: %s\n",
 716                        tt->advanced_tt ? "Advance" : "Legacy");
 717        pos += scnprintf(buf + pos, bufsz - pos,
 718                        "Thermal Throttling State: %d\n",
 719                        tt->state);
 720        if (tt->advanced_tt) {
 721                restriction = tt->restriction + tt->state;
 722                pos += scnprintf(buf + pos, bufsz - pos,
 723                                "Tx mode: %d\n",
 724                                restriction->tx_stream);
 725                pos += scnprintf(buf + pos, bufsz - pos,
 726                                "Rx mode: %d\n",
 727                                restriction->rx_stream);
 728                pos += scnprintf(buf + pos, bufsz - pos,
 729                                "HT mode: %d\n",
 730                                restriction->is_ht);
 731        }
 732        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 733        return ret;
 734}
 735
 736static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
 737                                         const char __user *user_buf,
 738                                         size_t count, loff_t *ppos)
 739{
 740        struct iwl_priv *priv = file->private_data;
 741        char buf[8];
 742        int buf_size;
 743        int ht40;
 744
 745        memset(buf, 0, sizeof(buf));
 746        buf_size = min(count, sizeof(buf) -  1);
 747        if (copy_from_user(buf, user_buf, buf_size))
 748                return -EFAULT;
 749        if (sscanf(buf, "%d", &ht40) != 1)
 750                return -EFAULT;
 751        if (!iwl_is_associated(priv))
 752                priv->disable_ht40 = ht40 ? true : false;
 753        else {
 754                IWL_ERR(priv, "Sta associated with AP - "
 755                        "Change to 40MHz channel support is not allowed\n");
 756                return -EINVAL;
 757        }
 758
 759        return count;
 760}
 761
 762static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
 763                                         char __user *user_buf,
 764                                         size_t count, loff_t *ppos)
 765{
 766        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 767        char buf[100];
 768        int pos = 0;
 769        const size_t bufsz = sizeof(buf);
 770        ssize_t ret;
 771
 772        pos += scnprintf(buf + pos, bufsz - pos,
 773                        "11n 40MHz Mode: %s\n",
 774                        priv->disable_ht40 ? "Disabled" : "Enabled");
 775        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 776        return ret;
 777}
 778
 779static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
 780                                                    const char __user *user_buf,
 781                                                    size_t count, loff_t *ppos)
 782{
 783        struct iwl_priv *priv = file->private_data;
 784        char buf[8];
 785        int buf_size;
 786        int value;
 787
 788        memset(buf, 0, sizeof(buf));
 789        buf_size = min(count, sizeof(buf) -  1);
 790        if (copy_from_user(buf, user_buf, buf_size))
 791                return -EFAULT;
 792
 793        if (sscanf(buf, "%d", &value) != 1)
 794                return -EINVAL;
 795
 796        /*
 797         * Our users expect 0 to be "CAM", but 0 isn't actually
 798         * valid here. However, let's not confuse them and present
 799         * IWL_POWER_INDEX_1 as "1", not "0".
 800         */
 801        if (value > 0)
 802                value -= 1;
 803
 804        if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
 805                return -EINVAL;
 806
 807        priv->power_data.debug_sleep_level_override = value;
 808
 809        iwl_power_update_mode(priv, false);
 810
 811        return count;
 812}
 813
 814static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file,
 815                                                   char __user *user_buf,
 816                                                   size_t count, loff_t *ppos)
 817{
 818        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 819        char buf[10];
 820        int pos, value;
 821        const size_t bufsz = sizeof(buf);
 822
 823        /* see the write function */
 824        value = priv->power_data.debug_sleep_level_override;
 825        if (value >= 0)
 826                value += 1;
 827
 828        pos = scnprintf(buf, bufsz, "%d\n", value);
 829        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 830}
 831
 832static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
 833                                                    char __user *user_buf,
 834                                                    size_t count, loff_t *ppos)
 835{
 836        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 837        char buf[200];
 838        int pos = 0, i;
 839        const size_t bufsz = sizeof(buf);
 840        struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd;
 841
 842        pos += scnprintf(buf + pos, bufsz - pos,
 843                         "flags: %#.2x\n", le16_to_cpu(cmd->flags));
 844        pos += scnprintf(buf + pos, bufsz - pos,
 845                         "RX/TX timeout: %d/%d usec\n",
 846                         le32_to_cpu(cmd->rx_data_timeout),
 847                         le32_to_cpu(cmd->tx_data_timeout));
 848        for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
 849                pos += scnprintf(buf + pos, bufsz - pos,
 850                                 "sleep_interval[%d]: %d\n", i,
 851                                 le32_to_cpu(cmd->sleep_interval[i]));
 852
 853        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 854}
 855
 856DEBUGFS_READ_WRITE_FILE_OPS(sram);
 857DEBUGFS_WRITE_FILE_OPS(log_event);
 858DEBUGFS_READ_FILE_OPS(nvm);
 859DEBUGFS_READ_FILE_OPS(stations);
 860DEBUGFS_READ_FILE_OPS(channels);
 861DEBUGFS_READ_FILE_OPS(status);
 862DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
 863DEBUGFS_READ_FILE_OPS(qos);
 864#ifdef CONFIG_IWLWIFI_LEDS
 865DEBUGFS_READ_FILE_OPS(led);
 866#endif
 867DEBUGFS_READ_FILE_OPS(thermal_throttling);
 868DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
 869DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
 870DEBUGFS_READ_FILE_OPS(current_sleep_command);
 871
 872static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
 873                                         char __user *user_buf,
 874                                         size_t count, loff_t *ppos)
 875{
 876        struct iwl_priv *priv = file->private_data;
 877        int pos = 0, ofs = 0;
 878        int cnt = 0, entry;
 879        struct iwl_tx_queue *txq;
 880        struct iwl_queue *q;
 881        struct iwl_rx_queue *rxq = &priv->rxq;
 882        char *buf;
 883        int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
 884                (IWL_MAX_NUM_QUEUES * 32 * 8) + 400;
 885        const u8 *ptr;
 886        ssize_t ret;
 887
 888        buf = kzalloc(bufsz, GFP_KERNEL);
 889        if (!buf) {
 890                IWL_ERR(priv, "Can not allocate buffer\n");
 891                return -ENOMEM;
 892        }
 893        pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
 894        for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
 895                txq = &priv->txq[cnt];
 896                q = &txq->q;
 897                pos += scnprintf(buf + pos, bufsz - pos,
 898                                "q[%d]: read_ptr: %u, write_ptr: %u\n",
 899                                cnt, q->read_ptr, q->write_ptr);
 900        }
 901        if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) {
 902                ptr = priv->tx_traffic;
 903                pos += scnprintf(buf + pos, bufsz - pos,
 904                                "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
 905                for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
 906                        for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
 907                             entry++,  ofs += 16) {
 908                                pos += scnprintf(buf + pos, bufsz - pos,
 909                                                "0x%.4x ", ofs);
 910                                hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
 911                                                   buf + pos, bufsz - pos, 0);
 912                                pos += strlen(buf + pos);
 913                                if (bufsz - pos > 0)
 914                                        buf[pos++] = '\n';
 915                        }
 916                }
 917        }
 918
 919        pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
 920        pos += scnprintf(buf + pos, bufsz - pos,
 921                        "read: %u, write: %u\n",
 922                         rxq->read, rxq->write);
 923
 924        if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) {
 925                ptr = priv->rx_traffic;
 926                pos += scnprintf(buf + pos, bufsz - pos,
 927                                "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
 928                for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
 929                        for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
 930                             entry++,  ofs += 16) {
 931                                pos += scnprintf(buf + pos, bufsz - pos,
 932                                                "0x%.4x ", ofs);
 933                                hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
 934                                                   buf + pos, bufsz - pos, 0);
 935                                pos += strlen(buf + pos);
 936                                if (bufsz - pos > 0)
 937                                        buf[pos++] = '\n';
 938                        }
 939                }
 940        }
 941
 942        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 943        kfree(buf);
 944        return ret;
 945}
 946
 947static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
 948                                         const char __user *user_buf,
 949                                         size_t count, loff_t *ppos)
 950{
 951        struct iwl_priv *priv = file->private_data;
 952        char buf[8];
 953        int buf_size;
 954        int traffic_log;
 955
 956        memset(buf, 0, sizeof(buf));
 957        buf_size = min(count, sizeof(buf) -  1);
 958        if (copy_from_user(buf, user_buf, buf_size))
 959                return -EFAULT;
 960        if (sscanf(buf, "%d", &traffic_log) != 1)
 961                return -EFAULT;
 962        if (traffic_log == 0)
 963                iwl_reset_traffic_log(priv);
 964
 965        return count;
 966}
 967
 968static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
 969                                                char __user *user_buf,
 970                                                size_t count, loff_t *ppos) {
 971
 972        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
 973        struct iwl_tx_queue *txq;
 974        struct iwl_queue *q;
 975        char *buf;
 976        int pos = 0;
 977        int cnt;
 978        int ret;
 979        const size_t bufsz = sizeof(char) * 60 * IWL_MAX_NUM_QUEUES;
 980
 981        buf = kzalloc(bufsz, GFP_KERNEL);
 982        if (!buf)
 983                return -ENOMEM;
 984
 985        for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
 986                txq = &priv->txq[cnt];
 987                q = &txq->q;
 988                pos += scnprintf(buf + pos, bufsz - pos,
 989                                "hwq %.2d: read=%u write=%u stop=%d"
 990                                " swq_id=%#.2x (ac %d/hwq %d)\n",
 991                                cnt, q->read_ptr, q->write_ptr,
 992                                !!test_bit(cnt, priv->queue_stopped),
 993                                txq->swq_id,
 994                                txq->swq_id & 0x80 ? txq->swq_id & 3 :
 995                                txq->swq_id,
 996                                txq->swq_id & 0x80 ? (txq->swq_id >> 2) &
 997                                0x1f : txq->swq_id);
 998                if (cnt >= 4)
 999                        continue;
1000                /* for the ACs, display the stop count too */
1001                pos += scnprintf(buf + pos, bufsz - pos,
1002                                "        stop-count: %d\n",
1003                                atomic_read(&priv->queue_stop_count[cnt]));
1004        }
1005        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1006        kfree(buf);
1007        return ret;
1008}
1009
1010static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
1011                                                char __user *user_buf,
1012                                                size_t count, loff_t *ppos) {
1013
1014        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1015        struct iwl_rx_queue *rxq = &priv->rxq;
1016        char buf[256];
1017        int pos = 0;
1018        const size_t bufsz = sizeof(buf);
1019
1020        pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
1021                                                rxq->read);
1022        pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
1023                                                rxq->write);
1024        pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
1025                                                rxq->free_count);
1026        pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
1027                         le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF);
1028        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1029}
1030
1031#define UCODE_STATISTICS_CLEAR_MSK              (0x1 << 0)
1032#define UCODE_STATISTICS_FREQUENCY_MSK          (0x1 << 1)
1033#define UCODE_STATISTICS_NARROW_BAND_MSK        (0x1 << 2)
1034
1035static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
1036                                     int bufsz)
1037{
1038        int p = 0;
1039
1040        p += scnprintf(buf + p, bufsz - p,
1041                "Statistics Flag(0x%X):\n",
1042                le32_to_cpu(priv->statistics.flag));
1043        if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
1044                p += scnprintf(buf + p, bufsz - p,
1045                "\tStatistics have been cleared\n");
1046        p += scnprintf(buf + p, bufsz - p,
1047                "\tOperational Frequency: %s\n",
1048                (le32_to_cpu(priv->statistics.flag) &
1049                UCODE_STATISTICS_FREQUENCY_MSK)
1050                 ? "2.4 GHz" : "5.2 GHz");
1051        p += scnprintf(buf + p, bufsz - p,
1052                "\tTGj Narrow Band: %s\n",
1053                (le32_to_cpu(priv->statistics.flag) &
1054                UCODE_STATISTICS_NARROW_BAND_MSK)
1055                 ? "enabled" : "disabled");
1056        return p;
1057}
1058
1059
1060static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
1061                                        char __user *user_buf,
1062                                        size_t count, loff_t *ppos)
1063{
1064        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1065        int pos = 0;
1066        char *buf;
1067        int bufsz = sizeof(struct statistics_rx_phy) * 20 +
1068                sizeof(struct statistics_rx_non_phy) * 20 +
1069                sizeof(struct statistics_rx_ht_phy) * 20 + 400;
1070        ssize_t ret;
1071        struct statistics_rx_phy *ofdm;
1072        struct statistics_rx_phy *cck;
1073        struct statistics_rx_non_phy *general;
1074        struct statistics_rx_ht_phy *ht;
1075
1076        if (!iwl_is_alive(priv))
1077                return -EAGAIN;
1078
1079        /* make request to uCode to retrieve statistics information */
1080        mutex_lock(&priv->mutex);
1081        ret = iwl_send_statistics_request(priv, 0);
1082        mutex_unlock(&priv->mutex);
1083
1084        if (ret) {
1085                IWL_ERR(priv,
1086                        "Error sending statistics request: %zd\n", ret);
1087                return -EAGAIN;
1088        }
1089        buf = kzalloc(bufsz, GFP_KERNEL);
1090        if (!buf) {
1091                IWL_ERR(priv, "Can not allocate Buffer\n");
1092                return -ENOMEM;
1093        }
1094
1095        /* the statistic information display here is based on
1096         * the last statistics notification from uCode
1097         * might not reflect the current uCode activity
1098         */
1099        ofdm = &priv->statistics.rx.ofdm;
1100        cck = &priv->statistics.rx.cck;
1101        general = &priv->statistics.rx.general;
1102        ht = &priv->statistics.rx.ofdm_ht;
1103        pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1104        pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n");
1105        pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
1106                         le32_to_cpu(ofdm->ina_cnt));
1107        pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
1108                         le32_to_cpu(ofdm->fina_cnt));
1109        pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1110                         le32_to_cpu(ofdm->plcp_err));
1111        pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1112                         le32_to_cpu(ofdm->crc32_err));
1113        pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1114                         le32_to_cpu(ofdm->overrun_err));
1115        pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1116                         le32_to_cpu(ofdm->early_overrun_err));
1117        pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1118                         le32_to_cpu(ofdm->crc32_good));
1119        pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
1120                         le32_to_cpu(ofdm->false_alarm_cnt));
1121        pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
1122                         le32_to_cpu(ofdm->fina_sync_err_cnt));
1123        pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
1124                         le32_to_cpu(ofdm->sfd_timeout));
1125        pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
1126                         le32_to_cpu(ofdm->fina_timeout));
1127        pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
1128                         le32_to_cpu(ofdm->unresponded_rts));
1129        pos += scnprintf(buf + pos, bufsz - pos,
1130                        "rxe_frame_limit_overrun: %u\n",
1131                        le32_to_cpu(ofdm->rxe_frame_limit_overrun));
1132        pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
1133                         le32_to_cpu(ofdm->sent_ack_cnt));
1134        pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
1135                         le32_to_cpu(ofdm->sent_cts_cnt));
1136        pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
1137                         le32_to_cpu(ofdm->sent_ba_rsp_cnt));
1138        pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
1139                         le32_to_cpu(ofdm->dsp_self_kill));
1140        pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1141                         le32_to_cpu(ofdm->mh_format_err));
1142        pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
1143                         le32_to_cpu(ofdm->re_acq_main_rssi_sum));
1144
1145        pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n");
1146        pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
1147                         le32_to_cpu(cck->ina_cnt));
1148        pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
1149                         le32_to_cpu(cck->fina_cnt));
1150        pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1151                         le32_to_cpu(cck->plcp_err));
1152        pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1153                         le32_to_cpu(cck->crc32_err));
1154        pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1155                         le32_to_cpu(cck->overrun_err));
1156        pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1157                         le32_to_cpu(cck->early_overrun_err));
1158        pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1159                         le32_to_cpu(cck->crc32_good));
1160        pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
1161                         le32_to_cpu(cck->false_alarm_cnt));
1162        pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
1163                         le32_to_cpu(cck->fina_sync_err_cnt));
1164        pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
1165                         le32_to_cpu(cck->sfd_timeout));
1166        pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
1167                         le32_to_cpu(cck->fina_timeout));
1168        pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
1169                         le32_to_cpu(cck->unresponded_rts));
1170        pos += scnprintf(buf + pos, bufsz - pos,
1171                        "rxe_frame_limit_overrun: %u\n",
1172                        le32_to_cpu(cck->rxe_frame_limit_overrun));
1173        pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
1174                         le32_to_cpu(cck->sent_ack_cnt));
1175        pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
1176                         le32_to_cpu(cck->sent_cts_cnt));
1177        pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
1178                         le32_to_cpu(cck->sent_ba_rsp_cnt));
1179        pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
1180                         le32_to_cpu(cck->dsp_self_kill));
1181        pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1182                         le32_to_cpu(cck->mh_format_err));
1183        pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
1184                         le32_to_cpu(cck->re_acq_main_rssi_sum));
1185
1186        pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n");
1187        pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts: %u\n",
1188                         le32_to_cpu(general->bogus_cts));
1189        pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack: %u\n",
1190                         le32_to_cpu(general->bogus_ack));
1191        pos += scnprintf(buf + pos, bufsz - pos, "non_bssid_frames: %u\n",
1192                         le32_to_cpu(general->non_bssid_frames));
1193        pos += scnprintf(buf + pos, bufsz - pos, "filtered_frames: %u\n",
1194                         le32_to_cpu(general->filtered_frames));
1195        pos += scnprintf(buf + pos, bufsz - pos, "non_channel_beacons: %u\n",
1196                         le32_to_cpu(general->non_channel_beacons));
1197        pos += scnprintf(buf + pos, bufsz - pos, "channel_beacons: %u\n",
1198                         le32_to_cpu(general->channel_beacons));
1199        pos += scnprintf(buf + pos, bufsz - pos, "num_missed_bcon: %u\n",
1200                         le32_to_cpu(general->num_missed_bcon));
1201        pos += scnprintf(buf + pos, bufsz - pos,
1202                        "adc_rx_saturation_time: %u\n",
1203                        le32_to_cpu(general->adc_rx_saturation_time));
1204        pos += scnprintf(buf + pos, bufsz - pos,
1205                        "ina_detection_search_time: %u\n",
1206                        le32_to_cpu(general->ina_detection_search_time));
1207        pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_a: %u\n",
1208                         le32_to_cpu(general->beacon_silence_rssi_a));
1209        pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_b: %u\n",
1210                         le32_to_cpu(general->beacon_silence_rssi_b));
1211        pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_c: %u\n",
1212                         le32_to_cpu(general->beacon_silence_rssi_c));
1213        pos += scnprintf(buf + pos, bufsz - pos,
1214                        "interference_data_flag: %u\n",
1215                        le32_to_cpu(general->interference_data_flag));
1216        pos += scnprintf(buf + pos, bufsz - pos, "channel_load: %u\n",
1217                         le32_to_cpu(general->channel_load));
1218        pos += scnprintf(buf + pos, bufsz - pos, "dsp_false_alarms: %u\n",
1219                         le32_to_cpu(general->dsp_false_alarms));
1220        pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_a: %u\n",
1221                         le32_to_cpu(general->beacon_rssi_a));
1222        pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_b: %u\n",
1223                         le32_to_cpu(general->beacon_rssi_b));
1224        pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_c: %u\n",
1225                         le32_to_cpu(general->beacon_rssi_c));
1226        pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_a: %u\n",
1227                         le32_to_cpu(general->beacon_energy_a));
1228        pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_b: %u\n",
1229                         le32_to_cpu(general->beacon_energy_b));
1230        pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_c: %u\n",
1231                         le32_to_cpu(general->beacon_energy_c));
1232
1233        pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
1234        pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1235                         le32_to_cpu(ht->plcp_err));
1236        pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1237                         le32_to_cpu(ht->overrun_err));
1238        pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1239                         le32_to_cpu(ht->early_overrun_err));
1240        pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1241                         le32_to_cpu(ht->crc32_good));
1242        pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1243                         le32_to_cpu(ht->crc32_err));
1244        pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1245                         le32_to_cpu(ht->mh_format_err));
1246        pos += scnprintf(buf + pos, bufsz - pos, "agg_crc32_good: %u\n",
1247                         le32_to_cpu(ht->agg_crc32_good));
1248        pos += scnprintf(buf + pos, bufsz - pos, "agg_mpdu_cnt: %u\n",
1249                         le32_to_cpu(ht->agg_mpdu_cnt));
1250        pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt: %u\n",
1251                         le32_to_cpu(ht->agg_cnt));
1252
1253        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1254        kfree(buf);
1255        return ret;
1256}
1257
1258static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
1259                                        char __user *user_buf,
1260                                        size_t count, loff_t *ppos)
1261{
1262        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1263        int pos = 0;
1264        char *buf;
1265        int bufsz = (sizeof(struct statistics_tx) * 24) + 250;
1266        ssize_t ret;
1267        struct statistics_tx *tx;
1268
1269        if (!iwl_is_alive(priv))
1270                return -EAGAIN;
1271
1272        /* make request to uCode to retrieve statistics information */
1273        mutex_lock(&priv->mutex);
1274        ret = iwl_send_statistics_request(priv, 0);
1275        mutex_unlock(&priv->mutex);
1276
1277        if (ret) {
1278                IWL_ERR(priv,
1279                        "Error sending statistics request: %zd\n", ret);
1280                return -EAGAIN;
1281        }
1282        buf = kzalloc(bufsz, GFP_KERNEL);
1283        if (!buf) {
1284                IWL_ERR(priv, "Can not allocate Buffer\n");
1285                return -ENOMEM;
1286        }
1287
1288        /* the statistic information display here is based on
1289         * the last statistics notification from uCode
1290         * might not reflect the current uCode activity
1291         */
1292        tx = &priv->statistics.tx;
1293        pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1294        pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n");
1295        pos += scnprintf(buf + pos, bufsz - pos, "preamble: %u\n",
1296                         le32_to_cpu(tx->preamble_cnt));
1297        pos += scnprintf(buf + pos, bufsz - pos, "rx_detected_cnt: %u\n",
1298                         le32_to_cpu(tx->rx_detected_cnt));
1299        pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_defer_cnt: %u\n",
1300                         le32_to_cpu(tx->bt_prio_defer_cnt));
1301        pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_kill_cnt: %u\n",
1302                         le32_to_cpu(tx->bt_prio_kill_cnt));
1303        pos += scnprintf(buf + pos, bufsz - pos, "few_bytes_cnt: %u\n",
1304                         le32_to_cpu(tx->few_bytes_cnt));
1305        pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout: %u\n",
1306                         le32_to_cpu(tx->cts_timeout));
1307        pos += scnprintf(buf + pos, bufsz - pos, "ack_timeout: %u\n",
1308                         le32_to_cpu(tx->ack_timeout));
1309        pos += scnprintf(buf + pos, bufsz - pos, "expected_ack_cnt: %u\n",
1310                         le32_to_cpu(tx->expected_ack_cnt));
1311        pos += scnprintf(buf + pos, bufsz - pos, "actual_ack_cnt: %u\n",
1312                         le32_to_cpu(tx->actual_ack_cnt));
1313        pos += scnprintf(buf + pos, bufsz - pos, "dump_msdu_cnt: %u\n",
1314                         le32_to_cpu(tx->dump_msdu_cnt));
1315        pos += scnprintf(buf + pos, bufsz - pos,
1316                        "burst_abort_next_frame_mismatch_cnt: %u\n",
1317                        le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt));
1318        pos += scnprintf(buf + pos, bufsz - pos,
1319                        "burst_abort_missing_next_frame_cnt: %u\n",
1320                        le32_to_cpu(tx->burst_abort_missing_next_frame_cnt));
1321        pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout_collision: %u\n",
1322                         le32_to_cpu(tx->cts_timeout_collision));
1323        pos += scnprintf(buf + pos, bufsz - pos,
1324                        "ack_or_ba_timeout_collision: %u\n",
1325                        le32_to_cpu(tx->ack_or_ba_timeout_collision));
1326        pos += scnprintf(buf + pos, bufsz - pos, "agg ba_timeout: %u\n",
1327                         le32_to_cpu(tx->agg.ba_timeout));
1328        pos += scnprintf(buf + pos, bufsz - pos,
1329                        "agg ba_reschedule_frames: %u\n",
1330                        le32_to_cpu(tx->agg.ba_reschedule_frames));
1331        pos += scnprintf(buf + pos, bufsz - pos,
1332                        "agg scd_query_agg_frame_cnt: %u\n",
1333                        le32_to_cpu(tx->agg.scd_query_agg_frame_cnt));
1334        pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_no_agg: %u\n",
1335                         le32_to_cpu(tx->agg.scd_query_no_agg));
1336        pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_agg: %u\n",
1337                         le32_to_cpu(tx->agg.scd_query_agg));
1338        pos += scnprintf(buf + pos, bufsz - pos,
1339                        "agg scd_query_mismatch: %u\n",
1340                        le32_to_cpu(tx->agg.scd_query_mismatch));
1341        pos += scnprintf(buf + pos, bufsz - pos, "agg frame_not_ready: %u\n",
1342                         le32_to_cpu(tx->agg.frame_not_ready));
1343        pos += scnprintf(buf + pos, bufsz - pos, "agg underrun: %u\n",
1344                         le32_to_cpu(tx->agg.underrun));
1345        pos += scnprintf(buf + pos, bufsz - pos, "agg bt_prio_kill: %u\n",
1346                         le32_to_cpu(tx->agg.bt_prio_kill));
1347        pos += scnprintf(buf + pos, bufsz - pos, "agg rx_ba_rsp_cnt: %u\n",
1348                         le32_to_cpu(tx->agg.rx_ba_rsp_cnt));
1349
1350        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1351        kfree(buf);
1352        return ret;
1353}
1354
1355static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
1356                                        char __user *user_buf,
1357                                        size_t count, loff_t *ppos)
1358{
1359        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1360        int pos = 0;
1361        char *buf;
1362        int bufsz = sizeof(struct statistics_general) * 4 + 250;
1363        ssize_t ret;
1364        struct statistics_general *general;
1365        struct statistics_dbg *dbg;
1366        struct statistics_div *div;
1367
1368        if (!iwl_is_alive(priv))
1369                return -EAGAIN;
1370
1371        /* make request to uCode to retrieve statistics information */
1372        mutex_lock(&priv->mutex);
1373        ret = iwl_send_statistics_request(priv, 0);
1374        mutex_unlock(&priv->mutex);
1375
1376        if (ret) {
1377                IWL_ERR(priv,
1378                        "Error sending statistics request: %zd\n", ret);
1379                return -EAGAIN;
1380        }
1381        buf = kzalloc(bufsz, GFP_KERNEL);
1382        if (!buf) {
1383                IWL_ERR(priv, "Can not allocate Buffer\n");
1384                return -ENOMEM;
1385        }
1386
1387        /* the statistic information display here is based on
1388         * the last statistics notification from uCode
1389         * might not reflect the current uCode activity
1390         */
1391        general = &priv->statistics.general;
1392        dbg = &priv->statistics.general.dbg;
1393        div = &priv->statistics.general.div;
1394        pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1395        pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n");
1396        pos += scnprintf(buf + pos, bufsz - pos, "temperature: %u\n",
1397                         le32_to_cpu(general->temperature));
1398        pos += scnprintf(buf + pos, bufsz - pos, "temperature_m: %u\n",
1399                         le32_to_cpu(general->temperature_m));
1400        pos += scnprintf(buf + pos, bufsz - pos, "burst_check: %u\n",
1401                         le32_to_cpu(dbg->burst_check));
1402        pos += scnprintf(buf + pos, bufsz - pos, "burst_count: %u\n",
1403                         le32_to_cpu(dbg->burst_count));
1404        pos += scnprintf(buf + pos, bufsz - pos, "sleep_time: %u\n",
1405                         le32_to_cpu(general->sleep_time));
1406        pos += scnprintf(buf + pos, bufsz - pos, "slots_out: %u\n",
1407                         le32_to_cpu(general->slots_out));
1408        pos += scnprintf(buf + pos, bufsz - pos, "slots_idle: %u\n",
1409                         le32_to_cpu(general->slots_idle));
1410        pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp: %u\n",
1411                         le32_to_cpu(general->ttl_timestamp));
1412        pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a: %u\n",
1413                         le32_to_cpu(div->tx_on_a));
1414        pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b: %u\n",
1415                         le32_to_cpu(div->tx_on_b));
1416        pos += scnprintf(buf + pos, bufsz - pos, "exec_time: %u\n",
1417                         le32_to_cpu(div->exec_time));
1418        pos += scnprintf(buf + pos, bufsz - pos, "probe_time: %u\n",
1419                         le32_to_cpu(div->probe_time));
1420        pos += scnprintf(buf + pos, bufsz - pos, "rx_enable_counter: %u\n",
1421                         le32_to_cpu(general->rx_enable_counter));
1422        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1423        kfree(buf);
1424        return ret;
1425}
1426
1427static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
1428                                        char __user *user_buf,
1429                                        size_t count, loff_t *ppos) {
1430
1431        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1432        int pos = 0;
1433        int cnt = 0;
1434        char *buf;
1435        int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
1436        ssize_t ret;
1437        struct iwl_sensitivity_data *data;
1438
1439        data = &priv->sensitivity_data;
1440        buf = kzalloc(bufsz, GFP_KERNEL);
1441        if (!buf) {
1442                IWL_ERR(priv, "Can not allocate Buffer\n");
1443                return -ENOMEM;
1444        }
1445
1446        pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
1447                        data->auto_corr_ofdm);
1448        pos += scnprintf(buf + pos, bufsz - pos,
1449                        "auto_corr_ofdm_mrc:\t\t %u\n",
1450                        data->auto_corr_ofdm_mrc);
1451        pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
1452                        data->auto_corr_ofdm_x1);
1453        pos += scnprintf(buf + pos, bufsz - pos,
1454                        "auto_corr_ofdm_mrc_x1:\t\t %u\n",
1455                        data->auto_corr_ofdm_mrc_x1);
1456        pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
1457                        data->auto_corr_cck);
1458        pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
1459                        data->auto_corr_cck_mrc);
1460        pos += scnprintf(buf + pos, bufsz - pos,
1461                        "last_bad_plcp_cnt_ofdm:\t\t %u\n",
1462                        data->last_bad_plcp_cnt_ofdm);
1463        pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
1464                        data->last_fa_cnt_ofdm);
1465        pos += scnprintf(buf + pos, bufsz - pos,
1466                        "last_bad_plcp_cnt_cck:\t\t %u\n",
1467                        data->last_bad_plcp_cnt_cck);
1468        pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
1469                        data->last_fa_cnt_cck);
1470        pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
1471                        data->nrg_curr_state);
1472        pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
1473                        data->nrg_prev_state);
1474        pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
1475        for (cnt = 0; cnt < 10; cnt++) {
1476                pos += scnprintf(buf + pos, bufsz - pos, " %u",
1477                                data->nrg_value[cnt]);
1478        }
1479        pos += scnprintf(buf + pos, bufsz - pos, "\n");
1480        pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
1481        for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
1482                pos += scnprintf(buf + pos, bufsz - pos, " %u",
1483                                data->nrg_silence_rssi[cnt]);
1484        }
1485        pos += scnprintf(buf + pos, bufsz - pos, "\n");
1486        pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
1487                        data->nrg_silence_ref);
1488        pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
1489                        data->nrg_energy_idx);
1490        pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
1491                        data->nrg_silence_idx);
1492        pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
1493                        data->nrg_th_cck);
1494        pos += scnprintf(buf + pos, bufsz - pos,
1495                        "nrg_auto_corr_silence_diff:\t %u\n",
1496                        data->nrg_auto_corr_silence_diff);
1497        pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
1498                        data->num_in_cck_no_fa);
1499        pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
1500                        data->nrg_th_ofdm);
1501
1502        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1503        kfree(buf);
1504        return ret;
1505}
1506
1507
1508static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
1509                                        char __user *user_buf,
1510                                        size_t count, loff_t *ppos) {
1511
1512        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1513        int pos = 0;
1514        int cnt = 0;
1515        char *buf;
1516        int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
1517        ssize_t ret;
1518        struct iwl_chain_noise_data *data;
1519
1520        data = &priv->chain_noise_data;
1521        buf = kzalloc(bufsz, GFP_KERNEL);
1522        if (!buf) {
1523                IWL_ERR(priv, "Can not allocate Buffer\n");
1524                return -ENOMEM;
1525        }
1526
1527        pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
1528                        data->active_chains);
1529        pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
1530                        data->chain_noise_a);
1531        pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
1532                        data->chain_noise_b);
1533        pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
1534                        data->chain_noise_c);
1535        pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
1536                        data->chain_signal_a);
1537        pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
1538                        data->chain_signal_b);
1539        pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
1540                        data->chain_signal_c);
1541        pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
1542                        data->beacon_count);
1543
1544        pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
1545        for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1546                pos += scnprintf(buf + pos, bufsz - pos, " %u",
1547                                data->disconn_array[cnt]);
1548        }
1549        pos += scnprintf(buf + pos, bufsz - pos, "\n");
1550        pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
1551        for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1552                pos += scnprintf(buf + pos, bufsz - pos, " %u",
1553                                data->delta_gain_code[cnt]);
1554        }
1555        pos += scnprintf(buf + pos, bufsz - pos, "\n");
1556        pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1557                        data->radio_write);
1558        pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1559                        data->state);
1560
1561        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1562        kfree(buf);
1563        return ret;
1564}
1565
1566static ssize_t iwl_dbgfs_tx_power_read(struct file *file,
1567                                        char __user *user_buf,
1568                                        size_t count, loff_t *ppos) {
1569
1570        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1571        char buf[128];
1572        int pos = 0;
1573        ssize_t ret;
1574        const size_t bufsz = sizeof(buf);
1575        struct statistics_tx *tx;
1576
1577        if (!iwl_is_alive(priv))
1578                pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
1579        else {
1580                /* make request to uCode to retrieve statistics information */
1581                mutex_lock(&priv->mutex);
1582                ret = iwl_send_statistics_request(priv, 0);
1583                mutex_unlock(&priv->mutex);
1584
1585                if (ret) {
1586                        IWL_ERR(priv, "Error sending statistics request: %zd\n",
1587                                ret);
1588                        return -EAGAIN;
1589                }
1590                tx = &priv->statistics.tx;
1591                if (tx->tx_power.ant_a ||
1592                    tx->tx_power.ant_b ||
1593                    tx->tx_power.ant_c) {
1594                        pos += scnprintf(buf + pos, bufsz - pos,
1595                                "tx power: (1/2 dB step)\n");
1596                        if ((priv->cfg->valid_tx_ant & ANT_A) &&
1597                            tx->tx_power.ant_a)
1598                                pos += scnprintf(buf + pos, bufsz - pos,
1599                                                "\tantenna A: 0x%X\n",
1600                                                tx->tx_power.ant_a);
1601                        if ((priv->cfg->valid_tx_ant & ANT_B) &&
1602                            tx->tx_power.ant_b)
1603                                pos += scnprintf(buf + pos, bufsz - pos,
1604                                                "\tantenna B: 0x%X\n",
1605                                                tx->tx_power.ant_b);
1606                        if ((priv->cfg->valid_tx_ant & ANT_C) &&
1607                            tx->tx_power.ant_c)
1608                                pos += scnprintf(buf + pos, bufsz - pos,
1609                                                "\tantenna C: 0x%X\n",
1610                                                tx->tx_power.ant_c);
1611                } else
1612                        pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
1613        }
1614        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1615}
1616
1617DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
1618DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
1619DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
1620DEBUGFS_READ_FILE_OPS(rx_queue);
1621DEBUGFS_READ_FILE_OPS(tx_queue);
1622DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1623DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1624DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1625DEBUGFS_READ_FILE_OPS(sensitivity);
1626DEBUGFS_READ_FILE_OPS(chain_noise);
1627DEBUGFS_READ_FILE_OPS(tx_power);
1628
1629/*
1630 * Create the debugfs files and directories
1631 *
1632 */
1633int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
1634{
1635        struct iwl_debugfs *dbgfs;
1636        struct dentry *phyd = priv->hw->wiphy->debugfsdir;
1637        int ret = 0;
1638
1639        dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
1640        if (!dbgfs) {
1641                ret = -ENOMEM;
1642                goto err;
1643        }
1644
1645        priv->dbgfs = dbgfs;
1646        dbgfs->name = name;
1647        dbgfs->dir_drv = debugfs_create_dir(name, phyd);
1648        if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) {
1649                ret = -ENOENT;
1650                goto err;
1651        }
1652
1653        DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
1654        DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
1655        DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv);
1656        DEBUGFS_ADD_FILE(nvm, data);
1657        DEBUGFS_ADD_FILE(sram, data);
1658        DEBUGFS_ADD_FILE(log_event, data);
1659        DEBUGFS_ADD_FILE(stations, data);
1660        DEBUGFS_ADD_FILE(channels, data);
1661        DEBUGFS_ADD_FILE(status, data);
1662        DEBUGFS_ADD_FILE(interrupt, data);
1663        DEBUGFS_ADD_FILE(qos, data);
1664#ifdef CONFIG_IWLWIFI_LEDS
1665        DEBUGFS_ADD_FILE(led, data);
1666#endif
1667        DEBUGFS_ADD_FILE(sleep_level_override, data);
1668        DEBUGFS_ADD_FILE(current_sleep_command, data);
1669        DEBUGFS_ADD_FILE(thermal_throttling, data);
1670        DEBUGFS_ADD_FILE(disable_ht40, data);
1671        DEBUGFS_ADD_FILE(rx_statistics, debug);
1672        DEBUGFS_ADD_FILE(tx_statistics, debug);
1673        DEBUGFS_ADD_FILE(traffic_log, debug);
1674        DEBUGFS_ADD_FILE(rx_queue, debug);
1675        DEBUGFS_ADD_FILE(tx_queue, debug);
1676        DEBUGFS_ADD_FILE(tx_power, debug);
1677        if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
1678                DEBUGFS_ADD_FILE(ucode_rx_stats, debug);
1679                DEBUGFS_ADD_FILE(ucode_tx_stats, debug);
1680                DEBUGFS_ADD_FILE(ucode_general_stats, debug);
1681                DEBUGFS_ADD_FILE(sensitivity, debug);
1682                DEBUGFS_ADD_FILE(chain_noise, debug);
1683        }
1684        DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
1685        DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
1686                         &priv->disable_chain_noise_cal);
1687        if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
1688            ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
1689                DEBUGFS_ADD_BOOL(disable_tx_power, rf,
1690                                &priv->disable_tx_power_cal);
1691        return 0;
1692
1693err:
1694        IWL_ERR(priv, "Can't open the debugfs directory\n");
1695        iwl_dbgfs_unregister(priv);
1696        return ret;
1697}
1698EXPORT_SYMBOL(iwl_dbgfs_register);
1699
1700/**
1701 * Remove the debugfs files and directories
1702 *
1703 */
1704void iwl_dbgfs_unregister(struct iwl_priv *priv)
1705{
1706        if (!priv->dbgfs)
1707                return;
1708
1709        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override);
1710        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command);
1711        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
1712        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
1713        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
1714        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
1715        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
1716        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
1717        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
1718        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos);
1719#ifdef CONFIG_IWLWIFI_LEDS
1720        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
1721#endif
1722        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
1723        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
1724        DEBUGFS_REMOVE(priv->dbgfs->dir_data);
1725        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
1726        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
1727        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
1728        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
1729        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
1730        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power);
1731        if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
1732                DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1733                        file_ucode_rx_stats);
1734                DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1735                        file_ucode_tx_stats);
1736                DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1737                        file_ucode_general_stats);
1738                DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1739                        file_sensitivity);
1740                DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1741                        file_chain_noise);
1742        }
1743        DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
1744        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
1745        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
1746        if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
1747            ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
1748                DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
1749        DEBUGFS_REMOVE(priv->dbgfs->dir_rf);
1750        DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
1751        kfree(priv->dbgfs);
1752        priv->dbgfs = NULL;
1753}
1754EXPORT_SYMBOL(iwl_dbgfs_unregister);
1755
1756
1757
1758