162306a36Sopenharmony_ci// SPDX-License-Identifier: ISC
262306a36Sopenharmony_ci/* Copyright (C) 2023 MediaTek Inc. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "mt792x.h"
562306a36Sopenharmony_ci
662306a36Sopenharmony_cistatic void
762306a36Sopenharmony_cimt792x_ampdu_stat_read_phy(struct mt792x_phy *phy,
862306a36Sopenharmony_ci			   struct seq_file *file)
962306a36Sopenharmony_ci{
1062306a36Sopenharmony_ci	struct mt792x_dev *dev = file->private;
1162306a36Sopenharmony_ci	int bound[15], range[4], i;
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci	if (!phy)
1462306a36Sopenharmony_ci		return;
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	mt792x_mac_update_mib_stats(phy);
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	/* Tx ampdu stat */
1962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(range); i++)
2062306a36Sopenharmony_ci		range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i));
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(bound); i++)
2362306a36Sopenharmony_ci		bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	seq_puts(file, "\nPhy0\n");
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	seq_printf(file, "Length: %8d | ", bound[0]);
2862306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)
2962306a36Sopenharmony_ci		seq_printf(file, "%3d  %3d | ", bound[i] + 1, bound[i + 1]);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	seq_puts(file, "\nCount:  ");
3262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(bound); i++)
3362306a36Sopenharmony_ci		seq_printf(file, "%8d | ", phy->mt76->aggr_stats[i]);
3462306a36Sopenharmony_ci	seq_puts(file, "\n");
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ciint mt792x_tx_stats_show(struct seq_file *file, void *data)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	struct mt792x_dev *dev = file->private;
4262306a36Sopenharmony_ci	struct mt792x_phy *phy = &dev->phy;
4362306a36Sopenharmony_ci	struct mt76_mib_stats *mib = &phy->mib;
4462306a36Sopenharmony_ci	int i;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	mt792x_mutex_acquire(dev);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	mt792x_ampdu_stat_read_phy(phy, file);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	seq_puts(file, "Tx MSDU stat:\n");
5162306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
5262306a36Sopenharmony_ci		seq_printf(file, "AMSDU pack count of %d MSDU in TXD: %8d ",
5362306a36Sopenharmony_ci			   i + 1, mib->tx_amsdu[i]);
5462306a36Sopenharmony_ci		if (mib->tx_amsdu_cnt)
5562306a36Sopenharmony_ci			seq_printf(file, "(%3d%%)\n",
5662306a36Sopenharmony_ci				   mib->tx_amsdu[i] * 100 / mib->tx_amsdu_cnt);
5762306a36Sopenharmony_ci		else
5862306a36Sopenharmony_ci			seq_puts(file, "\n");
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	mt792x_mutex_release(dev);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	return 0;
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_tx_stats_show);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ciint mt792x_queues_acq(struct seq_file *s, void *data)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	struct mt792x_dev *dev = dev_get_drvdata(s->private);
7062306a36Sopenharmony_ci	int i;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	mt792x_mutex_acquire(dev);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
7562306a36Sopenharmony_ci		u32 ctrl, val, qlen = 0;
7662306a36Sopenharmony_ci		int j;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci		val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i));
7962306a36Sopenharmony_ci		ctrl = BIT(31) | BIT(11) | (i << 24);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci		for (j = 0; j < 32; j++) {
8262306a36Sopenharmony_ci			if (val & BIT(j))
8362306a36Sopenharmony_ci				continue;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci			mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j);
8662306a36Sopenharmony_ci			qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
8762306a36Sopenharmony_ci					       GENMASK(11, 0));
8862306a36Sopenharmony_ci		}
8962306a36Sopenharmony_ci		seq_printf(s, "AC%d: queued=%d\n", i, qlen);
9062306a36Sopenharmony_ci	}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	mt792x_mutex_release(dev);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	return 0;
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_queues_acq);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ciint mt792x_queues_read(struct seq_file *s, void *data)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	struct mt792x_dev *dev = dev_get_drvdata(s->private);
10162306a36Sopenharmony_ci	struct {
10262306a36Sopenharmony_ci		struct mt76_queue *q;
10362306a36Sopenharmony_ci		char *queue;
10462306a36Sopenharmony_ci	} queue_map[] = {
10562306a36Sopenharmony_ci		{ dev->mphy.q_tx[MT_TXQ_BE],	 "WFDMA0" },
10662306a36Sopenharmony_ci		{ dev->mt76.q_mcu[MT_MCUQ_WM],	 "MCUWM"  },
10762306a36Sopenharmony_ci		{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },
10862306a36Sopenharmony_ci	};
10962306a36Sopenharmony_ci	int i;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
11262306a36Sopenharmony_ci		struct mt76_queue *q = queue_map[i].q;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci		if (!q)
11562306a36Sopenharmony_ci			continue;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci		seq_printf(s,
11862306a36Sopenharmony_ci			   "%s:	queued=%d head=%d tail=%d\n",
11962306a36Sopenharmony_ci			   queue_map[i].queue, q->queued, q->head,
12062306a36Sopenharmony_ci			   q->tail);
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	return 0;
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_queues_read);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ciint mt792x_pm_stats(struct seq_file *s, void *data)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	struct mt792x_dev *dev = dev_get_drvdata(s->private);
13062306a36Sopenharmony_ci	struct mt76_connac_pm *pm = &dev->pm;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	unsigned long awake_time = pm->stats.awake_time;
13362306a36Sopenharmony_ci	unsigned long doze_time = pm->stats.doze_time;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	if (!test_bit(MT76_STATE_PM, &dev->mphy.state))
13662306a36Sopenharmony_ci		awake_time += jiffies - pm->stats.last_wake_event;
13762306a36Sopenharmony_ci	else
13862306a36Sopenharmony_ci		doze_time += jiffies - pm->stats.last_doze_event;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	seq_printf(s, "awake time: %14u\ndoze time: %15u\n",
14162306a36Sopenharmony_ci		   jiffies_to_msecs(awake_time),
14262306a36Sopenharmony_ci		   jiffies_to_msecs(doze_time));
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	seq_printf(s, "low power wakes: %9d\n", pm->stats.lp_wake);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	return 0;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_pm_stats);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ciint mt792x_pm_idle_timeout_set(void *data, u64 val)
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	struct mt792x_dev *dev = data;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	dev->pm.idle_timeout = msecs_to_jiffies(val);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	return 0;
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_pm_idle_timeout_set);
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ciint mt792x_pm_idle_timeout_get(void *data, u64 *val)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	struct mt792x_dev *dev = data;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	*val = jiffies_to_msecs(dev->pm.idle_timeout);
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	return 0;
16762306a36Sopenharmony_ci}
16862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_pm_idle_timeout_get);
169