[][openwrt][mt7988][tops][add cpu utilization fetching]

[Description]
Add cpu utilization fetching and refactor debugfs of trm and tops

Via reading debugfs file(/sys/kernel/debug/tops/trm/cpu-utilization)
to fetch each core's cpu utilization

[Release-log]
N/A

Change-Id: Iff4c965294c3054a54ba92263191856cd5c722c7
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7907085
diff --git a/feed/tops-tool/src/inc/dump.h b/feed/tops-tool/src/inc/dump.h
index 0d331c9..69b4340 100644
--- a/feed/tops-tool/src/inc/dump.h
+++ b/feed/tops-tool/src/inc/dump.h
@@ -12,7 +12,7 @@
 
 #define DUMP_INFO_NAME_MAX_LEN		32
 #define RELAY_DUMP_SUBBUF_SIZE		2048
-#define DUMP_DATA_PATH			"/sys/kernel/debug/tops/dump_data"
+#define DUMP_DATA_PATH			"/sys/kernel/debug/tops/trm/dump-data"
 
 #define DUMP_LOG_FMT(FMT) "[TOPS_TOOL] [%s]: " FMT, __func__
 
diff --git a/package-21.02/kernel/tops/src/Makefile b/package-21.02/kernel/tops/src/Makefile
index 820ebb4..845f657 100644
--- a/package-21.02/kernel/tops/src/Makefile
+++ b/package-21.02/kernel/tops/src/Makefile
@@ -24,6 +24,7 @@
 tops-y += tdma.o
 tops-y += trm-fs.o
 tops-y += trm-mcu.o
+tops-y += trm-debugfs.o
 tops-y += trm.o
 tops-y += wdt.o
 
diff --git a/package-21.02/kernel/tops/src/inc/debugfs.h b/package-21.02/kernel/tops/src/inc/debugfs.h
new file mode 100644
index 0000000..ea1847c
--- /dev/null
+++ b/package-21.02/kernel/tops/src/inc/debugfs.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2023 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Alvin Kuo <alvin.kuo@mediatek.com>
+ */
+
+#ifndef _TOPS_DEBUGFS_H_
+#define _TOPS_DEBUGFS_H_
+
+extern struct dentry *tops_debugfs_root;
+
+#endif /* _TOPS_DEBUGFS_H_ */
diff --git a/package-21.02/kernel/tops/src/inc/mbox_id.h b/package-21.02/kernel/tops/src/inc/mbox_id.h
index bb46250..4ce3f6d 100644
--- a/package-21.02/kernel/tops/src/inc/mbox_id.h
+++ b/package-21.02/kernel/tops/src/inc/mbox_id.h
@@ -20,6 +20,7 @@
 	MBOX_AP2CM_CMD_CORE_CTRL = 0,
 	MBOX_AP2CM_CMD_NET = 1,
 	MBOX_AP2CM_CMD_WDT = 2,
+	MBOX_AP2CM_CMD_TRM = 3,
 	MBOX_AP2CM_CMD_TNL_OFFLOAD = 11,
 	MBOX_AP2CM_CMD_TEST = 31,
 	__MBOX_AP2CM_CMD_MAX = 32,
@@ -35,6 +36,7 @@
 	MBOX_AP2CX_CMD_CORE_CTRL = 0,
 	MBOX_AP2CX_CMD_NET = 1,
 	MBOX_AP2CX_CMD_WDT = 2,
+	MBOX_AP2CX_CMD_TRM = 3,
 	__MBOX_AP2CX_CMD_MAX = 32,
 };
 
diff --git a/package-21.02/kernel/tops/src/inc/trm-debugfs.h b/package-21.02/kernel/tops/src/inc/trm-debugfs.h
new file mode 100644
index 0000000..5425485
--- /dev/null
+++ b/package-21.02/kernel/tops/src/inc/trm-debugfs.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2023 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Alvin Kuo <alvin.kuo@mediatek.com>
+ */
+
+#ifndef _TRM_DEBUGFS_H_
+#define _TRM_DEBUGFS_H_
+
+#include <linux/debugfs.h>
+
+extern struct dentry *trm_debugfs_root;
+
+int mtk_trm_debugfs_init(void);
+void mtk_trm_debugfs_deinit(void);
+#endif /* _TRM_DEBUGFS_H_ */
diff --git a/package-21.02/kernel/tops/src/inc/trm.h b/package-21.02/kernel/tops/src/inc/trm.h
index 4b5118f..2acf54a 100644
--- a/package-21.02/kernel/tops/src/inc/trm.h
+++ b/package-21.02/kernel/tops/src/inc/trm.h
@@ -56,6 +56,13 @@
 #define TRM_RSN_FE_RESET			(TRM_RSN(FE_RESET))
 #define TRM_RSN_MCU_STATE_ACT_FAIL		(TRM_RSN(MCU_STATE_ACT_FAIL))
 
+enum trm_cmd_type {
+	TRM_CMD_TYPE_NULL,
+	TRM_CMD_TYPE_CPU_UTILIZATION,
+
+	__TRM_CMD_TYPE_MAX,
+};
+
 enum trm_config_flag {
 	TRM_CONFIG_F_ENABLE_BIT,
 	TRM_CONFIG_F_CORE_DUMP_BIT,
@@ -97,6 +104,7 @@
 	int (*trm_hw_dump)(void *dst, u32 ofs, u32 len);
 };
 
+int mtk_trm_cpu_utilization(enum core_id core, u32 *cpu_utilization);
 int mtk_trm_dump(u32 dump_rsn);
 int mtk_trm_cfg_setup(char *name, u32 offset, u32 size, u8 enable);
 int mtk_tops_trm_init(void);
diff --git a/package-21.02/kernel/tops/src/init.c b/package-21.02/kernel/tops/src/init.c
index 8c47546..05a7fe4 100644
--- a/package-21.02/kernel/tops/src/init.c
+++ b/package-21.02/kernel/tops/src/init.c
@@ -9,6 +9,7 @@
 #include <linux/err.h>
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/debugfs.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 
@@ -29,6 +30,7 @@
 #include "wdt.h"
 
 struct device *tops_dev;
+struct dentry *tops_debugfs_root;
 
 static int mtk_tops_post_init(struct platform_device *pdev)
 {
@@ -200,6 +202,12 @@
 
 static int __init mtk_tops_init(void)
 {
+	tops_debugfs_root = debugfs_create_dir("tops", NULL);
+	if (IS_ERR(tops_debugfs_root)) {
+		TOPS_ERR("create tops debugfs root directory failed\n");
+		return PTR_ERR(tops_debugfs_root);
+	}
+
 	mtk_tops_mbox_init();
 
 	mtk_tops_hpdma_init();
@@ -218,6 +226,8 @@
 	mtk_tops_hpdma_exit();
 
 	mtk_tops_mbox_exit();
+
+	debugfs_remove_recursive(tops_debugfs_root);
 }
 
 module_init(mtk_tops_init);
diff --git a/package-21.02/kernel/tops/src/trm-debugfs.c b/package-21.02/kernel/tops/src/trm-debugfs.c
new file mode 100644
index 0000000..66c64f3
--- /dev/null
+++ b/package-21.02/kernel/tops/src/trm-debugfs.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Alvin Kuo <alvin.kuog@mediatek.com>
+ */
+
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#include "debugfs.h"
+#include "internal.h"
+#include "tops.h"
+#include "trm-debugfs.h"
+#include "trm.h"
+
+struct dentry *trm_debugfs_root;
+
+static int cpu_utilization_debug_read(struct seq_file *s, void *private)
+{
+	u32 cpu_utilization;
+	enum core_id core;
+	int ret;
+
+	seq_puts(s, "CPU Utilization:\n");
+	for (core = CORE_OFFLOAD_0; core <= CORE_MGMT; core++) {
+		ret = mtk_trm_cpu_utilization(core, &cpu_utilization);
+		if (ret) {
+			if (core <= CORE_OFFLOAD_3)
+				TOPS_ERR("fetch Core%d cpu utilization failed(%d)\n", core, ret);
+			else
+				TOPS_ERR("fetch CoreM cpu utilization failed(%d)\n", ret);
+
+			return ret;
+		}
+
+		if (core <= CORE_OFFLOAD_3)
+			seq_printf(s, "Core%d\t\t%u%%\n", core, cpu_utilization);
+		else
+			seq_printf(s, "CoreM\t\t%u%%\n", cpu_utilization);
+	}
+
+	return 0;
+}
+
+static int cpu_utilization_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, cpu_utilization_debug_read, file->private_data);
+}
+
+static ssize_t cpu_utilization_debug_write(struct file *file,
+					   const char __user *buffer,
+					   size_t count, loff_t *data)
+{
+	return count;
+}
+
+static const struct file_operations cpu_utilization_debug_ops = {
+	.open = cpu_utilization_debug_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.write = cpu_utilization_debug_write,
+	.release = single_release,
+};
+
+int mtk_trm_debugfs_init(void)
+{
+	if (!tops_debugfs_root)
+		return -ENOENT;
+
+	if (!trm_debugfs_root) {
+		trm_debugfs_root = debugfs_create_dir("trm", tops_debugfs_root);
+		if (IS_ERR(trm_debugfs_root)) {
+			TOPS_ERR("create trm debugfs root directory failed\n");
+			return PTR_ERR(trm_debugfs_root);
+		}
+	}
+
+	debugfs_create_file("cpu-utilization", 0644, trm_debugfs_root, NULL,
+			    &cpu_utilization_debug_ops);
+
+	return 0;
+}
+
+void mtk_trm_debugfs_deinit(void)
+{
+	debugfs_remove_recursive(trm_debugfs_root);
+}
diff --git a/package-21.02/kernel/tops/src/trm-fs.c b/package-21.02/kernel/tops/src/trm-fs.c
index 3728ee1..81ae77a 100644
--- a/package-21.02/kernel/tops/src/trm-fs.c
+++ b/package-21.02/kernel/tops/src/trm-fs.c
@@ -11,13 +11,13 @@
 #include <linux/err.h>
 #include <linux/relay.h>
 
+#include "trm-debugfs.h"
 #include "trm-fs.h"
 #include "trm-mcu.h"
 #include "trm.h"
 
 #define RLY_RETRY_NUM				3
 
-static struct dentry *debugfs_dir;
 static struct rchan *relay;
 static bool trm_fs_is_init;
 
@@ -56,7 +56,7 @@
 {
 	struct dentry *debugfs_file;
 
-	debugfs_file = debugfs_create_file("dump_data", mode,
+	debugfs_file = debugfs_create_file("dump-data", mode,
 					   parent, buf,
 					   &relay_file_operations);
 
@@ -80,39 +80,22 @@
 	};
 	int ret = 0;
 
-	if (!debugfs_dir) {
-		debugfs_dir = debugfs_create_dir("tops", NULL);
-		if (IS_ERR(debugfs_dir)) {
-			ret = PTR_ERR(debugfs_dir);
-			goto out;
-		}
-	}
+	if (!trm_debugfs_root)
+		return -ENOENT;
 
 	if (!relay) {
-		relay = relay_open("dump_data", debugfs_dir,
+		relay = relay_open("dump-data", trm_debugfs_root,
 				   RLY_DUMP_SUBBUF_SZ,
 				   RLY_DUMP_SUBBUF_NUM,
 				   &relay_cb, NULL);
-		if (!relay) {
-			ret = -EINVAL;
-			goto err_debugfs_remove;
-		}
+		if (!relay)
+			return -EINVAL;
 	}
 
 	relay_reset(relay);
 
 	trm_fs_is_init = true;
 
-out:
-	return ret;
-
-err_debugfs_remove:
-	trm_fs_is_init = false;
-
-	debugfs_remove(debugfs_dir);
-
-	debugfs_dir = NULL;
-
 	return ret;
 }
 
@@ -121,6 +104,4 @@
 	trm_fs_is_init = false;
 
 	relay_close(relay);
-
-	debugfs_remove(debugfs_dir);
 }
diff --git a/package-21.02/kernel/tops/src/trm-mcu.c b/package-21.02/kernel/tops/src/trm-mcu.c
index 4550122..b475dc0 100644
--- a/package-21.02/kernel/tops/src/trm-mcu.c
+++ b/package-21.02/kernel/tops/src/trm-mcu.c
@@ -14,6 +14,7 @@
 
 #include "internal.h"
 #include "mcu.h"
+#include "trm-debugfs.h"
 #include "trm-fs.h"
 #include "trm-mcu.h"
 #include "trm.h"
@@ -342,6 +343,10 @@
 	if (!ocd.base)
 		return -ENOMEM;
 
+	ret = mtk_trm_debugfs_init();
+	if (ret)
+		return ret;
+
 	ret = mtk_trm_fs_init();
 	if (ret)
 		return ret;
@@ -355,6 +360,8 @@
 {
 	mtk_trm_fs_deinit();
 
+	mtk_trm_debugfs_deinit();
+
 	return 0;
 }
 
diff --git a/package-21.02/kernel/tops/src/trm.c b/package-21.02/kernel/tops/src/trm.c
index 5fdc909..a3f959f 100644
--- a/package-21.02/kernel/tops/src/trm.c
+++ b/package-21.02/kernel/tops/src/trm.c
@@ -17,6 +17,7 @@
 #include <linux/relay.h>
 #include <linux/types.h>
 
+#include "internal.h"
 #include "mbox.h"
 #include "mcu.h"
 #include "netsys.h"
@@ -28,6 +29,11 @@
 
 #define RLY_DUMP_SUBBUF_DATA_MAX		(RLY_DUMP_SUBBUF_SZ - TRM_HDR_LEN)
 
+struct tops_runtime_monitor {
+	struct mailbox_dev mgmt_send_mdev;
+	struct mailbox_dev offload_send_mdev[CORE_OFFLOAD_NUM];
+};
+
 struct trm_info {
 	char name[TRM_CONFIG_NAME_MAX_LEN];
 	u64 dump_time;
@@ -45,6 +51,15 @@
 
 struct device *trm_dev;
 
+static struct tops_runtime_monitor trm = {
+	.mgmt_send_mdev = MBOX_SEND_MGMT_DEV(TRM),
+	.offload_send_mdev = {
+		[CORE_OFFLOAD_0] = MBOX_SEND_OFFLOAD_DEV(0, TRM),
+		[CORE_OFFLOAD_1] = MBOX_SEND_OFFLOAD_DEV(1, TRM),
+		[CORE_OFFLOAD_2] = MBOX_SEND_OFFLOAD_DEV(2, TRM),
+		[CORE_OFFLOAD_3] = MBOX_SEND_OFFLOAD_DEV(3, TRM),
+	},
+};
 static struct trm_hw_config *trm_hw_configs[__TRM_HARDWARE_MAX];
 struct mutex trm_lock;
 
@@ -202,6 +217,55 @@
 		mtk_trm_fs_relay_flush();
 	}
 
+	return 0;
+}
+
+static void trm_cpu_utilization_ret_handler(void *priv,
+					    struct mailbox_msg *msg)
+{
+	u32 *cpu_utilization = priv;
+
+	/*
+	 * msg1: ticks of idle task
+	 * msg2: ticks of this statistic period
+	 */
+	if (msg->msg2 != 0)
+		*cpu_utilization = (msg->msg2 - msg->msg1) * 100U / msg->msg2;
+}
+
+int mtk_trm_cpu_utilization(enum core_id core, u32 *cpu_utilization)
+{
+	struct mailbox_dev *send_mdev;
+	struct mailbox_msg msg;
+	int ret;
+
+	if (core > CORE_MGMT || !cpu_utilization)
+		return -EINVAL;
+
+	if (!mtk_tops_mcu_alive()) {
+		TRM_ERR("mcu not alive\n");
+		return -EAGAIN;
+	}
+
+	memset(&msg, 0, sizeof(struct mailbox_msg));
+	msg.msg1 = TRM_CMD_TYPE_CPU_UTILIZATION;
+
+	*cpu_utilization = 0;
+
+	if (core == CORE_MGMT)
+		send_mdev = &trm.mgmt_send_mdev;
+	else
+		send_mdev = &trm.offload_send_mdev[core];
+
+	ret = mbox_send_msg(send_mdev,
+			    &msg,
+			    cpu_utilization,
+			    trm_cpu_utilization_ret_handler);
+	if (ret) {
+		TRM_ERR("send CPU_UTILIZATION cmd failed(%d)\n", ret);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -253,15 +317,64 @@
 	return ret;
 }
 
+static int mtk_tops_trm_register_mbox(void)
+{
+	int ret;
+	int i;
+
+	ret = register_mbox_dev(MBOX_SEND, &trm.mgmt_send_mdev);
+	if (ret) {
+		TRM_ERR("register trm mgmt mbox send failed: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < CORE_OFFLOAD_NUM; i++) {
+		ret = register_mbox_dev(MBOX_SEND, &trm.offload_send_mdev[i]);
+		if (ret) {
+			TRM_ERR("register trm offload %d mbox send failed: %d\n",
+				i, ret);
+			goto err_unregister_offload_mbox;
+		}
+	}
+
+	return ret;
+
+err_unregister_offload_mbox:
+	for (i -= 1; i >= 0; i--)
+		unregister_mbox_dev(MBOX_SEND, &trm.offload_send_mdev[i]);
+
+	unregister_mbox_dev(MBOX_SEND, &trm.mgmt_send_mdev);
+
+	return ret;
+}
+
+static void mtk_tops_trm_unregister_mbox(void)
+{
+	int i;
+
+	unregister_mbox_dev(MBOX_SEND, &trm.mgmt_send_mdev);
+
+	for (i = 0; i < CORE_OFFLOAD_NUM; i++)
+		unregister_mbox_dev(MBOX_SEND, &trm.offload_send_mdev[i]);
+}
+
 int __init mtk_tops_trm_init(void)
 {
+	int ret;
+
 	mutex_init(&trm_lock);
 
+	ret = mtk_tops_trm_register_mbox();
+	if (ret)
+		return ret;
+
 	return mtk_tops_trm_mcu_init();
 }
 
 void __exit mtk_tops_trm_exit(void)
 {
+	mtk_tops_trm_unregister_mbox();
+
 	mtk_tops_trm_mcu_exit();
 }