diff --git a/kernel/sched/walt/Makefile b/kernel/sched/walt/Makefile index 870d9b2fcfe3..ed35366108ed 100644 --- a/kernel/sched/walt/Makefile +++ b/kernel/sched/walt/Makefile @@ -4,7 +4,7 @@ KCOV_INSTRUMENT := n KCSAN_SANITIZE := n obj-$(CONFIG_SCHED_WALT) += sched-walt.o -sched-walt-$(CONFIG_SCHED_WALT) := walt.o boost.o sched_avg.o walt_pause.o core_ctl.o trace.o input-boost.o sysctl.o cpufreq_walt.o fixup.o walt_lb.o walt_rt.o walt_cfs.o +sched-walt-$(CONFIG_SCHED_WALT) := walt.o boost.o sched_avg.o walt_pause.o core_ctl.o trace.o input-boost.o sysctl.o cpufreq_walt.o fixup.o walt_lb.o walt_rt.o walt_cfs.o walt_tp.o obj-$(CONFIG_SCHED_WALT_DEBUG) += sched-walt-debug.o sched-walt-debug-$(CONFIG_SCHED_WALT_DEBUG) := walt_debug.o preemptirq_long.o diff --git a/kernel/sched/walt/sysctl.c b/kernel/sched/walt/sysctl.c index a005b3004413..578af892a5a8 100644 --- a/kernel/sched/walt/sysctl.c +++ b/kernel/sched/walt/sysctl.c @@ -773,6 +773,15 @@ struct ctl_table walt_table[] = { .extra1 = SYSCTL_ONE, .extra2 = SYSCTL_INT_MAX, }, + { + .procname = "sched_enable_tp", + .data = &sysctl_sched_dynamic_tp_enable, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = sched_dynamic_tp_handler, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, { } }; diff --git a/kernel/sched/walt/trace.h b/kernel/sched/walt/trace.h index 8b8780a2d97b..dad667d8a2a9 100644 --- a/kernel/sched/walt/trace.h +++ b/kernel/sched/walt/trace.h @@ -1186,6 +1186,28 @@ DEFINE_EVENT(walt_cfs_mvp_task_template, walt_cfs_mvp_wakeup_preempt, TP_PROTO(struct task_struct *p, struct walt_task_struct *wts, unsigned int limit), TP_ARGS(p, wts, limit)); +#define SPAN_SIZE (NR_CPUS/4) + +TRACE_EVENT(sched_overutilized, + + TP_PROTO(int overutilized, char *span), + + TP_ARGS(overutilized, span), + + TP_STRUCT__entry( + __field(int, overutilized) + __array(char, span, SPAN_SIZE) + ), + + TP_fast_assign( + __entry->overutilized = overutilized; + strscpy(__entry->span, span, SPAN_SIZE); + ), + + TP_printk("overutilized=%d span=0x%s", + __entry->overutilized, __entry->span) +); + #endif /* _TRACE_WALT_H */ #undef TRACE_INCLUDE_PATH diff --git a/kernel/sched/walt/walt.h b/kernel/sched/walt/walt.h index b0dc1690ae15..72e7616487f3 100644 --- a/kernel/sched/walt/walt.h +++ b/kernel/sched/walt/walt.h @@ -228,6 +228,9 @@ extern unsigned int sysctl_sched_many_wakeup_threshold; extern unsigned int sysctl_walt_rtg_cfs_boost_prio; extern __read_mostly unsigned int sysctl_sched_force_lb_enable; extern const int sched_user_hint_max; +extern unsigned int sysctl_sched_dynamic_tp_enable; +extern int sched_dynamic_tp_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos); extern struct list_head cluster_head; #define for_each_sched_cluster(cluster) \ diff --git a/kernel/sched/walt/walt_tp.c b/kernel/sched/walt/walt_tp.c new file mode 100644 index 000000000000..f809128fddd0 --- /dev/null +++ b/kernel/sched/walt/walt_tp.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include "trace.h" + +unsigned int sysctl_sched_dynamic_tp_enable; + +static void sched_overutilized(void *data, struct root_domain *rd, + bool overutilized) +{ + if (trace_sched_overutilized_enabled()) { + char span[SPAN_SIZE]; + + cpumap_print_to_pagebuf(false, span, sched_trace_rd_span(rd)); + trace_sched_overutilized(overutilized, span); + } +} + +static void walt_register_dynamic_tp_events(void) +{ + register_trace_sched_overutilized_tp(sched_overutilized, NULL); +} + +static void walt_unregister_dynamic_tp_events(void) +{ + unregister_trace_sched_overutilized_tp(sched_overutilized, NULL); +} + +int sched_dynamic_tp_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + static DEFINE_MUTEX(mutex); + int ret = 0, *val = (unsigned int *)table->data; + unsigned int old_val; + + mutex_lock(&mutex); + old_val = sysctl_sched_dynamic_tp_enable; + + ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); + if (ret || !write || (old_val == sysctl_sched_dynamic_tp_enable)) + goto done; + + if (*val) + walt_register_dynamic_tp_events(); + else + walt_unregister_dynamic_tp_events(); +done: + mutex_unlock(&mutex); + return ret; +}