linux/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: ISC
   2
   3#include "mt7615.h"
   4
   5static int
   6mt7615_radar_pattern_set(void *data, u64 val)
   7{
   8        struct mt7615_dev *dev = data;
   9        int err;
  10
  11        if (!mt7615_wait_for_mcu_init(dev))
  12                return 0;
  13
  14        mt7615_mutex_acquire(dev);
  15        err = mt7615_mcu_rdd_send_pattern(dev);
  16        mt7615_mutex_release(dev);
  17
  18        return err;
  19}
  20
  21DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_pattern, NULL,
  22                         mt7615_radar_pattern_set, "%lld\n");
  23
  24static int mt7615_config(void *data, u64 val)
  25{
  26        struct mt7615_dev *dev = data;
  27        int ret;
  28
  29        mt7615_mutex_acquire(dev);
  30        ret = mt76_connac_mcu_chip_config(&dev->mt76);
  31        mt7615_mutex_release(dev);
  32
  33        return ret;
  34}
  35
  36DEFINE_DEBUGFS_ATTRIBUTE(fops_config, NULL, mt7615_config, "%lld\n");
  37
  38static int
  39mt7615_scs_set(void *data, u64 val)
  40{
  41        struct mt7615_dev *dev = data;
  42        struct mt7615_phy *ext_phy;
  43
  44        if (!mt7615_wait_for_mcu_init(dev))
  45                return 0;
  46
  47        mt7615_mac_set_scs(&dev->phy, val);
  48        ext_phy = mt7615_ext_phy(dev);
  49        if (ext_phy)
  50                mt7615_mac_set_scs(ext_phy, val);
  51
  52        return 0;
  53}
  54
  55static int
  56mt7615_scs_get(void *data, u64 *val)
  57{
  58        struct mt7615_dev *dev = data;
  59
  60        *val = dev->phy.scs_en;
  61
  62        return 0;
  63}
  64
  65DEFINE_DEBUGFS_ATTRIBUTE(fops_scs, mt7615_scs_get,
  66                         mt7615_scs_set, "%lld\n");
  67
  68static int
  69mt7615_pm_set(void *data, u64 val)
  70{
  71        struct mt7615_dev *dev = data;
  72        struct mt76_connac_pm *pm = &dev->pm;
  73        int ret = 0;
  74
  75        if (!mt7615_wait_for_mcu_init(dev))
  76                return 0;
  77
  78        if (!mt7615_firmware_offload(dev) || mt76_is_usb(&dev->mt76))
  79                return -EOPNOTSUPP;
  80
  81        if (val == pm->enable)
  82                return 0;
  83
  84        mt7615_mutex_acquire(dev);
  85
  86        if (dev->phy.n_beacon_vif) {
  87                ret = -EBUSY;
  88                goto out;
  89        }
  90
  91        if (!pm->enable) {
  92                pm->stats.last_wake_event = jiffies;
  93                pm->stats.last_doze_event = jiffies;
  94        }
  95        pm->enable = val;
  96out:
  97        mt7615_mutex_release(dev);
  98
  99        return ret;
 100}
 101
 102static int
 103mt7615_pm_get(void *data, u64 *val)
 104{
 105        struct mt7615_dev *dev = data;
 106
 107        *val = dev->pm.enable;
 108
 109        return 0;
 110}
 111
 112DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7615_pm_get, mt7615_pm_set, "%lld\n");
 113
 114static int
 115mt7615_pm_stats(struct seq_file *s, void *data)
 116{
 117        struct mt7615_dev *dev = dev_get_drvdata(s->private);
 118        struct mt76_connac_pm *pm = &dev->pm;
 119        unsigned long awake_time = pm->stats.awake_time;
 120        unsigned long doze_time = pm->stats.doze_time;
 121
 122        if (!test_bit(MT76_STATE_PM, &dev->mphy.state))
 123                awake_time += jiffies - pm->stats.last_wake_event;
 124        else
 125                doze_time += jiffies - pm->stats.last_doze_event;
 126
 127        seq_printf(s, "awake time: %14u\ndoze time: %15u\n",
 128                   jiffies_to_msecs(awake_time),
 129                   jiffies_to_msecs(doze_time));
 130
 131        return 0;
 132}
 133
 134static int
 135mt7615_pm_idle_timeout_set(void *data, u64 val)
 136{
 137        struct mt7615_dev *dev = data;
 138
 139        dev->pm.idle_timeout = msecs_to_jiffies(val);
 140
 141        return 0;
 142}
 143
 144static int
 145mt7615_pm_idle_timeout_get(void *data, u64 *val)
 146{
 147        struct mt7615_dev *dev = data;
 148
 149        *val = jiffies_to_msecs(dev->pm.idle_timeout);
 150
 151        return 0;
 152}
 153
 154DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7615_pm_idle_timeout_get,
 155                         mt7615_pm_idle_timeout_set, "%lld\n");
 156
 157static int
 158mt7615_dbdc_set(void *data, u64 val)
 159{
 160        struct mt7615_dev *dev = data;
 161
 162        if (!mt7615_wait_for_mcu_init(dev))
 163                return 0;
 164
 165        if (val)
 166                mt7615_register_ext_phy(dev);
 167        else
 168                mt7615_unregister_ext_phy(dev);
 169
 170        return 0;
 171}
 172
 173static int
 174mt7615_dbdc_get(void *data, u64 *val)
 175{
 176        struct mt7615_dev *dev = data;
 177
 178        *val = !!mt7615_ext_phy(dev);
 179
 180        return 0;
 181}
 182
 183DEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7615_dbdc_get,
 184                         mt7615_dbdc_set, "%lld\n");
 185
 186static int
 187mt7615_fw_debug_set(void *data, u64 val)
 188{
 189        struct mt7615_dev *dev = data;
 190
 191        if (!mt7615_wait_for_mcu_init(dev))
 192                return 0;
 193
 194        dev->fw_debug = val;
 195
 196        mt7615_mutex_acquire(dev);
 197        mt7615_mcu_fw_log_2_host(dev, dev->fw_debug ? 2 : 0);
 198        mt7615_mutex_release(dev);
 199
 200        return 0;
 201}
 202
 203static int
 204mt7615_fw_debug_get(void *data, u64 *val)
 205{
 206        struct mt7615_dev *dev = data;
 207
 208        *val = dev->fw_debug;
 209
 210        return 0;
 211}
 212
 213DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7615_fw_debug_get,
 214                         mt7615_fw_debug_set, "%lld\n");
 215
 216static int
 217mt7615_reset_test_set(void *data, u64 val)
 218{
 219        struct mt7615_dev *dev = data;
 220        struct sk_buff *skb;
 221
 222        if (!mt7615_wait_for_mcu_init(dev))
 223                return 0;
 224
 225        skb = alloc_skb(1, GFP_KERNEL);
 226        if (!skb)
 227                return -ENOMEM;
 228
 229        skb_put(skb, 1);
 230
 231        mt7615_mutex_acquire(dev);
 232        mt76_tx_queue_skb_raw(dev, dev->mphy.q_tx[0], skb, 0);
 233        mt7615_mutex_release(dev);
 234
 235        return 0;
 236}
 237
 238DEFINE_DEBUGFS_ATTRIBUTE(fops_reset_test, NULL,
 239                         mt7615_reset_test_set, "%lld\n");
 240
 241static void
 242mt7615_ampdu_stat_read_phy(struct mt7615_phy *phy,
 243                           struct seq_file *file)
 244{
 245        struct mt7615_dev *dev = file->private;
 246        u32 reg = is_mt7663(&dev->mt76) ? MT_MIB_ARNG(0) : MT_AGG_ASRCR0;
 247        bool ext_phy = phy != &dev->phy;
 248        int bound[7], i, range;
 249
 250        if (!phy)
 251                return;
 252
 253        range = mt76_rr(dev, reg);
 254        for (i = 0; i < 4; i++)
 255                bound[i] = MT_AGG_ASRCR_RANGE(range, i) + 1;
 256
 257        range = mt76_rr(dev, reg + 4);
 258        for (i = 0; i < 3; i++)
 259                bound[i + 4] = MT_AGG_ASRCR_RANGE(range, i) + 1;
 260
 261        seq_printf(file, "\nPhy %d\n", ext_phy);
 262
 263        seq_printf(file, "Length: %8d | ", bound[0]);
 264        for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)
 265                seq_printf(file, "%3d -%3d | ",
 266                           bound[i], bound[i + 1]);
 267        seq_puts(file, "\nCount:  ");
 268
 269        range = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
 270        for (i = 0; i < ARRAY_SIZE(bound); i++)
 271                seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i + range]);
 272        seq_puts(file, "\n");
 273
 274        seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);
 275        seq_printf(file, "PER: %ld.%1ld%%\n",
 276                   phy->mib.aggr_per / 10, phy->mib.aggr_per % 10);
 277}
 278
 279static int
 280mt7615_ampdu_stat_show(struct seq_file *file, void *data)
 281{
 282        struct mt7615_dev *dev = file->private;
 283
 284        mt7615_mutex_acquire(dev);
 285
 286        mt7615_ampdu_stat_read_phy(&dev->phy, file);
 287        mt7615_ampdu_stat_read_phy(mt7615_ext_phy(dev), file);
 288
 289        mt7615_mutex_release(dev);
 290
 291        return 0;
 292}
 293
 294DEFINE_SHOW_ATTRIBUTE(mt7615_ampdu_stat);
 295
 296static void
 297mt7615_radio_read_phy(struct mt7615_phy *phy, struct seq_file *s)
 298{
 299        struct mt7615_dev *dev = dev_get_drvdata(s->private);
 300        bool ext_phy = phy != &dev->phy;
 301
 302        if (!phy)
 303                return;
 304
 305        seq_printf(s, "Radio %d sensitivity: ofdm=%d cck=%d\n", ext_phy,
 306                   phy->ofdm_sensitivity, phy->cck_sensitivity);
 307        seq_printf(s, "Radio %d false CCA: ofdm=%d cck=%d\n", ext_phy,
 308                   phy->false_cca_ofdm, phy->false_cca_cck);
 309}
 310
 311static int
 312mt7615_radio_read(struct seq_file *s, void *data)
 313{
 314        struct mt7615_dev *dev = dev_get_drvdata(s->private);
 315
 316        mt7615_radio_read_phy(&dev->phy, s);
 317        mt7615_radio_read_phy(mt7615_ext_phy(dev), s);
 318
 319        return 0;
 320}
 321
 322static int
 323mt7615_queues_acq(struct seq_file *s, void *data)
 324{
 325        struct mt7615_dev *dev = dev_get_drvdata(s->private);
 326        int i;
 327
 328        mt7615_mutex_acquire(dev);
 329
 330        for (i = 0; i < 16; i++) {
 331                int j, wmm_idx = i % MT7615_MAX_WMM_SETS;
 332                int acs = i / MT7615_MAX_WMM_SETS;
 333                u32 ctrl, val, qlen = 0;
 334
 335                val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, wmm_idx));
 336                ctrl = BIT(31) | BIT(15) | (acs << 8);
 337
 338                for (j = 0; j < 32; j++) {
 339                        if (val & BIT(j))
 340                                continue;
 341
 342                        mt76_wr(dev, MT_PLE_FL_Q0_CTRL,
 343                                ctrl | (j + (wmm_idx << 5)));
 344                        qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
 345                                               GENMASK(11, 0));
 346                }
 347                seq_printf(s, "AC%d%d: queued=%d\n", wmm_idx, acs, qlen);
 348        }
 349
 350        mt7615_mutex_release(dev);
 351
 352        return 0;
 353}
 354
 355static int
 356mt7615_queues_read(struct seq_file *s, void *data)
 357{
 358        struct mt7615_dev *dev = dev_get_drvdata(s->private);
 359        struct {
 360                struct mt76_queue *q;
 361                char *queue;
 362        } queue_map[] = {
 363                { dev->mphy.q_tx[MT_TXQ_BE], "PDMA0" },
 364                { dev->mt76.q_mcu[MT_MCUQ_WM], "MCUQ" },
 365                { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },
 366        };
 367        int i;
 368
 369        for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
 370                struct mt76_queue *q = queue_map[i].q;
 371
 372                seq_printf(s,
 373                           "%s: queued=%d head=%d tail=%d\n",
 374                           queue_map[i].queue, q->queued, q->head,
 375                           q->tail);
 376        }
 377
 378        return 0;
 379}
 380
 381static int
 382mt7615_rf_reg_set(void *data, u64 val)
 383{
 384        struct mt7615_dev *dev = data;
 385
 386        mt7615_rf_wr(dev, dev->debugfs_rf_wf, dev->debugfs_rf_reg, val);
 387
 388        return 0;
 389}
 390
 391static int
 392mt7615_rf_reg_get(void *data, u64 *val)
 393{
 394        struct mt7615_dev *dev = data;
 395
 396        *val = mt7615_rf_rr(dev, dev->debugfs_rf_wf, dev->debugfs_rf_reg);
 397
 398        return 0;
 399}
 400
 401DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_reg, mt7615_rf_reg_get, mt7615_rf_reg_set,
 402                         "0x%08llx\n");
 403
 404static ssize_t
 405mt7615_ext_mac_addr_read(struct file *file, char __user *userbuf,
 406                         size_t count, loff_t *ppos)
 407{
 408        struct mt7615_dev *dev = file->private_data;
 409        char buf[32 * ((ETH_ALEN * 3) + 4) + 1];
 410        u8 addr[ETH_ALEN];
 411        int ofs = 0;
 412        int i;
 413
 414        for (i = 0; i < 32; i++) {
 415                if (!(dev->muar_mask & BIT(i)))
 416                        continue;
 417
 418                mt76_wr(dev, MT_WF_RMAC_MAR1,
 419                        FIELD_PREP(MT_WF_RMAC_MAR1_IDX, i * 2) |
 420                        MT_WF_RMAC_MAR1_START);
 421                put_unaligned_le32(mt76_rr(dev, MT_WF_RMAC_MAR0), addr);
 422                put_unaligned_le16((mt76_rr(dev, MT_WF_RMAC_MAR1) &
 423                                    MT_WF_RMAC_MAR1_ADDR), addr + 4);
 424                ofs += snprintf(buf + ofs, sizeof(buf) - ofs, "%d=%pM\n", i, addr);
 425        }
 426
 427        return simple_read_from_buffer(userbuf, count, ppos, buf, ofs);
 428}
 429
 430static ssize_t
 431mt7615_ext_mac_addr_write(struct file *file, const char __user *userbuf,
 432                          size_t count, loff_t *ppos)
 433{
 434        struct mt7615_dev *dev = file->private_data;
 435        unsigned long idx = 0;
 436        u8 addr[ETH_ALEN];
 437        char buf[32];
 438        char *p;
 439
 440        if (count > sizeof(buf))
 441                return -EINVAL;
 442
 443        if (copy_from_user(buf, userbuf, count))
 444                return -EFAULT;
 445
 446        buf[sizeof(buf) - 1] = '\0';
 447
 448        p = strchr(buf, '=');
 449        if (p) {
 450                *p = 0;
 451                p++;
 452
 453                if (kstrtoul(buf, 0, &idx) || idx > 31)
 454                        return -EINVAL;
 455        } else {
 456                idx = 0;
 457                p = buf;
 458        }
 459
 460        if (!mac_pton(p, addr))
 461                return -EINVAL;
 462
 463        if (is_valid_ether_addr(addr)) {
 464                dev->muar_mask |= BIT(idx);
 465        } else {
 466                memset(addr, 0, sizeof(addr));
 467                dev->muar_mask &= ~BIT(idx);
 468        }
 469
 470        mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, 1);
 471        mt76_wr(dev, MT_WF_RMAC_MAR0, get_unaligned_le32(addr));
 472        mt76_wr(dev, MT_WF_RMAC_MAR1,
 473                get_unaligned_le16(addr + 4) |
 474                FIELD_PREP(MT_WF_RMAC_MAR1_IDX, idx * 2) |
 475                MT_WF_RMAC_MAR1_START |
 476                MT_WF_RMAC_MAR1_WRITE);
 477
 478        mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, !!dev->muar_mask);
 479
 480        return count;
 481}
 482
 483static const struct file_operations fops_ext_mac_addr = {
 484        .open = simple_open,
 485        .llseek = generic_file_llseek,
 486        .read = mt7615_ext_mac_addr_read,
 487        .write = mt7615_ext_mac_addr_write,
 488        .owner = THIS_MODULE,
 489};
 490
 491static int
 492mt7663s_sched_quota_read(struct seq_file *s, void *data)
 493{
 494        struct mt7615_dev *dev = dev_get_drvdata(s->private);
 495        struct mt76_sdio *sdio = &dev->mt76.sdio;
 496
 497        seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota);
 498        seq_printf(s, "ple_data_quota\t%d\n", sdio->sched.ple_data_quota);
 499        seq_printf(s, "pse_mcu_quota\t%d\n", sdio->sched.pse_mcu_quota);
 500        seq_printf(s, "sched_deficit\t%d\n", sdio->sched.deficit);
 501
 502        return 0;
 503}
 504
 505int mt7615_init_debugfs(struct mt7615_dev *dev)
 506{
 507        struct dentry *dir;
 508
 509        dir = mt76_register_debugfs(&dev->mt76);
 510        if (!dir)
 511                return -ENOMEM;
 512
 513        if (is_mt7615(&dev->mt76))
 514                debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,
 515                                            mt7615_queues_read);
 516        else
 517                debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,
 518                                            mt76_queues_read);
 519        debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
 520                                    mt7615_queues_acq);
 521        debugfs_create_file("ampdu_stat", 0400, dir, dev, &mt7615_ampdu_stat_fops);
 522        debugfs_create_file("scs", 0600, dir, dev, &fops_scs);
 523        debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc);
 524        debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
 525        debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
 526        debugfs_create_file("idle-timeout", 0600, dir, dev,
 527                            &fops_pm_idle_timeout);
 528        debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
 529                                    mt7615_pm_stats);
 530        debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir,
 531                                    mt7615_radio_read);
 532
 533        if (is_mt7615(&dev->mt76)) {
 534                debugfs_create_u32("dfs_hw_pattern", 0400, dir,
 535                                   &dev->hw_pattern);
 536                /* test pattern knobs */
 537                debugfs_create_u8("pattern_len", 0600, dir,
 538                                  &dev->radar_pattern.n_pulses);
 539                debugfs_create_u32("pulse_period", 0600, dir,
 540                                   &dev->radar_pattern.period);
 541                debugfs_create_u16("pulse_width", 0600, dir,
 542                                   &dev->radar_pattern.width);
 543                debugfs_create_u16("pulse_power", 0600, dir,
 544                                   &dev->radar_pattern.power);
 545                debugfs_create_file("radar_trigger", 0200, dir, dev,
 546                                    &fops_radar_pattern);
 547        }
 548
 549        debugfs_create_file("reset_test", 0200, dir, dev,
 550                            &fops_reset_test);
 551        debugfs_create_file("ext_mac_addr", 0600, dir, dev, &fops_ext_mac_addr);
 552
 553        debugfs_create_u32("rf_wfidx", 0600, dir, &dev->debugfs_rf_wf);
 554        debugfs_create_u32("rf_regidx", 0600, dir, &dev->debugfs_rf_reg);
 555        debugfs_create_file_unsafe("rf_regval", 0600, dir, dev,
 556                                   &fops_rf_reg);
 557        if (is_mt7663(&dev->mt76))
 558                debugfs_create_file("chip_config", 0600, dir, dev,
 559                                    &fops_config);
 560        if (mt76_is_sdio(&dev->mt76))
 561                debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir,
 562                                            mt7663s_sched_quota_read);
 563
 564        return 0;
 565}
 566EXPORT_SYMBOL_GPL(mt7615_init_debugfs);
 567