525 lines
12 KiB
C
525 lines
12 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
#include "perf_ioctl.h"
|
|
|
|
#if defined(CONFIG_MTK_FPSGO) || defined(CONFIG_MTK_FPSGO_V3)
|
|
#include "tchbst.h"
|
|
#include "io_ctrl.h"
|
|
#endif
|
|
|
|
#define TAG "PERF_IOCTL"
|
|
|
|
void (*fpsgo_notify_qudeq_fp)(int qudeq,
|
|
unsigned int startend,
|
|
int pid, unsigned long long identifier);
|
|
void (*fpsgo_notify_connect_fp)(int pid,
|
|
int connectedAPI, unsigned long long identifier);
|
|
void (*fpsgo_notify_bqid_fp)(int pid, unsigned long long bufID,
|
|
int queue_SF, unsigned long long identifier, int create);
|
|
void (*fpsgo_notify_vsync_fp)(void);
|
|
void (*fpsgo_get_fps_fp)(int *pid, int *fps);
|
|
void (*fpsgo_notify_nn_job_begin_fp)(unsigned int tid, unsigned long long mid);
|
|
void (*fpsgo_notify_nn_job_end_fp)(int pid, int tid, unsigned long long mid,
|
|
int num_step, __s32 *boost, __s32 *device, __u64 *exec_time);
|
|
int (*fpsgo_get_nn_priority_fp)(unsigned int pid, unsigned long long mid);
|
|
void (*fpsgo_get_nn_ttime_fp)(unsigned int pid, unsigned long long mid,
|
|
int num_step, __u64 *ttime);
|
|
|
|
void (*rsu_getusage_fp)(__s32 *devusage, __u32 *bwusage, __u32 pid);
|
|
void (*rsu_getstate_fp)(int *throttled);
|
|
void (*fpsgo_notify_swap_buffer_fp)(int pid);
|
|
|
|
void (*gbe_get_cmd_fp)(int *cmd, int *value1, int *value2);
|
|
void (*perf_rsi_getindex_fp)(__s32 *data, __s32 input_size);
|
|
void (*perf_rsi_switch_collect_fp)(__s32 cmd);
|
|
|
|
static unsigned long perfctl_copy_from_user(void *pvTo,
|
|
const void __user *pvFrom, unsigned long ulBytes)
|
|
{
|
|
if (access_ok(VERIFY_READ, pvFrom, ulBytes))
|
|
return __copy_from_user(pvTo, pvFrom, ulBytes);
|
|
|
|
return ulBytes;
|
|
}
|
|
|
|
static unsigned long perfctl_copy_to_user(void __user *pvTo,
|
|
const void *pvFrom, unsigned long ulBytes)
|
|
{
|
|
if (access_ok(VERIFY_WRITE, pvTo, ulBytes))
|
|
return __copy_to_user(pvTo, pvFrom, ulBytes);
|
|
|
|
return ulBytes;
|
|
}
|
|
|
|
static void perfctl_notify_fpsgo_nn_begin(
|
|
struct _EARA_NN_PACKAGE *msgKM,
|
|
struct _EARA_NN_PACKAGE *msgUM)
|
|
{
|
|
int arr_length;
|
|
__u64 *__target_time = NULL;
|
|
|
|
if (!fpsgo_notify_nn_job_begin_fp || !fpsgo_get_nn_ttime_fp)
|
|
return;
|
|
|
|
fpsgo_notify_nn_job_begin_fp(msgKM->tid, msgKM->mid);
|
|
|
|
arr_length = msgKM->num_step * MAX_DEVICE;
|
|
__target_time =
|
|
kcalloc(arr_length, sizeof(__u64), GFP_KERNEL);
|
|
|
|
if (!__target_time)
|
|
return;
|
|
|
|
fpsgo_get_nn_ttime_fp(msgKM->pid,
|
|
msgKM->mid, msgKM->num_step, __target_time);
|
|
|
|
if (msgKM->target_time)
|
|
perfctl_copy_to_user(msgKM->target_time,
|
|
__target_time, arr_length * sizeof(__u64));
|
|
|
|
kfree(__target_time);
|
|
}
|
|
|
|
static void perfctl_notify_fpsgo_nn_end(
|
|
struct _EARA_NN_PACKAGE *msgKM,
|
|
struct _EARA_NN_PACKAGE *msgUM)
|
|
{
|
|
__s32 *boost, *device;
|
|
__u64 *exec_time;
|
|
int size;
|
|
|
|
if (!fpsgo_notify_nn_job_end_fp || !fpsgo_get_nn_priority_fp)
|
|
return;
|
|
|
|
size = msgKM->num_step * MAX_DEVICE;
|
|
|
|
if (!msgKM->boost || !msgKM->device || !msgKM->exec_time)
|
|
goto out_um_malloc_fail;
|
|
|
|
boost = kmalloc_array(size, sizeof(__s32), GFP_KERNEL);
|
|
if (!boost)
|
|
goto out_boost_malloc_fail;
|
|
device = kmalloc_array(size, sizeof(__s32), GFP_KERNEL);
|
|
if (!device)
|
|
goto out_device_malloc_fail;
|
|
exec_time = kmalloc_array(size, sizeof(__u64), GFP_KERNEL);
|
|
if (!exec_time)
|
|
goto out_exec_time_malloc_fail;
|
|
|
|
perfctl_copy_from_user(boost,
|
|
msgKM->boost, size * sizeof(__s32));
|
|
perfctl_copy_from_user(device,
|
|
msgKM->device, size * sizeof(__s32));
|
|
perfctl_copy_from_user(exec_time,
|
|
msgKM->exec_time, size * sizeof(__u64));
|
|
|
|
fpsgo_notify_nn_job_end_fp(msgKM->pid, msgKM->tid, msgKM->mid,
|
|
msgKM->num_step, boost, device, exec_time);
|
|
|
|
msgKM->priority = fpsgo_get_nn_priority_fp(msgKM->pid, msgKM->mid);
|
|
|
|
perfctl_copy_to_user(msgUM, msgKM, sizeof(struct _EARA_NN_PACKAGE));
|
|
return;
|
|
|
|
out_exec_time_malloc_fail:
|
|
kfree(device);
|
|
out_device_malloc_fail:
|
|
kfree(boost);
|
|
out_boost_malloc_fail:
|
|
out_um_malloc_fail:
|
|
fpsgo_notify_nn_job_end_fp(msgKM->pid, msgKM->tid, msgKM->mid,
|
|
msgKM->num_step, NULL, NULL, NULL);
|
|
}
|
|
|
|
|
|
/*--------------------DEV OP------------------------*/
|
|
static int eara_show(struct seq_file *m, void *v)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int eara_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, eara_show, inode->i_private);
|
|
}
|
|
|
|
static long eara_ioctl_impl(struct file *filp,
|
|
unsigned int cmd, unsigned long arg, void *pKM)
|
|
{
|
|
ssize_t ret = 0;
|
|
struct _EARA_NN_PACKAGE *msgKM = NULL,
|
|
*msgUM = (struct _EARA_NN_PACKAGE *)arg;
|
|
struct _EARA_NN_PACKAGE smsgKM;
|
|
|
|
msgKM = (struct _EARA_NN_PACKAGE *)pKM;
|
|
if (!msgKM) {
|
|
msgKM = &smsgKM;
|
|
if (perfctl_copy_from_user(msgKM, msgUM,
|
|
sizeof(struct _EARA_NN_PACKAGE))) {
|
|
ret = -EFAULT;
|
|
goto ret_ioctl;
|
|
}
|
|
}
|
|
|
|
switch (cmd) {
|
|
case EARA_NN_BEGIN:
|
|
perfctl_notify_fpsgo_nn_begin(msgKM, msgUM);
|
|
break;
|
|
case EARA_NN_END:
|
|
perfctl_notify_fpsgo_nn_end(msgKM, msgUM);
|
|
break;
|
|
case EARA_GETUSAGE:
|
|
msgKM->bw_usage = 0;
|
|
|
|
if (rsu_getusage_fp)
|
|
rsu_getusage_fp(&msgKM->dev_usage, &msgKM->bw_usage,
|
|
msgKM->pid);
|
|
else
|
|
msgKM->dev_usage = 0;
|
|
|
|
perfctl_copy_to_user(msgUM, msgKM,
|
|
sizeof(struct _EARA_NN_PACKAGE));
|
|
|
|
break;
|
|
case EARA_GETSTATE:
|
|
if (rsu_getstate_fp)
|
|
rsu_getstate_fp(&msgKM->thrm_throttled);
|
|
else
|
|
msgKM->thrm_throttled = -1;
|
|
|
|
perfctl_copy_to_user(msgUM, msgKM,
|
|
sizeof(struct _EARA_NN_PACKAGE));
|
|
break;
|
|
default:
|
|
pr_debug(TAG "%s %d: unknown cmd %x\n",
|
|
__FILE__, __LINE__, cmd);
|
|
ret = -1;
|
|
goto ret_ioctl;
|
|
}
|
|
|
|
ret_ioctl:
|
|
return ret;
|
|
}
|
|
|
|
static long eara_ioctl(struct file *filp,
|
|
unsigned int cmd, unsigned long arg)
|
|
{
|
|
return eara_ioctl_impl(filp, cmd, arg, NULL);
|
|
}
|
|
|
|
static long eara_compat_ioctl(struct file *filp,
|
|
unsigned int cmd, unsigned long arg)
|
|
{
|
|
int ret = -EFAULT;
|
|
struct _EARA_NN_PACKAGE_32 {
|
|
__u32 pid;
|
|
__u32 tid;
|
|
__u64 mid;
|
|
__s32 errorno;
|
|
__s32 priority;
|
|
__s32 num_step;
|
|
|
|
__s32 dev_usage;
|
|
__u32 bw_usage;
|
|
__s32 thrm_throttled;
|
|
|
|
union {
|
|
__u32 device;
|
|
__u64 p_dummy_device;
|
|
};
|
|
union {
|
|
__u32 boost;
|
|
__u64 p_dummy_boost;
|
|
};
|
|
union {
|
|
__u32 exec_time;
|
|
__u64 p_dummy_exec_time;
|
|
};
|
|
union {
|
|
__u32 target_time;
|
|
__u64 p_dummy_target_time;
|
|
};
|
|
};
|
|
struct _EARA_NN_PACKAGE sEaraPackageKM64;
|
|
struct _EARA_NN_PACKAGE_32 sEaraPackageKM32;
|
|
struct _EARA_NN_PACKAGE_32 *psEaraPackageKM32 = &sEaraPackageKM32;
|
|
struct _EARA_NN_PACKAGE_32 *psEaraPackageUM32 =
|
|
(struct _EARA_NN_PACKAGE_32 *)arg;
|
|
|
|
if (perfctl_copy_from_user(psEaraPackageKM32,
|
|
psEaraPackageUM32, sizeof(struct _EARA_NN_PACKAGE_32)))
|
|
goto unlock_and_return;
|
|
|
|
sEaraPackageKM64 = *((struct _EARA_NN_PACKAGE *)psEaraPackageKM32);
|
|
sEaraPackageKM64.device =
|
|
(void *)((size_t) psEaraPackageKM32->device);
|
|
sEaraPackageKM64.boost =
|
|
(void *)((size_t) psEaraPackageKM32->boost);
|
|
sEaraPackageKM64.exec_time =
|
|
(void *)((size_t) psEaraPackageKM32->exec_time);
|
|
sEaraPackageKM64.target_time =
|
|
(void *)((size_t) psEaraPackageKM32->target_time);
|
|
|
|
ret = eara_ioctl_impl(filp, cmd, arg, &sEaraPackageKM64);
|
|
|
|
unlock_and_return:
|
|
return ret;
|
|
}
|
|
|
|
static const struct file_operations eara_Fops = {
|
|
.unlocked_ioctl = eara_ioctl,
|
|
.compat_ioctl = eara_compat_ioctl,
|
|
.open = eara_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
};
|
|
|
|
/*--------------------INIT------------------------*/
|
|
|
|
static int device_show(struct seq_file *m, void *v)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int device_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, device_show, inode->i_private);
|
|
}
|
|
|
|
static long device_ioctl(struct file *filp,
|
|
unsigned int cmd, unsigned long arg)
|
|
{
|
|
ssize_t ret = 0;
|
|
int pwr_pid = -1, pwr_fps = -1;
|
|
int pwr_cmd = -1, value1 = -1, value2 = -1;
|
|
struct _FPSGO_PACKAGE *msgKM = NULL,
|
|
*msgUM = (struct _FPSGO_PACKAGE *)arg;
|
|
struct _FPSGO_PACKAGE smsgKM;
|
|
|
|
msgKM = &smsgKM;
|
|
|
|
if (perfctl_copy_from_user(msgKM, msgUM,
|
|
sizeof(struct _FPSGO_PACKAGE))) {
|
|
ret = -EFAULT;
|
|
goto ret_ioctl;
|
|
}
|
|
|
|
switch (cmd) {
|
|
#if defined(CONFIG_MTK_FPSGO_V3)
|
|
case FPSGO_QUEUE:
|
|
if (fpsgo_notify_qudeq_fp)
|
|
fpsgo_notify_qudeq_fp(1,
|
|
msgKM->start, msgKM->tid,
|
|
msgKM->identifier);
|
|
break;
|
|
case FPSGO_DEQUEUE:
|
|
if (fpsgo_notify_qudeq_fp)
|
|
fpsgo_notify_qudeq_fp(0,
|
|
msgKM->start, msgKM->tid,
|
|
msgKM->identifier);
|
|
break;
|
|
case FPSGO_QUEUE_CONNECT:
|
|
if (fpsgo_notify_connect_fp)
|
|
fpsgo_notify_connect_fp(msgKM->tid,
|
|
msgKM->connectedAPI, msgKM->identifier);
|
|
break;
|
|
case FPSGO_BQID:
|
|
if (fpsgo_notify_bqid_fp)
|
|
fpsgo_notify_bqid_fp(msgKM->tid, msgKM->bufID,
|
|
msgKM->queue_SF, msgKM->identifier,
|
|
msgKM->start);
|
|
break;
|
|
case FPSGO_TOUCH:
|
|
usrtch_ioctl(cmd, msgKM->frame_time);
|
|
break;
|
|
case FPSGO_SWAP_BUFFER:
|
|
if (fpsgo_notify_swap_buffer_fp)
|
|
fpsgo_notify_swap_buffer_fp(msgKM->tid);
|
|
break;
|
|
case FPSGO_VSYNC:
|
|
if (fpsgo_notify_vsync_fp)
|
|
fpsgo_notify_vsync_fp();
|
|
break;
|
|
case FPSGO_GET_FPS:
|
|
if (fpsgo_get_fps_fp) {
|
|
fpsgo_get_fps_fp(&pwr_pid, &pwr_fps);
|
|
msgKM->tid = pwr_pid;
|
|
msgKM->value1 = pwr_fps;
|
|
} else
|
|
ret = -1;
|
|
perfctl_copy_to_user(msgUM, msgKM,
|
|
sizeof(struct _FPSGO_PACKAGE));
|
|
break;
|
|
case FPSGO_GET_CMD:
|
|
ret = -1;
|
|
break;
|
|
|
|
case FPSGO_GBE_GET_CMD:
|
|
if (gbe_get_cmd_fp) {
|
|
gbe_get_cmd_fp(&pwr_cmd, &value1, &value2);
|
|
msgKM->cmd = pwr_cmd;
|
|
msgKM->value1 = value1;
|
|
msgKM->value2 = value2;
|
|
} else
|
|
ret = -1;
|
|
perfctl_copy_to_user(msgUM, msgKM,
|
|
sizeof(struct _FPSGO_PACKAGE));
|
|
break;
|
|
|
|
#else
|
|
case FPSGO_QUEUE:
|
|
/* FALLTHROUGH */
|
|
case FPSGO_DEQUEUE:
|
|
/* FALLTHROUGH */
|
|
case FPSGO_QUEUE_CONNECT:
|
|
/* FALLTHROUGH */
|
|
case FPSGO_VSYNC:
|
|
/* FALLTHROUGH */
|
|
case FPSGO_BQID:
|
|
/* FALLTHROUGH */
|
|
case FPSGO_TOUCH:
|
|
/* FALLTHROUGH */
|
|
case FPSGO_SWAP_BUFFER:
|
|
break;
|
|
case FPSGO_GET_FPS:
|
|
pwr_pid = -1;
|
|
pwr_fps = -1;
|
|
ret = -1;
|
|
break;
|
|
case FPSGO_GET_CMD:
|
|
ret = -1;
|
|
break;
|
|
case FPSGO_GBE_GET_CMD:
|
|
pwr_cmd = -1;
|
|
value1 = -1;
|
|
value2 = -1;
|
|
ret = -1;
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
pr_debug(TAG "%s %d: unknown cmd %x\n",
|
|
__FILE__, __LINE__, cmd);
|
|
ret = -1;
|
|
goto ret_ioctl;
|
|
}
|
|
|
|
ret_ioctl:
|
|
return ret;
|
|
}
|
|
|
|
static int earasys_show(struct seq_file *m, void *v)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int earasys_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, earasys_show, inode->i_private);
|
|
}
|
|
|
|
static long earasys_ioctl(struct file *filp,
|
|
unsigned int cmd, unsigned long arg)
|
|
{
|
|
ssize_t ret = 0;
|
|
struct _EARA_SYS_PACKAGE *msgKM = NULL;
|
|
struct _EARA_SYS_PACKAGE *msgUM = (struct _EARA_SYS_PACKAGE *)arg;
|
|
struct _EARA_SYS_PACKAGE smsgKM = {0};
|
|
|
|
msgKM = &smsgKM;
|
|
|
|
switch (cmd) {
|
|
case EARA_GETINDEX:
|
|
if (perf_rsi_getindex_fp)
|
|
perf_rsi_getindex_fp(smsgKM.data, sizeof(struct _EARA_SYS_PACKAGE));
|
|
|
|
perfctl_copy_to_user(msgUM, msgKM,
|
|
sizeof(struct _EARA_SYS_PACKAGE));
|
|
|
|
break;
|
|
case EARA_COLLECT:
|
|
if (perfctl_copy_from_user(msgKM, msgUM,
|
|
sizeof(struct _EARA_SYS_PACKAGE))) {
|
|
ret = -EFAULT;
|
|
goto ret_ioctl;
|
|
}
|
|
|
|
if (perf_rsi_switch_collect_fp)
|
|
perf_rsi_switch_collect_fp(msgKM->cmd);
|
|
break;
|
|
default:
|
|
pr_debug(TAG "%s %d: unknown cmd %x\n",
|
|
__FILE__, __LINE__, cmd);
|
|
ret = -1;
|
|
goto ret_ioctl;
|
|
}
|
|
|
|
ret_ioctl:
|
|
return ret;
|
|
}
|
|
|
|
static const struct file_operations earasys_Fops = {
|
|
.unlocked_ioctl = earasys_ioctl,
|
|
.compat_ioctl = earasys_ioctl,
|
|
.open = earasys_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
};
|
|
|
|
static const struct file_operations Fops = {
|
|
.unlocked_ioctl = device_ioctl,
|
|
.compat_ioctl = device_ioctl,
|
|
.open = device_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
};
|
|
|
|
/*--------------------INIT------------------------*/
|
|
int init_perfctl(struct proc_dir_entry *parent)
|
|
{
|
|
struct proc_dir_entry *pe;
|
|
int ret_val = 0;
|
|
|
|
|
|
pr_debug(TAG"Start to init perf_ioctl driver\n");
|
|
|
|
pe = proc_create("perf_ioctl", 0664, parent, &Fops);
|
|
if (!pe) {
|
|
pr_debug(TAG"%s failed with %d\n",
|
|
"Creating file node ",
|
|
ret_val);
|
|
ret_val = -ENOMEM;
|
|
goto out_wq;
|
|
}
|
|
|
|
pe = proc_create("eara_ioctl", 0664, parent, &eara_Fops);
|
|
if (!pe) {
|
|
pr_debug(TAG"%s failed with %d\n",
|
|
"Creating file node ",
|
|
ret_val);
|
|
ret_val = -ENOMEM;
|
|
goto out_wq;
|
|
}
|
|
|
|
pe = proc_create("eara_sys_ioctl", 0664, parent, &earasys_Fops);
|
|
if (!pe) {
|
|
pr_debug(TAG"%s failed with %d\n",
|
|
"Creating file node ",
|
|
ret_val);
|
|
ret_val = -ENOMEM;
|
|
goto out_wq;
|
|
}
|
|
pr_debug(TAG"init perf_ioctl driver done\n");
|
|
|
|
return 0;
|
|
|
|
out_wq:
|
|
return ret_val;
|
|
}
|
|
|