Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: ISC
0002 /* Copyright (C) 2020 MediaTek Inc. */
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     /* Tx ampdu stat */
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     /* make sure the chip is awake here and ps_work is scheduled
0283      * just at end of the this routine.
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         /* Reset wifisys directly. */
0400         mt7921_reset(&dev->mt76);
0401         break;
0402     default:
0403         /* Collect the core dump before reset wifisys. */
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 }