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