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