linux/drivers/net/wireless/ti/wlcore/debugfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * This file is part of wl1271
   4 *
   5 * Copyright (C) 2009 Nokia Corporation
   6 *
   7 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
   8 */
   9
  10#include "debugfs.h"
  11
  12#include <linux/skbuff.h>
  13#include <linux/slab.h>
  14#include <linux/module.h>
  15#include <linux/pm_runtime.h>
  16
  17#include "wlcore.h"
  18#include "debug.h"
  19#include "acx.h"
  20#include "ps.h"
  21#include "io.h"
  22#include "tx.h"
  23#include "hw_ops.h"
  24
  25/* ms */
  26#define WL1271_DEBUGFS_STATS_LIFETIME 1000
  27
  28#define WLCORE_MAX_BLOCK_SIZE ((size_t)(4*PAGE_SIZE))
  29
  30/* debugfs macros idea from mac80211 */
  31int wl1271_format_buffer(char __user *userbuf, size_t count,
  32                         loff_t *ppos, char *fmt, ...)
  33{
  34        va_list args;
  35        char buf[DEBUGFS_FORMAT_BUFFER_SIZE];
  36        int res;
  37
  38        va_start(args, fmt);
  39        res = vscnprintf(buf, sizeof(buf), fmt, args);
  40        va_end(args);
  41
  42        return simple_read_from_buffer(userbuf, count, ppos, buf, res);
  43}
  44EXPORT_SYMBOL_GPL(wl1271_format_buffer);
  45
  46void wl1271_debugfs_update_stats(struct wl1271 *wl)
  47{
  48        int ret;
  49
  50        mutex_lock(&wl->mutex);
  51
  52        if (unlikely(wl->state != WLCORE_STATE_ON))
  53                goto out;
  54
  55        ret = pm_runtime_get_sync(wl->dev);
  56        if (ret < 0) {
  57                pm_runtime_put_noidle(wl->dev);
  58                goto out;
  59        }
  60
  61        if (!wl->plt &&
  62            time_after(jiffies, wl->stats.fw_stats_update +
  63                       msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {
  64                wl1271_acx_statistics(wl, wl->stats.fw_stats);
  65                wl->stats.fw_stats_update = jiffies;
  66        }
  67
  68        pm_runtime_mark_last_busy(wl->dev);
  69        pm_runtime_put_autosuspend(wl->dev);
  70
  71out:
  72        mutex_unlock(&wl->mutex);
  73}
  74EXPORT_SYMBOL_GPL(wl1271_debugfs_update_stats);
  75
  76DEBUGFS_READONLY_FILE(retry_count, "%u", wl->stats.retry_count);
  77DEBUGFS_READONLY_FILE(excessive_retries, "%u",
  78                      wl->stats.excessive_retries);
  79
  80static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
  81                                 size_t count, loff_t *ppos)
  82{
  83        struct wl1271 *wl = file->private_data;
  84        u32 queue_len;
  85        char buf[20];
  86        int res;
  87
  88        queue_len = wl1271_tx_total_queue_count(wl);
  89
  90        res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
  91        return simple_read_from_buffer(userbuf, count, ppos, buf, res);
  92}
  93
  94static const struct file_operations tx_queue_len_ops = {
  95        .read = tx_queue_len_read,
  96        .open = simple_open,
  97        .llseek = default_llseek,
  98};
  99
 100static void chip_op_handler(struct wl1271 *wl, unsigned long value,
 101                            void *arg)
 102{
 103        int ret;
 104        int (*chip_op) (struct wl1271 *wl);
 105
 106        if (!arg) {
 107                wl1271_warning("debugfs chip_op_handler with no callback");
 108                return;
 109        }
 110
 111        ret = pm_runtime_get_sync(wl->dev);
 112        if (ret < 0) {
 113                pm_runtime_put_noidle(wl->dev);
 114
 115                return;
 116        }
 117
 118        chip_op = arg;
 119        chip_op(wl);
 120
 121        pm_runtime_mark_last_busy(wl->dev);
 122        pm_runtime_put_autosuspend(wl->dev);
 123}
 124
 125#define WL12XX_CONF_DEBUGFS(param, conf_sub_struct,                     \
 126                            min_val, max_val, write_handler_locked,     \
 127                            write_handler_arg)                          \
 128        static ssize_t param##_read(struct file *file,                  \
 129                                      char __user *user_buf,            \
 130                                      size_t count, loff_t *ppos)       \
 131        {                                                               \
 132        struct wl1271 *wl = file->private_data;                         \
 133        return wl1271_format_buffer(user_buf, count,                    \
 134                                    ppos, "%d\n",                       \
 135                                    wl->conf.conf_sub_struct.param);    \
 136        }                                                               \
 137                                                                        \
 138        static ssize_t param##_write(struct file *file,                 \
 139                                     const char __user *user_buf,       \
 140                                     size_t count, loff_t *ppos)        \
 141        {                                                               \
 142        struct wl1271 *wl = file->private_data;                         \
 143        unsigned long value;                                            \
 144        int ret;                                                        \
 145                                                                        \
 146        ret = kstrtoul_from_user(user_buf, count, 10, &value);          \
 147        if (ret < 0) {                                                  \
 148                wl1271_warning("illegal value for " #param);            \
 149                return -EINVAL;                                         \
 150        }                                                               \
 151                                                                        \
 152        if (value < min_val || value > max_val) {                       \
 153                wl1271_warning(#param " is not in valid range");        \
 154                return -ERANGE;                                         \
 155        }                                                               \
 156                                                                        \
 157        mutex_lock(&wl->mutex);                                         \
 158        wl->conf.conf_sub_struct.param = value;                         \
 159                                                                        \
 160        write_handler_locked(wl, value, write_handler_arg);             \
 161                                                                        \
 162        mutex_unlock(&wl->mutex);                                       \
 163        return count;                                                   \
 164        }                                                               \
 165                                                                        \
 166        static const struct file_operations param##_ops = {             \
 167                .read = param##_read,                                   \
 168                .write = param##_write,                                 \
 169                .open = simple_open,                                    \
 170                .llseek = default_llseek,                               \
 171        };
 172
 173WL12XX_CONF_DEBUGFS(irq_pkt_threshold, rx, 0, 65535,
 174                    chip_op_handler, wl1271_acx_init_rx_interrupt)
 175WL12XX_CONF_DEBUGFS(irq_blk_threshold, rx, 0, 65535,
 176                    chip_op_handler, wl1271_acx_init_rx_interrupt)
 177WL12XX_CONF_DEBUGFS(irq_timeout, rx, 0, 100,
 178                    chip_op_handler, wl1271_acx_init_rx_interrupt)
 179
 180static ssize_t gpio_power_read(struct file *file, char __user *user_buf,
 181                          size_t count, loff_t *ppos)
 182{
 183        struct wl1271 *wl = file->private_data;
 184        bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
 185
 186        int res;
 187        char buf[10];
 188
 189        res = scnprintf(buf, sizeof(buf), "%d\n", state);
 190
 191        return simple_read_from_buffer(user_buf, count, ppos, buf, res);
 192}
 193
 194static ssize_t gpio_power_write(struct file *file,
 195                           const char __user *user_buf,
 196                           size_t count, loff_t *ppos)
 197{
 198        struct wl1271 *wl = file->private_data;
 199        unsigned long value;
 200        int ret;
 201
 202        ret = kstrtoul_from_user(user_buf, count, 10, &value);
 203        if (ret < 0) {
 204                wl1271_warning("illegal value in gpio_power");
 205                return -EINVAL;
 206        }
 207
 208        mutex_lock(&wl->mutex);
 209
 210        if (value)
 211                wl1271_power_on(wl);
 212        else
 213                wl1271_power_off(wl);
 214
 215        mutex_unlock(&wl->mutex);
 216        return count;
 217}
 218
 219static const struct file_operations gpio_power_ops = {
 220        .read = gpio_power_read,
 221        .write = gpio_power_write,
 222        .open = simple_open,
 223        .llseek = default_llseek,
 224};
 225
 226static ssize_t start_recovery_write(struct file *file,
 227                                    const char __user *user_buf,
 228                                    size_t count, loff_t *ppos)
 229{
 230        struct wl1271 *wl = file->private_data;
 231
 232        mutex_lock(&wl->mutex);
 233        wl12xx_queue_recovery_work(wl);
 234        mutex_unlock(&wl->mutex);
 235
 236        return count;
 237}
 238
 239static const struct file_operations start_recovery_ops = {
 240        .write = start_recovery_write,
 241        .open = simple_open,
 242        .llseek = default_llseek,
 243};
 244
 245static ssize_t dynamic_ps_timeout_read(struct file *file, char __user *user_buf,
 246                          size_t count, loff_t *ppos)
 247{
 248        struct wl1271 *wl = file->private_data;
 249
 250        return wl1271_format_buffer(user_buf, count,
 251                                    ppos, "%d\n",
 252                                    wl->conf.conn.dynamic_ps_timeout);
 253}
 254
 255static ssize_t dynamic_ps_timeout_write(struct file *file,
 256                                    const char __user *user_buf,
 257                                    size_t count, loff_t *ppos)
 258{
 259        struct wl1271 *wl = file->private_data;
 260        struct wl12xx_vif *wlvif;
 261        unsigned long value;
 262        int ret;
 263
 264        ret = kstrtoul_from_user(user_buf, count, 10, &value);
 265        if (ret < 0) {
 266                wl1271_warning("illegal value in dynamic_ps");
 267                return -EINVAL;
 268        }
 269
 270        if (value < 1 || value > 65535) {
 271                wl1271_warning("dynamic_ps_timeout is not in valid range");
 272                return -ERANGE;
 273        }
 274
 275        mutex_lock(&wl->mutex);
 276
 277        wl->conf.conn.dynamic_ps_timeout = value;
 278
 279        if (unlikely(wl->state != WLCORE_STATE_ON))
 280                goto out;
 281
 282        ret = pm_runtime_get_sync(wl->dev);
 283        if (ret < 0) {
 284                pm_runtime_put_noidle(wl->dev);
 285                goto out;
 286        }
 287
 288        /* In case we're already in PSM, trigger it again to set new timeout
 289         * immediately without waiting for re-association
 290         */
 291
 292        wl12xx_for_each_wlvif_sta(wl, wlvif) {
 293                if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags))
 294                        wl1271_ps_set_mode(wl, wlvif, STATION_AUTO_PS_MODE);
 295        }
 296
 297        pm_runtime_mark_last_busy(wl->dev);
 298        pm_runtime_put_autosuspend(wl->dev);
 299
 300out:
 301        mutex_unlock(&wl->mutex);
 302        return count;
 303}
 304
 305static const struct file_operations dynamic_ps_timeout_ops = {
 306        .read = dynamic_ps_timeout_read,
 307        .write = dynamic_ps_timeout_write,
 308        .open = simple_open,
 309        .llseek = default_llseek,
 310};
 311
 312static ssize_t forced_ps_read(struct file *file, char __user *user_buf,
 313                          size_t count, loff_t *ppos)
 314{
 315        struct wl1271 *wl = file->private_data;
 316
 317        return wl1271_format_buffer(user_buf, count,
 318                                    ppos, "%d\n",
 319                                    wl->conf.conn.forced_ps);
 320}
 321
 322static ssize_t forced_ps_write(struct file *file,
 323                                    const char __user *user_buf,
 324                                    size_t count, loff_t *ppos)
 325{
 326        struct wl1271 *wl = file->private_data;
 327        struct wl12xx_vif *wlvif;
 328        unsigned long value;
 329        int ret, ps_mode;
 330
 331        ret = kstrtoul_from_user(user_buf, count, 10, &value);
 332        if (ret < 0) {
 333                wl1271_warning("illegal value in forced_ps");
 334                return -EINVAL;
 335        }
 336
 337        if (value != 1 && value != 0) {
 338                wl1271_warning("forced_ps should be either 0 or 1");
 339                return -ERANGE;
 340        }
 341
 342        mutex_lock(&wl->mutex);
 343
 344        if (wl->conf.conn.forced_ps == value)
 345                goto out;
 346
 347        wl->conf.conn.forced_ps = value;
 348
 349        if (unlikely(wl->state != WLCORE_STATE_ON))
 350                goto out;
 351
 352        ret = pm_runtime_get_sync(wl->dev);
 353        if (ret < 0) {
 354                pm_runtime_put_noidle(wl->dev);
 355                goto out;
 356        }
 357
 358        /* In case we're already in PSM, trigger it again to switch mode
 359         * immediately without waiting for re-association
 360         */
 361
 362        ps_mode = value ? STATION_POWER_SAVE_MODE : STATION_AUTO_PS_MODE;
 363
 364        wl12xx_for_each_wlvif_sta(wl, wlvif) {
 365                if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags))
 366                        wl1271_ps_set_mode(wl, wlvif, ps_mode);
 367        }
 368
 369        pm_runtime_mark_last_busy(wl->dev);
 370        pm_runtime_put_autosuspend(wl->dev);
 371
 372out:
 373        mutex_unlock(&wl->mutex);
 374        return count;
 375}
 376
 377static const struct file_operations forced_ps_ops = {
 378        .read = forced_ps_read,
 379        .write = forced_ps_write,
 380        .open = simple_open,
 381        .llseek = default_llseek,
 382};
 383
 384static ssize_t split_scan_timeout_read(struct file *file, char __user *user_buf,
 385                          size_t count, loff_t *ppos)
 386{
 387        struct wl1271 *wl = file->private_data;
 388
 389        return wl1271_format_buffer(user_buf, count,
 390                                    ppos, "%d\n",
 391                                    wl->conf.scan.split_scan_timeout / 1000);
 392}
 393
 394static ssize_t split_scan_timeout_write(struct file *file,
 395                                    const char __user *user_buf,
 396                                    size_t count, loff_t *ppos)
 397{
 398        struct wl1271 *wl = file->private_data;
 399        unsigned long value;
 400        int ret;
 401
 402        ret = kstrtoul_from_user(user_buf, count, 10, &value);
 403        if (ret < 0) {
 404                wl1271_warning("illegal value in split_scan_timeout");
 405                return -EINVAL;
 406        }
 407
 408        if (value == 0)
 409                wl1271_info("split scan will be disabled");
 410
 411        mutex_lock(&wl->mutex);
 412
 413        wl->conf.scan.split_scan_timeout = value * 1000;
 414
 415        mutex_unlock(&wl->mutex);
 416        return count;
 417}
 418
 419static const struct file_operations split_scan_timeout_ops = {
 420        .read = split_scan_timeout_read,
 421        .write = split_scan_timeout_write,
 422        .open = simple_open,
 423        .llseek = default_llseek,
 424};
 425
 426static ssize_t driver_state_read(struct file *file, char __user *user_buf,
 427                                 size_t count, loff_t *ppos)
 428{
 429        struct wl1271 *wl = file->private_data;
 430        int res = 0;
 431        ssize_t ret;
 432        char *buf;
 433        struct wl12xx_vif *wlvif;
 434
 435#define DRIVER_STATE_BUF_LEN 1024
 436
 437        buf = kmalloc(DRIVER_STATE_BUF_LEN, GFP_KERNEL);
 438        if (!buf)
 439                return -ENOMEM;
 440
 441        mutex_lock(&wl->mutex);
 442
 443#define DRIVER_STATE_PRINT(x, fmt)   \
 444        (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\
 445                          #x " = " fmt "\n", wl->x))
 446
 447#define DRIVER_STATE_PRINT_GENERIC(x, fmt, args...)   \
 448        (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\
 449                          #x " = " fmt "\n", args))
 450
 451#define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld")
 452#define DRIVER_STATE_PRINT_INT(x)  DRIVER_STATE_PRINT(x, "%d")
 453#define DRIVER_STATE_PRINT_STR(x)  DRIVER_STATE_PRINT(x, "%s")
 454#define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx")
 455#define DRIVER_STATE_PRINT_HEX(x)  DRIVER_STATE_PRINT(x, "0x%x")
 456
 457        wl12xx_for_each_wlvif_sta(wl, wlvif) {
 458                if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
 459                        continue;
 460
 461                DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel,
 462                                           wlvif->p2p ? "P2P-CL" : "STA");
 463        }
 464
 465        wl12xx_for_each_wlvif_ap(wl, wlvif)
 466                DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel,
 467                                           wlvif->p2p ? "P2P-GO" : "AP");
 468
 469        DRIVER_STATE_PRINT_INT(tx_blocks_available);
 470        DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
 471        DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]);
 472        DRIVER_STATE_PRINT_INT(tx_allocated_pkts[1]);
 473        DRIVER_STATE_PRINT_INT(tx_allocated_pkts[2]);
 474        DRIVER_STATE_PRINT_INT(tx_allocated_pkts[3]);
 475        DRIVER_STATE_PRINT_INT(tx_frames_cnt);
 476        DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
 477        DRIVER_STATE_PRINT_INT(tx_queue_count[0]);
 478        DRIVER_STATE_PRINT_INT(tx_queue_count[1]);
 479        DRIVER_STATE_PRINT_INT(tx_queue_count[2]);
 480        DRIVER_STATE_PRINT_INT(tx_queue_count[3]);
 481        DRIVER_STATE_PRINT_INT(tx_packets_count);
 482        DRIVER_STATE_PRINT_INT(tx_results_count);
 483        DRIVER_STATE_PRINT_LHEX(flags);
 484        DRIVER_STATE_PRINT_INT(tx_blocks_freed);
 485        DRIVER_STATE_PRINT_INT(rx_counter);
 486        DRIVER_STATE_PRINT_INT(state);
 487        DRIVER_STATE_PRINT_INT(band);
 488        DRIVER_STATE_PRINT_INT(power_level);
 489        DRIVER_STATE_PRINT_INT(sg_enabled);
 490        DRIVER_STATE_PRINT_INT(enable_11a);
 491        DRIVER_STATE_PRINT_INT(noise);
 492        DRIVER_STATE_PRINT_LHEX(ap_fw_ps_map);
 493        DRIVER_STATE_PRINT_LHEX(ap_ps_map);
 494        DRIVER_STATE_PRINT_HEX(quirks);
 495        DRIVER_STATE_PRINT_HEX(irq);
 496        /* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */
 497        DRIVER_STATE_PRINT_HEX(hw_pg_ver);
 498        DRIVER_STATE_PRINT_HEX(irq_flags);
 499        DRIVER_STATE_PRINT_HEX(chip.id);
 500        DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
 501        DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str);
 502        DRIVER_STATE_PRINT_INT(recovery_count);
 503
 504#undef DRIVER_STATE_PRINT_INT
 505#undef DRIVER_STATE_PRINT_LONG
 506#undef DRIVER_STATE_PRINT_HEX
 507#undef DRIVER_STATE_PRINT_LHEX
 508#undef DRIVER_STATE_PRINT_STR
 509#undef DRIVER_STATE_PRINT
 510#undef DRIVER_STATE_BUF_LEN
 511
 512        mutex_unlock(&wl->mutex);
 513
 514        ret = simple_read_from_buffer(user_buf, count, ppos, buf, res);
 515        kfree(buf);
 516        return ret;
 517}
 518
 519static const struct file_operations driver_state_ops = {
 520        .read = driver_state_read,
 521        .open = simple_open,
 522        .llseek = default_llseek,
 523};
 524
 525static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
 526                                 size_t count, loff_t *ppos)
 527{
 528        struct wl1271 *wl = file->private_data;
 529        struct wl12xx_vif *wlvif;
 530        int ret, res = 0;
 531        const int buf_size = 4096;
 532        char *buf;
 533        char tmp_buf[64];
 534
 535        buf = kzalloc(buf_size, GFP_KERNEL);
 536        if (!buf)
 537                return -ENOMEM;
 538
 539        mutex_lock(&wl->mutex);
 540
 541#define VIF_STATE_PRINT(x, fmt)                         \
 542        (res += scnprintf(buf + res, buf_size - res,    \
 543                          #x " = " fmt "\n", wlvif->x))
 544
 545#define VIF_STATE_PRINT_LONG(x)  VIF_STATE_PRINT(x, "%ld")
 546#define VIF_STATE_PRINT_INT(x)   VIF_STATE_PRINT(x, "%d")
 547#define VIF_STATE_PRINT_STR(x)   VIF_STATE_PRINT(x, "%s")
 548#define VIF_STATE_PRINT_LHEX(x)  VIF_STATE_PRINT(x, "0x%lx")
 549#define VIF_STATE_PRINT_LLHEX(x) VIF_STATE_PRINT(x, "0x%llx")
 550#define VIF_STATE_PRINT_HEX(x)   VIF_STATE_PRINT(x, "0x%x")
 551
 552#define VIF_STATE_PRINT_NSTR(x, len)                            \
 553        do {                                                    \
 554                memset(tmp_buf, 0, sizeof(tmp_buf));            \
 555                memcpy(tmp_buf, wlvif->x,                       \
 556                       min_t(u8, len, sizeof(tmp_buf) - 1));    \
 557                res += scnprintf(buf + res, buf_size - res,     \
 558                                 #x " = %s\n", tmp_buf);        \
 559        } while (0)
 560
 561        wl12xx_for_each_wlvif(wl, wlvif) {
 562                VIF_STATE_PRINT_INT(role_id);
 563                VIF_STATE_PRINT_INT(bss_type);
 564                VIF_STATE_PRINT_LHEX(flags);
 565                VIF_STATE_PRINT_INT(p2p);
 566                VIF_STATE_PRINT_INT(dev_role_id);
 567                VIF_STATE_PRINT_INT(dev_hlid);
 568
 569                if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
 570                    wlvif->bss_type == BSS_TYPE_IBSS) {
 571                        VIF_STATE_PRINT_INT(sta.hlid);
 572                        VIF_STATE_PRINT_INT(sta.basic_rate_idx);
 573                        VIF_STATE_PRINT_INT(sta.ap_rate_idx);
 574                        VIF_STATE_PRINT_INT(sta.p2p_rate_idx);
 575                        VIF_STATE_PRINT_INT(sta.qos);
 576                } else {
 577                        VIF_STATE_PRINT_INT(ap.global_hlid);
 578                        VIF_STATE_PRINT_INT(ap.bcast_hlid);
 579                        VIF_STATE_PRINT_LHEX(ap.sta_hlid_map[0]);
 580                        VIF_STATE_PRINT_INT(ap.mgmt_rate_idx);
 581                        VIF_STATE_PRINT_INT(ap.bcast_rate_idx);
 582                        VIF_STATE_PRINT_INT(ap.ucast_rate_idx[0]);
 583                        VIF_STATE_PRINT_INT(ap.ucast_rate_idx[1]);
 584                        VIF_STATE_PRINT_INT(ap.ucast_rate_idx[2]);
 585                        VIF_STATE_PRINT_INT(ap.ucast_rate_idx[3]);
 586                }
 587                VIF_STATE_PRINT_INT(last_tx_hlid);
 588                VIF_STATE_PRINT_INT(tx_queue_count[0]);
 589                VIF_STATE_PRINT_INT(tx_queue_count[1]);
 590                VIF_STATE_PRINT_INT(tx_queue_count[2]);
 591                VIF_STATE_PRINT_INT(tx_queue_count[3]);
 592                VIF_STATE_PRINT_LHEX(links_map[0]);
 593                VIF_STATE_PRINT_NSTR(ssid, wlvif->ssid_len);
 594                VIF_STATE_PRINT_INT(band);
 595                VIF_STATE_PRINT_INT(channel);
 596                VIF_STATE_PRINT_HEX(bitrate_masks[0]);
 597                VIF_STATE_PRINT_HEX(bitrate_masks[1]);
 598                VIF_STATE_PRINT_HEX(basic_rate_set);
 599                VIF_STATE_PRINT_HEX(basic_rate);
 600                VIF_STATE_PRINT_HEX(rate_set);
 601                VIF_STATE_PRINT_INT(beacon_int);
 602                VIF_STATE_PRINT_INT(default_key);
 603                VIF_STATE_PRINT_INT(aid);
 604                VIF_STATE_PRINT_INT(psm_entry_retry);
 605                VIF_STATE_PRINT_INT(power_level);
 606                VIF_STATE_PRINT_INT(rssi_thold);
 607                VIF_STATE_PRINT_INT(last_rssi_event);
 608                VIF_STATE_PRINT_INT(ba_support);
 609                VIF_STATE_PRINT_INT(ba_allowed);
 610                VIF_STATE_PRINT_LLHEX(total_freed_pkts);
 611        }
 612
 613#undef VIF_STATE_PRINT_INT
 614#undef VIF_STATE_PRINT_LONG
 615#undef VIF_STATE_PRINT_HEX
 616#undef VIF_STATE_PRINT_LHEX
 617#undef VIF_STATE_PRINT_LLHEX
 618#undef VIF_STATE_PRINT_STR
 619#undef VIF_STATE_PRINT_NSTR
 620#undef VIF_STATE_PRINT
 621
 622        mutex_unlock(&wl->mutex);
 623
 624        ret = simple_read_from_buffer(user_buf, count, ppos, buf, res);
 625        kfree(buf);
 626        return ret;
 627}
 628
 629static const struct file_operations vifs_state_ops = {
 630        .read = vifs_state_read,
 631        .open = simple_open,
 632        .llseek = default_llseek,
 633};
 634
 635static ssize_t dtim_interval_read(struct file *file, char __user *user_buf,
 636                                  size_t count, loff_t *ppos)
 637{
 638        struct wl1271 *wl = file->private_data;
 639        u8 value;
 640
 641        if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_DTIM ||
 642            wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM)
 643                value = wl->conf.conn.listen_interval;
 644        else
 645                value = 0;
 646
 647        return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
 648}
 649
 650static ssize_t dtim_interval_write(struct file *file,
 651                                   const char __user *user_buf,
 652                                   size_t count, loff_t *ppos)
 653{
 654        struct wl1271 *wl = file->private_data;
 655        unsigned long value;
 656        int ret;
 657
 658        ret = kstrtoul_from_user(user_buf, count, 10, &value);
 659        if (ret < 0) {
 660                wl1271_warning("illegal value for dtim_interval");
 661                return -EINVAL;
 662        }
 663
 664        if (value < 1 || value > 10) {
 665                wl1271_warning("dtim value is not in valid range");
 666                return -ERANGE;
 667        }
 668
 669        mutex_lock(&wl->mutex);
 670
 671        wl->conf.conn.listen_interval = value;
 672        /* for some reason there are different event types for 1 and >1 */
 673        if (value == 1)
 674                wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_DTIM;
 675        else
 676                wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM;
 677
 678        /*
 679         * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only
 680         * take effect on the next time we enter psm.
 681         */
 682        mutex_unlock(&wl->mutex);
 683        return count;
 684}
 685
 686static const struct file_operations dtim_interval_ops = {
 687        .read = dtim_interval_read,
 688        .write = dtim_interval_write,
 689        .open = simple_open,
 690        .llseek = default_llseek,
 691};
 692
 693
 694
 695static ssize_t suspend_dtim_interval_read(struct file *file,
 696                                          char __user *user_buf,
 697                                          size_t count, loff_t *ppos)
 698{
 699        struct wl1271 *wl = file->private_data;
 700        u8 value;
 701
 702        if (wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_DTIM ||
 703            wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM)
 704                value = wl->conf.conn.suspend_listen_interval;
 705        else
 706                value = 0;
 707
 708        return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
 709}
 710
 711static ssize_t suspend_dtim_interval_write(struct file *file,
 712                                           const char __user *user_buf,
 713                                           size_t count, loff_t *ppos)
 714{
 715        struct wl1271 *wl = file->private_data;
 716        unsigned long value;
 717        int ret;
 718
 719        ret = kstrtoul_from_user(user_buf, count, 10, &value);
 720        if (ret < 0) {
 721                wl1271_warning("illegal value for suspend_dtim_interval");
 722                return -EINVAL;
 723        }
 724
 725        if (value < 1 || value > 10) {
 726                wl1271_warning("suspend_dtim value is not in valid range");
 727                return -ERANGE;
 728        }
 729
 730        mutex_lock(&wl->mutex);
 731
 732        wl->conf.conn.suspend_listen_interval = value;
 733        /* for some reason there are different event types for 1 and >1 */
 734        if (value == 1)
 735                wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_DTIM;
 736        else
 737                wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM;
 738
 739        mutex_unlock(&wl->mutex);
 740        return count;
 741}
 742
 743
 744static const struct file_operations suspend_dtim_interval_ops = {
 745        .read = suspend_dtim_interval_read,
 746        .write = suspend_dtim_interval_write,
 747        .open = simple_open,
 748        .llseek = default_llseek,
 749};
 750
 751static ssize_t beacon_interval_read(struct file *file, char __user *user_buf,
 752                                    size_t count, loff_t *ppos)
 753{
 754        struct wl1271 *wl = file->private_data;
 755        u8 value;
 756
 757        if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_BEACON ||
 758            wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_BEACONS)
 759                value = wl->conf.conn.listen_interval;
 760        else
 761                value = 0;
 762
 763        return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
 764}
 765
 766static ssize_t beacon_interval_write(struct file *file,
 767                                     const char __user *user_buf,
 768                                     size_t count, loff_t *ppos)
 769{
 770        struct wl1271 *wl = file->private_data;
 771        unsigned long value;
 772        int ret;
 773
 774        ret = kstrtoul_from_user(user_buf, count, 10, &value);
 775        if (ret < 0) {
 776                wl1271_warning("illegal value for beacon_interval");
 777                return -EINVAL;
 778        }
 779
 780        if (value < 1 || value > 255) {
 781                wl1271_warning("beacon interval value is not in valid range");
 782                return -ERANGE;
 783        }
 784
 785        mutex_lock(&wl->mutex);
 786
 787        wl->conf.conn.listen_interval = value;
 788        /* for some reason there are different event types for 1 and >1 */
 789        if (value == 1)
 790                wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_BEACON;
 791        else
 792                wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_BEACONS;
 793
 794        /*
 795         * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only
 796         * take effect on the next time we enter psm.
 797         */
 798        mutex_unlock(&wl->mutex);
 799        return count;
 800}
 801
 802static const struct file_operations beacon_interval_ops = {
 803        .read = beacon_interval_read,
 804        .write = beacon_interval_write,
 805        .open = simple_open,
 806        .llseek = default_llseek,
 807};
 808
 809static ssize_t rx_streaming_interval_write(struct file *file,
 810                           const char __user *user_buf,
 811                           size_t count, loff_t *ppos)
 812{
 813        struct wl1271 *wl = file->private_data;
 814        struct wl12xx_vif *wlvif;
 815        unsigned long value;
 816        int ret;
 817
 818        ret = kstrtoul_from_user(user_buf, count, 10, &value);
 819        if (ret < 0) {
 820                wl1271_warning("illegal value in rx_streaming_interval!");
 821                return -EINVAL;
 822        }
 823
 824        /* valid values: 0, 10-100 */
 825        if (value && (value < 10 || value > 100)) {
 826                wl1271_warning("value is not in range!");
 827                return -ERANGE;
 828        }
 829
 830        mutex_lock(&wl->mutex);
 831
 832        wl->conf.rx_streaming.interval = value;
 833
 834        ret = pm_runtime_get_sync(wl->dev);
 835        if (ret < 0) {
 836                pm_runtime_put_noidle(wl->dev);
 837                goto out;
 838        }
 839
 840        wl12xx_for_each_wlvif_sta(wl, wlvif) {
 841                wl1271_recalc_rx_streaming(wl, wlvif);
 842        }
 843
 844        pm_runtime_mark_last_busy(wl->dev);
 845        pm_runtime_put_autosuspend(wl->dev);
 846out:
 847        mutex_unlock(&wl->mutex);
 848        return count;
 849}
 850
 851static ssize_t rx_streaming_interval_read(struct file *file,
 852                            char __user *userbuf,
 853                            size_t count, loff_t *ppos)
 854{
 855        struct wl1271 *wl = file->private_data;
 856        return wl1271_format_buffer(userbuf, count, ppos,
 857                                    "%d\n", wl->conf.rx_streaming.interval);
 858}
 859
 860static const struct file_operations rx_streaming_interval_ops = {
 861        .read = rx_streaming_interval_read,
 862        .write = rx_streaming_interval_write,
 863        .open = simple_open,
 864        .llseek = default_llseek,
 865};
 866
 867static ssize_t rx_streaming_always_write(struct file *file,
 868                           const char __user *user_buf,
 869                           size_t count, loff_t *ppos)
 870{
 871        struct wl1271 *wl = file->private_data;
 872        struct wl12xx_vif *wlvif;
 873        unsigned long value;
 874        int ret;
 875
 876        ret = kstrtoul_from_user(user_buf, count, 10, &value);
 877        if (ret < 0) {
 878                wl1271_warning("illegal value in rx_streaming_write!");
 879                return -EINVAL;
 880        }
 881
 882        /* valid values: 0, 10-100 */
 883        if (!(value == 0 || value == 1)) {
 884                wl1271_warning("value is not in valid!");
 885                return -EINVAL;
 886        }
 887
 888        mutex_lock(&wl->mutex);
 889
 890        wl->conf.rx_streaming.always = value;
 891
 892        ret = pm_runtime_get_sync(wl->dev);
 893        if (ret < 0) {
 894                pm_runtime_put_noidle(wl->dev);
 895                goto out;
 896        }
 897
 898        wl12xx_for_each_wlvif_sta(wl, wlvif) {
 899                wl1271_recalc_rx_streaming(wl, wlvif);
 900        }
 901
 902        pm_runtime_mark_last_busy(wl->dev);
 903        pm_runtime_put_autosuspend(wl->dev);
 904out:
 905        mutex_unlock(&wl->mutex);
 906        return count;
 907}
 908
 909static ssize_t rx_streaming_always_read(struct file *file,
 910                            char __user *userbuf,
 911                            size_t count, loff_t *ppos)
 912{
 913        struct wl1271 *wl = file->private_data;
 914        return wl1271_format_buffer(userbuf, count, ppos,
 915                                    "%d\n", wl->conf.rx_streaming.always);
 916}
 917
 918static const struct file_operations rx_streaming_always_ops = {
 919        .read = rx_streaming_always_read,
 920        .write = rx_streaming_always_write,
 921        .open = simple_open,
 922        .llseek = default_llseek,
 923};
 924
 925static ssize_t beacon_filtering_write(struct file *file,
 926                                      const char __user *user_buf,
 927                                      size_t count, loff_t *ppos)
 928{
 929        struct wl1271 *wl = file->private_data;
 930        struct wl12xx_vif *wlvif;
 931        unsigned long value;
 932        int ret;
 933
 934        ret = kstrtoul_from_user(user_buf, count, 0, &value);
 935        if (ret < 0) {
 936                wl1271_warning("illegal value for beacon_filtering!");
 937                return -EINVAL;
 938        }
 939
 940        mutex_lock(&wl->mutex);
 941
 942        ret = pm_runtime_get_sync(wl->dev);
 943        if (ret < 0) {
 944                pm_runtime_put_noidle(wl->dev);
 945                goto out;
 946        }
 947
 948        wl12xx_for_each_wlvif(wl, wlvif) {
 949                ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value);
 950        }
 951
 952        pm_runtime_mark_last_busy(wl->dev);
 953        pm_runtime_put_autosuspend(wl->dev);
 954out:
 955        mutex_unlock(&wl->mutex);
 956        return count;
 957}
 958
 959static const struct file_operations beacon_filtering_ops = {
 960        .write = beacon_filtering_write,
 961        .open = simple_open,
 962        .llseek = default_llseek,
 963};
 964
 965static ssize_t fw_stats_raw_read(struct file *file,
 966                                 char __user *userbuf,
 967                                 size_t count, loff_t *ppos)
 968{
 969        struct wl1271 *wl = file->private_data;
 970
 971        wl1271_debugfs_update_stats(wl);
 972
 973        return simple_read_from_buffer(userbuf, count, ppos,
 974                                       wl->stats.fw_stats,
 975                                       wl->stats.fw_stats_len);
 976}
 977
 978static const struct file_operations fw_stats_raw_ops = {
 979        .read = fw_stats_raw_read,
 980        .open = simple_open,
 981        .llseek = default_llseek,
 982};
 983
 984static ssize_t sleep_auth_read(struct file *file, char __user *user_buf,
 985                               size_t count, loff_t *ppos)
 986{
 987        struct wl1271 *wl = file->private_data;
 988
 989        return wl1271_format_buffer(user_buf, count,
 990                                    ppos, "%d\n",
 991                                    wl->sleep_auth);
 992}
 993
 994static ssize_t sleep_auth_write(struct file *file,
 995                                const char __user *user_buf,
 996                                size_t count, loff_t *ppos)
 997{
 998        struct wl1271 *wl = file->private_data;
 999        unsigned long value;
1000        int ret;
1001
1002        ret = kstrtoul_from_user(user_buf, count, 0, &value);
1003        if (ret < 0) {
1004                wl1271_warning("illegal value in sleep_auth");
1005                return -EINVAL;
1006        }
1007
1008        if (value > WL1271_PSM_MAX) {
1009                wl1271_warning("sleep_auth must be between 0 and %d",
1010                               WL1271_PSM_MAX);
1011                return -ERANGE;
1012        }
1013
1014        mutex_lock(&wl->mutex);
1015
1016        wl->conf.conn.sta_sleep_auth = value;
1017
1018        if (unlikely(wl->state != WLCORE_STATE_ON)) {
1019                /* this will show up on "read" in case we are off */
1020                wl->sleep_auth = value;
1021                goto out;
1022        }
1023
1024        ret = pm_runtime_get_sync(wl->dev);
1025        if (ret < 0) {
1026                pm_runtime_put_noidle(wl->dev);
1027                goto out;
1028        }
1029
1030        ret = wl1271_acx_sleep_auth(wl, value);
1031        if (ret < 0)
1032                goto out_sleep;
1033
1034out_sleep:
1035        pm_runtime_mark_last_busy(wl->dev);
1036        pm_runtime_put_autosuspend(wl->dev);
1037out:
1038        mutex_unlock(&wl->mutex);
1039        return count;
1040}
1041
1042static const struct file_operations sleep_auth_ops = {
1043        .read = sleep_auth_read,
1044        .write = sleep_auth_write,
1045        .open = simple_open,
1046        .llseek = default_llseek,
1047};
1048
1049static ssize_t dev_mem_read(struct file *file,
1050             char __user *user_buf, size_t count,
1051             loff_t *ppos)
1052{
1053        struct wl1271 *wl = file->private_data;
1054        struct wlcore_partition_set part, old_part;
1055        size_t bytes = count;
1056        int ret;
1057        char *buf;
1058
1059        /* only requests of dword-aligned size and offset are supported */
1060        if (bytes % 4)
1061                return -EINVAL;
1062
1063        if (*ppos % 4)
1064                return -EINVAL;
1065
1066        /* function should return in reasonable time */
1067        bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE);
1068
1069        if (bytes == 0)
1070                return -EINVAL;
1071
1072        memset(&part, 0, sizeof(part));
1073        part.mem.start = *ppos;
1074        part.mem.size = bytes;
1075
1076        buf = kmalloc(bytes, GFP_KERNEL);
1077        if (!buf)
1078                return -ENOMEM;
1079
1080        mutex_lock(&wl->mutex);
1081
1082        if (unlikely(wl->state == WLCORE_STATE_OFF)) {
1083                ret = -EFAULT;
1084                goto skip_read;
1085        }
1086
1087        /*
1088         * Don't fail if elp_wakeup returns an error, so the device's memory
1089         * could be read even if the FW crashed
1090         */
1091        pm_runtime_get_sync(wl->dev);
1092
1093        /* store current partition and switch partition */
1094        memcpy(&old_part, &wl->curr_part, sizeof(old_part));
1095        ret = wlcore_set_partition(wl, &part);
1096        if (ret < 0)
1097                goto part_err;
1098
1099        ret = wlcore_raw_read(wl, 0, buf, bytes, false);
1100        if (ret < 0)
1101                goto read_err;
1102
1103read_err:
1104        /* recover partition */
1105        ret = wlcore_set_partition(wl, &old_part);
1106        if (ret < 0)
1107                goto part_err;
1108
1109part_err:
1110        pm_runtime_mark_last_busy(wl->dev);
1111        pm_runtime_put_autosuspend(wl->dev);
1112
1113skip_read:
1114        mutex_unlock(&wl->mutex);
1115
1116        if (ret == 0) {
1117                ret = copy_to_user(user_buf, buf, bytes);
1118                if (ret < bytes) {
1119                        bytes -= ret;
1120                        *ppos += bytes;
1121                        ret = 0;
1122                } else {
1123                        ret = -EFAULT;
1124                }
1125        }
1126
1127        kfree(buf);
1128
1129        return ((ret == 0) ? bytes : ret);
1130}
1131
1132static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,
1133                size_t count, loff_t *ppos)
1134{
1135        struct wl1271 *wl = file->private_data;
1136        struct wlcore_partition_set part, old_part;
1137        size_t bytes = count;
1138        int ret;
1139        char *buf;
1140
1141        /* only requests of dword-aligned size and offset are supported */
1142        if (bytes % 4)
1143                return -EINVAL;
1144
1145        if (*ppos % 4)
1146                return -EINVAL;
1147
1148        /* function should return in reasonable time */
1149        bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE);
1150
1151        if (bytes == 0)
1152                return -EINVAL;
1153
1154        memset(&part, 0, sizeof(part));
1155        part.mem.start = *ppos;
1156        part.mem.size = bytes;
1157
1158        buf = memdup_user(user_buf, bytes);
1159        if (IS_ERR(buf))
1160                return PTR_ERR(buf);
1161
1162        mutex_lock(&wl->mutex);
1163
1164        if (unlikely(wl->state == WLCORE_STATE_OFF)) {
1165                ret = -EFAULT;
1166                goto skip_write;
1167        }
1168
1169        /*
1170         * Don't fail if elp_wakeup returns an error, so the device's memory
1171         * could be read even if the FW crashed
1172         */
1173        pm_runtime_get_sync(wl->dev);
1174
1175        /* store current partition and switch partition */
1176        memcpy(&old_part, &wl->curr_part, sizeof(old_part));
1177        ret = wlcore_set_partition(wl, &part);
1178        if (ret < 0)
1179                goto part_err;
1180
1181        ret = wlcore_raw_write(wl, 0, buf, bytes, false);
1182        if (ret < 0)
1183                goto write_err;
1184
1185write_err:
1186        /* recover partition */
1187        ret = wlcore_set_partition(wl, &old_part);
1188        if (ret < 0)
1189                goto part_err;
1190
1191part_err:
1192        pm_runtime_mark_last_busy(wl->dev);
1193        pm_runtime_put_autosuspend(wl->dev);
1194
1195skip_write:
1196        mutex_unlock(&wl->mutex);
1197
1198        if (ret == 0)
1199                *ppos += bytes;
1200
1201        kfree(buf);
1202
1203        return ((ret == 0) ? bytes : ret);
1204}
1205
1206static loff_t dev_mem_seek(struct file *file, loff_t offset, int orig)
1207{
1208        /* only requests of dword-aligned size and offset are supported */
1209        if (offset % 4)
1210                return -EINVAL;
1211
1212        return no_seek_end_llseek(file, offset, orig);
1213}
1214
1215static const struct file_operations dev_mem_ops = {
1216        .open = simple_open,
1217        .read = dev_mem_read,
1218        .write = dev_mem_write,
1219        .llseek = dev_mem_seek,
1220};
1221
1222static ssize_t fw_logger_read(struct file *file, char __user *user_buf,
1223                              size_t count, loff_t *ppos)
1224{
1225        struct wl1271 *wl = file->private_data;
1226
1227        return wl1271_format_buffer(user_buf, count,
1228                                        ppos, "%d\n",
1229                                        wl->conf.fwlog.output);
1230}
1231
1232static ssize_t fw_logger_write(struct file *file,
1233                               const char __user *user_buf,
1234                               size_t count, loff_t *ppos)
1235{
1236        struct wl1271 *wl = file->private_data;
1237        unsigned long value;
1238        int ret;
1239
1240        ret = kstrtoul_from_user(user_buf, count, 0, &value);
1241        if (ret < 0) {
1242                wl1271_warning("illegal value in fw_logger");
1243                return -EINVAL;
1244        }
1245
1246        if ((value > 2) || (value == 0)) {
1247                wl1271_warning("fw_logger value must be 1-UART 2-SDIO");
1248                return -ERANGE;
1249        }
1250
1251        if (wl->conf.fwlog.output == 0) {
1252                wl1271_warning("invalid operation - fw logger disabled by default, please change mode via wlconf");
1253                return -EINVAL;
1254        }
1255
1256        mutex_lock(&wl->mutex);
1257        ret = pm_runtime_get_sync(wl->dev);
1258        if (ret < 0) {
1259                pm_runtime_put_noidle(wl->dev);
1260                count = ret;
1261                goto out;
1262        }
1263
1264        wl->conf.fwlog.output = value;
1265
1266        ret = wl12xx_cmd_config_fwlog(wl);
1267
1268        pm_runtime_mark_last_busy(wl->dev);
1269        pm_runtime_put_autosuspend(wl->dev);
1270
1271out:
1272        mutex_unlock(&wl->mutex);
1273        return count;
1274}
1275
1276static const struct file_operations fw_logger_ops = {
1277        .open = simple_open,
1278        .read = fw_logger_read,
1279        .write = fw_logger_write,
1280        .llseek = default_llseek,
1281};
1282
1283static void wl1271_debugfs_add_files(struct wl1271 *wl,
1284                                     struct dentry *rootdir)
1285{
1286        struct dentry *streaming;
1287
1288        DEBUGFS_ADD(tx_queue_len, rootdir);
1289        DEBUGFS_ADD(retry_count, rootdir);
1290        DEBUGFS_ADD(excessive_retries, rootdir);
1291
1292        DEBUGFS_ADD(gpio_power, rootdir);
1293        DEBUGFS_ADD(start_recovery, rootdir);
1294        DEBUGFS_ADD(driver_state, rootdir);
1295        DEBUGFS_ADD(vifs_state, rootdir);
1296        DEBUGFS_ADD(dtim_interval, rootdir);
1297        DEBUGFS_ADD(suspend_dtim_interval, rootdir);
1298        DEBUGFS_ADD(beacon_interval, rootdir);
1299        DEBUGFS_ADD(beacon_filtering, rootdir);
1300        DEBUGFS_ADD(dynamic_ps_timeout, rootdir);
1301        DEBUGFS_ADD(forced_ps, rootdir);
1302        DEBUGFS_ADD(split_scan_timeout, rootdir);
1303        DEBUGFS_ADD(irq_pkt_threshold, rootdir);
1304        DEBUGFS_ADD(irq_blk_threshold, rootdir);
1305        DEBUGFS_ADD(irq_timeout, rootdir);
1306        DEBUGFS_ADD(fw_stats_raw, rootdir);
1307        DEBUGFS_ADD(sleep_auth, rootdir);
1308        DEBUGFS_ADD(fw_logger, rootdir);
1309
1310        streaming = debugfs_create_dir("rx_streaming", rootdir);
1311
1312        DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming);
1313        DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming);
1314
1315        DEBUGFS_ADD_PREFIX(dev, mem, rootdir);
1316}
1317
1318void wl1271_debugfs_reset(struct wl1271 *wl)
1319{
1320        if (!wl->stats.fw_stats)
1321                return;
1322
1323        memset(wl->stats.fw_stats, 0, wl->stats.fw_stats_len);
1324        wl->stats.retry_count = 0;
1325        wl->stats.excessive_retries = 0;
1326}
1327
1328int wl1271_debugfs_init(struct wl1271 *wl)
1329{
1330        int ret;
1331        struct dentry *rootdir;
1332
1333        rootdir = debugfs_create_dir(KBUILD_MODNAME,
1334                                     wl->hw->wiphy->debugfsdir);
1335
1336        wl->stats.fw_stats = kzalloc(wl->stats.fw_stats_len, GFP_KERNEL);
1337        if (!wl->stats.fw_stats) {
1338                ret = -ENOMEM;
1339                goto out_remove;
1340        }
1341
1342        wl->stats.fw_stats_update = jiffies;
1343
1344        wl1271_debugfs_add_files(wl, rootdir);
1345
1346        ret = wlcore_debugfs_init(wl, rootdir);
1347        if (ret < 0)
1348                goto out_exit;
1349
1350        goto out;
1351
1352out_exit:
1353        wl1271_debugfs_exit(wl);
1354
1355out_remove:
1356        debugfs_remove_recursive(rootdir);
1357
1358out:
1359        return ret;
1360}
1361
1362void wl1271_debugfs_exit(struct wl1271 *wl)
1363{
1364        kfree(wl->stats.fw_stats);
1365        wl->stats.fw_stats = NULL;
1366}
1367