Files
android/drivers/misc/mediatek/mtprof/sched_monitor_test.c
T
threeeye bc1d038eac REVVL 6 Pro kernel bring-up: full working tree snapshot (2026-09-12)
Squashed backup commit (no shallow-clone history issues) of
xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2 branch, upstream
commit 9eece662e) plus all fixes applied to get everpal_defconfig building
clean against a modern (GCC 15.2.0) toolchain -- see the previous commit
message on the lineage-23.2 branch (also in this repo history is not
available here since this is a squashed snapshot; full incremental history
lives in the local DL380 checkout and the upstream GitHub remote).

Upstream: https://github.com/xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2)
2026-09-12 13:36:46 +00:00

188 lines
4.3 KiB
C

/*
* Copyright (C) 2018 MediaTek Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
/* TIMER_SOFTIRQ duration warning test */
static struct timer_list timer;
static void delayed_timer(unsigned long arg)
{
mdelay(600);
}
void sched_mon_test_TIMER_SOFTIRQ(void)
{
setup_timer(&timer, delayed_timer, 0);
mod_timer(&timer, jiffies + msecs_to_jiffies(100));
}
/* TASKLET_SOFTIRQ duration warning test */
static struct tasklet_struct sched_mon_tasklet;
static void sched_mon_tasklet_func(unsigned long data)
{
mdelay(600);
}
void sched_mon_test_TASKLET_SOFTIRQ(void)
{
tasklet_init(&sched_mon_tasklet, sched_mon_tasklet_func, 0);
tasklet_schedule(&sched_mon_tasklet);
}
/* RCU_SOFTIRQ duration warning test */
struct sched_mon_rcu_t {
int val;
};
static struct sched_mon_rcu_t __rcu *sched_mon_rcu_g;
static struct rcu_head sched_mon_rcu_head;
static void delayed_rcu_callback(struct rcu_head *r)
{
/* RCU_SOFTIRQ handler */
mdelay(600);
}
void sched_mon_test_RCU_SOFTIRQ(void)
{
struct sched_mon_rcu_t *sched_mon_rcu;
sched_mon_rcu = kmalloc(sizeof(*sched_mon_rcu), GFP_KERNEL);
if (!sched_mon_rcu)
return;
sched_mon_rcu->val = 100;
RCU_INIT_POINTER(sched_mon_rcu_g, sched_mon_rcu);
call_rcu(&sched_mon_rcu_head, delayed_rcu_callback);
}
/* irq_work monitor test */
static struct irq_work sched_mon_irqwork;
static void sched_mon_irq_work(struct irq_work *work)
{
mdelay(600);
}
void sched_mon_test_irq_work(void)
{
init_irq_work(&sched_mon_irqwork, sched_mon_irq_work);
irq_work_queue(&sched_mon_irqwork);
}
/* IRQ disable monitor test */
void sched_mon_test_irq_disable(void)
{
unsigned long flags;
local_irq_save(flags);
mdelay(600);
local_irq_restore(flags);
/* The test will trigger KernelAPI Dump */
}
/* hrtimer monitor test */
static struct hrtimer sched_mon_hrtimer;
static enum hrtimer_restart sched_mon_hrtimer_func(struct hrtimer *unused)
{
mdelay(600);
return HRTIMER_NORESTART;
}
void sched_mon_test_HRTIMER(void)
{
hrtimer_init(&sched_mon_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
sched_mon_hrtimer.function = sched_mon_hrtimer_func;
hrtimer_start(&sched_mon_hrtimer, ms_to_ktime(0),
HRTIMER_MODE_REL_PINNED);
}
/* preempt count monitor test */
static struct hrtimer sched_mon_hrtimer2;
static enum hrtimer_restart sched_mon_hrtimer_func2(struct hrtimer *unused)
{
preempt_disable();
return HRTIMER_NORESTART;
}
void sched_mon_test_PREEMPT_COUNT(void)
{
hrtimer_init(&sched_mon_hrtimer2, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
sched_mon_hrtimer2.function = sched_mon_hrtimer_func2;
hrtimer_start(&sched_mon_hrtimer2, ms_to_ktime(0),
HRTIMER_MODE_REL_PINNED);
}
struct sched_mon_test_func {
char name[32];
void (*func)(void);
};
struct sched_mon_test_func sched_mon_test_list[] = {
{"sirq_timer_dur", sched_mon_test_TIMER_SOFTIRQ},
{"sirq_tasklet_dur", sched_mon_test_TASKLET_SOFTIRQ},
{"sirq_rcu_dur", sched_mon_test_RCU_SOFTIRQ},
{"irq_work_dur", sched_mon_test_irq_work},
{"hirq_disable", sched_mon_test_irq_disable},
{"hrtimer_dur", sched_mon_test_HRTIMER},
{"preempt_count", sched_mon_test_PREEMPT_COUNT},
};
static ssize_t
sched_mon_test_write(struct file *file, const char *ubuf,
size_t count, loff_t *ppos)
{
int i;
char buf[32];
if (count >= sizeof(buf) || count == 0)
return -EINVAL;
if (copy_from_user(&buf, ubuf, count))
return -EFAULT;
buf[count] = '\0';
for (i = 0; i < ARRAY_SIZE(sched_mon_test_list); i++) {
if (!strncmp(buf, sched_mon_test_list[i].name,
strlen(sched_mon_test_list[i].name)))
sched_mon_test_list[i].func();
}
return count;
}
static const struct file_operations proc_sched_monitor_test_fops = {
.open = simple_open,
.write = sched_mon_test_write,
};
void mt_sched_monitor_test_init(struct proc_dir_entry *dir)
{
proc_create("sched_mon_test", 0220, dir,
&proc_sched_monitor_test_fops);
}