Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7615/debugfs.c
48525 views
// SPDX-License-Identifier: ISC12#include "mt7615.h"34static int5mt7615_reg_set(void *data, u64 val)6{7struct mt7615_dev *dev = data;89mt7615_mutex_acquire(dev);10mt76_wr(dev, dev->mt76.debugfs_reg, val);11mt7615_mutex_release(dev);1213return 0;14}1516static int17mt7615_reg_get(void *data, u64 *val)18{19struct mt7615_dev *dev = data;2021mt7615_mutex_acquire(dev);22*val = mt76_rr(dev, dev->mt76.debugfs_reg);23mt7615_mutex_release(dev);2425return 0;26}2728DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7615_reg_get, mt7615_reg_set,29"0x%08llx\n");3031static int32mt7615_radar_pattern_set(void *data, u64 val)33{34struct mt7615_dev *dev = data;35int err;3637if (!mt7615_wait_for_mcu_init(dev))38return 0;3940mt7615_mutex_acquire(dev);41err = mt7615_mcu_rdd_send_pattern(dev);42mt7615_mutex_release(dev);4344return err;45}4647DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_pattern, NULL,48mt7615_radar_pattern_set, "%lld\n");4950static int mt7615_config(void *data, u64 val)51{52struct mt7615_dev *dev = data;53int ret;5455mt7615_mutex_acquire(dev);56ret = mt76_connac_mcu_chip_config(&dev->mt76);57mt7615_mutex_release(dev);5859return ret;60}6162DEFINE_DEBUGFS_ATTRIBUTE(fops_config, NULL, mt7615_config, "%lld\n");6364static int65mt7615_scs_set(void *data, u64 val)66{67struct mt7615_dev *dev = data;68struct mt7615_phy *ext_phy;6970if (!mt7615_wait_for_mcu_init(dev))71return 0;7273mt7615_mac_set_scs(&dev->phy, val);74ext_phy = mt7615_ext_phy(dev);75if (ext_phy)76mt7615_mac_set_scs(ext_phy, val);7778return 0;79}8081static int82mt7615_scs_get(void *data, u64 *val)83{84struct mt7615_dev *dev = data;8586*val = dev->phy.scs_en;8788return 0;89}9091DEFINE_DEBUGFS_ATTRIBUTE(fops_scs, mt7615_scs_get,92mt7615_scs_set, "%lld\n");9394static int95mt7615_pm_set(void *data, u64 val)96{97struct mt7615_dev *dev = data;98struct mt76_connac_pm *pm = &dev->pm;99int ret = 0;100101if (!mt7615_wait_for_mcu_init(dev))102return 0;103104if (!mt7615_firmware_offload(dev) || mt76_is_usb(&dev->mt76))105return -EOPNOTSUPP;106107mutex_lock(&dev->mt76.mutex);108109if (val == pm->enable)110goto out;111112if (dev->phy.n_beacon_vif) {113ret = -EBUSY;114goto out;115}116117if (!pm->enable) {118pm->stats.last_wake_event = jiffies;119pm->stats.last_doze_event = jiffies;120}121/* make sure the chip is awake here and ps_work is scheduled122* just at end of the this routine.123*/124pm->enable = false;125mt76_connac_pm_wake(&dev->mphy, pm);126127pm->enable = val;128mt76_connac_power_save_sched(&dev->mphy, pm);129out:130mutex_unlock(&dev->mt76.mutex);131132return ret;133}134135static int136mt7615_pm_get(void *data, u64 *val)137{138struct mt7615_dev *dev = data;139140*val = dev->pm.enable;141142return 0;143}144145DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7615_pm_get, mt7615_pm_set, "%lld\n");146147static int148mt7615_pm_stats(struct seq_file *s, void *data)149{150struct mt7615_dev *dev = dev_get_drvdata(s->private);151struct mt76_connac_pm *pm = &dev->pm;152unsigned long awake_time = pm->stats.awake_time;153unsigned long doze_time = pm->stats.doze_time;154155if (!test_bit(MT76_STATE_PM, &dev->mphy.state))156awake_time += jiffies - pm->stats.last_wake_event;157else158doze_time += jiffies - pm->stats.last_doze_event;159160seq_printf(s, "awake time: %14u\ndoze time: %15u\n",161jiffies_to_msecs(awake_time),162jiffies_to_msecs(doze_time));163164return 0;165}166167static int168mt7615_pm_idle_timeout_set(void *data, u64 val)169{170struct mt7615_dev *dev = data;171172dev->pm.idle_timeout = msecs_to_jiffies(val);173174return 0;175}176177static int178mt7615_pm_idle_timeout_get(void *data, u64 *val)179{180struct mt7615_dev *dev = data;181182*val = jiffies_to_msecs(dev->pm.idle_timeout);183184return 0;185}186187DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7615_pm_idle_timeout_get,188mt7615_pm_idle_timeout_set, "%lld\n");189190static int191mt7615_dbdc_set(void *data, u64 val)192{193struct mt7615_dev *dev = data;194195if (!mt7615_wait_for_mcu_init(dev))196return 0;197198if (val)199mt7615_register_ext_phy(dev);200else201mt7615_unregister_ext_phy(dev);202203return 0;204}205206static int207mt7615_dbdc_get(void *data, u64 *val)208{209struct mt7615_dev *dev = data;210211*val = !!mt7615_ext_phy(dev);212213return 0;214}215216DEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7615_dbdc_get,217mt7615_dbdc_set, "%lld\n");218219static int220mt7615_fw_debug_set(void *data, u64 val)221{222struct mt7615_dev *dev = data;223224if (!mt7615_wait_for_mcu_init(dev))225return 0;226227dev->fw_debug = val;228229mt7615_mutex_acquire(dev);230mt7615_mcu_fw_log_2_host(dev, dev->fw_debug ? 2 : 0);231mt7615_mutex_release(dev);232233return 0;234}235236static int237mt7615_fw_debug_get(void *data, u64 *val)238{239struct mt7615_dev *dev = data;240241*val = dev->fw_debug;242243return 0;244}245246DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7615_fw_debug_get,247mt7615_fw_debug_set, "%lld\n");248249static int250mt7615_reset_test_set(void *data, u64 val)251{252struct mt7615_dev *dev = data;253struct sk_buff *skb;254255if (!mt7615_wait_for_mcu_init(dev))256return 0;257258skb = alloc_skb(1, GFP_KERNEL);259if (!skb)260return -ENOMEM;261262skb_put(skb, 1);263264mt7615_mutex_acquire(dev);265mt76_tx_queue_skb_raw(dev, dev->mphy.q_tx[0], skb, 0);266mt7615_mutex_release(dev);267268return 0;269}270271DEFINE_DEBUGFS_ATTRIBUTE(fops_reset_test, NULL,272mt7615_reset_test_set, "%lld\n");273274static void275mt7615_ampdu_stat_read_phy(struct mt7615_phy *phy,276struct seq_file *file)277{278struct mt7615_dev *dev = file->private;279u32 reg = is_mt7663(&dev->mt76) ? MT_MIB_ARNG(0) : MT_AGG_ASRCR0;280int bound[7], i, range;281282if (!phy)283return;284285range = mt76_rr(dev, reg);286for (i = 0; i < 4; i++)287bound[i] = MT_AGG_ASRCR_RANGE(range, i) + 1;288289range = mt76_rr(dev, reg + 4);290for (i = 0; i < 3; i++)291bound[i + 4] = MT_AGG_ASRCR_RANGE(range, i) + 1;292293seq_printf(file, "\nPhy %d\n", phy != &dev->phy);294295seq_printf(file, "Length: %8d | ", bound[0]);296for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)297seq_printf(file, "%3d -%3d | ",298bound[i], bound[i + 1]);299seq_puts(file, "\nCount: ");300301for (i = 0; i < ARRAY_SIZE(bound); i++)302seq_printf(file, "%8d | ", phy->mt76->aggr_stats[i]);303seq_puts(file, "\n");304305seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);306seq_printf(file, "PER: %ld.%1ld%%\n",307phy->mib.aggr_per / 10, phy->mib.aggr_per % 10);308}309310static int311mt7615_ampdu_stat_show(struct seq_file *file, void *data)312{313struct mt7615_dev *dev = file->private;314315mt7615_mutex_acquire(dev);316317mt7615_ampdu_stat_read_phy(&dev->phy, file);318mt7615_ampdu_stat_read_phy(mt7615_ext_phy(dev), file);319320mt7615_mutex_release(dev);321322return 0;323}324325DEFINE_SHOW_ATTRIBUTE(mt7615_ampdu_stat);326327static void328mt7615_radio_read_phy(struct mt7615_phy *phy, struct seq_file *s)329{330struct mt7615_dev *dev = dev_get_drvdata(s->private);331bool ext_phy = phy != &dev->phy;332333if (!phy)334return;335336seq_printf(s, "Radio %d sensitivity: ofdm=%d cck=%d\n", ext_phy,337phy->ofdm_sensitivity, phy->cck_sensitivity);338seq_printf(s, "Radio %d false CCA: ofdm=%d cck=%d\n", ext_phy,339phy->false_cca_ofdm, phy->false_cca_cck);340}341342static int343mt7615_radio_read(struct seq_file *s, void *data)344{345struct mt7615_dev *dev = dev_get_drvdata(s->private);346347mt7615_radio_read_phy(&dev->phy, s);348mt7615_radio_read_phy(mt7615_ext_phy(dev), s);349350return 0;351}352353static int354mt7615_queues_acq(struct seq_file *s, void *data)355{356struct mt7615_dev *dev = dev_get_drvdata(s->private);357int i;358359mt7615_mutex_acquire(dev);360361for (i = 0; i < 16; i++) {362int j, wmm_idx = i % MT7615_MAX_WMM_SETS;363int acs = i / MT7615_MAX_WMM_SETS;364u32 ctrl, val, qlen = 0;365366if (wmm_idx == 3 && is_mt7663(&dev->mt76))367continue;368369val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, wmm_idx));370ctrl = BIT(31) | BIT(15) | (acs << 8);371372for (j = 0; j < 32; j++) {373if (val & BIT(j))374continue;375376mt76_wr(dev, MT_PLE_FL_Q0_CTRL,377ctrl | (j + (wmm_idx << 5)));378qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,379GENMASK(11, 0));380}381seq_printf(s, "AC%d%d: queued=%d\n", wmm_idx, acs, qlen);382}383384mt7615_mutex_release(dev);385386return 0;387}388389static int390mt7615_queues_read(struct seq_file *s, void *data)391{392struct mt7615_dev *dev = dev_get_drvdata(s->private);393struct {394struct mt76_queue *q;395char *queue;396} queue_map[] = {397{ dev->mphy.q_tx[MT_TXQ_BE], "PDMA0" },398{ dev->mt76.q_mcu[MT_MCUQ_WM], "MCUQ" },399{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },400};401int i;402403for (i = 0; i < ARRAY_SIZE(queue_map); i++) {404struct mt76_queue *q = queue_map[i].q;405406seq_printf(s,407"%s: queued=%d head=%d tail=%d\n",408queue_map[i].queue, q->queued, q->head,409q->tail);410}411412return 0;413}414415static int416mt7615_rf_reg_set(void *data, u64 val)417{418struct mt7615_dev *dev = data;419420mt7615_rf_wr(dev, dev->debugfs_rf_wf, dev->debugfs_rf_reg, val);421422return 0;423}424425static int426mt7615_rf_reg_get(void *data, u64 *val)427{428struct mt7615_dev *dev = data;429430*val = mt7615_rf_rr(dev, dev->debugfs_rf_wf, dev->debugfs_rf_reg);431432return 0;433}434435DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_reg, mt7615_rf_reg_get, mt7615_rf_reg_set,436"0x%08llx\n");437438static ssize_t439mt7615_ext_mac_addr_read(struct file *file, char __user *userbuf,440size_t count, loff_t *ppos)441{442struct mt7615_dev *dev = file->private_data;443u32 len = 32 * ((ETH_ALEN * 3) + 4) + 1;444u8 addr[ETH_ALEN];445char *buf;446int ofs = 0;447int i;448449buf = kzalloc(len, GFP_KERNEL);450if (!buf)451return -ENOMEM;452453for (i = 0; i < 32; i++) {454if (!(dev->muar_mask & BIT(i)))455continue;456457mt76_wr(dev, MT_WF_RMAC_MAR1,458FIELD_PREP(MT_WF_RMAC_MAR1_IDX, i * 2) |459MT_WF_RMAC_MAR1_START);460put_unaligned_le32(mt76_rr(dev, MT_WF_RMAC_MAR0), addr);461put_unaligned_le16((mt76_rr(dev, MT_WF_RMAC_MAR1) &462MT_WF_RMAC_MAR1_ADDR), addr + 4);463ofs += snprintf(buf + ofs, len - ofs, "%d=%pM\n", i, addr);464}465466ofs = simple_read_from_buffer(userbuf, count, ppos, buf, ofs);467468kfree(buf);469return ofs;470}471472static ssize_t473mt7615_ext_mac_addr_write(struct file *file, const char __user *userbuf,474size_t count, loff_t *ppos)475{476struct mt7615_dev *dev = file->private_data;477unsigned long idx = 0;478u8 addr[ETH_ALEN];479char buf[32];480char *p;481482if (count > sizeof(buf))483return -EINVAL;484485if (copy_from_user(buf, userbuf, count))486return -EFAULT;487488buf[sizeof(buf) - 1] = '\0';489490p = strchr(buf, '=');491if (p) {492*p = 0;493p++;494495if (kstrtoul(buf, 0, &idx) || idx > 31)496return -EINVAL;497} else {498idx = 0;499p = buf;500}501502if (!mac_pton(p, addr))503return -EINVAL;504505if (is_valid_ether_addr(addr)) {506dev->muar_mask |= BIT(idx);507} else {508memset(addr, 0, sizeof(addr));509dev->muar_mask &= ~BIT(idx);510}511512mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, 1);513mt76_wr(dev, MT_WF_RMAC_MAR0, get_unaligned_le32(addr));514mt76_wr(dev, MT_WF_RMAC_MAR1,515get_unaligned_le16(addr + 4) |516FIELD_PREP(MT_WF_RMAC_MAR1_IDX, idx * 2) |517MT_WF_RMAC_MAR1_START |518MT_WF_RMAC_MAR1_WRITE);519520mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, !!dev->muar_mask);521522return count;523}524525static const struct file_operations fops_ext_mac_addr = {526.open = simple_open,527.llseek = generic_file_llseek,528.read = mt7615_ext_mac_addr_read,529.write = mt7615_ext_mac_addr_write,530.owner = THIS_MODULE,531};532533static int534mt7663s_sched_quota_read(struct seq_file *s, void *data)535{536struct mt7615_dev *dev = dev_get_drvdata(s->private);537struct mt76_sdio *sdio = &dev->mt76.sdio;538539seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota);540seq_printf(s, "ple_data_quota\t%d\n", sdio->sched.ple_data_quota);541seq_printf(s, "pse_mcu_quota\t%d\n", sdio->sched.pse_mcu_quota);542seq_printf(s, "sched_deficit\t%d\n", sdio->sched.deficit);543544return 0;545}546547int mt7615_init_debugfs(struct mt7615_dev *dev)548{549struct dentry *dir;550551dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);552if (!dir)553return -ENOMEM;554555if (is_mt7615(&dev->mt76))556debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,557mt7615_queues_read);558else559debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,560mt76_queues_read);561debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,562mt7615_queues_acq);563debugfs_create_file("ampdu_stat", 0400, dir, dev, &mt7615_ampdu_stat_fops);564debugfs_create_file("scs", 0600, dir, dev, &fops_scs);565debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc);566debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);567debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);568debugfs_create_file("idle-timeout", 0600, dir, dev,569&fops_pm_idle_timeout);570debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,571mt7615_pm_stats);572debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir,573mt7615_radio_read);574575if (is_mt7615(&dev->mt76)) {576debugfs_create_u32("dfs_hw_pattern", 0400, dir,577&dev->hw_pattern);578/* test pattern knobs */579debugfs_create_u8("pattern_len", 0600, dir,580&dev->radar_pattern.n_pulses);581debugfs_create_u32("pulse_period", 0600, dir,582&dev->radar_pattern.period);583debugfs_create_u16("pulse_width", 0600, dir,584&dev->radar_pattern.width);585debugfs_create_u16("pulse_power", 0600, dir,586&dev->radar_pattern.power);587debugfs_create_file("radar_trigger", 0200, dir, dev,588&fops_radar_pattern);589}590591debugfs_create_file("reset_test", 0200, dir, dev,592&fops_reset_test);593debugfs_create_file("ext_mac_addr", 0600, dir, dev, &fops_ext_mac_addr);594595debugfs_create_u32("rf_wfidx", 0600, dir, &dev->debugfs_rf_wf);596debugfs_create_u32("rf_regidx", 0600, dir, &dev->debugfs_rf_reg);597debugfs_create_file_unsafe("rf_regval", 0600, dir, dev,598&fops_rf_reg);599if (is_mt7663(&dev->mt76))600debugfs_create_file("chip_config", 0600, dir, dev,601&fops_config);602if (mt76_is_sdio(&dev->mt76))603debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir,604mt7663s_sched_quota_read);605606return 0;607}608EXPORT_SYMBOL_GPL(mt7615_init_debugfs);609610611