610 lines · c
1// SPDX-License-Identifier: ISC2 3#include "mt7615.h"4 5static int6mt7615_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 int18mt7615_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 int33mt7615_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 int66mt7615_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 int83mt7615_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 int96mt7615_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 scheduled123 * 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 int137mt7615_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 int149mt7615_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 else159 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 int169mt7615_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 int179mt7615_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 int192mt7615_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 else202 mt7615_unregister_ext_phy(dev);203 204 return 0;205}206 207static int208mt7615_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 int221mt7615_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 int238mt7615_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 int251mt7615_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 void276mt7615_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 int bound[7], i, range;282 283 if (!phy)284 return;285 286 range = mt76_rr(dev, reg);287 for (i = 0; i < 4; i++)288 bound[i] = MT_AGG_ASRCR_RANGE(range, i) + 1;289 290 range = mt76_rr(dev, reg + 4);291 for (i = 0; i < 3; i++)292 bound[i + 4] = MT_AGG_ASRCR_RANGE(range, i) + 1;293 294 seq_printf(file, "\nPhy %d\n", phy != &dev->phy);295 296 seq_printf(file, "Length: %8d | ", bound[0]);297 for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)298 seq_printf(file, "%3d -%3d | ",299 bound[i], bound[i + 1]);300 seq_puts(file, "\nCount: ");301 302 for (i = 0; i < ARRAY_SIZE(bound); i++)303 seq_printf(file, "%8d | ", phy->mt76->aggr_stats[i]);304 seq_puts(file, "\n");305 306 seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);307 seq_printf(file, "PER: %ld.%1ld%%\n",308 phy->mib.aggr_per / 10, phy->mib.aggr_per % 10);309}310 311static int312mt7615_ampdu_stat_show(struct seq_file *file, void *data)313{314 struct mt7615_dev *dev = file->private;315 316 mt7615_mutex_acquire(dev);317 318 mt7615_ampdu_stat_read_phy(&dev->phy, file);319 mt7615_ampdu_stat_read_phy(mt7615_ext_phy(dev), file);320 321 mt7615_mutex_release(dev);322 323 return 0;324}325 326DEFINE_SHOW_ATTRIBUTE(mt7615_ampdu_stat);327 328static void329mt7615_radio_read_phy(struct mt7615_phy *phy, struct seq_file *s)330{331 struct mt7615_dev *dev = dev_get_drvdata(s->private);332 bool ext_phy = phy != &dev->phy;333 334 if (!phy)335 return;336 337 seq_printf(s, "Radio %d sensitivity: ofdm=%d cck=%d\n", ext_phy,338 phy->ofdm_sensitivity, phy->cck_sensitivity);339 seq_printf(s, "Radio %d false CCA: ofdm=%d cck=%d\n", ext_phy,340 phy->false_cca_ofdm, phy->false_cca_cck);341}342 343static int344mt7615_radio_read(struct seq_file *s, void *data)345{346 struct mt7615_dev *dev = dev_get_drvdata(s->private);347 348 mt7615_radio_read_phy(&dev->phy, s);349 mt7615_radio_read_phy(mt7615_ext_phy(dev), s);350 351 return 0;352}353 354static int355mt7615_queues_acq(struct seq_file *s, void *data)356{357 struct mt7615_dev *dev = dev_get_drvdata(s->private);358 int i;359 360 mt7615_mutex_acquire(dev);361 362 for (i = 0; i < 16; i++) {363 int j, wmm_idx = i % MT7615_MAX_WMM_SETS;364 int acs = i / MT7615_MAX_WMM_SETS;365 u32 ctrl, val, qlen = 0;366 367 if (wmm_idx == 3 && is_mt7663(&dev->mt76))368 continue;369 370 val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, wmm_idx));371 ctrl = BIT(31) | BIT(15) | (acs << 8);372 373 for (j = 0; j < 32; j++) {374 if (val & BIT(j))375 continue;376 377 mt76_wr(dev, MT_PLE_FL_Q0_CTRL,378 ctrl | (j + (wmm_idx << 5)));379 qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,380 GENMASK(11, 0));381 }382 seq_printf(s, "AC%d%d: queued=%d\n", wmm_idx, acs, qlen);383 }384 385 mt7615_mutex_release(dev);386 387 return 0;388}389 390static int391mt7615_queues_read(struct seq_file *s, void *data)392{393 struct mt7615_dev *dev = dev_get_drvdata(s->private);394 struct {395 struct mt76_queue *q;396 char *queue;397 } queue_map[] = {398 { dev->mphy.q_tx[MT_TXQ_BE], "PDMA0" },399 { dev->mt76.q_mcu[MT_MCUQ_WM], "MCUQ" },400 { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },401 };402 int i;403 404 for (i = 0; i < ARRAY_SIZE(queue_map); i++) {405 struct mt76_queue *q = queue_map[i].q;406 407 seq_printf(s,408 "%s: queued=%d head=%d tail=%d\n",409 queue_map[i].queue, q->queued, q->head,410 q->tail);411 }412 413 return 0;414}415 416static int417mt7615_rf_reg_set(void *data, u64 val)418{419 struct mt7615_dev *dev = data;420 421 mt7615_rf_wr(dev, dev->debugfs_rf_wf, dev->debugfs_rf_reg, val);422 423 return 0;424}425 426static int427mt7615_rf_reg_get(void *data, u64 *val)428{429 struct mt7615_dev *dev = data;430 431 *val = mt7615_rf_rr(dev, dev->debugfs_rf_wf, dev->debugfs_rf_reg);432 433 return 0;434}435 436DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_reg, mt7615_rf_reg_get, mt7615_rf_reg_set,437 "0x%08llx\n");438 439static ssize_t440mt7615_ext_mac_addr_read(struct file *file, char __user *userbuf,441 size_t count, loff_t *ppos)442{443 struct mt7615_dev *dev = file->private_data;444 u32 len = 32 * ((ETH_ALEN * 3) + 4) + 1;445 u8 addr[ETH_ALEN];446 char *buf;447 int ofs = 0;448 int i;449 450 buf = kzalloc(len, GFP_KERNEL);451 if (!buf)452 return -ENOMEM;453 454 for (i = 0; i < 32; i++) {455 if (!(dev->muar_mask & BIT(i)))456 continue;457 458 mt76_wr(dev, MT_WF_RMAC_MAR1,459 FIELD_PREP(MT_WF_RMAC_MAR1_IDX, i * 2) |460 MT_WF_RMAC_MAR1_START);461 put_unaligned_le32(mt76_rr(dev, MT_WF_RMAC_MAR0), addr);462 put_unaligned_le16((mt76_rr(dev, MT_WF_RMAC_MAR1) &463 MT_WF_RMAC_MAR1_ADDR), addr + 4);464 ofs += snprintf(buf + ofs, len - ofs, "%d=%pM\n", i, addr);465 }466 467 ofs = simple_read_from_buffer(userbuf, count, ppos, buf, ofs);468 469 kfree(buf);470 return ofs;471}472 473static ssize_t474mt7615_ext_mac_addr_write(struct file *file, const char __user *userbuf,475 size_t count, loff_t *ppos)476{477 struct mt7615_dev *dev = file->private_data;478 unsigned long idx = 0;479 u8 addr[ETH_ALEN];480 char buf[32];481 char *p;482 483 if (count > sizeof(buf))484 return -EINVAL;485 486 if (copy_from_user(buf, userbuf, count))487 return -EFAULT;488 489 buf[sizeof(buf) - 1] = '\0';490 491 p = strchr(buf, '=');492 if (p) {493 *p = 0;494 p++;495 496 if (kstrtoul(buf, 0, &idx) || idx > 31)497 return -EINVAL;498 } else {499 idx = 0;500 p = buf;501 }502 503 if (!mac_pton(p, addr))504 return -EINVAL;505 506 if (is_valid_ether_addr(addr)) {507 dev->muar_mask |= BIT(idx);508 } else {509 memset(addr, 0, sizeof(addr));510 dev->muar_mask &= ~BIT(idx);511 }512 513 mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, 1);514 mt76_wr(dev, MT_WF_RMAC_MAR0, get_unaligned_le32(addr));515 mt76_wr(dev, MT_WF_RMAC_MAR1,516 get_unaligned_le16(addr + 4) |517 FIELD_PREP(MT_WF_RMAC_MAR1_IDX, idx * 2) |518 MT_WF_RMAC_MAR1_START |519 MT_WF_RMAC_MAR1_WRITE);520 521 mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, !!dev->muar_mask);522 523 return count;524}525 526static const struct file_operations fops_ext_mac_addr = {527 .open = simple_open,528 .llseek = generic_file_llseek,529 .read = mt7615_ext_mac_addr_read,530 .write = mt7615_ext_mac_addr_write,531 .owner = THIS_MODULE,532};533 534static int535mt7663s_sched_quota_read(struct seq_file *s, void *data)536{537 struct mt7615_dev *dev = dev_get_drvdata(s->private);538 struct mt76_sdio *sdio = &dev->mt76.sdio;539 540 seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota);541 seq_printf(s, "ple_data_quota\t%d\n", sdio->sched.ple_data_quota);542 seq_printf(s, "pse_mcu_quota\t%d\n", sdio->sched.pse_mcu_quota);543 seq_printf(s, "sched_deficit\t%d\n", sdio->sched.deficit);544 545 return 0;546}547 548int mt7615_init_debugfs(struct mt7615_dev *dev)549{550 struct dentry *dir;551 552 dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);553 if (!dir)554 return -ENOMEM;555 556 if (is_mt7615(&dev->mt76))557 debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,558 mt7615_queues_read);559 else560 debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,561 mt76_queues_read);562 debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,563 mt7615_queues_acq);564 debugfs_create_file("ampdu_stat", 0400, dir, dev, &mt7615_ampdu_stat_fops);565 debugfs_create_file("scs", 0600, dir, dev, &fops_scs);566 debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc);567 debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);568 debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);569 debugfs_create_file("idle-timeout", 0600, dir, dev,570 &fops_pm_idle_timeout);571 debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,572 mt7615_pm_stats);573 debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir,574 mt7615_radio_read);575 576 if (is_mt7615(&dev->mt76)) {577 debugfs_create_u32("dfs_hw_pattern", 0400, dir,578 &dev->hw_pattern);579 /* test pattern knobs */580 debugfs_create_u8("pattern_len", 0600, dir,581 &dev->radar_pattern.n_pulses);582 debugfs_create_u32("pulse_period", 0600, dir,583 &dev->radar_pattern.period);584 debugfs_create_u16("pulse_width", 0600, dir,585 &dev->radar_pattern.width);586 debugfs_create_u16("pulse_power", 0600, dir,587 &dev->radar_pattern.power);588 debugfs_create_file("radar_trigger", 0200, dir, dev,589 &fops_radar_pattern);590 }591 592 debugfs_create_file("reset_test", 0200, dir, dev,593 &fops_reset_test);594 debugfs_create_file("ext_mac_addr", 0600, dir, dev, &fops_ext_mac_addr);595 596 debugfs_create_u32("rf_wfidx", 0600, dir, &dev->debugfs_rf_wf);597 debugfs_create_u32("rf_regidx", 0600, dir, &dev->debugfs_rf_reg);598 debugfs_create_file_unsafe("rf_regval", 0600, dir, dev,599 &fops_rf_reg);600 if (is_mt7663(&dev->mt76))601 debugfs_create_file("chip_config", 0600, dir, dev,602 &fops_config);603 if (mt76_is_sdio(&dev->mt76))604 debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir,605 mt7663s_sched_quota_read);606 607 return 0;608}609EXPORT_SYMBOL_GPL(mt7615_init_debugfs);610