unplugged-kernel/drivers/misc/mediatek/performance/gbe/gbe_common.c

285 lines
6.5 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 MediaTek Inc.
*/
#include <linux/sched/clock.h>
#include <linux/sched/mm.h>
#include <linux/sched/numa_balancing.h>
#include <linux/sched/task_stack.h>
#include <linux/sched/task.h>
#include <linux/sched/cputime.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/kallsyms.h>
#include <linux/trace_events.h>
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/miscdevice.h> /* for misc_register, and SYNTH_MINOR */
#include <linux/proc_fs.h>
#include "cpu_ctrl.h"
#include "eas_ctrl.h"
#include <linux/workqueue.h>
#include <linux/unistd.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/pm_qos.h>
#include "gbe_common.h"
#include "gbe1.h"
#include "gbe2.h"
#include "gbe_sysfs.h"
static DEFINE_MUTEX(gbe_lock);
static int boost_set[KIR_NUM];
static unsigned long policy_mask;
enum GBE_BOOST_DEVICE {
GBE_BOOST_UNKNOWN = -1,
GBE_BOOST_CPU = 0,
GBE_BOOST_EAS = 1,
GBE_BOOST_VCORE = 2,
GBE_BOOST_IO = 3,
GBE_BOOST_HE = 4,
GBE_BOOST_GPU = 5,
GBE_BOOST_LLF = 6,
GBE_BOOST_NUM = 7,
};
static unsigned long __read_mostly tracing_mark_write_addr;
static inline void __mt_update_tracing_mark_write_addr(void)
{
if (unlikely(tracing_mark_write_addr == 0))
tracing_mark_write_addr =
kallsyms_lookup_name("tracing_mark_write");
}
void gbe_trace_printk(int pid, char *module, char *string)
{
__mt_update_tracing_mark_write_addr();
preempt_disable();
event_trace_printk(tracing_mark_write_addr, "%d [%s] %s\n",
pid, module, string);
preempt_enable();
}
void gbe_trace_count(int tid, unsigned long long bufID,
int val, const char *fmt, ...)
{
char log[32];
va_list args;
int len;
memset(log, ' ', sizeof(log));
va_start(args, fmt);
len = vsnprintf(log, sizeof(log), fmt, args);
va_end(args);
if (unlikely(len < 0))
return;
else if (unlikely(len == 32))
log[31] = '\0';
__mt_update_tracing_mark_write_addr();
preempt_disable();
if (!strstr(CONFIG_MTK_PLATFORM, "mt8")) {
if (!bufID)
event_trace_printk(tracing_mark_write_addr, "C|%d|%s|%d\n",
tid, log, val);
else
event_trace_printk(tracing_mark_write_addr, "C|%d|%s|%d|0x%llx\n",
tid, log, val, bufID);
} else {
event_trace_printk(tracing_mark_write_addr, "C|%s|%d\n",
log, val);
}
preempt_enable();
}
struct k_list {
struct list_head queue_list;
int gbe2pwr_cmd;
int gbe2pwr_value1;
int gbe2pwr_value2;
};
static LIST_HEAD(head);
static int condition_get_cmd;
static DEFINE_MUTEX(gbe2pwr_lock);
static DECLARE_WAIT_QUEUE_HEAD(pwr_queue);
void gbe_sentcmd(int cmd, int value1, int value2)
{
static struct k_list *node;
mutex_lock(&gbe2pwr_lock);
node = kmalloc(sizeof(*node), GFP_KERNEL);
if (node == NULL)
goto out;
node->gbe2pwr_cmd = cmd;
node->gbe2pwr_value1 = value1;
node->gbe2pwr_value2 = value2;
list_add_tail(&node->queue_list, &head);
condition_get_cmd = 1;
out:
mutex_unlock(&gbe2pwr_lock);
wake_up_interruptible(&pwr_queue);
}
void gbe_ctrl2base_get_pwr_cmd(int *cmd, int *value1, int *value2)
{
static struct k_list *node;
wait_event_interruptible(pwr_queue, condition_get_cmd);
mutex_lock(&gbe2pwr_lock);
if (!list_empty(&head)) {
node = list_first_entry(&head, struct k_list, queue_list);
*cmd = node->gbe2pwr_cmd;
*value1 = node->gbe2pwr_value1;
*value2 = node->gbe2pwr_value2;
list_del(&node->queue_list);
kfree(node);
}
if (list_empty(&head))
condition_get_cmd = 0;
mutex_unlock(&gbe2pwr_lock);
}
void gbe_boost(enum GBE_KICKER kicker, int boost)
{
int i;
int boost_final = 0;
int cpu_boost = 0, eas_boost = -1, vcore_boost = -1,
io_boost = 0, he_boost = 0, gpu_boost = 0,
llf_boost = 0;
mutex_lock(&gbe_lock);
if (boost_set[kicker] == !!boost)
goto out;
boost_set[kicker] = !!boost;
for (i = 0; i < KIR_NUM; i++)
if (boost_set[i] == 1) {
boost_final = 1;
break;
}
if (boost_final) {
cpu_boost = 1;
eas_boost = 100;
vcore_boost = 0;
io_boost = 1;
he_boost = 1;
gpu_boost = 1;
llf_boost = 1;
}
if (test_bit(GBE_BOOST_CPU, &policy_mask))
gbe_sentcmd(GBE_BOOST_CPU, cpu_boost, -1);
if (test_bit(GBE_BOOST_EAS, &policy_mask))
gbe_sentcmd(GBE_BOOST_EAS, eas_boost, -1);
if (test_bit(GBE_BOOST_VCORE, &policy_mask))
gbe_sentcmd(GBE_BOOST_VCORE, vcore_boost, -1);
if (test_bit(GBE_BOOST_IO, &policy_mask))
gbe_sentcmd(GBE_BOOST_IO, io_boost, -1);
if (test_bit(GBE_BOOST_HE, &policy_mask))
gbe_sentcmd(GBE_BOOST_HE, he_boost, -1);
if (test_bit(GBE_BOOST_GPU, &policy_mask))
gbe_sentcmd(GBE_BOOST_GPU, gpu_boost, -1);
if (test_bit(GBE_BOOST_LLF, &policy_mask))
gbe_sentcmd(GBE_BOOST_LLF, llf_boost, -1);
out:
mutex_unlock(&gbe_lock);
}
static ssize_t gbe_policy_mask_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%d\n", policy_mask);
}
static ssize_t gbe_policy_mask_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
int val = 0;
char acBuffer[GBE_SYSFS_MAX_BUFF_SIZE];
int arg;
int cpu_boost = 0, eas_boost = -1, vcore_boost = -1,
io_boost = 0, he_boost = 0, gpu_boost = 0,
llf_boost = 0;
if ((count > 0) && (count < GBE_SYSFS_MAX_BUFF_SIZE)) {
if (scnprintf(acBuffer, GBE_SYSFS_MAX_BUFF_SIZE, "%s", buf)) {
if (kstrtoint(acBuffer, 0, &arg) == 0)
val = arg;
else
return count;
}
}
if (val > 1 << GBE_BOOST_NUM || val < 0)
return count;
mutex_lock(&gbe_lock);
policy_mask = val;
gbe_sentcmd(GBE_BOOST_CPU, cpu_boost, -1);
gbe_sentcmd(GBE_BOOST_EAS, eas_boost, -1);
gbe_sentcmd(GBE_BOOST_VCORE, vcore_boost, -1);
gbe_sentcmd(GBE_BOOST_IO, io_boost, -1);
gbe_sentcmd(GBE_BOOST_HE, he_boost, -1);
gbe_sentcmd(GBE_BOOST_GPU, gpu_boost, -1);
gbe_sentcmd(GBE_BOOST_LLF, llf_boost, -1);
mutex_unlock(&gbe_lock);
return count;
}
static KOBJ_ATTR_RW(gbe_policy_mask);
static void __exit gbe_common_exit(void)
{
gbe_sysfs_remove_file(&kobj_attr_gbe_policy_mask);
gbe_sysfs_exit();
}
struct dentry *gbe_debugfs_dir;
static int __init gbe_common_init(void)
{
gbe_get_cmd_fp = gbe_ctrl2base_get_pwr_cmd;
gbe_sysfs_init();
gbe1_init();
gbe2_init();
gbe_sysfs_create_file(&kobj_attr_gbe_policy_mask);
set_bit(GBE_BOOST_CPU, &policy_mask);
set_bit(GBE_BOOST_EAS, &policy_mask);
set_bit(GBE_BOOST_VCORE, &policy_mask);
set_bit(GBE_BOOST_HE, &policy_mask);
return 0;
}
module_init(gbe_common_init);
module_exit(gbe_common_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MediaTek GBE");
MODULE_AUTHOR("MediaTek Inc.");