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