0001
0002
0003
0004 #include "mt7921.h"
0005 #include "eeprom.h"
0006
0007 static int
0008 mt7921_reg_set(void *data, u64 val)
0009 {
0010 struct mt7921_dev *dev = data;
0011
0012 mt7921_mutex_acquire(dev);
0013 mt76_wr(dev, dev->mt76.debugfs_reg, val);
0014 mt7921_mutex_release(dev);
0015
0016 return 0;
0017 }
0018
0019 static int
0020 mt7921_reg_get(void *data, u64 *val)
0021 {
0022 struct mt7921_dev *dev = data;
0023
0024 mt7921_mutex_acquire(dev);
0025 *val = mt76_rr(dev, dev->mt76.debugfs_reg);
0026 mt7921_mutex_release(dev);
0027
0028 return 0;
0029 }
0030
0031 DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7921_reg_get, mt7921_reg_set,
0032 "0x%08llx\n");
0033 static int
0034 mt7921_fw_debug_set(void *data, u64 val)
0035 {
0036 struct mt7921_dev *dev = data;
0037
0038 mt7921_mutex_acquire(dev);
0039
0040 dev->fw_debug = (u8)val;
0041 mt7921_mcu_fw_log_2_host(dev, dev->fw_debug);
0042
0043 mt7921_mutex_release(dev);
0044
0045 return 0;
0046 }
0047
0048 static int
0049 mt7921_fw_debug_get(void *data, u64 *val)
0050 {
0051 struct mt7921_dev *dev = data;
0052
0053 *val = dev->fw_debug;
0054
0055 return 0;
0056 }
0057
0058 DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7921_fw_debug_get,
0059 mt7921_fw_debug_set, "%lld\n");
0060
0061 static void
0062 mt7921_ampdu_stat_read_phy(struct mt7921_phy *phy,
0063 struct seq_file *file)
0064 {
0065 struct mt7921_dev *dev = file->private;
0066 int bound[15], range[4], i;
0067
0068 if (!phy)
0069 return;
0070
0071 mt7921_mac_update_mib_stats(phy);
0072
0073
0074 for (i = 0; i < ARRAY_SIZE(range); i++)
0075 range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i));
0076
0077 for (i = 0; i < ARRAY_SIZE(bound); i++)
0078 bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1;
0079
0080 seq_printf(file, "\nPhy0\n");
0081
0082 seq_printf(file, "Length: %8d | ", bound[0]);
0083 for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)
0084 seq_printf(file, "%3d %3d | ", bound[i] + 1, bound[i + 1]);
0085
0086 seq_puts(file, "\nCount: ");
0087 for (i = 0; i < ARRAY_SIZE(bound); i++)
0088 seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i]);
0089 seq_puts(file, "\n");
0090
0091 seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);
0092 }
0093
0094 static int
0095 mt7921_tx_stats_show(struct seq_file *file, void *data)
0096 {
0097 struct mt7921_dev *dev = file->private;
0098 struct mt7921_phy *phy = &dev->phy;
0099 struct mib_stats *mib = &phy->mib;
0100 int i;
0101
0102 mt7921_mutex_acquire(dev);
0103
0104 mt7921_ampdu_stat_read_phy(phy, file);
0105
0106 seq_puts(file, "Tx MSDU stat:\n");
0107 for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
0108 seq_printf(file, "AMSDU pack count of %d MSDU in TXD: %8d ",
0109 i + 1, mib->tx_amsdu[i]);
0110 if (mib->tx_amsdu_cnt)
0111 seq_printf(file, "(%3d%%)\n",
0112 mib->tx_amsdu[i] * 100 / mib->tx_amsdu_cnt);
0113 else
0114 seq_puts(file, "\n");
0115 }
0116
0117 mt7921_mutex_release(dev);
0118
0119 return 0;
0120 }
0121
0122 DEFINE_SHOW_ATTRIBUTE(mt7921_tx_stats);
0123
0124 static int
0125 mt7921_queues_acq(struct seq_file *s, void *data)
0126 {
0127 struct mt7921_dev *dev = dev_get_drvdata(s->private);
0128 int i;
0129
0130 mt7921_mutex_acquire(dev);
0131
0132 for (i = 0; i < 4; i++) {
0133 u32 ctrl, val, qlen = 0;
0134 int j;
0135
0136 val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i));
0137 ctrl = BIT(31) | BIT(11) | (i << 24);
0138
0139 for (j = 0; j < 32; j++) {
0140 if (val & BIT(j))
0141 continue;
0142
0143 mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j);
0144 qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
0145 GENMASK(11, 0));
0146 }
0147 seq_printf(s, "AC%d: queued=%d\n", i, qlen);
0148 }
0149
0150 mt7921_mutex_release(dev);
0151
0152 return 0;
0153 }
0154
0155 static int
0156 mt7921_queues_read(struct seq_file *s, void *data)
0157 {
0158 struct mt7921_dev *dev = dev_get_drvdata(s->private);
0159 struct {
0160 struct mt76_queue *q;
0161 char *queue;
0162 } queue_map[] = {
0163 { dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" },
0164 { dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" },
0165 { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },
0166 };
0167 int i;
0168
0169 for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
0170 struct mt76_queue *q = queue_map[i].q;
0171
0172 if (!q)
0173 continue;
0174
0175 seq_printf(s,
0176 "%s: queued=%d head=%d tail=%d\n",
0177 queue_map[i].queue, q->queued, q->head,
0178 q->tail);
0179 }
0180
0181 return 0;
0182 }
0183
0184 static void
0185 mt7921_seq_puts_array(struct seq_file *file, const char *str,
0186 s8 *val, int len)
0187 {
0188 int i;
0189
0190 seq_printf(file, "%-16s:", str);
0191 for (i = 0; i < len; i++)
0192 if (val[i] == 127)
0193 seq_printf(file, " %6s", "N.A");
0194 else
0195 seq_printf(file, " %6d", val[i]);
0196 seq_puts(file, "\n");
0197 }
0198
0199 #define mt7921_print_txpwr_entry(prefix, rate) \
0200 ({ \
0201 mt7921_seq_puts_array(s, #prefix " (user)", \
0202 txpwr.data[TXPWR_USER].rate, \
0203 ARRAY_SIZE(txpwr.data[TXPWR_USER].rate)); \
0204 mt7921_seq_puts_array(s, #prefix " (eeprom)", \
0205 txpwr.data[TXPWR_EEPROM].rate, \
0206 ARRAY_SIZE(txpwr.data[TXPWR_EEPROM].rate)); \
0207 mt7921_seq_puts_array(s, #prefix " (tmac)", \
0208 txpwr.data[TXPWR_MAC].rate, \
0209 ARRAY_SIZE(txpwr.data[TXPWR_MAC].rate)); \
0210 })
0211
0212 static int
0213 mt7921_txpwr(struct seq_file *s, void *data)
0214 {
0215 struct mt7921_dev *dev = dev_get_drvdata(s->private);
0216 struct mt7921_txpwr txpwr;
0217 int ret;
0218
0219 mt7921_mutex_acquire(dev);
0220 ret = mt7921_get_txpwr_info(dev, &txpwr);
0221 mt7921_mutex_release(dev);
0222
0223 if (ret)
0224 return ret;
0225
0226 seq_printf(s, "Tx power table (channel %d)\n", txpwr.ch);
0227 seq_printf(s, "%-16s %6s %6s %6s %6s\n",
0228 " ", "1m", "2m", "5m", "11m");
0229 mt7921_print_txpwr_entry(CCK, cck);
0230
0231 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
0232 " ", "6m", "9m", "12m", "18m", "24m", "36m",
0233 "48m", "54m");
0234 mt7921_print_txpwr_entry(OFDM, ofdm);
0235
0236 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
0237 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
0238 "mcs6", "mcs7");
0239 mt7921_print_txpwr_entry(HT20, ht20);
0240
0241 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
0242 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
0243 "mcs6", "mcs7", "mcs32");
0244 mt7921_print_txpwr_entry(HT40, ht40);
0245
0246 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
0247 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
0248 "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
0249 mt7921_print_txpwr_entry(VHT20, vht20);
0250 mt7921_print_txpwr_entry(VHT40, vht40);
0251 mt7921_print_txpwr_entry(VHT80, vht80);
0252 mt7921_print_txpwr_entry(VHT160, vht160);
0253 mt7921_print_txpwr_entry(HE26, he26);
0254 mt7921_print_txpwr_entry(HE52, he52);
0255 mt7921_print_txpwr_entry(HE106, he106);
0256 mt7921_print_txpwr_entry(HE242, he242);
0257 mt7921_print_txpwr_entry(HE484, he484);
0258 mt7921_print_txpwr_entry(HE996, he996);
0259 mt7921_print_txpwr_entry(HE996x2, he996x2);
0260
0261 return 0;
0262 }
0263
0264 static int
0265 mt7921_pm_set(void *data, u64 val)
0266 {
0267 struct mt7921_dev *dev = data;
0268 struct mt76_connac_pm *pm = &dev->pm;
0269
0270 if (mt76_is_usb(&dev->mt76))
0271 return -EOPNOTSUPP;
0272
0273 mutex_lock(&dev->mt76.mutex);
0274
0275 if (val == pm->enable_user)
0276 goto out;
0277
0278 if (!pm->enable_user) {
0279 pm->stats.last_wake_event = jiffies;
0280 pm->stats.last_doze_event = jiffies;
0281 }
0282
0283
0284
0285 pm->enable = false;
0286 mt76_connac_pm_wake(&dev->mphy, pm);
0287
0288 pm->enable_user = val;
0289 mt7921_set_runtime_pm(dev);
0290 mt76_connac_power_save_sched(&dev->mphy, pm);
0291 out:
0292 mutex_unlock(&dev->mt76.mutex);
0293
0294 return 0;
0295 }
0296
0297 static int
0298 mt7921_pm_get(void *data, u64 *val)
0299 {
0300 struct mt7921_dev *dev = data;
0301
0302 *val = dev->pm.enable_user;
0303
0304 return 0;
0305 }
0306
0307 DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n");
0308
0309 static int
0310 mt7921_deep_sleep_set(void *data, u64 val)
0311 {
0312 struct mt7921_dev *dev = data;
0313 struct mt76_connac_pm *pm = &dev->pm;
0314 bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR);
0315 bool enable = !!val;
0316
0317 if (mt76_is_usb(&dev->mt76))
0318 return -EOPNOTSUPP;
0319
0320 mt7921_mutex_acquire(dev);
0321 if (pm->ds_enable_user == enable)
0322 goto out;
0323
0324 pm->ds_enable_user = enable;
0325 pm->ds_enable = enable && !monitor;
0326 mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable);
0327 out:
0328 mt7921_mutex_release(dev);
0329
0330 return 0;
0331 }
0332
0333 static int
0334 mt7921_deep_sleep_get(void *data, u64 *val)
0335 {
0336 struct mt7921_dev *dev = data;
0337
0338 *val = dev->pm.ds_enable_user;
0339
0340 return 0;
0341 }
0342
0343 DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7921_deep_sleep_get,
0344 mt7921_deep_sleep_set, "%lld\n");
0345
0346 static int
0347 mt7921_pm_stats(struct seq_file *s, void *data)
0348 {
0349 struct mt7921_dev *dev = dev_get_drvdata(s->private);
0350 struct mt76_connac_pm *pm = &dev->pm;
0351
0352 unsigned long awake_time = pm->stats.awake_time;
0353 unsigned long doze_time = pm->stats.doze_time;
0354
0355 if (!test_bit(MT76_STATE_PM, &dev->mphy.state))
0356 awake_time += jiffies - pm->stats.last_wake_event;
0357 else
0358 doze_time += jiffies - pm->stats.last_doze_event;
0359
0360 seq_printf(s, "awake time: %14u\ndoze time: %15u\n",
0361 jiffies_to_msecs(awake_time),
0362 jiffies_to_msecs(doze_time));
0363
0364 seq_printf(s, "low power wakes: %9d\n", pm->stats.lp_wake);
0365
0366 return 0;
0367 }
0368
0369 static int
0370 mt7921_pm_idle_timeout_set(void *data, u64 val)
0371 {
0372 struct mt7921_dev *dev = data;
0373
0374 dev->pm.idle_timeout = msecs_to_jiffies(val);
0375
0376 return 0;
0377 }
0378
0379 static int
0380 mt7921_pm_idle_timeout_get(void *data, u64 *val)
0381 {
0382 struct mt7921_dev *dev = data;
0383
0384 *val = jiffies_to_msecs(dev->pm.idle_timeout);
0385
0386 return 0;
0387 }
0388
0389 DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7921_pm_idle_timeout_get,
0390 mt7921_pm_idle_timeout_set, "%lld\n");
0391
0392 static int mt7921_chip_reset(void *data, u64 val)
0393 {
0394 struct mt7921_dev *dev = data;
0395 int ret = 0;
0396
0397 switch (val) {
0398 case 1:
0399
0400 mt7921_reset(&dev->mt76);
0401 break;
0402 default:
0403
0404 mt7921_mutex_acquire(dev);
0405 ret = mt76_connac_mcu_chip_config(&dev->mt76);
0406 mt7921_mutex_release(dev);
0407 break;
0408 }
0409
0410 return ret;
0411 }
0412
0413 DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7921_chip_reset, "%lld\n");
0414
0415 static int
0416 mt7921s_sched_quota_read(struct seq_file *s, void *data)
0417 {
0418 struct mt7921_dev *dev = dev_get_drvdata(s->private);
0419 struct mt76_sdio *sdio = &dev->mt76.sdio;
0420
0421 seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota);
0422 seq_printf(s, "ple_data_quota\t%d\n", sdio->sched.ple_data_quota);
0423 seq_printf(s, "pse_mcu_quota\t%d\n", sdio->sched.pse_mcu_quota);
0424 seq_printf(s, "sched_deficit\t%d\n", sdio->sched.deficit);
0425
0426 return 0;
0427 }
0428
0429 int mt7921_init_debugfs(struct mt7921_dev *dev)
0430 {
0431 struct dentry *dir;
0432
0433 dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
0434 if (!dir)
0435 return -ENOMEM;
0436
0437 if (mt76_is_mmio(&dev->mt76))
0438 debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
0439 dir, mt7921_queues_read);
0440 else
0441 debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
0442 dir, mt76_queues_read);
0443
0444 debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
0445 mt7921_queues_acq);
0446 debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
0447 mt7921_txpwr);
0448 debugfs_create_file("tx_stats", 0400, dir, dev, &mt7921_tx_stats_fops);
0449 debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
0450 debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
0451 debugfs_create_file("idle-timeout", 0600, dir, dev,
0452 &fops_pm_idle_timeout);
0453 debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset);
0454 debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
0455 mt7921_pm_stats);
0456 debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds);
0457 if (mt76_is_sdio(&dev->mt76))
0458 debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir,
0459 mt7921s_sched_quota_read);
0460 return 0;
0461 }