1 // SPDX-License-Identifier: ISC 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 4 #include <linux/relay.h> 5 #include "mt7915.h" 6 #include "eeprom.h" 7 #include "mcu.h" 8 #include "mac.h" 9 10 #define FW_BIN_LOG_MAGIC 0x44e98caf 11 12 /** global debugfs **/ 13 14 struct hw_queue_map { 15 const char *name; 16 u8 index; 17 u8 pid; 18 u8 qid; 19 }; 20 21 static int 22 mt7915_implicit_txbf_set(void *data, u64 val) 23 { 24 struct mt7915_dev *dev = data; 25 26 if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) 27 return -EBUSY; 28 29 dev->ibf = !!val; 30 31 return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE); 32 } 33 34 static int 35 mt7915_implicit_txbf_get(void *data, u64 *val) 36 { 37 struct mt7915_dev *dev = data; 38 39 *val = dev->ibf; 40 41 return 0; 42 } 43 44 DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7915_implicit_txbf_get, 45 mt7915_implicit_txbf_set, "%lld\n"); 46 47 /* test knob of system error recovery */ 48 static ssize_t 49 mt7915_fw_ser_set(struct file *file, const char __user *user_buf, 50 size_t count, loff_t *ppos) 51 { 52 struct mt7915_phy *phy = file->private_data; 53 struct mt7915_dev *dev = phy->dev; 54 bool ext_phy = phy != &dev->phy; 55 char buf[16]; 56 int ret = 0; 57 u16 val; 58 59 if (count >= sizeof(buf)) 60 return -EINVAL; 61 62 if (copy_from_user(buf, user_buf, count)) 63 return -EFAULT; 64 65 if (count && buf[count - 1] == '\n') 66 buf[count - 1] = '\0'; 67 else 68 buf[count] = '\0'; 69 70 if (kstrtou16(buf, 0, &val)) 71 return -EINVAL; 72 73 switch (val) { 74 case SER_QUERY: 75 /* grab firmware SER stats */ 76 ret = mt7915_mcu_set_ser(dev, 0, 0, ext_phy); 77 break; 78 case SER_SET_RECOVER_L1: 79 case SER_SET_RECOVER_L2: 80 case SER_SET_RECOVER_L3_RX_ABORT: 81 case SER_SET_RECOVER_L3_TX_ABORT: 82 case SER_SET_RECOVER_L3_TX_DISABLE: 83 case SER_SET_RECOVER_L3_BF: 84 ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), ext_phy); 85 if (ret) 86 return ret; 87 88 ret = mt7915_mcu_set_ser(dev, SER_RECOVER, val, ext_phy); 89 break; 90 default: 91 break; 92 } 93 94 return ret ? ret : count; 95 } 96 97 static ssize_t 98 mt7915_fw_ser_get(struct file *file, char __user *user_buf, 99 size_t count, loff_t *ppos) 100 { 101 struct mt7915_phy *phy = file->private_data; 102 struct mt7915_dev *dev = phy->dev; 103 char *buff; 104 int desc = 0; 105 ssize_t ret; 106 static const size_t bufsz = 400; 107 108 buff = kmalloc(bufsz, GFP_KERNEL); 109 if (!buff) 110 return -ENOMEM; 111 112 desc += scnprintf(buff + desc, bufsz - desc, 113 "::E R , SER_STATUS = 0x%08x\n", 114 mt76_rr(dev, MT_SWDEF_SER_STATS)); 115 desc += scnprintf(buff + desc, bufsz - desc, 116 "::E R , SER_PLE_ERR = 0x%08x\n", 117 mt76_rr(dev, MT_SWDEF_PLE_STATS)); 118 desc += scnprintf(buff + desc, bufsz - desc, 119 "::E R , SER_PLE_ERR_1 = 0x%08x\n", 120 mt76_rr(dev, MT_SWDEF_PLE1_STATS)); 121 desc += scnprintf(buff + desc, bufsz - desc, 122 "::E R , SER_PLE_ERR_AMSDU = 0x%08x\n", 123 mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATS)); 124 desc += scnprintf(buff + desc, bufsz - desc, 125 "::E R , SER_PSE_ERR = 0x%08x\n", 126 mt76_rr(dev, MT_SWDEF_PSE_STATS)); 127 desc += scnprintf(buff + desc, bufsz - desc, 128 "::E R , SER_PSE_ERR_1 = 0x%08x\n", 129 mt76_rr(dev, MT_SWDEF_PSE1_STATS)); 130 desc += scnprintf(buff + desc, bufsz - desc, 131 "::E R , SER_LMAC_WISR6_B0 = 0x%08x\n", 132 mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATS)); 133 desc += scnprintf(buff + desc, bufsz - desc, 134 "::E R , SER_LMAC_WISR6_B1 = 0x%08x\n", 135 mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATS)); 136 desc += scnprintf(buff + desc, bufsz - desc, 137 "::E R , SER_LMAC_WISR7_B0 = 0x%08x\n", 138 mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATS)); 139 desc += scnprintf(buff + desc, bufsz - desc, 140 "::E R , SER_LMAC_WISR7_B1 = 0x%08x\n", 141 mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS)); 142 143 ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); 144 kfree(buff); 145 return ret; 146 } 147 148 static const struct file_operations mt7915_fw_ser_ops = { 149 .write = mt7915_fw_ser_set, 150 .read = mt7915_fw_ser_get, 151 .open = simple_open, 152 .llseek = default_llseek, 153 }; 154 155 static int 156 mt7915_radar_trigger(void *data, u64 val) 157 { 158 struct mt7915_dev *dev = data; 159 160 if (val > MT_RX_SEL2) 161 return -EINVAL; 162 163 return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_RADAR_EMULATE, 164 val, 0, 0); 165 } 166 167 DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL, 168 mt7915_radar_trigger, "%lld\n"); 169 170 static int 171 mt7915_muru_debug_set(void *data, u64 val) 172 { 173 struct mt7915_dev *dev = data; 174 175 dev->muru_debug = val; 176 mt7915_mcu_muru_debug_set(dev, dev->muru_debug); 177 178 return 0; 179 } 180 181 static int 182 mt7915_muru_debug_get(void *data, u64 *val) 183 { 184 struct mt7915_dev *dev = data; 185 186 *val = dev->muru_debug; 187 188 return 0; 189 } 190 191 DEFINE_DEBUGFS_ATTRIBUTE(fops_muru_debug, mt7915_muru_debug_get, 192 mt7915_muru_debug_set, "%lld\n"); 193 194 static int mt7915_muru_stats_show(struct seq_file *file, void *data) 195 { 196 struct mt7915_phy *phy = file->private; 197 struct mt7915_dev *dev = phy->dev; 198 struct mt7915_mcu_muru_stats mu_stats = {}; 199 static const char * const dl_non_he_type[] = { 200 "CCK", "OFDM", "HT MIX", "HT GF", 201 "VHT SU", "VHT 2MU", "VHT 3MU", "VHT 4MU" 202 }; 203 static const char * const dl_he_type[] = { 204 "HE SU", "HE EXT", "HE 2MU", "HE 3MU", "HE 4MU", 205 "HE 2RU", "HE 3RU", "HE 4RU", "HE 5-8RU", "HE 9-16RU", 206 "HE >16RU" 207 }; 208 static const char * const ul_he_type[] = { 209 "HE 2MU", "HE 3MU", "HE 4MU", "HE SU", "HE 2RU", 210 "HE 3RU", "HE 4RU", "HE 5-8RU", "HE 9-16RU", "HE >16RU" 211 }; 212 int ret, i; 213 u64 total_ppdu_cnt, sub_total_cnt; 214 215 if (!dev->muru_debug) { 216 seq_puts(file, "Please enable muru_debug first.\n"); 217 return 0; 218 } 219 220 mutex_lock(&dev->mt76.mutex); 221 222 ret = mt7915_mcu_muru_debug_get(phy, &mu_stats); 223 if (ret) 224 goto exit; 225 226 /* Non-HE Downlink*/ 227 seq_puts(file, "[Non-HE]\nDownlink\nData Type: "); 228 229 for (i = 0; i < 5; i++) 230 seq_printf(file, "%8s | ", dl_non_he_type[i]); 231 232 #define __dl_u32(s) le32_to_cpu(mu_stats.dl.s) 233 seq_puts(file, "\nTotal Count:"); 234 seq_printf(file, "%8u | %8u | %8u | %8u | %8u | ", 235 __dl_u32(cck_cnt), 236 __dl_u32(ofdm_cnt), 237 __dl_u32(htmix_cnt), 238 __dl_u32(htgf_cnt), 239 __dl_u32(vht_su_cnt)); 240 241 seq_puts(file, "\nDownlink MU-MIMO\nData Type: "); 242 243 for (i = 5; i < 8; i++) 244 seq_printf(file, "%8s | ", dl_non_he_type[i]); 245 246 seq_puts(file, "\nTotal Count:"); 247 seq_printf(file, "%8u | %8u | %8u | ", 248 __dl_u32(vht_2mu_cnt), 249 __dl_u32(vht_3mu_cnt), 250 __dl_u32(vht_4mu_cnt)); 251 252 sub_total_cnt = __dl_u32(vht_2mu_cnt) + 253 __dl_u32(vht_3mu_cnt) + 254 __dl_u32(vht_4mu_cnt); 255 256 seq_printf(file, "\nTotal non-HE MU-MIMO DL PPDU count: %lld", 257 sub_total_cnt); 258 259 total_ppdu_cnt = sub_total_cnt + 260 __dl_u32(cck_cnt) + 261 __dl_u32(ofdm_cnt) + 262 __dl_u32(htmix_cnt) + 263 __dl_u32(htgf_cnt) + 264 __dl_u32(vht_su_cnt); 265 266 seq_printf(file, "\nAll non-HE DL PPDU count: %lld", total_ppdu_cnt); 267 268 /* HE Downlink */ 269 seq_puts(file, "\n\n[HE]\nDownlink\nData Type: "); 270 271 for (i = 0; i < 2; i++) 272 seq_printf(file, "%8s | ", dl_he_type[i]); 273 274 seq_puts(file, "\nTotal Count:"); 275 seq_printf(file, "%8u | %8u | ", 276 __dl_u32(he_su_cnt), 277 __dl_u32(he_ext_su_cnt)); 278 279 seq_puts(file, "\nDownlink MU-MIMO\nData Type: "); 280 281 for (i = 2; i < 5; i++) 282 seq_printf(file, "%8s | ", dl_he_type[i]); 283 284 seq_puts(file, "\nTotal Count:"); 285 seq_printf(file, "%8u | %8u | %8u | ", 286 __dl_u32(he_2mu_cnt), 287 __dl_u32(he_3mu_cnt), 288 __dl_u32(he_4mu_cnt)); 289 290 seq_puts(file, "\nDownlink OFDMA\nData Type: "); 291 292 for (i = 5; i < 11; i++) 293 seq_printf(file, "%8s | ", dl_he_type[i]); 294 295 seq_puts(file, "\nTotal Count:"); 296 seq_printf(file, "%8u | %8u | %8u | %8u | %9u | %8u | ", 297 __dl_u32(he_2ru_cnt), 298 __dl_u32(he_3ru_cnt), 299 __dl_u32(he_4ru_cnt), 300 __dl_u32(he_5to8ru_cnt), 301 __dl_u32(he_9to16ru_cnt), 302 __dl_u32(he_gtr16ru_cnt)); 303 304 sub_total_cnt = __dl_u32(he_2mu_cnt) + 305 __dl_u32(he_3mu_cnt) + 306 __dl_u32(he_4mu_cnt); 307 total_ppdu_cnt = sub_total_cnt; 308 309 seq_printf(file, "\nTotal HE MU-MIMO DL PPDU count: %lld", 310 sub_total_cnt); 311 312 sub_total_cnt = __dl_u32(he_2ru_cnt) + 313 __dl_u32(he_3ru_cnt) + 314 __dl_u32(he_4ru_cnt) + 315 __dl_u32(he_5to8ru_cnt) + 316 __dl_u32(he_9to16ru_cnt) + 317 __dl_u32(he_gtr16ru_cnt); 318 total_ppdu_cnt += sub_total_cnt; 319 320 seq_printf(file, "\nTotal HE OFDMA DL PPDU count: %lld", 321 sub_total_cnt); 322 323 total_ppdu_cnt += __dl_u32(he_su_cnt) + 324 __dl_u32(he_ext_su_cnt); 325 326 seq_printf(file, "\nAll HE DL PPDU count: %lld", total_ppdu_cnt); 327 #undef __dl_u32 328 329 /* HE Uplink */ 330 seq_puts(file, "\n\nUplink"); 331 seq_puts(file, "\nTrigger-based Uplink MU-MIMO\nData Type: "); 332 333 for (i = 0; i < 3; i++) 334 seq_printf(file, "%8s | ", ul_he_type[i]); 335 336 #define __ul_u32(s) le32_to_cpu(mu_stats.ul.s) 337 seq_puts(file, "\nTotal Count:"); 338 seq_printf(file, "%8u | %8u | %8u | ", 339 __ul_u32(hetrig_2mu_cnt), 340 __ul_u32(hetrig_3mu_cnt), 341 __ul_u32(hetrig_4mu_cnt)); 342 343 seq_puts(file, "\nTrigger-based Uplink OFDMA\nData Type: "); 344 345 for (i = 3; i < 10; i++) 346 seq_printf(file, "%8s | ", ul_he_type[i]); 347 348 seq_puts(file, "\nTotal Count:"); 349 seq_printf(file, "%8u | %8u | %8u | %8u | %8u | %9u | %7u | ", 350 __ul_u32(hetrig_su_cnt), 351 __ul_u32(hetrig_2ru_cnt), 352 __ul_u32(hetrig_3ru_cnt), 353 __ul_u32(hetrig_4ru_cnt), 354 __ul_u32(hetrig_5to8ru_cnt), 355 __ul_u32(hetrig_9to16ru_cnt), 356 __ul_u32(hetrig_gtr16ru_cnt)); 357 358 sub_total_cnt = __ul_u32(hetrig_2mu_cnt) + 359 __ul_u32(hetrig_3mu_cnt) + 360 __ul_u32(hetrig_4mu_cnt); 361 total_ppdu_cnt = sub_total_cnt; 362 363 seq_printf(file, "\nTotal HE MU-MIMO UL TB PPDU count: %lld", 364 sub_total_cnt); 365 366 sub_total_cnt = __ul_u32(hetrig_2ru_cnt) + 367 __ul_u32(hetrig_3ru_cnt) + 368 __ul_u32(hetrig_4ru_cnt) + 369 __ul_u32(hetrig_5to8ru_cnt) + 370 __ul_u32(hetrig_9to16ru_cnt) + 371 __ul_u32(hetrig_gtr16ru_cnt); 372 total_ppdu_cnt += sub_total_cnt; 373 374 seq_printf(file, "\nTotal HE OFDMA UL TB PPDU count: %lld", 375 sub_total_cnt); 376 377 total_ppdu_cnt += __ul_u32(hetrig_su_cnt); 378 379 seq_printf(file, "\nAll HE UL TB PPDU count: %lld\n", total_ppdu_cnt); 380 #undef __ul_u32 381 382 exit: 383 mutex_unlock(&dev->mt76.mutex); 384 385 return ret; 386 } 387 DEFINE_SHOW_ATTRIBUTE(mt7915_muru_stats); 388 389 static int 390 mt7915_rdd_monitor(struct seq_file *s, void *data) 391 { 392 struct mt7915_dev *dev = dev_get_drvdata(s->private); 393 struct cfg80211_chan_def *chandef = &dev->rdd2_chandef; 394 const char *bw; 395 int ret = 0; 396 397 mutex_lock(&dev->mt76.mutex); 398 399 if (!cfg80211_chandef_valid(chandef)) { 400 ret = -EINVAL; 401 goto out; 402 } 403 404 if (!dev->rdd2_phy) { 405 seq_puts(s, "not running\n"); 406 goto out; 407 } 408 409 switch (chandef->width) { 410 case NL80211_CHAN_WIDTH_40: 411 bw = "40"; 412 break; 413 case NL80211_CHAN_WIDTH_80: 414 bw = "80"; 415 break; 416 case NL80211_CHAN_WIDTH_160: 417 bw = "160"; 418 break; 419 case NL80211_CHAN_WIDTH_80P80: 420 bw = "80P80"; 421 break; 422 default: 423 bw = "20"; 424 break; 425 } 426 427 seq_printf(s, "channel %d (%d MHz) width %s MHz center1: %d MHz\n", 428 chandef->chan->hw_value, chandef->chan->center_freq, 429 bw, chandef->center_freq1); 430 out: 431 mutex_unlock(&dev->mt76.mutex); 432 433 return ret; 434 } 435 436 static int 437 mt7915_fw_debug_wm_set(void *data, u64 val) 438 { 439 struct mt7915_dev *dev = data; 440 enum { 441 DEBUG_TXCMD = 62, 442 DEBUG_CMD_RPT_TX, 443 DEBUG_CMD_RPT_TRIG, 444 DEBUG_SPL, 445 DEBUG_RPT_RX, 446 } debug; 447 bool tx, rx, en; 448 int ret; 449 450 dev->fw.debug_wm = val ? MCU_FW_LOG_TO_HOST : 0; 451 452 if (dev->fw.debug_bin) 453 val = 16; 454 else 455 val = dev->fw.debug_wm; 456 457 tx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(1)); 458 rx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(2)); 459 en = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(0)); 460 461 ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, val); 462 if (ret) 463 goto out; 464 465 for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RX; debug++) { 466 if (debug == DEBUG_RPT_RX) 467 val = en && rx; 468 else 469 val = en && tx; 470 471 ret = mt7915_mcu_fw_dbg_ctrl(dev, debug, val); 472 if (ret) 473 goto out; 474 } 475 476 /* WM CPU info record control */ 477 mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0)); 478 mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw.debug_wm); 479 mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5)); 480 mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5)); 481 482 out: 483 if (ret) 484 dev->fw.debug_wm = 0; 485 486 return ret; 487 } 488 489 static int 490 mt7915_fw_debug_wm_get(void *data, u64 *val) 491 { 492 struct mt7915_dev *dev = data; 493 494 *val = dev->fw.debug_wm; 495 496 return 0; 497 } 498 499 DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_wm, mt7915_fw_debug_wm_get, 500 mt7915_fw_debug_wm_set, "%lld\n"); 501 502 static int 503 mt7915_fw_debug_wa_set(void *data, u64 val) 504 { 505 struct mt7915_dev *dev = data; 506 int ret; 507 508 dev->fw.debug_wa = val ? MCU_FW_LOG_TO_HOST : 0; 509 510 ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, dev->fw.debug_wa); 511 if (ret) 512 goto out; 513 514 ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), 515 MCU_WA_PARAM_PDMA_RX, !!dev->fw.debug_wa, 0); 516 out: 517 if (ret) 518 dev->fw.debug_wa = 0; 519 520 return ret; 521 } 522 523 static int 524 mt7915_fw_debug_wa_get(void *data, u64 *val) 525 { 526 struct mt7915_dev *dev = data; 527 528 *val = dev->fw.debug_wa; 529 530 return 0; 531 } 532 533 DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_wa, mt7915_fw_debug_wa_get, 534 mt7915_fw_debug_wa_set, "%lld\n"); 535 536 static struct dentry * 537 create_buf_file_cb(const char *filename, struct dentry *parent, umode_t mode, 538 struct rchan_buf *buf, int *is_global) 539 { 540 struct dentry *f; 541 542 f = debugfs_create_file("fwlog_data", mode, parent, buf, 543 &relay_file_operations); 544 if (IS_ERR(f)) 545 return NULL; 546 547 *is_global = 1; 548 549 return f; 550 } 551 552 static int 553 remove_buf_file_cb(struct dentry *f) 554 { 555 debugfs_remove(f); 556 557 return 0; 558 } 559 560 static int 561 mt7915_fw_debug_bin_set(void *data, u64 val) 562 { 563 static struct rchan_callbacks relay_cb = { 564 .create_buf_file = create_buf_file_cb, 565 .remove_buf_file = remove_buf_file_cb, 566 }; 567 struct mt7915_dev *dev = data; 568 569 if (!dev->relay_fwlog) 570 dev->relay_fwlog = relay_open("fwlog_data", dev->debugfs_dir, 571 1500, 512, &relay_cb, NULL); 572 if (!dev->relay_fwlog) 573 return -ENOMEM; 574 575 dev->fw.debug_bin = val; 576 577 relay_reset(dev->relay_fwlog); 578 579 return mt7915_fw_debug_wm_set(dev, dev->fw.debug_wm); 580 } 581 582 static int 583 mt7915_fw_debug_bin_get(void *data, u64 *val) 584 { 585 struct mt7915_dev *dev = data; 586 587 *val = dev->fw.debug_bin; 588 589 return 0; 590 } 591 592 DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_bin, mt7915_fw_debug_bin_get, 593 mt7915_fw_debug_bin_set, "%lld\n"); 594 595 static int 596 mt7915_fw_util_wm_show(struct seq_file *file, void *data) 597 { 598 struct mt7915_dev *dev = file->private; 599 600 seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WM_MCU_PC)); 601 seq_printf(file, "Exception state: 0x%x\n", 602 is_mt7915(&dev->mt76) ? 603 (u32)mt76_get_field(dev, MT_FW_EXCEPTION, GENMASK(15, 8)) : 604 (u32)mt76_get_field(dev, MT_FW_EXCEPTION, GENMASK(7, 0))); 605 606 if (dev->fw.debug_wm) { 607 seq_printf(file, "Busy: %u%% Peak busy: %u%%\n", 608 mt76_rr(dev, MT_CPU_UTIL_BUSY_PCT), 609 mt76_rr(dev, MT_CPU_UTIL_PEAK_BUSY_PCT)); 610 seq_printf(file, "Idle count: %u Peak idle count: %u\n", 611 mt76_rr(dev, MT_CPU_UTIL_IDLE_CNT), 612 mt76_rr(dev, MT_CPU_UTIL_PEAK_IDLE_CNT)); 613 } 614 615 return 0; 616 } 617 618 DEFINE_SHOW_ATTRIBUTE(mt7915_fw_util_wm); 619 620 static int 621 mt7915_fw_util_wa_show(struct seq_file *file, void *data) 622 { 623 struct mt7915_dev *dev = file->private; 624 625 seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WA_MCU_PC)); 626 627 if (dev->fw.debug_wa) 628 return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(QUERY), 629 MCU_WA_PARAM_CPU_UTIL, 0, 0); 630 631 return 0; 632 } 633 634 DEFINE_SHOW_ATTRIBUTE(mt7915_fw_util_wa); 635 636 static void 637 mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy, 638 struct seq_file *file) 639 { 640 struct mt7915_dev *dev = phy->dev; 641 bool ext_phy = phy != &dev->phy; 642 int bound[15], range[4], i, n; 643 644 /* Tx ampdu stat */ 645 for (i = 0; i < ARRAY_SIZE(range); i++) 646 range[i] = mt76_rr(dev, MT_MIB_ARNG(phy->band_idx, i)); 647 648 for (i = 0; i < ARRAY_SIZE(bound); i++) 649 bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1; 650 651 seq_printf(file, "\nPhy %d, Phy band %d\n", ext_phy, phy->band_idx); 652 653 seq_printf(file, "Length: %8d | ", bound[0]); 654 for (i = 0; i < ARRAY_SIZE(bound) - 1; i++) 655 seq_printf(file, "%3d -%3d | ", 656 bound[i] + 1, bound[i + 1]); 657 658 seq_puts(file, "\nCount: "); 659 n = phy->band_idx ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; 660 for (i = 0; i < ARRAY_SIZE(bound); i++) 661 seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i + n]); 662 seq_puts(file, "\n"); 663 664 seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt); 665 } 666 667 static void 668 mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s) 669 { 670 static const char * const bw[] = { 671 "BW20", "BW40", "BW80", "BW160" 672 }; 673 struct mib_stats *mib = &phy->mib; 674 675 /* Tx Beamformer monitor */ 676 seq_puts(s, "\nTx Beamformer applied PPDU counts: "); 677 678 seq_printf(s, "iBF: %d, eBF: %d\n", 679 mib->tx_bf_ibf_ppdu_cnt, 680 mib->tx_bf_ebf_ppdu_cnt); 681 682 /* Tx Beamformer Rx feedback monitor */ 683 seq_puts(s, "Tx Beamformer Rx feedback statistics: "); 684 685 seq_printf(s, "All: %d, HE: %d, VHT: %d, HT: %d, ", 686 mib->tx_bf_rx_fb_all_cnt, 687 mib->tx_bf_rx_fb_he_cnt, 688 mib->tx_bf_rx_fb_vht_cnt, 689 mib->tx_bf_rx_fb_ht_cnt); 690 691 seq_printf(s, "%s, NC: %d, NR: %d\n", 692 bw[mib->tx_bf_rx_fb_bw], 693 mib->tx_bf_rx_fb_nc_cnt, 694 mib->tx_bf_rx_fb_nr_cnt); 695 696 /* Tx Beamformee Rx NDPA & Tx feedback report */ 697 seq_printf(s, "Tx Beamformee successful feedback frames: %d\n", 698 mib->tx_bf_fb_cpl_cnt); 699 seq_printf(s, "Tx Beamformee feedback triggered counts: %d\n", 700 mib->tx_bf_fb_trig_cnt); 701 702 /* Tx SU & MU counters */ 703 seq_printf(s, "Tx multi-user Beamforming counts: %d\n", 704 mib->tx_bf_cnt); 705 seq_printf(s, "Tx multi-user MPDU counts: %d\n", mib->tx_mu_mpdu_cnt); 706 seq_printf(s, "Tx multi-user successful MPDU counts: %d\n", 707 mib->tx_mu_acked_mpdu_cnt); 708 seq_printf(s, "Tx single-user successful MPDU counts: %d\n", 709 mib->tx_su_acked_mpdu_cnt); 710 711 seq_puts(s, "\n"); 712 } 713 714 static int 715 mt7915_tx_stats_show(struct seq_file *file, void *data) 716 { 717 struct mt7915_phy *phy = file->private; 718 struct mt7915_dev *dev = phy->dev; 719 struct mib_stats *mib = &phy->mib; 720 int i; 721 722 mutex_lock(&dev->mt76.mutex); 723 724 mt7915_ampdu_stat_read_phy(phy, file); 725 mt7915_mac_update_stats(phy); 726 mt7915_txbf_stat_read_phy(phy, file); 727 728 /* Tx amsdu info */ 729 seq_puts(file, "Tx MSDU statistics:\n"); 730 for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { 731 seq_printf(file, "AMSDU pack count of %d MSDU in TXD: %8d ", 732 i + 1, mib->tx_amsdu[i]); 733 if (mib->tx_amsdu_cnt) 734 seq_printf(file, "(%3d%%)\n", 735 mib->tx_amsdu[i] * 100 / mib->tx_amsdu_cnt); 736 else 737 seq_puts(file, "\n"); 738 } 739 740 mutex_unlock(&dev->mt76.mutex); 741 742 return 0; 743 } 744 745 DEFINE_SHOW_ATTRIBUTE(mt7915_tx_stats); 746 747 static void 748 mt7915_hw_queue_read(struct seq_file *s, u32 size, 749 const struct hw_queue_map *map) 750 { 751 struct mt7915_phy *phy = s->private; 752 struct mt7915_dev *dev = phy->dev; 753 u32 i, val; 754 755 val = mt76_rr(dev, MT_FL_Q_EMPTY); 756 for (i = 0; i < size; i++) { 757 u32 ctrl, head, tail, queued; 758 759 if (val & BIT(map[i].index)) 760 continue; 761 762 ctrl = BIT(31) | (map[i].pid << 10) | (map[i].qid << 24); 763 mt76_wr(dev, MT_FL_Q0_CTRL, ctrl); 764 765 head = mt76_get_field(dev, MT_FL_Q2_CTRL, 766 GENMASK(11, 0)); 767 tail = mt76_get_field(dev, MT_FL_Q2_CTRL, 768 GENMASK(27, 16)); 769 queued = mt76_get_field(dev, MT_FL_Q3_CTRL, 770 GENMASK(11, 0)); 771 772 seq_printf(s, "\t%s: ", map[i].name); 773 seq_printf(s, "queued:0x%03x head:0x%03x tail:0x%03x\n", 774 queued, head, tail); 775 } 776 } 777 778 static void 779 mt7915_sta_hw_queue_read(void *data, struct ieee80211_sta *sta) 780 { 781 struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 782 struct mt7915_dev *dev = msta->vif->phy->dev; 783 struct seq_file *s = data; 784 u8 ac; 785 786 for (ac = 0; ac < 4; ac++) { 787 u32 qlen, ctrl, val; 788 u32 idx = msta->wcid.idx >> 5; 789 u8 offs = msta->wcid.idx & GENMASK(4, 0); 790 791 ctrl = BIT(31) | BIT(11) | (ac << 24); 792 val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx)); 793 794 if (val & BIT(offs)) 795 continue; 796 797 mt76_wr(dev, MT_FL_Q0_CTRL, ctrl | msta->wcid.idx); 798 qlen = mt76_get_field(dev, MT_FL_Q3_CTRL, 799 GENMASK(11, 0)); 800 seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n", 801 sta->addr, msta->wcid.idx, 802 msta->vif->mt76.wmm_idx, ac, qlen); 803 } 804 } 805 806 static int 807 mt7915_hw_queues_show(struct seq_file *file, void *data) 808 { 809 struct mt7915_phy *phy = file->private; 810 struct mt7915_dev *dev = phy->dev; 811 static const struct hw_queue_map ple_queue_map[] = { 812 { "CPU_Q0", 0, 1, MT_CTX0 }, 813 { "CPU_Q1", 1, 1, MT_CTX0 + 1 }, 814 { "CPU_Q2", 2, 1, MT_CTX0 + 2 }, 815 { "CPU_Q3", 3, 1, MT_CTX0 + 3 }, 816 { "ALTX_Q0", 8, 2, MT_LMAC_ALTX0 }, 817 { "BMC_Q0", 9, 2, MT_LMAC_BMC0 }, 818 { "BCN_Q0", 10, 2, MT_LMAC_BCN0 }, 819 { "PSMP_Q0", 11, 2, MT_LMAC_PSMP0 }, 820 { "ALTX_Q1", 12, 2, MT_LMAC_ALTX0 + 4 }, 821 { "BMC_Q1", 13, 2, MT_LMAC_BMC0 + 4 }, 822 { "BCN_Q1", 14, 2, MT_LMAC_BCN0 + 4 }, 823 { "PSMP_Q1", 15, 2, MT_LMAC_PSMP0 + 4 }, 824 }; 825 static const struct hw_queue_map pse_queue_map[] = { 826 { "CPU Q0", 0, 1, MT_CTX0 }, 827 { "CPU Q1", 1, 1, MT_CTX0 + 1 }, 828 { "CPU Q2", 2, 1, MT_CTX0 + 2 }, 829 { "CPU Q3", 3, 1, MT_CTX0 + 3 }, 830 { "HIF_Q0", 8, 0, MT_HIF0 }, 831 { "HIF_Q1", 9, 0, MT_HIF0 + 1 }, 832 { "HIF_Q2", 10, 0, MT_HIF0 + 2 }, 833 { "HIF_Q3", 11, 0, MT_HIF0 + 3 }, 834 { "HIF_Q4", 12, 0, MT_HIF0 + 4 }, 835 { "HIF_Q5", 13, 0, MT_HIF0 + 5 }, 836 { "LMAC_Q", 16, 2, 0 }, 837 { "MDP_TXQ", 17, 2, 1 }, 838 { "MDP_RXQ", 18, 2, 2 }, 839 { "SEC_TXQ", 19, 2, 3 }, 840 { "SEC_RXQ", 20, 2, 4 }, 841 }; 842 u32 val, head, tail; 843 844 /* ple queue */ 845 val = mt76_rr(dev, MT_PLE_FREEPG_CNT); 846 head = mt76_get_field(dev, MT_PLE_FREEPG_HEAD_TAIL, GENMASK(11, 0)); 847 tail = mt76_get_field(dev, MT_PLE_FREEPG_HEAD_TAIL, GENMASK(27, 16)); 848 seq_puts(file, "PLE page info:\n"); 849 seq_printf(file, 850 "\tTotal free page: 0x%08x head: 0x%03x tail: 0x%03x\n", 851 val, head, tail); 852 853 val = mt76_rr(dev, MT_PLE_PG_HIF_GROUP); 854 head = mt76_get_field(dev, MT_PLE_HIF_PG_INFO, GENMASK(11, 0)); 855 tail = mt76_get_field(dev, MT_PLE_HIF_PG_INFO, GENMASK(27, 16)); 856 seq_printf(file, "\tHIF free page: 0x%03x res: 0x%03x used: 0x%03x\n", 857 val, head, tail); 858 859 seq_puts(file, "PLE non-empty queue info:\n"); 860 mt7915_hw_queue_read(file, ARRAY_SIZE(ple_queue_map), 861 &ple_queue_map[0]); 862 863 /* iterate per-sta ple queue */ 864 ieee80211_iterate_stations_atomic(phy->mt76->hw, 865 mt7915_sta_hw_queue_read, file); 866 /* pse queue */ 867 seq_puts(file, "PSE non-empty queue info:\n"); 868 mt7915_hw_queue_read(file, ARRAY_SIZE(pse_queue_map), 869 &pse_queue_map[0]); 870 871 return 0; 872 } 873 874 DEFINE_SHOW_ATTRIBUTE(mt7915_hw_queues); 875 876 static int 877 mt7915_xmit_queues_show(struct seq_file *file, void *data) 878 { 879 struct mt7915_phy *phy = file->private; 880 struct mt7915_dev *dev = phy->dev; 881 struct { 882 struct mt76_queue *q; 883 char *queue; 884 } queue_map[] = { 885 { phy->mt76->q_tx[MT_TXQ_BE], " MAIN" }, 886 { dev->mt76.q_mcu[MT_MCUQ_WM], " MCUWM" }, 887 { dev->mt76.q_mcu[MT_MCUQ_WA], " MCUWA" }, 888 { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWDL" }, 889 }; 890 int i; 891 892 seq_puts(file, " queue | hw-queued | head | tail |\n"); 893 for (i = 0; i < ARRAY_SIZE(queue_map); i++) { 894 struct mt76_queue *q = queue_map[i].q; 895 896 if (!q) 897 continue; 898 899 seq_printf(file, " %s | %9d | %9d | %9d |\n", 900 queue_map[i].queue, q->queued, q->head, 901 q->tail); 902 } 903 904 return 0; 905 } 906 907 DEFINE_SHOW_ATTRIBUTE(mt7915_xmit_queues); 908 909 static int 910 mt7915_rate_txpower_show(struct seq_file *file, void *data) 911 { 912 static const char * const sku_group_name[] = { 913 "CCK", "OFDM", "HT20", "HT40", 914 "VHT20", "VHT40", "VHT80", "VHT160", 915 "RU26", "RU52", "RU106", "RU242/SU20", 916 "RU484/SU40", "RU996/SU80", "RU2x996/SU160" 917 }; 918 struct mt7915_phy *phy = file->private; 919 s8 txpower[MT7915_SKU_RATE_NUM], *buf; 920 int i; 921 922 seq_printf(file, "\nBand %d\n", phy != &phy->dev->phy); 923 mt7915_mcu_get_txpower_sku(phy, txpower, sizeof(txpower)); 924 for (i = 0, buf = txpower; i < ARRAY_SIZE(mt7915_sku_group_len); i++) { 925 u8 mcs_num = mt7915_sku_group_len[i]; 926 927 if (i >= SKU_VHT_BW20 && i <= SKU_VHT_BW160) 928 mcs_num = 10; 929 930 mt76_seq_puts_array(file, sku_group_name[i], buf, mcs_num); 931 buf += mt7915_sku_group_len[i]; 932 } 933 934 return 0; 935 } 936 937 DEFINE_SHOW_ATTRIBUTE(mt7915_rate_txpower); 938 939 static int 940 mt7915_twt_stats(struct seq_file *s, void *data) 941 { 942 struct mt7915_dev *dev = dev_get_drvdata(s->private); 943 struct mt7915_twt_flow *iter; 944 945 rcu_read_lock(); 946 947 seq_puts(s, " wcid | id | flags | exp | mantissa"); 948 seq_puts(s, " | duration | tsf |\n"); 949 list_for_each_entry_rcu(iter, &dev->twt_list, list) 950 seq_printf(s, 951 "%9d | %8d | %5c%c%c%c | %8d | %8d | %8d | %14lld |\n", 952 iter->wcid, iter->id, 953 iter->sched ? 's' : 'u', 954 iter->protection ? 'p' : '-', 955 iter->trigger ? 't' : '-', 956 iter->flowtype ? '-' : 'a', 957 iter->exp, iter->mantissa, 958 iter->duration, iter->tsf); 959 960 rcu_read_unlock(); 961 962 return 0; 963 } 964 965 /* The index of RF registers use the generic regidx, combined with two parts: 966 * WF selection [31:28] and offset [27:0]. 967 */ 968 static int 969 mt7915_rf_regval_get(void *data, u64 *val) 970 { 971 struct mt7915_dev *dev = data; 972 u32 regval; 973 int ret; 974 975 ret = mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, ®val, false); 976 if (ret) 977 return ret; 978 979 *val = regval; 980 981 return 0; 982 } 983 984 static int 985 mt7915_rf_regval_set(void *data, u64 val) 986 { 987 struct mt7915_dev *dev = data; 988 u32 val32 = val; 989 990 return mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, &val32, true); 991 } 992 993 DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7915_rf_regval_get, 994 mt7915_rf_regval_set, "0x%08llx\n"); 995 996 int mt7915_init_debugfs(struct mt7915_phy *phy) 997 { 998 struct mt7915_dev *dev = phy->dev; 999 bool ext_phy = phy != &dev->phy; 1000 struct dentry *dir; 1001 1002 dir = mt76_register_debugfs_fops(phy->mt76, NULL); 1003 if (!dir) 1004 return -ENOMEM; 1005 debugfs_create_file("muru_debug", 0600, dir, dev, &fops_muru_debug); 1006 debugfs_create_file("muru_stats", 0400, dir, phy, 1007 &mt7915_muru_stats_fops); 1008 debugfs_create_file("hw-queues", 0400, dir, phy, 1009 &mt7915_hw_queues_fops); 1010 debugfs_create_file("xmit-queues", 0400, dir, phy, 1011 &mt7915_xmit_queues_fops); 1012 debugfs_create_file("tx_stats", 0400, dir, phy, &mt7915_tx_stats_fops); 1013 debugfs_create_file("fw_ser", 0600, dir, phy, &mt7915_fw_ser_ops); 1014 debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm); 1015 debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa); 1016 debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin); 1017 debugfs_create_file("fw_util_wm", 0400, dir, dev, 1018 &mt7915_fw_util_wm_fops); 1019 debugfs_create_file("fw_util_wa", 0400, dir, dev, 1020 &mt7915_fw_util_wa_fops); 1021 debugfs_create_file("implicit_txbf", 0600, dir, dev, 1022 &fops_implicit_txbf); 1023 debugfs_create_file("txpower_sku", 0400, dir, phy, 1024 &mt7915_rate_txpower_fops); 1025 debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir, 1026 mt7915_twt_stats); 1027 debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval); 1028 1029 if (!dev->dbdc_support || phy->band_idx) { 1030 debugfs_create_u32("dfs_hw_pattern", 0400, dir, 1031 &dev->hw_pattern); 1032 debugfs_create_file("radar_trigger", 0200, dir, dev, 1033 &fops_radar_trigger); 1034 debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir, 1035 mt7915_rdd_monitor); 1036 } 1037 1038 if (!ext_phy) 1039 dev->debugfs_dir = dir; 1040 1041 return 0; 1042 } 1043 1044 static void 1045 mt7915_debugfs_write_fwlog(struct mt7915_dev *dev, const void *hdr, int hdrlen, 1046 const void *data, int len) 1047 { 1048 static DEFINE_SPINLOCK(lock); 1049 unsigned long flags; 1050 void *dest; 1051 1052 spin_lock_irqsave(&lock, flags); 1053 dest = relay_reserve(dev->relay_fwlog, hdrlen + len + 4); 1054 if (dest) { 1055 *(u32 *)dest = hdrlen + len; 1056 dest += 4; 1057 1058 if (hdrlen) { 1059 memcpy(dest, hdr, hdrlen); 1060 dest += hdrlen; 1061 } 1062 1063 memcpy(dest, data, len); 1064 relay_flush(dev->relay_fwlog); 1065 } 1066 spin_unlock_irqrestore(&lock, flags); 1067 } 1068 1069 void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int len) 1070 { 1071 struct { 1072 __le32 magic; 1073 __le32 timestamp; 1074 __le16 msg_type; 1075 __le16 len; 1076 } hdr = { 1077 .magic = cpu_to_le32(FW_BIN_LOG_MAGIC), 1078 .msg_type = cpu_to_le16(PKT_TYPE_RX_FW_MONITOR), 1079 }; 1080 1081 if (!dev->relay_fwlog) 1082 return; 1083 1084 hdr.timestamp = cpu_to_le32(mt76_rr(dev, MT_LPON_FRCR(0))); 1085 hdr.len = *(__le16 *)data; 1086 mt7915_debugfs_write_fwlog(dev, &hdr, sizeof(hdr), data, len); 1087 } 1088 1089 bool mt7915_debugfs_rx_log(struct mt7915_dev *dev, const void *data, int len) 1090 { 1091 if (get_unaligned_le32(data) != FW_BIN_LOG_MAGIC) 1092 return false; 1093 1094 if (dev->relay_fwlog) 1095 mt7915_debugfs_write_fwlog(dev, NULL, 0, data, len); 1096 1097 return true; 1098 } 1099 1100 #ifdef CONFIG_MAC80211_DEBUGFS 1101 /** per-station debugfs **/ 1102 1103 static ssize_t mt7915_sta_fixed_rate_set(struct file *file, 1104 const char __user *user_buf, 1105 size_t count, loff_t *ppos) 1106 { 1107 struct ieee80211_sta *sta = file->private_data; 1108 struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 1109 struct mt7915_dev *dev = msta->vif->phy->dev; 1110 struct ieee80211_vif *vif; 1111 struct sta_phy phy = {}; 1112 char buf[100]; 1113 int ret; 1114 u32 field; 1115 u8 i, gi, he_ltf; 1116 1117 if (count >= sizeof(buf)) 1118 return -EINVAL; 1119 1120 if (copy_from_user(buf, user_buf, count)) 1121 return -EFAULT; 1122 1123 if (count && buf[count - 1] == '\n') 1124 buf[count - 1] = '\0'; 1125 else 1126 buf[count] = '\0'; 1127 1128 /* mode - cck: 0, ofdm: 1, ht: 2, gf: 3, vht: 4, he_su: 8, he_er: 9 1129 * bw - bw20: 0, bw40: 1, bw80: 2, bw160: 3 1130 * nss - vht: 1~4, he: 1~4, others: ignore 1131 * mcs - cck: 0~4, ofdm: 0~7, ht: 0~32, vht: 0~9, he_su: 0~11, he_er: 0~2 1132 * gi - (ht/vht) lgi: 0, sgi: 1; (he) 0.8us: 0, 1.6us: 1, 3.2us: 2 1133 * ldpc - off: 0, on: 1 1134 * stbc - off: 0, on: 1 1135 * he_ltf - 1xltf: 0, 2xltf: 1, 4xltf: 2 1136 */ 1137 if (sscanf(buf, "%hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu", 1138 &phy.type, &phy.bw, &phy.nss, &phy.mcs, &gi, 1139 &phy.ldpc, &phy.stbc, &he_ltf) != 8) { 1140 dev_warn(dev->mt76.dev, 1141 "format: Mode BW NSS MCS (HE)GI LDPC STBC HE_LTF\n"); 1142 field = RATE_PARAM_AUTO; 1143 goto out; 1144 } 1145 1146 phy.ldpc = (phy.bw || phy.ldpc) * GENMASK(2, 0); 1147 for (i = 0; i <= phy.bw; i++) { 1148 phy.sgi |= gi << (i << sta->deflink.he_cap.has_he); 1149 phy.he_ltf |= he_ltf << (i << sta->deflink.he_cap.has_he); 1150 } 1151 field = RATE_PARAM_FIXED; 1152 1153 out: 1154 vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); 1155 ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, field); 1156 if (ret) 1157 return -EFAULT; 1158 1159 return count; 1160 } 1161 1162 static const struct file_operations fops_fixed_rate = { 1163 .write = mt7915_sta_fixed_rate_set, 1164 .open = simple_open, 1165 .owner = THIS_MODULE, 1166 .llseek = default_llseek, 1167 }; 1168 1169 static int 1170 mt7915_queues_show(struct seq_file *s, void *data) 1171 { 1172 struct ieee80211_sta *sta = s->private; 1173 1174 mt7915_sta_hw_queue_read(s, sta); 1175 1176 return 0; 1177 } 1178 1179 DEFINE_SHOW_ATTRIBUTE(mt7915_queues); 1180 1181 void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 1182 struct ieee80211_sta *sta, struct dentry *dir) 1183 { 1184 debugfs_create_file("fixed_rate", 0600, dir, sta, &fops_fixed_rate); 1185 debugfs_create_file("hw-queues", 0400, dir, sta, &mt7915_queues_fops); 1186 } 1187 1188 #endif 1189