út 10. 12. 2024 v 21:44 odesílatel Sasha Levin <sashal@xxxxxxxxxx> napsal: > > This is a note to let you know that I've just added the patch titled > > rtla/utils: Add idle state disabling via libcpupower > > to the 6.12-stable tree which can be found at: > http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary > > The filename of the patch is: > rtla-utils-add-idle-state-disabling-via-libcpupower.patch > and it can be found in the queue-6.12 subdirectory. > > If you, or anyone else, feels it should not be added to the stable tree, > please let <stable@xxxxxxxxxxxxxxx> know about it. This is a part of a patchset implementing a new feature, rtla idle state disabling, see [1]. It seems it was included in this stable queue and also the one for 6.6 by mistake. Also, the patch by itself does not do anything, because it depends on preceding commits from the patchset to enable HAVE_LIBCPUPOWER_SUPPORT and on following commits to actually implement the functionality in the rtla command line interface. Perhaps AUTOSEL picked it due to some merge conflicts with other patches? I don't know of any though. [1] - https://lore.kernel.org/linux-trace-kernel/20241017140914.3200454-1-tglozar@xxxxxxxxxx > > > > commit 354bcd3b3efd600f4d23cee6898a6968659bb3a9 > Author: Tomas Glozar <tglozar@xxxxxxxxxx> > Date: Thu Oct 17 16:09:11 2024 +0200 > > rtla/utils: Add idle state disabling via libcpupower > > [ Upstream commit 083d29d3784319e9e9fab3ac02683a7b26ae3480 ] > > Add functions to utils.c to disable idle states through functions of > libcpupower. This will serve as the basis for disabling idle states > per cpu when running timerlat. > > Link: https://lore.kernel.org/20241017140914.3200454-4-tglozar@xxxxxxxxxx > Signed-off-by: Tomas Glozar <tglozar@xxxxxxxxxx> > Signed-off-by: Steven Rostedt (Google) <rostedt@xxxxxxxxxxx> > Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> > > diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c > index 0735fcb827ed7..230f9fc7502dd 100644 > --- a/tools/tracing/rtla/src/utils.c > +++ b/tools/tracing/rtla/src/utils.c > @@ -4,6 +4,9 @@ > */ > > #define _GNU_SOURCE > +#ifdef HAVE_LIBCPUPOWER_SUPPORT > +#include <cpuidle.h> > +#endif /* HAVE_LIBCPUPOWER_SUPPORT */ > #include <dirent.h> > #include <stdarg.h> > #include <stdlib.h> > @@ -519,6 +522,153 @@ int set_cpu_dma_latency(int32_t latency) > return fd; > } > > +#ifdef HAVE_LIBCPUPOWER_SUPPORT > +static unsigned int **saved_cpu_idle_disable_state; > +static size_t saved_cpu_idle_disable_state_alloc_ctr; > + > +/* > + * save_cpu_idle_state_disable - save disable for all idle states of a cpu > + * > + * Saves the current disable of all idle states of a cpu, to be subsequently > + * restored via restore_cpu_idle_disable_state. > + * > + * Return: idle state count on success, negative on error > + */ > +int save_cpu_idle_disable_state(unsigned int cpu) > +{ > + unsigned int nr_states; > + unsigned int state; > + int disabled; > + int nr_cpus; > + > + nr_states = cpuidle_state_count(cpu); > + > + if (nr_states == 0) > + return 0; > + > + if (saved_cpu_idle_disable_state == NULL) { > + nr_cpus = sysconf(_SC_NPROCESSORS_CONF); > + saved_cpu_idle_disable_state = calloc(nr_cpus, sizeof(unsigned int *)); > + if (!saved_cpu_idle_disable_state) > + return -1; > + } > + > + saved_cpu_idle_disable_state[cpu] = calloc(nr_states, sizeof(unsigned int)); > + if (!saved_cpu_idle_disable_state[cpu]) > + return -1; > + saved_cpu_idle_disable_state_alloc_ctr++; > + > + for (state = 0; state < nr_states; state++) { > + disabled = cpuidle_is_state_disabled(cpu, state); > + if (disabled < 0) > + return disabled; > + saved_cpu_idle_disable_state[cpu][state] = disabled; > + } > + > + return nr_states; > +} > + > +/* > + * restore_cpu_idle_disable_state - restore disable for all idle states of a cpu > + * > + * Restores the current disable state of all idle states of a cpu that was > + * previously saved by save_cpu_idle_disable_state. > + * > + * Return: idle state count on success, negative on error > + */ > +int restore_cpu_idle_disable_state(unsigned int cpu) > +{ > + unsigned int nr_states; > + unsigned int state; > + int disabled; > + int result; > + > + nr_states = cpuidle_state_count(cpu); > + > + if (nr_states == 0) > + return 0; > + > + if (!saved_cpu_idle_disable_state) > + return -1; > + > + for (state = 0; state < nr_states; state++) { > + if (!saved_cpu_idle_disable_state[cpu]) > + return -1; > + disabled = saved_cpu_idle_disable_state[cpu][state]; > + result = cpuidle_state_disable(cpu, state, disabled); > + if (result < 0) > + return result; > + } > + > + free(saved_cpu_idle_disable_state[cpu]); > + saved_cpu_idle_disable_state[cpu] = NULL; > + saved_cpu_idle_disable_state_alloc_ctr--; > + if (saved_cpu_idle_disable_state_alloc_ctr == 0) { > + free(saved_cpu_idle_disable_state); > + saved_cpu_idle_disable_state = NULL; > + } > + > + return nr_states; > +} > + > +/* > + * free_cpu_idle_disable_states - free saved idle state disable for all cpus > + * > + * Frees the memory used for storing cpu idle state disable for all cpus > + * and states. > + * > + * Normally, the memory is freed automatically in > + * restore_cpu_idle_disable_state; this is mostly for cleaning up after an > + * error. > + */ > +void free_cpu_idle_disable_states(void) > +{ > + int cpu; > + int nr_cpus; > + > + if (!saved_cpu_idle_disable_state) > + return; > + > + nr_cpus = sysconf(_SC_NPROCESSORS_CONF); > + > + for (cpu = 0; cpu < nr_cpus; cpu++) { > + free(saved_cpu_idle_disable_state[cpu]); > + saved_cpu_idle_disable_state[cpu] = NULL; > + } > + > + free(saved_cpu_idle_disable_state); > + saved_cpu_idle_disable_state = NULL; > +} > + > +/* > + * set_deepest_cpu_idle_state - limit idle state of cpu > + * > + * Disables all idle states deeper than the one given in > + * deepest_state (assuming states with higher number are deeper). > + * > + * This is used to reduce the exit from idle latency. Unlike > + * set_cpu_dma_latency, it can disable idle states per cpu. > + * > + * Return: idle state count on success, negative on error > + */ > +int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int deepest_state) > +{ > + unsigned int nr_states; > + unsigned int state; > + int result; > + > + nr_states = cpuidle_state_count(cpu); > + > + for (state = deepest_state + 1; state < nr_states; state++) { > + result = cpuidle_state_disable(cpu, state, 1); > + if (result < 0) > + return result; > + } > + > + return nr_states; > +} > +#endif /* HAVE_LIBCPUPOWER_SUPPORT */ > + > #define _STR(x) #x > #define STR(x) _STR(x) > > diff --git a/tools/tracing/rtla/src/utils.h b/tools/tracing/rtla/src/utils.h > index 99c9cf81bcd02..101d4799a0090 100644 > --- a/tools/tracing/rtla/src/utils.h > +++ b/tools/tracing/rtla/src/utils.h > @@ -66,6 +66,19 @@ int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr); > int set_comm_cgroup(const char *comm_prefix, const char *cgroup); > int set_pid_cgroup(pid_t pid, const char *cgroup); > int set_cpu_dma_latency(int32_t latency); > +#ifdef HAVE_LIBCPUPOWER_SUPPORT > +int save_cpu_idle_disable_state(unsigned int cpu); > +int restore_cpu_idle_disable_state(unsigned int cpu); > +void free_cpu_idle_disable_states(void); > +int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int state); > +static inline int have_libcpupower_support(void) { return 1; } > +#else > +static inline int save_cpu_idle_disable_state(unsigned int cpu) { return -1; } > +static inline int restore_cpu_idle_disable_state(unsigned int cpu) { return -1; } > +static inline void free_cpu_idle_disable_states(void) { } > +static inline int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int state) { return -1; } > +static inline int have_libcpupower_support(void) { return 0; } > +#endif /* HAVE_LIBCPUPOWER_SUPPORT */ > int auto_house_keeping(cpu_set_t *monitored_cpus); > > #define ns_to_usf(x) (((double)x/1000)) > Tomas