18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: ISC 28c2ecf20Sopenharmony_ci/* Copyright (C) 2020 MediaTek Inc. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include "mt7915.h" 58c2ecf20Sopenharmony_ci#include "eeprom.h" 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci/** global debugfs **/ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci/* test knob of system layer 1/2 error recovery */ 108c2ecf20Sopenharmony_cistatic int mt7915_ser_trigger_set(void *data, u64 val) 118c2ecf20Sopenharmony_ci{ 128c2ecf20Sopenharmony_ci enum { 138c2ecf20Sopenharmony_ci SER_SET_RECOVER_L1 = 1, 148c2ecf20Sopenharmony_ci SER_SET_RECOVER_L2, 158c2ecf20Sopenharmony_ci SER_ENABLE = 2, 168c2ecf20Sopenharmony_ci SER_RECOVER 178c2ecf20Sopenharmony_ci }; 188c2ecf20Sopenharmony_ci struct mt7915_dev *dev = data; 198c2ecf20Sopenharmony_ci int ret = 0; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci switch (val) { 228c2ecf20Sopenharmony_ci case SER_SET_RECOVER_L1: 238c2ecf20Sopenharmony_ci case SER_SET_RECOVER_L2: 248c2ecf20Sopenharmony_ci ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), 0); 258c2ecf20Sopenharmony_ci if (ret) 268c2ecf20Sopenharmony_ci return ret; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci return mt7915_mcu_set_ser(dev, SER_RECOVER, val, 0); 298c2ecf20Sopenharmony_ci default: 308c2ecf20Sopenharmony_ci break; 318c2ecf20Sopenharmony_ci } 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci return ret; 348c2ecf20Sopenharmony_ci} 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_ser_trigger, NULL, 378c2ecf20Sopenharmony_ci mt7915_ser_trigger_set, "%lld\n"); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic int 408c2ecf20Sopenharmony_cimt7915_radar_trigger(void *data, u64 val) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci struct mt7915_dev *dev = data; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci return mt7915_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, 1, 0, 0); 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL, 488c2ecf20Sopenharmony_ci mt7915_radar_trigger, "%lld\n"); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic int 518c2ecf20Sopenharmony_cimt7915_dbdc_set(void *data, u64 val) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci struct mt7915_dev *dev = data; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (val) 568c2ecf20Sopenharmony_ci mt7915_register_ext_phy(dev); 578c2ecf20Sopenharmony_ci else 588c2ecf20Sopenharmony_ci mt7915_unregister_ext_phy(dev); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci return 0; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic int 648c2ecf20Sopenharmony_cimt7915_dbdc_get(void *data, u64 *val) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci struct mt7915_dev *dev = data; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci *val = !!mt7915_ext_phy(dev); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci return 0; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7915_dbdc_get, 748c2ecf20Sopenharmony_ci mt7915_dbdc_set, "%lld\n"); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic int 778c2ecf20Sopenharmony_cimt7915_fw_debug_set(void *data, u64 val) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci struct mt7915_dev *dev = data; 808c2ecf20Sopenharmony_ci enum { 818c2ecf20Sopenharmony_ci DEBUG_TXCMD = 62, 828c2ecf20Sopenharmony_ci DEBUG_CMD_RPT_TX, 838c2ecf20Sopenharmony_ci DEBUG_CMD_RPT_TRIG, 848c2ecf20Sopenharmony_ci DEBUG_SPL, 858c2ecf20Sopenharmony_ci DEBUG_RPT_RX, 868c2ecf20Sopenharmony_ci } debug; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci dev->fw_debug = !!val; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci mt7915_mcu_fw_log_2_host(dev, dev->fw_debug ? 2 : 0); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RX; debug++) 938c2ecf20Sopenharmony_ci mt7915_mcu_fw_dbg_ctrl(dev, debug, dev->fw_debug); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci return 0; 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic int 998c2ecf20Sopenharmony_cimt7915_fw_debug_get(void *data, u64 *val) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci struct mt7915_dev *dev = data; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci *val = dev->fw_debug; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci return 0; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7915_fw_debug_get, 1098c2ecf20Sopenharmony_ci mt7915_fw_debug_set, "%lld\n"); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic void 1128c2ecf20Sopenharmony_cimt7915_ampdu_stat_read_phy(struct mt7915_phy *phy, 1138c2ecf20Sopenharmony_ci struct seq_file *file) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci struct mt7915_dev *dev = file->private; 1168c2ecf20Sopenharmony_ci bool ext_phy = phy != &dev->phy; 1178c2ecf20Sopenharmony_ci int bound[15], range[4], i, n; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (!phy) 1208c2ecf20Sopenharmony_ci return; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci /* Tx ampdu stat */ 1238c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(range); i++) 1248c2ecf20Sopenharmony_ci range[i] = mt76_rr(dev, MT_MIB_ARNG(ext_phy, i)); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bound); i++) 1278c2ecf20Sopenharmony_ci bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci seq_printf(file, "\nPhy %d\n", ext_phy); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci seq_printf(file, "Length: %8d | ", bound[0]); 1328c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bound) - 1; i++) 1338c2ecf20Sopenharmony_ci seq_printf(file, "%3d -%3d | ", 1348c2ecf20Sopenharmony_ci bound[i] + 1, bound[i + 1]); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci seq_puts(file, "\nCount: "); 1378c2ecf20Sopenharmony_ci n = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; 1388c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bound); i++) 1398c2ecf20Sopenharmony_ci seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i + n]); 1408c2ecf20Sopenharmony_ci seq_puts(file, "\n"); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt); 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic void 1468c2ecf20Sopenharmony_cimt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci struct mt7915_dev *dev = s->private; 1498c2ecf20Sopenharmony_ci bool ext_phy = phy != &dev->phy; 1508c2ecf20Sopenharmony_ci int cnt; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci if (!phy) 1538c2ecf20Sopenharmony_ci return; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci /* Tx Beamformer monitor */ 1568c2ecf20Sopenharmony_ci seq_puts(s, "\nTx Beamformer applied PPDU counts: "); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(ext_phy)); 1598c2ecf20Sopenharmony_ci seq_printf(s, "iBF: %ld, eBF: %ld\n", 1608c2ecf20Sopenharmony_ci FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt), 1618c2ecf20Sopenharmony_ci FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt)); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* Tx Beamformer Rx feedback monitor */ 1648c2ecf20Sopenharmony_ci seq_puts(s, "Tx Beamformer Rx feedback statistics: "); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy)); 1678c2ecf20Sopenharmony_ci seq_printf(s, "All: %ld, HE: %ld, VHT: %ld, HT: %ld\n", 1688c2ecf20Sopenharmony_ci FIELD_GET(MT_ETBF_RX_FB_ALL, cnt), 1698c2ecf20Sopenharmony_ci FIELD_GET(MT_ETBF_RX_FB_HE, cnt), 1708c2ecf20Sopenharmony_ci FIELD_GET(MT_ETBF_RX_FB_VHT, cnt), 1718c2ecf20Sopenharmony_ci FIELD_GET(MT_ETBF_RX_FB_HT, cnt)); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* Tx Beamformee Rx NDPA & Tx feedback report */ 1748c2ecf20Sopenharmony_ci cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy)); 1758c2ecf20Sopenharmony_ci seq_printf(s, "Tx Beamformee successful feedback frames: %ld\n", 1768c2ecf20Sopenharmony_ci FIELD_GET(MT_ETBF_TX_FB_CPL, cnt)); 1778c2ecf20Sopenharmony_ci seq_printf(s, "Tx Beamformee feedback triggered counts: %ld\n", 1788c2ecf20Sopenharmony_ci FIELD_GET(MT_ETBF_TX_FB_TRI, cnt)); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* Tx SU & MU counters */ 1818c2ecf20Sopenharmony_ci cnt = mt76_rr(dev, MT_MIB_SDR34(ext_phy)); 1828c2ecf20Sopenharmony_ci seq_printf(s, "Tx multi-user Beamforming counts: %ld\n", 1838c2ecf20Sopenharmony_ci FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt)); 1848c2ecf20Sopenharmony_ci cnt = mt76_rr(dev, MT_MIB_DR8(ext_phy)); 1858c2ecf20Sopenharmony_ci seq_printf(s, "Tx multi-user MPDU counts: %d\n", cnt); 1868c2ecf20Sopenharmony_ci cnt = mt76_rr(dev, MT_MIB_DR9(ext_phy)); 1878c2ecf20Sopenharmony_ci seq_printf(s, "Tx multi-user successful MPDU counts: %d\n", cnt); 1888c2ecf20Sopenharmony_ci cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy)); 1898c2ecf20Sopenharmony_ci seq_printf(s, "Tx single-user successful MPDU counts: %d\n", cnt); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci seq_puts(s, "\n"); 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic int 1958c2ecf20Sopenharmony_cimt7915_tx_stats_read(struct seq_file *file, void *data) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci struct mt7915_dev *dev = file->private; 1988c2ecf20Sopenharmony_ci int stat[8], i, n; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci mt7915_ampdu_stat_read_phy(&dev->phy, file); 2018c2ecf20Sopenharmony_ci mt7915_txbf_stat_read_phy(&dev->phy, file); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci mt7915_ampdu_stat_read_phy(mt7915_ext_phy(dev), file); 2048c2ecf20Sopenharmony_ci mt7915_txbf_stat_read_phy(mt7915_ext_phy(dev), file); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci /* Tx amsdu info */ 2078c2ecf20Sopenharmony_ci seq_puts(file, "Tx MSDU stat:\n"); 2088c2ecf20Sopenharmony_ci for (i = 0, n = 0; i < ARRAY_SIZE(stat); i++) { 2098c2ecf20Sopenharmony_ci stat[i] = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); 2108c2ecf20Sopenharmony_ci n += stat[i]; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(stat); i++) { 2148c2ecf20Sopenharmony_ci seq_printf(file, "AMSDU pack count of %d MSDU in TXD: 0x%x ", 2158c2ecf20Sopenharmony_ci i + 1, stat[i]); 2168c2ecf20Sopenharmony_ci if (n != 0) 2178c2ecf20Sopenharmony_ci seq_printf(file, "(%d%%)\n", stat[i] * 100 / n); 2188c2ecf20Sopenharmony_ci else 2198c2ecf20Sopenharmony_ci seq_puts(file, "\n"); 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci return 0; 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic int 2268c2ecf20Sopenharmony_cimt7915_tx_stats_open(struct inode *inode, struct file *f) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci return single_open(f, mt7915_tx_stats_read, inode->i_private); 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_cistatic const struct file_operations fops_tx_stats = { 2328c2ecf20Sopenharmony_ci .open = mt7915_tx_stats_open, 2338c2ecf20Sopenharmony_ci .read = seq_read, 2348c2ecf20Sopenharmony_ci .llseek = seq_lseek, 2358c2ecf20Sopenharmony_ci .release = single_release, 2368c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2378c2ecf20Sopenharmony_ci}; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cistatic int mt7915_read_temperature(struct seq_file *s, void *data) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci struct mt7915_dev *dev = dev_get_drvdata(s->private); 2428c2ecf20Sopenharmony_ci int temp; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci /* cpu */ 2458c2ecf20Sopenharmony_ci temp = mt7915_mcu_get_temperature(dev, 0); 2468c2ecf20Sopenharmony_ci seq_printf(s, "Temperature: %d\n", temp); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci return 0; 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cistatic int 2528c2ecf20Sopenharmony_cimt7915_queues_acq(struct seq_file *s, void *data) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci struct mt7915_dev *dev = dev_get_drvdata(s->private); 2558c2ecf20Sopenharmony_ci int i; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 2588c2ecf20Sopenharmony_ci int j, acs = i / 4, index = i % 4; 2598c2ecf20Sopenharmony_ci u32 ctrl, val, qlen = 0; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index)); 2628c2ecf20Sopenharmony_ci ctrl = BIT(31) | BIT(15) | (acs << 8); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci for (j = 0; j < 32; j++) { 2658c2ecf20Sopenharmony_ci if (val & BIT(j)) 2668c2ecf20Sopenharmony_ci continue; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci mt76_wr(dev, MT_PLE_FL_Q0_CTRL, 2698c2ecf20Sopenharmony_ci ctrl | (j + (index << 5))); 2708c2ecf20Sopenharmony_ci qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL, 2718c2ecf20Sopenharmony_ci GENMASK(11, 0)); 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen); 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci return 0; 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cistatic int 2808c2ecf20Sopenharmony_cimt7915_queues_read(struct seq_file *s, void *data) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci struct mt7915_dev *dev = dev_get_drvdata(s->private); 2838c2ecf20Sopenharmony_ci static const struct { 2848c2ecf20Sopenharmony_ci char *queue; 2858c2ecf20Sopenharmony_ci int id; 2868c2ecf20Sopenharmony_ci } queue_map[] = { 2878c2ecf20Sopenharmony_ci { "WFDMA0", MT_TXQ_BE }, 2888c2ecf20Sopenharmony_ci { "MCUWM", MT_TXQ_MCU }, 2898c2ecf20Sopenharmony_ci { "MCUWA", MT_TXQ_MCU_WA }, 2908c2ecf20Sopenharmony_ci { "MCUFWQ", MT_TXQ_FWDL }, 2918c2ecf20Sopenharmony_ci }; 2928c2ecf20Sopenharmony_ci int i; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(queue_map); i++) { 2958c2ecf20Sopenharmony_ci struct mt76_queue *q = dev->mt76.q_tx[queue_map[i].id]; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci if (!q) 2988c2ecf20Sopenharmony_ci continue; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci seq_printf(s, 3018c2ecf20Sopenharmony_ci "%s: queued=%d head=%d tail=%d\n", 3028c2ecf20Sopenharmony_ci queue_map[i].queue, q->queued, q->head, 3038c2ecf20Sopenharmony_ci q->tail); 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci return 0; 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_cistatic void 3108c2ecf20Sopenharmony_cimt7915_puts_rate_txpower(struct seq_file *s, s8 *delta, 3118c2ecf20Sopenharmony_ci s8 txpower_cur, int band) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci static const char * const sku_group_name[] = { 3148c2ecf20Sopenharmony_ci "CCK", "OFDM", "HT20", "HT40", 3158c2ecf20Sopenharmony_ci "VHT20", "VHT40", "VHT80", "VHT160", 3168c2ecf20Sopenharmony_ci "RU26", "RU52", "RU106", "RU242/SU20", 3178c2ecf20Sopenharmony_ci "RU484/SU40", "RU996/SU80", "RU2x996/SU160" 3188c2ecf20Sopenharmony_ci }; 3198c2ecf20Sopenharmony_ci s8 txpower[MT7915_SKU_RATE_NUM]; 3208c2ecf20Sopenharmony_ci int i, idx = 0; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci for (i = 0; i < MT7915_SKU_RATE_NUM; i++) 3238c2ecf20Sopenharmony_ci txpower[i] = DIV_ROUND_UP(txpower_cur + delta[i], 2); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci for (i = 0; i < MAX_SKU_RATE_GROUP_NUM; i++) { 3268c2ecf20Sopenharmony_ci const struct sku_group *sku = &mt7915_sku_groups[i]; 3278c2ecf20Sopenharmony_ci u32 offset = sku->offset[band]; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci if (!offset) { 3308c2ecf20Sopenharmony_ci idx += sku->len; 3318c2ecf20Sopenharmony_ci continue; 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci mt76_seq_puts_array(s, sku_group_name[i], 3358c2ecf20Sopenharmony_ci txpower + idx, sku->len); 3368c2ecf20Sopenharmony_ci idx += sku->len; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_cistatic int 3418c2ecf20Sopenharmony_cimt7915_read_rate_txpower(struct seq_file *s, void *data) 3428c2ecf20Sopenharmony_ci{ 3438c2ecf20Sopenharmony_ci struct mt7915_dev *dev = dev_get_drvdata(s->private); 3448c2ecf20Sopenharmony_ci struct mt76_phy *mphy = &dev->mphy; 3458c2ecf20Sopenharmony_ci enum nl80211_band band = mphy->chandef.chan->band; 3468c2ecf20Sopenharmony_ci s8 *delta = dev->rate_power[band]; 3478c2ecf20Sopenharmony_ci s8 txpower_base = mphy->txpower_cur - delta[MT7915_SKU_MAX_DELTA_IDX]; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci seq_puts(s, "Band 0:\n"); 3508c2ecf20Sopenharmony_ci mt7915_puts_rate_txpower(s, delta, txpower_base, band); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci if (dev->mt76.phy2) { 3538c2ecf20Sopenharmony_ci mphy = dev->mt76.phy2; 3548c2ecf20Sopenharmony_ci band = mphy->chandef.chan->band; 3558c2ecf20Sopenharmony_ci delta = dev->rate_power[band]; 3568c2ecf20Sopenharmony_ci txpower_base = mphy->txpower_cur - 3578c2ecf20Sopenharmony_ci delta[MT7915_SKU_MAX_DELTA_IDX]; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci seq_puts(s, "Band 1:\n"); 3608c2ecf20Sopenharmony_ci mt7915_puts_rate_txpower(s, delta, txpower_base, band); 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci return 0; 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ciint mt7915_init_debugfs(struct mt7915_dev *dev) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci struct dentry *dir; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci dir = mt76_register_debugfs(&dev->mt76); 3718c2ecf20Sopenharmony_ci if (!dir) 3728c2ecf20Sopenharmony_ci return -ENOMEM; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, 3758c2ecf20Sopenharmony_ci mt7915_queues_read); 3768c2ecf20Sopenharmony_ci debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, 3778c2ecf20Sopenharmony_ci mt7915_queues_acq); 3788c2ecf20Sopenharmony_ci debugfs_create_file("tx_stats", 0400, dir, dev, &fops_tx_stats); 3798c2ecf20Sopenharmony_ci debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc); 3808c2ecf20Sopenharmony_ci debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug); 3818c2ecf20Sopenharmony_ci debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); 3828c2ecf20Sopenharmony_ci /* test knobs */ 3838c2ecf20Sopenharmony_ci debugfs_create_file("radar_trigger", 0200, dir, dev, 3848c2ecf20Sopenharmony_ci &fops_radar_trigger); 3858c2ecf20Sopenharmony_ci debugfs_create_file("ser_trigger", 0200, dir, dev, &fops_ser_trigger); 3868c2ecf20Sopenharmony_ci debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir, 3878c2ecf20Sopenharmony_ci mt7915_read_temperature); 3888c2ecf20Sopenharmony_ci debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir, 3898c2ecf20Sopenharmony_ci mt7915_read_rate_txpower); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci return 0; 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci#ifdef CONFIG_MAC80211_DEBUGFS 3958c2ecf20Sopenharmony_ci/** per-station debugfs **/ 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci/* usage: <tx mode> <ldpc> <stbc> <bw> <gi> <nss> <mcs> */ 3988c2ecf20Sopenharmony_cistatic int mt7915_sta_fixed_rate_set(void *data, u64 rate) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci struct ieee80211_sta *sta = data; 4018c2ecf20Sopenharmony_ci struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci return mt7915_mcu_set_fixed_rate(msta->vif->phy->dev, sta, rate); 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_fixed_rate, NULL, 4078c2ecf20Sopenharmony_ci mt7915_sta_fixed_rate_set, "%llx\n"); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_cistatic int 4108c2ecf20Sopenharmony_cimt7915_sta_stats_read(struct seq_file *s, void *data) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci struct ieee80211_sta *sta = s->private; 4138c2ecf20Sopenharmony_ci struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 4148c2ecf20Sopenharmony_ci struct mt7915_sta_stats *stats = &msta->stats; 4158c2ecf20Sopenharmony_ci struct rate_info *rate = &stats->prob_rate; 4168c2ecf20Sopenharmony_ci static const char * const bw[] = { 4178c2ecf20Sopenharmony_ci "BW20", "BW5", "BW10", "BW40", 4188c2ecf20Sopenharmony_ci "BW80", "BW160", "BW_HE_RU" 4198c2ecf20Sopenharmony_ci }; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci if (!rate->legacy && !rate->flags) 4228c2ecf20Sopenharmony_ci return 0; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci seq_puts(s, "Probing rate - "); 4258c2ecf20Sopenharmony_ci if (rate->flags & RATE_INFO_FLAGS_MCS) 4268c2ecf20Sopenharmony_ci seq_puts(s, "HT "); 4278c2ecf20Sopenharmony_ci else if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) 4288c2ecf20Sopenharmony_ci seq_puts(s, "VHT "); 4298c2ecf20Sopenharmony_ci else if (rate->flags & RATE_INFO_FLAGS_HE_MCS) 4308c2ecf20Sopenharmony_ci seq_puts(s, "HE "); 4318c2ecf20Sopenharmony_ci else 4328c2ecf20Sopenharmony_ci seq_printf(s, "Bitrate %d\n", rate->legacy); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci if (rate->flags) { 4358c2ecf20Sopenharmony_ci seq_printf(s, "%s NSS%d MCS%d ", 4368c2ecf20Sopenharmony_ci bw[rate->bw], rate->nss, rate->mcs); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) 4398c2ecf20Sopenharmony_ci seq_puts(s, "SGI "); 4408c2ecf20Sopenharmony_ci else if (rate->he_gi) 4418c2ecf20Sopenharmony_ci seq_puts(s, "HE GI "); 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci if (rate->he_dcm) 4448c2ecf20Sopenharmony_ci seq_puts(s, "DCM "); 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci seq_printf(s, "\nPPDU PER: %ld.%1ld%%\n", 4488c2ecf20Sopenharmony_ci stats->per / 10, stats->per % 10); 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci return 0; 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_cistatic int 4548c2ecf20Sopenharmony_cimt7915_sta_stats_open(struct inode *inode, struct file *f) 4558c2ecf20Sopenharmony_ci{ 4568c2ecf20Sopenharmony_ci return single_open(f, mt7915_sta_stats_read, inode->i_private); 4578c2ecf20Sopenharmony_ci} 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_cistatic const struct file_operations fops_sta_stats = { 4608c2ecf20Sopenharmony_ci .open = mt7915_sta_stats_open, 4618c2ecf20Sopenharmony_ci .read = seq_read, 4628c2ecf20Sopenharmony_ci .llseek = seq_lseek, 4638c2ecf20Sopenharmony_ci .release = single_release, 4648c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 4658c2ecf20Sopenharmony_ci}; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_civoid mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 4688c2ecf20Sopenharmony_ci struct ieee80211_sta *sta, struct dentry *dir) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci debugfs_create_file("fixed_rate", 0600, dir, sta, &fops_fixed_rate); 4718c2ecf20Sopenharmony_ci debugfs_create_file("stats", 0400, dir, sta, &fops_sta_stats); 4728c2ecf20Sopenharmony_ci} 4738c2ecf20Sopenharmony_ci#endif 474