linux/net/mac80211/debugfs_netdev.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2006   Jiri Benc <jbenc@suse.cz>
   4 * Copyright 2007       Johannes Berg <johannes@sipsolutions.net>
   5 * Copyright (C) 2020 Intel Corporation
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/device.h>
  10#include <linux/if.h>
  11#include <linux/if_ether.h>
  12#include <linux/interrupt.h>
  13#include <linux/netdevice.h>
  14#include <linux/rtnetlink.h>
  15#include <linux/slab.h>
  16#include <linux/notifier.h>
  17#include <net/mac80211.h>
  18#include <net/cfg80211.h>
  19#include "ieee80211_i.h"
  20#include "rate.h"
  21#include "debugfs.h"
  22#include "debugfs_netdev.h"
  23#include "driver-ops.h"
  24
  25static ssize_t ieee80211_if_read(
  26        struct ieee80211_sub_if_data *sdata,
  27        char __user *userbuf,
  28        size_t count, loff_t *ppos,
  29        ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
  30{
  31        char buf[200];
  32        ssize_t ret = -EINVAL;
  33
  34        read_lock(&dev_base_lock);
  35        ret = (*format)(sdata, buf, sizeof(buf));
  36        read_unlock(&dev_base_lock);
  37
  38        if (ret >= 0)
  39                ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
  40
  41        return ret;
  42}
  43
  44static ssize_t ieee80211_if_write(
  45        struct ieee80211_sub_if_data *sdata,
  46        const char __user *userbuf,
  47        size_t count, loff_t *ppos,
  48        ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int))
  49{
  50        char buf[64];
  51        ssize_t ret;
  52
  53        if (count >= sizeof(buf))
  54                return -E2BIG;
  55
  56        if (copy_from_user(buf, userbuf, count))
  57                return -EFAULT;
  58        buf[count] = '\0';
  59
  60        ret = -ENODEV;
  61        rtnl_lock();
  62        ret = (*write)(sdata, buf, count);
  63        rtnl_unlock();
  64
  65        return ret;
  66}
  67
  68#define IEEE80211_IF_FMT(name, field, format_string)                    \
  69static ssize_t ieee80211_if_fmt_##name(                                 \
  70        const struct ieee80211_sub_if_data *sdata, char *buf,           \
  71        int buflen)                                                     \
  72{                                                                       \
  73        return scnprintf(buf, buflen, format_string, sdata->field);     \
  74}
  75#define IEEE80211_IF_FMT_DEC(name, field)                               \
  76                IEEE80211_IF_FMT(name, field, "%d\n")
  77#define IEEE80211_IF_FMT_HEX(name, field)                               \
  78                IEEE80211_IF_FMT(name, field, "%#x\n")
  79#define IEEE80211_IF_FMT_LHEX(name, field)                              \
  80                IEEE80211_IF_FMT(name, field, "%#lx\n")
  81#define IEEE80211_IF_FMT_SIZE(name, field)                              \
  82                IEEE80211_IF_FMT(name, field, "%zd\n")
  83
  84#define IEEE80211_IF_FMT_HEXARRAY(name, field)                          \
  85static ssize_t ieee80211_if_fmt_##name(                                 \
  86        const struct ieee80211_sub_if_data *sdata,                      \
  87        char *buf, int buflen)                                          \
  88{                                                                       \
  89        char *p = buf;                                                  \
  90        int i;                                                          \
  91        for (i = 0; i < sizeof(sdata->field); i++) {                    \
  92                p += scnprintf(p, buflen + buf - p, "%.2x ",            \
  93                                 sdata->field[i]);                      \
  94        }                                                               \
  95        p += scnprintf(p, buflen + buf - p, "\n");                      \
  96        return p - buf;                                                 \
  97}
  98
  99#define IEEE80211_IF_FMT_ATOMIC(name, field)                            \
 100static ssize_t ieee80211_if_fmt_##name(                                 \
 101        const struct ieee80211_sub_if_data *sdata,                      \
 102        char *buf, int buflen)                                          \
 103{                                                                       \
 104        return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
 105}
 106
 107#define IEEE80211_IF_FMT_MAC(name, field)                               \
 108static ssize_t ieee80211_if_fmt_##name(                                 \
 109        const struct ieee80211_sub_if_data *sdata, char *buf,           \
 110        int buflen)                                                     \
 111{                                                                       \
 112        return scnprintf(buf, buflen, "%pM\n", sdata->field);           \
 113}
 114
 115#define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, field)                     \
 116static ssize_t ieee80211_if_fmt_##name(                                 \
 117        const struct ieee80211_sub_if_data *sdata,                      \
 118        char *buf, int buflen)                                          \
 119{                                                                       \
 120        return scnprintf(buf, buflen, "%d\n",                           \
 121                         jiffies_to_msecs(sdata->field));               \
 122}
 123
 124#define _IEEE80211_IF_FILE_OPS(name, _read, _write)                     \
 125static const struct file_operations name##_ops = {                      \
 126        .read = (_read),                                                \
 127        .write = (_write),                                              \
 128        .open = simple_open,                                            \
 129        .llseek = generic_file_llseek,                                  \
 130}
 131
 132#define _IEEE80211_IF_FILE_R_FN(name)                                   \
 133static ssize_t ieee80211_if_read_##name(struct file *file,              \
 134                                        char __user *userbuf,           \
 135                                        size_t count, loff_t *ppos)     \
 136{                                                                       \
 137        return ieee80211_if_read(file->private_data,                    \
 138                                 userbuf, count, ppos,                  \
 139                                 ieee80211_if_fmt_##name);              \
 140}
 141
 142#define _IEEE80211_IF_FILE_W_FN(name)                                   \
 143static ssize_t ieee80211_if_write_##name(struct file *file,             \
 144                                         const char __user *userbuf,    \
 145                                         size_t count, loff_t *ppos)    \
 146{                                                                       \
 147        return ieee80211_if_write(file->private_data, userbuf, count,   \
 148                                  ppos, ieee80211_if_parse_##name);     \
 149}
 150
 151#define IEEE80211_IF_FILE_R(name)                                       \
 152        _IEEE80211_IF_FILE_R_FN(name)                                   \
 153        _IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, NULL)
 154
 155#define IEEE80211_IF_FILE_W(name)                                       \
 156        _IEEE80211_IF_FILE_W_FN(name)                                   \
 157        _IEEE80211_IF_FILE_OPS(name, NULL, ieee80211_if_write_##name)
 158
 159#define IEEE80211_IF_FILE_RW(name)                                      \
 160        _IEEE80211_IF_FILE_R_FN(name)                                   \
 161        _IEEE80211_IF_FILE_W_FN(name)                                   \
 162        _IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name,          \
 163                               ieee80211_if_write_##name)
 164
 165#define IEEE80211_IF_FILE(name, field, format)                          \
 166        IEEE80211_IF_FMT_##format(name, field)                          \
 167        IEEE80211_IF_FILE_R(name)
 168
 169/* common attributes */
 170IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[NL80211_BAND_2GHZ],
 171                  HEX);
 172IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[NL80211_BAND_5GHZ],
 173                  HEX);
 174IEEE80211_IF_FILE(rc_rateidx_mcs_mask_2ghz,
 175                  rc_rateidx_mcs_mask[NL80211_BAND_2GHZ], HEXARRAY);
 176IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz,
 177                  rc_rateidx_mcs_mask[NL80211_BAND_5GHZ], HEXARRAY);
 178
 179static ssize_t ieee80211_if_fmt_rc_rateidx_vht_mcs_mask_2ghz(
 180                                const struct ieee80211_sub_if_data *sdata,
 181                                char *buf, int buflen)
 182{
 183        int i, len = 0;
 184        const u16 *mask = sdata->rc_rateidx_vht_mcs_mask[NL80211_BAND_2GHZ];
 185
 186        for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
 187                len += scnprintf(buf + len, buflen - len, "%04x ", mask[i]);
 188        len += scnprintf(buf + len, buflen - len, "\n");
 189
 190        return len;
 191}
 192
 193IEEE80211_IF_FILE_R(rc_rateidx_vht_mcs_mask_2ghz);
 194
 195static ssize_t ieee80211_if_fmt_rc_rateidx_vht_mcs_mask_5ghz(
 196                                const struct ieee80211_sub_if_data *sdata,
 197                                char *buf, int buflen)
 198{
 199        int i, len = 0;
 200        const u16 *mask = sdata->rc_rateidx_vht_mcs_mask[NL80211_BAND_5GHZ];
 201
 202        for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
 203                len += scnprintf(buf + len, buflen - len, "%04x ", mask[i]);
 204        len += scnprintf(buf + len, buflen - len, "\n");
 205
 206        return len;
 207}
 208
 209IEEE80211_IF_FILE_R(rc_rateidx_vht_mcs_mask_5ghz);
 210
 211IEEE80211_IF_FILE(flags, flags, HEX);
 212IEEE80211_IF_FILE(state, state, LHEX);
 213IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC);
 214IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC);
 215IEEE80211_IF_FILE(user_power_level, user_power_level, DEC);
 216
 217static ssize_t
 218ieee80211_if_fmt_hw_queues(const struct ieee80211_sub_if_data *sdata,
 219                           char *buf, int buflen)
 220{
 221        int len;
 222
 223        len = scnprintf(buf, buflen, "AC queues: VO:%d VI:%d BE:%d BK:%d\n",
 224                        sdata->vif.hw_queue[IEEE80211_AC_VO],
 225                        sdata->vif.hw_queue[IEEE80211_AC_VI],
 226                        sdata->vif.hw_queue[IEEE80211_AC_BE],
 227                        sdata->vif.hw_queue[IEEE80211_AC_BK]);
 228
 229        if (sdata->vif.type == NL80211_IFTYPE_AP)
 230                len += scnprintf(buf + len, buflen - len, "cab queue: %d\n",
 231                                 sdata->vif.cab_queue);
 232
 233        return len;
 234}
 235IEEE80211_IF_FILE_R(hw_queues);
 236
 237/* STA attributes */
 238IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
 239IEEE80211_IF_FILE(aid, vif.bss_conf.aid, DEC);
 240IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS);
 241
 242static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
 243                              enum ieee80211_smps_mode smps_mode)
 244{
 245        struct ieee80211_local *local = sdata->local;
 246        int err;
 247
 248        if (!(local->hw.wiphy->features & NL80211_FEATURE_STATIC_SMPS) &&
 249            smps_mode == IEEE80211_SMPS_STATIC)
 250                return -EINVAL;
 251
 252        /* auto should be dynamic if in PS mode */
 253        if (!(local->hw.wiphy->features & NL80211_FEATURE_DYNAMIC_SMPS) &&
 254            (smps_mode == IEEE80211_SMPS_DYNAMIC ||
 255             smps_mode == IEEE80211_SMPS_AUTOMATIC))
 256                return -EINVAL;
 257
 258        if (sdata->vif.type != NL80211_IFTYPE_STATION)
 259                return -EOPNOTSUPP;
 260
 261        sdata_lock(sdata);
 262        err = __ieee80211_request_smps_mgd(sdata, smps_mode);
 263        sdata_unlock(sdata);
 264
 265        return err;
 266}
 267
 268static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
 269        [IEEE80211_SMPS_AUTOMATIC] = "auto",
 270        [IEEE80211_SMPS_OFF] = "off",
 271        [IEEE80211_SMPS_STATIC] = "static",
 272        [IEEE80211_SMPS_DYNAMIC] = "dynamic",
 273};
 274
 275static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
 276                                     char *buf, int buflen)
 277{
 278        if (sdata->vif.type == NL80211_IFTYPE_STATION)
 279                return snprintf(buf, buflen, "request: %s\nused: %s\n",
 280                                smps_modes[sdata->u.mgd.req_smps],
 281                                smps_modes[sdata->smps_mode]);
 282        return -EINVAL;
 283}
 284
 285static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
 286                                       const char *buf, int buflen)
 287{
 288        enum ieee80211_smps_mode mode;
 289
 290        for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) {
 291                if (strncmp(buf, smps_modes[mode], buflen) == 0) {
 292                        int err = ieee80211_set_smps(sdata, mode);
 293                        if (!err)
 294                                return buflen;
 295                        return err;
 296                }
 297        }
 298
 299        return -EINVAL;
 300}
 301IEEE80211_IF_FILE_RW(smps);
 302
 303static ssize_t ieee80211_if_parse_tkip_mic_test(
 304        struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
 305{
 306        struct ieee80211_local *local = sdata->local;
 307        u8 addr[ETH_ALEN];
 308        struct sk_buff *skb;
 309        struct ieee80211_hdr *hdr;
 310        __le16 fc;
 311
 312        if (!mac_pton(buf, addr))
 313                return -EINVAL;
 314
 315        if (!ieee80211_sdata_running(sdata))
 316                return -ENOTCONN;
 317
 318        skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 100);
 319        if (!skb)
 320                return -ENOMEM;
 321        skb_reserve(skb, local->hw.extra_tx_headroom);
 322
 323        hdr = skb_put_zero(skb, 24);
 324        fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
 325
 326        switch (sdata->vif.type) {
 327        case NL80211_IFTYPE_AP:
 328                fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
 329                /* DA BSSID SA */
 330                memcpy(hdr->addr1, addr, ETH_ALEN);
 331                memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
 332                memcpy(hdr->addr3, sdata->vif.addr, ETH_ALEN);
 333                break;
 334        case NL80211_IFTYPE_STATION:
 335                fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
 336                /* BSSID SA DA */
 337                sdata_lock(sdata);
 338                if (!sdata->u.mgd.associated) {
 339                        sdata_unlock(sdata);
 340                        dev_kfree_skb(skb);
 341                        return -ENOTCONN;
 342                }
 343                memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN);
 344                memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
 345                memcpy(hdr->addr3, addr, ETH_ALEN);
 346                sdata_unlock(sdata);
 347                break;
 348        default:
 349                dev_kfree_skb(skb);
 350                return -EOPNOTSUPP;
 351        }
 352        hdr->frame_control = fc;
 353
 354        /*
 355         * Add some length to the test frame to make it look bit more valid.
 356         * The exact contents does not matter since the recipient is required
 357         * to drop this because of the Michael MIC failure.
 358         */
 359        skb_put_zero(skb, 50);
 360
 361        IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_TKIP_MIC_FAILURE;
 362
 363        ieee80211_tx_skb(sdata, skb);
 364
 365        return buflen;
 366}
 367IEEE80211_IF_FILE_W(tkip_mic_test);
 368
 369static ssize_t ieee80211_if_parse_beacon_loss(
 370        struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
 371{
 372        if (!ieee80211_sdata_running(sdata) || !sdata->vif.bss_conf.assoc)
 373                return -ENOTCONN;
 374
 375        ieee80211_beacon_loss(&sdata->vif);
 376
 377        return buflen;
 378}
 379IEEE80211_IF_FILE_W(beacon_loss);
 380
 381static ssize_t ieee80211_if_fmt_uapsd_queues(
 382        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 383{
 384        const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 385
 386        return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_queues);
 387}
 388
 389static ssize_t ieee80211_if_parse_uapsd_queues(
 390        struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
 391{
 392        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 393        u8 val;
 394        int ret;
 395
 396        ret = kstrtou8(buf, 0, &val);
 397        if (ret)
 398                return ret;
 399
 400        if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
 401                return -ERANGE;
 402
 403        ifmgd->uapsd_queues = val;
 404
 405        return buflen;
 406}
 407IEEE80211_IF_FILE_RW(uapsd_queues);
 408
 409static ssize_t ieee80211_if_fmt_uapsd_max_sp_len(
 410        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 411{
 412        const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 413
 414        return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_max_sp_len);
 415}
 416
 417static ssize_t ieee80211_if_parse_uapsd_max_sp_len(
 418        struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
 419{
 420        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 421        unsigned long val;
 422        int ret;
 423
 424        ret = kstrtoul(buf, 0, &val);
 425        if (ret)
 426                return -EINVAL;
 427
 428        if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
 429                return -ERANGE;
 430
 431        ifmgd->uapsd_max_sp_len = val;
 432
 433        return buflen;
 434}
 435IEEE80211_IF_FILE_RW(uapsd_max_sp_len);
 436
 437static ssize_t ieee80211_if_fmt_tdls_wider_bw(
 438        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 439{
 440        const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 441        bool tdls_wider_bw;
 442
 443        tdls_wider_bw = ieee80211_hw_check(&sdata->local->hw, TDLS_WIDER_BW) &&
 444                        !ifmgd->tdls_wider_bw_prohibited;
 445
 446        return snprintf(buf, buflen, "%d\n", tdls_wider_bw);
 447}
 448
 449static ssize_t ieee80211_if_parse_tdls_wider_bw(
 450        struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
 451{
 452        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 453        u8 val;
 454        int ret;
 455
 456        ret = kstrtou8(buf, 0, &val);
 457        if (ret)
 458                return ret;
 459
 460        ifmgd->tdls_wider_bw_prohibited = !val;
 461        return buflen;
 462}
 463IEEE80211_IF_FILE_RW(tdls_wider_bw);
 464
 465/* AP attributes */
 466IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC);
 467IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC);
 468IEEE80211_IF_FILE(dtim_count, u.ap.ps.dtim_count, DEC);
 469IEEE80211_IF_FILE(num_mcast_sta_vlan, u.vlan.num_mcast_sta, ATOMIC);
 470
 471static ssize_t ieee80211_if_fmt_num_buffered_multicast(
 472        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 473{
 474        return scnprintf(buf, buflen, "%u\n",
 475                         skb_queue_len(&sdata->u.ap.ps.bc_buf));
 476}
 477IEEE80211_IF_FILE_R(num_buffered_multicast);
 478
 479static ssize_t ieee80211_if_fmt_aqm(
 480        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 481{
 482        struct ieee80211_local *local = sdata->local;
 483        struct txq_info *txqi;
 484        int len;
 485
 486        if (!sdata->vif.txq)
 487                return 0;
 488
 489        txqi = to_txq_info(sdata->vif.txq);
 490
 491        spin_lock_bh(&local->fq.lock);
 492        rcu_read_lock();
 493
 494        len = scnprintf(buf,
 495                        buflen,
 496                        "ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets\n"
 497                        "%u %u %u %u %u %u %u %u %u %u\n",
 498                        txqi->txq.ac,
 499                        txqi->tin.backlog_bytes,
 500                        txqi->tin.backlog_packets,
 501                        txqi->tin.flows,
 502                        txqi->cstats.drop_count,
 503                        txqi->cstats.ecn_mark,
 504                        txqi->tin.overlimit,
 505                        txqi->tin.collisions,
 506                        txqi->tin.tx_bytes,
 507                        txqi->tin.tx_packets);
 508
 509        rcu_read_unlock();
 510        spin_unlock_bh(&local->fq.lock);
 511
 512        return len;
 513}
 514IEEE80211_IF_FILE_R(aqm);
 515
 516IEEE80211_IF_FILE(multicast_to_unicast, u.ap.multicast_to_unicast, HEX);
 517
 518/* IBSS attributes */
 519static ssize_t ieee80211_if_fmt_tsf(
 520        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 521{
 522        struct ieee80211_local *local = sdata->local;
 523        u64 tsf;
 524
 525        tsf = drv_get_tsf(local, (struct ieee80211_sub_if_data *)sdata);
 526
 527        return scnprintf(buf, buflen, "0x%016llx\n", (unsigned long long) tsf);
 528}
 529
 530static ssize_t ieee80211_if_parse_tsf(
 531        struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
 532{
 533        struct ieee80211_local *local = sdata->local;
 534        unsigned long long tsf;
 535        int ret;
 536        int tsf_is_delta = 0;
 537
 538        if (strncmp(buf, "reset", 5) == 0) {
 539                if (local->ops->reset_tsf) {
 540                        drv_reset_tsf(local, sdata);
 541                        wiphy_info(local->hw.wiphy, "debugfs reset TSF\n");
 542                }
 543        } else {
 544                if (buflen > 10 && buf[1] == '=') {
 545                        if (buf[0] == '+')
 546                                tsf_is_delta = 1;
 547                        else if (buf[0] == '-')
 548                                tsf_is_delta = -1;
 549                        else
 550                                return -EINVAL;
 551                        buf += 2;
 552                }
 553                ret = kstrtoull(buf, 10, &tsf);
 554                if (ret < 0)
 555                        return ret;
 556                if (tsf_is_delta && local->ops->offset_tsf) {
 557                        drv_offset_tsf(local, sdata, tsf_is_delta * tsf);
 558                        wiphy_info(local->hw.wiphy,
 559                                   "debugfs offset TSF by %018lld\n",
 560                                   tsf_is_delta * tsf);
 561                } else if (local->ops->set_tsf) {
 562                        if (tsf_is_delta)
 563                                tsf = drv_get_tsf(local, sdata) +
 564                                      tsf_is_delta * tsf;
 565                        drv_set_tsf(local, sdata, tsf);
 566                        wiphy_info(local->hw.wiphy,
 567                                   "debugfs set TSF to %#018llx\n", tsf);
 568                }
 569        }
 570
 571        ieee80211_recalc_dtim(local, sdata);
 572        return buflen;
 573}
 574IEEE80211_IF_FILE_RW(tsf);
 575
 576
 577/* WDS attributes */
 578IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
 579
 580#ifdef CONFIG_MAC80211_MESH
 581IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC);
 582
 583/* Mesh stats attributes */
 584IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC);
 585IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
 586IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
 587IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
 588IEEE80211_IF_FILE(dropped_frames_congestion,
 589                  u.mesh.mshstats.dropped_frames_congestion, DEC);
 590IEEE80211_IF_FILE(dropped_frames_no_route,
 591                  u.mesh.mshstats.dropped_frames_no_route, DEC);
 592
 593/* Mesh parameters */
 594IEEE80211_IF_FILE(dot11MeshMaxRetries,
 595                  u.mesh.mshcfg.dot11MeshMaxRetries, DEC);
 596IEEE80211_IF_FILE(dot11MeshRetryTimeout,
 597                  u.mesh.mshcfg.dot11MeshRetryTimeout, DEC);
 598IEEE80211_IF_FILE(dot11MeshConfirmTimeout,
 599                  u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC);
 600IEEE80211_IF_FILE(dot11MeshHoldingTimeout,
 601                  u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC);
 602IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC);
 603IEEE80211_IF_FILE(element_ttl, u.mesh.mshcfg.element_ttl, DEC);
 604IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC);
 605IEEE80211_IF_FILE(dot11MeshMaxPeerLinks,
 606                  u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC);
 607IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout,
 608                  u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC);
 609IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval,
 610                  u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC);
 611IEEE80211_IF_FILE(dot11MeshHWMPperrMinInterval,
 612                  u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC);
 613IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime,
 614                  u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC);
 615IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries,
 616                  u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC);
 617IEEE80211_IF_FILE(path_refresh_time,
 618                  u.mesh.mshcfg.path_refresh_time, DEC);
 619IEEE80211_IF_FILE(min_discovery_timeout,
 620                  u.mesh.mshcfg.min_discovery_timeout, DEC);
 621IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
 622                  u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
 623IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol,
 624                  u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC);
 625IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
 626                  u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
 627IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
 628IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
 629IEEE80211_IF_FILE(ht_opmode, u.mesh.mshcfg.ht_opmode, DEC);
 630IEEE80211_IF_FILE(dot11MeshHWMPactivePathToRootTimeout,
 631                  u.mesh.mshcfg.dot11MeshHWMPactivePathToRootTimeout, DEC);
 632IEEE80211_IF_FILE(dot11MeshHWMProotInterval,
 633                  u.mesh.mshcfg.dot11MeshHWMProotInterval, DEC);
 634IEEE80211_IF_FILE(dot11MeshHWMPconfirmationInterval,
 635                  u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval, DEC);
 636IEEE80211_IF_FILE(power_mode, u.mesh.mshcfg.power_mode, DEC);
 637IEEE80211_IF_FILE(dot11MeshAwakeWindowDuration,
 638                  u.mesh.mshcfg.dot11MeshAwakeWindowDuration, DEC);
 639IEEE80211_IF_FILE(dot11MeshConnectedToMeshGate,
 640                  u.mesh.mshcfg.dot11MeshConnectedToMeshGate, DEC);
 641IEEE80211_IF_FILE(dot11MeshNolearn, u.mesh.mshcfg.dot11MeshNolearn, DEC);
 642IEEE80211_IF_FILE(dot11MeshConnectedToAuthServer,
 643                  u.mesh.mshcfg.dot11MeshConnectedToAuthServer, DEC);
 644#endif
 645
 646#define DEBUGFS_ADD_MODE(name, mode) \
 647        debugfs_create_file(#name, mode, sdata->vif.debugfs_dir, \
 648                            sdata, &name##_ops);
 649
 650#define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400)
 651
 652static void add_common_files(struct ieee80211_sub_if_data *sdata)
 653{
 654        DEBUGFS_ADD(rc_rateidx_mask_2ghz);
 655        DEBUGFS_ADD(rc_rateidx_mask_5ghz);
 656        DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
 657        DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
 658        DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_2ghz);
 659        DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz);
 660        DEBUGFS_ADD(hw_queues);
 661
 662        if (sdata->local->ops->wake_tx_queue &&
 663            sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
 664            sdata->vif.type != NL80211_IFTYPE_NAN)
 665                DEBUGFS_ADD(aqm);
 666}
 667
 668static void add_sta_files(struct ieee80211_sub_if_data *sdata)
 669{
 670        DEBUGFS_ADD(bssid);
 671        DEBUGFS_ADD(aid);
 672        DEBUGFS_ADD(beacon_timeout);
 673        DEBUGFS_ADD_MODE(smps, 0600);
 674        DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
 675        DEBUGFS_ADD_MODE(beacon_loss, 0200);
 676        DEBUGFS_ADD_MODE(uapsd_queues, 0600);
 677        DEBUGFS_ADD_MODE(uapsd_max_sp_len, 0600);
 678        DEBUGFS_ADD_MODE(tdls_wider_bw, 0600);
 679}
 680
 681static void add_ap_files(struct ieee80211_sub_if_data *sdata)
 682{
 683        DEBUGFS_ADD(num_mcast_sta);
 684        DEBUGFS_ADD_MODE(smps, 0600);
 685        DEBUGFS_ADD(num_sta_ps);
 686        DEBUGFS_ADD(dtim_count);
 687        DEBUGFS_ADD(num_buffered_multicast);
 688        DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
 689        DEBUGFS_ADD_MODE(multicast_to_unicast, 0600);
 690}
 691
 692static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
 693{
 694        /* add num_mcast_sta_vlan using name num_mcast_sta */
 695        debugfs_create_file("num_mcast_sta", 0400, sdata->vif.debugfs_dir,
 696                            sdata, &num_mcast_sta_vlan_ops);
 697}
 698
 699static void add_ibss_files(struct ieee80211_sub_if_data *sdata)
 700{
 701        DEBUGFS_ADD_MODE(tsf, 0600);
 702}
 703
 704static void add_wds_files(struct ieee80211_sub_if_data *sdata)
 705{
 706        DEBUGFS_ADD(peer);
 707}
 708
 709#ifdef CONFIG_MAC80211_MESH
 710
 711static void add_mesh_files(struct ieee80211_sub_if_data *sdata)
 712{
 713        DEBUGFS_ADD_MODE(tsf, 0600);
 714        DEBUGFS_ADD_MODE(estab_plinks, 0400);
 715}
 716
 717static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
 718{
 719        struct dentry *dir = debugfs_create_dir("mesh_stats",
 720                                                sdata->vif.debugfs_dir);
 721#define MESHSTATS_ADD(name)\
 722        debugfs_create_file(#name, 0400, dir, sdata, &name##_ops);
 723
 724        MESHSTATS_ADD(fwded_mcast);
 725        MESHSTATS_ADD(fwded_unicast);
 726        MESHSTATS_ADD(fwded_frames);
 727        MESHSTATS_ADD(dropped_frames_ttl);
 728        MESHSTATS_ADD(dropped_frames_no_route);
 729        MESHSTATS_ADD(dropped_frames_congestion);
 730#undef MESHSTATS_ADD
 731}
 732
 733static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
 734{
 735        struct dentry *dir = debugfs_create_dir("mesh_config",
 736                                                sdata->vif.debugfs_dir);
 737
 738#define MESHPARAMS_ADD(name) \
 739        debugfs_create_file(#name, 0600, dir, sdata, &name##_ops);
 740
 741        MESHPARAMS_ADD(dot11MeshMaxRetries);
 742        MESHPARAMS_ADD(dot11MeshRetryTimeout);
 743        MESHPARAMS_ADD(dot11MeshConfirmTimeout);
 744        MESHPARAMS_ADD(dot11MeshHoldingTimeout);
 745        MESHPARAMS_ADD(dot11MeshTTL);
 746        MESHPARAMS_ADD(element_ttl);
 747        MESHPARAMS_ADD(auto_open_plinks);
 748        MESHPARAMS_ADD(dot11MeshMaxPeerLinks);
 749        MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout);
 750        MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval);
 751        MESHPARAMS_ADD(dot11MeshHWMPperrMinInterval);
 752        MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime);
 753        MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries);
 754        MESHPARAMS_ADD(path_refresh_time);
 755        MESHPARAMS_ADD(min_discovery_timeout);
 756        MESHPARAMS_ADD(dot11MeshHWMPRootMode);
 757        MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
 758        MESHPARAMS_ADD(dot11MeshForwarding);
 759        MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
 760        MESHPARAMS_ADD(rssi_threshold);
 761        MESHPARAMS_ADD(ht_opmode);
 762        MESHPARAMS_ADD(dot11MeshHWMPactivePathToRootTimeout);
 763        MESHPARAMS_ADD(dot11MeshHWMProotInterval);
 764        MESHPARAMS_ADD(dot11MeshHWMPconfirmationInterval);
 765        MESHPARAMS_ADD(power_mode);
 766        MESHPARAMS_ADD(dot11MeshAwakeWindowDuration);
 767        MESHPARAMS_ADD(dot11MeshConnectedToMeshGate);
 768        MESHPARAMS_ADD(dot11MeshNolearn);
 769        MESHPARAMS_ADD(dot11MeshConnectedToAuthServer);
 770#undef MESHPARAMS_ADD
 771}
 772#endif
 773
 774static void add_files(struct ieee80211_sub_if_data *sdata)
 775{
 776        if (!sdata->vif.debugfs_dir)
 777                return;
 778
 779        DEBUGFS_ADD(flags);
 780        DEBUGFS_ADD(state);
 781        DEBUGFS_ADD(txpower);
 782        DEBUGFS_ADD(user_power_level);
 783        DEBUGFS_ADD(ap_power_level);
 784
 785        if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
 786                add_common_files(sdata);
 787
 788        switch (sdata->vif.type) {
 789        case NL80211_IFTYPE_MESH_POINT:
 790#ifdef CONFIG_MAC80211_MESH
 791                add_mesh_files(sdata);
 792                add_mesh_stats(sdata);
 793                add_mesh_config(sdata);
 794#endif
 795                break;
 796        case NL80211_IFTYPE_STATION:
 797                add_sta_files(sdata);
 798                break;
 799        case NL80211_IFTYPE_ADHOC:
 800                add_ibss_files(sdata);
 801                break;
 802        case NL80211_IFTYPE_AP:
 803                add_ap_files(sdata);
 804                break;
 805        case NL80211_IFTYPE_AP_VLAN:
 806                add_vlan_files(sdata);
 807                break;
 808        case NL80211_IFTYPE_WDS:
 809                add_wds_files(sdata);
 810                break;
 811        default:
 812                break;
 813        }
 814}
 815
 816void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
 817{
 818        char buf[10+IFNAMSIZ];
 819
 820        sprintf(buf, "netdev:%s", sdata->name);
 821        sdata->vif.debugfs_dir = debugfs_create_dir(buf,
 822                sdata->local->hw.wiphy->debugfsdir);
 823        sdata->debugfs.subdir_stations = debugfs_create_dir("stations",
 824                                                        sdata->vif.debugfs_dir);
 825        add_files(sdata);
 826}
 827
 828void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 829{
 830        if (!sdata->vif.debugfs_dir)
 831                return;
 832
 833        debugfs_remove_recursive(sdata->vif.debugfs_dir);
 834        sdata->vif.debugfs_dir = NULL;
 835        sdata->debugfs.subdir_stations = NULL;
 836}
 837
 838void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
 839{
 840        struct dentry *dir;
 841        char buf[10 + IFNAMSIZ];
 842
 843        dir = sdata->vif.debugfs_dir;
 844
 845        if (IS_ERR_OR_NULL(dir))
 846                return;
 847
 848        sprintf(buf, "netdev:%s", sdata->name);
 849        debugfs_rename(dir->d_parent, dir, dir->d_parent, buf);
 850}
 851