1 // SPDX-License-Identifier: ISC 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 4 #include "mt7921.h" 5 #include "eeprom.h" 6 7 static int 8 mt7921_reg_set(void *data, u64 val) 9 { 10 struct mt7921_dev *dev = data; 11 12 mt7921_mutex_acquire(dev); 13 mt76_wr(dev, dev->mt76.debugfs_reg, val); 14 mt7921_mutex_release(dev); 15 16 return 0; 17 } 18 19 static int 20 mt7921_reg_get(void *data, u64 *val) 21 { 22 struct mt7921_dev *dev = data; 23 24 mt7921_mutex_acquire(dev); 25 *val = mt76_rr(dev, dev->mt76.debugfs_reg); 26 mt7921_mutex_release(dev); 27 28 return 0; 29 } 30 31 DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7921_reg_get, mt7921_reg_set, 32 "0x%08llx\n"); 33 static int 34 mt7921_fw_debug_set(void *data, u64 val) 35 { 36 struct mt7921_dev *dev = data; 37 38 mt7921_mutex_acquire(dev); 39 40 dev->fw_debug = (u8)val; 41 mt7921_mcu_fw_log_2_host(dev, dev->fw_debug); 42 43 mt7921_mutex_release(dev); 44 45 return 0; 46 } 47 48 static int 49 mt7921_fw_debug_get(void *data, u64 *val) 50 { 51 struct mt7921_dev *dev = data; 52 53 *val = dev->fw_debug; 54 55 return 0; 56 } 57 58 DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7921_fw_debug_get, 59 mt7921_fw_debug_set, "%lld\n"); 60 61 static void 62 mt7921_ampdu_stat_read_phy(struct mt7921_phy *phy, 63 struct seq_file *file) 64 { 65 struct mt7921_dev *dev = file->private; 66 int bound[15], range[4], i; 67 68 if (!phy) 69 return; 70 71 mt7921_mac_update_mib_stats(phy); 72 73 /* Tx ampdu stat */ 74 for (i = 0; i < ARRAY_SIZE(range); i++) 75 range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i)); 76 77 for (i = 0; i < ARRAY_SIZE(bound); i++) 78 bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1; 79 80 seq_printf(file, "\nPhy0\n"); 81 82 seq_printf(file, "Length: %8d | ", bound[0]); 83 for (i = 0; i < ARRAY_SIZE(bound) - 1; i++) 84 seq_printf(file, "%3d %3d | ", bound[i] + 1, bound[i + 1]); 85 86 seq_puts(file, "\nCount: "); 87 for (i = 0; i < ARRAY_SIZE(bound); i++) 88 seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i]); 89 seq_puts(file, "\n"); 90 91 seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt); 92 } 93 94 static int 95 mt7921_tx_stats_show(struct seq_file *file, void *data) 96 { 97 struct mt7921_dev *dev = file->private; 98 int stat[8], i, n; 99 100 mt7921_mutex_acquire(dev); 101 102 mt7921_ampdu_stat_read_phy(&dev->phy, file); 103 104 /* Tx amsdu info */ 105 seq_puts(file, "Tx MSDU stat:\n"); 106 for (i = 0, n = 0; i < ARRAY_SIZE(stat); i++) { 107 stat[i] = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); 108 n += stat[i]; 109 } 110 111 mt7921_mutex_release(dev); 112 113 for (i = 0; i < ARRAY_SIZE(stat); i++) { 114 seq_printf(file, "AMSDU pack count of %d MSDU in TXD: 0x%x ", 115 i + 1, stat[i]); 116 if (n != 0) 117 seq_printf(file, "(%d%%)\n", stat[i] * 100 / n); 118 else 119 seq_puts(file, "\n"); 120 } 121 122 return 0; 123 } 124 125 DEFINE_SHOW_ATTRIBUTE(mt7921_tx_stats); 126 127 static int 128 mt7921_queues_acq(struct seq_file *s, void *data) 129 { 130 struct mt7921_dev *dev = dev_get_drvdata(s->private); 131 int i; 132 133 mt7921_mutex_acquire(dev); 134 135 for (i = 0; i < 16; i++) { 136 int j, acs = i / 4, index = i % 4; 137 u32 ctrl, val, qlen = 0; 138 139 val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index)); 140 ctrl = BIT(31) | BIT(15) | (acs << 8); 141 142 for (j = 0; j < 32; j++) { 143 if (val & BIT(j)) 144 continue; 145 146 mt76_wr(dev, MT_PLE_FL_Q0_CTRL, 147 ctrl | (j + (index << 5))); 148 qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL, 149 GENMASK(11, 0)); 150 } 151 seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen); 152 } 153 154 mt7921_mutex_release(dev); 155 156 return 0; 157 } 158 159 static int 160 mt7921_queues_read(struct seq_file *s, void *data) 161 { 162 struct mt7921_dev *dev = dev_get_drvdata(s->private); 163 struct { 164 struct mt76_queue *q; 165 char *queue; 166 } queue_map[] = { 167 { dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" }, 168 { dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" }, 169 { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" }, 170 }; 171 int i; 172 173 for (i = 0; i < ARRAY_SIZE(queue_map); i++) { 174 struct mt76_queue *q = queue_map[i].q; 175 176 if (!q) 177 continue; 178 179 seq_printf(s, 180 "%s: queued=%d head=%d tail=%d\n", 181 queue_map[i].queue, q->queued, q->head, 182 q->tail); 183 } 184 185 return 0; 186 } 187 188 static void 189 mt7921_seq_puts_array(struct seq_file *file, const char *str, 190 s8 *val, int len) 191 { 192 int i; 193 194 seq_printf(file, "%-16s:", str); 195 for (i = 0; i < len; i++) 196 if (val[i] == 127) 197 seq_printf(file, " %6s", "N.A"); 198 else 199 seq_printf(file, " %6d", val[i]); 200 seq_puts(file, "\n"); 201 } 202 203 #define mt7921_print_txpwr_entry(prefix, rate) \ 204 ({ \ 205 mt7921_seq_puts_array(s, #prefix " (user)", \ 206 txpwr.data[TXPWR_USER].rate, \ 207 ARRAY_SIZE(txpwr.data[TXPWR_USER].rate)); \ 208 mt7921_seq_puts_array(s, #prefix " (eeprom)", \ 209 txpwr.data[TXPWR_EEPROM].rate, \ 210 ARRAY_SIZE(txpwr.data[TXPWR_EEPROM].rate)); \ 211 mt7921_seq_puts_array(s, #prefix " (tmac)", \ 212 txpwr.data[TXPWR_MAC].rate, \ 213 ARRAY_SIZE(txpwr.data[TXPWR_MAC].rate)); \ 214 }) 215 216 static int 217 mt7921_txpwr(struct seq_file *s, void *data) 218 { 219 struct mt7921_dev *dev = dev_get_drvdata(s->private); 220 struct mt7921_txpwr txpwr; 221 int ret; 222 223 mt7921_mutex_acquire(dev); 224 ret = mt7921_get_txpwr_info(dev, &txpwr); 225 mt7921_mutex_release(dev); 226 227 if (ret) 228 return ret; 229 230 seq_printf(s, "Tx power table (channel %d)\n", txpwr.ch); 231 seq_printf(s, "%-16s %6s %6s %6s %6s\n", 232 " ", "1m", "2m", "5m", "11m"); 233 mt7921_print_txpwr_entry(CCK, cck); 234 235 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n", 236 " ", "6m", "9m", "12m", "18m", "24m", "36m", 237 "48m", "54m"); 238 mt7921_print_txpwr_entry(OFDM, ofdm); 239 240 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n", 241 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", 242 "mcs6", "mcs7"); 243 mt7921_print_txpwr_entry(HT20, ht20); 244 245 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", 246 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", 247 "mcs6", "mcs7", "mcs32"); 248 mt7921_print_txpwr_entry(HT40, ht40); 249 250 seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", 251 " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", 252 "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11"); 253 mt7921_print_txpwr_entry(VHT20, vht20); 254 mt7921_print_txpwr_entry(VHT40, vht40); 255 mt7921_print_txpwr_entry(VHT80, vht80); 256 mt7921_print_txpwr_entry(VHT160, vht160); 257 mt7921_print_txpwr_entry(HE26, he26); 258 mt7921_print_txpwr_entry(HE52, he52); 259 mt7921_print_txpwr_entry(HE106, he106); 260 mt7921_print_txpwr_entry(HE242, he242); 261 mt7921_print_txpwr_entry(HE484, he484); 262 mt7921_print_txpwr_entry(HE996, he996); 263 mt7921_print_txpwr_entry(HE996x2, he996x2); 264 265 return 0; 266 } 267 268 static void 269 mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) 270 { 271 struct mt7921_dev *dev = priv; 272 273 mt7921_mcu_set_beacon_filter(dev, vif, dev->pm.enable); 274 } 275 276 static int 277 mt7921_pm_set(void *data, u64 val) 278 { 279 struct mt7921_dev *dev = data; 280 struct mt76_connac_pm *pm = &dev->pm; 281 282 mt7921_mutex_acquire(dev); 283 284 if (val == pm->enable) 285 goto out; 286 287 if (!pm->enable) { 288 pm->stats.last_wake_event = jiffies; 289 pm->stats.last_doze_event = jiffies; 290 } 291 pm->enable = val; 292 293 ieee80211_iterate_active_interfaces(mt76_hw(dev), 294 IEEE80211_IFACE_ITER_RESUME_ALL, 295 mt7921_pm_interface_iter, dev); 296 297 mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable); 298 299 out: 300 mt7921_mutex_release(dev); 301 302 return 0; 303 } 304 305 static int 306 mt7921_pm_get(void *data, u64 *val) 307 { 308 struct mt7921_dev *dev = data; 309 310 *val = dev->pm.enable; 311 312 return 0; 313 } 314 315 DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n"); 316 317 static int 318 mt7921_deep_sleep_set(void *data, u64 val) 319 { 320 struct mt7921_dev *dev = data; 321 struct mt76_connac_pm *pm = &dev->pm; 322 bool enable = !!val; 323 324 mt7921_mutex_acquire(dev); 325 if (pm->ds_enable != enable) { 326 mt76_connac_mcu_set_deep_sleep(&dev->mt76, enable); 327 pm->ds_enable = enable; 328 } 329 mt7921_mutex_release(dev); 330 331 return 0; 332 } 333 334 static int 335 mt7921_deep_sleep_get(void *data, u64 *val) 336 { 337 struct mt7921_dev *dev = data; 338 339 *val = dev->pm.ds_enable; 340 341 return 0; 342 } 343 344 DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7921_deep_sleep_get, 345 mt7921_deep_sleep_set, "%lld\n"); 346 347 static int 348 mt7921_pm_stats(struct seq_file *s, void *data) 349 { 350 struct mt7921_dev *dev = dev_get_drvdata(s->private); 351 struct mt76_connac_pm *pm = &dev->pm; 352 353 unsigned long awake_time = pm->stats.awake_time; 354 unsigned long doze_time = pm->stats.doze_time; 355 356 if (!test_bit(MT76_STATE_PM, &dev->mphy.state)) 357 awake_time += jiffies - pm->stats.last_wake_event; 358 else 359 doze_time += jiffies - pm->stats.last_doze_event; 360 361 seq_printf(s, "awake time: %14u\ndoze time: %15u\n", 362 jiffies_to_msecs(awake_time), 363 jiffies_to_msecs(doze_time)); 364 365 seq_printf(s, "low power wakes: %9d\n", pm->stats.lp_wake); 366 367 return 0; 368 } 369 370 static int 371 mt7921_pm_idle_timeout_set(void *data, u64 val) 372 { 373 struct mt7921_dev *dev = data; 374 375 dev->pm.idle_timeout = msecs_to_jiffies(val); 376 377 return 0; 378 } 379 380 static int 381 mt7921_pm_idle_timeout_get(void *data, u64 *val) 382 { 383 struct mt7921_dev *dev = data; 384 385 *val = jiffies_to_msecs(dev->pm.idle_timeout); 386 387 return 0; 388 } 389 390 DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7921_pm_idle_timeout_get, 391 mt7921_pm_idle_timeout_set, "%lld\n"); 392 393 static int mt7921_chip_reset(void *data, u64 val) 394 { 395 struct mt7921_dev *dev = data; 396 int ret = 0; 397 398 switch (val) { 399 case 1: 400 /* Reset wifisys directly. */ 401 mt7921_reset(&dev->mt76); 402 break; 403 default: 404 /* Collect the core dump before reset wifisys. */ 405 mt7921_mutex_acquire(dev); 406 ret = mt76_connac_mcu_chip_config(&dev->mt76); 407 mt7921_mutex_release(dev); 408 break; 409 } 410 411 return ret; 412 } 413 414 DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7921_chip_reset, "%lld\n"); 415 416 int mt7921_init_debugfs(struct mt7921_dev *dev) 417 { 418 struct dentry *dir; 419 420 dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval); 421 if (!dir) 422 return -ENOMEM; 423 424 debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, 425 mt7921_queues_read); 426 debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, 427 mt7921_queues_acq); 428 debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir, 429 mt7921_txpwr); 430 debugfs_create_file("tx_stats", 0400, dir, dev, &mt7921_tx_stats_fops); 431 debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug); 432 debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm); 433 debugfs_create_file("idle-timeout", 0600, dir, dev, 434 &fops_pm_idle_timeout); 435 debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset); 436 debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir, 437 mt7921_pm_stats); 438 debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds); 439 440 return 0; 441 } 442