From 874f635310648a5adcedbd7e02ea0555cfa1da56 Mon Sep 17 00:00:00 2001 From: Ionela Voinescu Date: Tue, 1 Sep 2020 21:55:47 +0100 Subject: cpufreq: report whether cpufreq supports Frequency Invariance (FI) Now that the update of the FI scale factor is done in cpufreq core for selected functions - target(), target_index() and fast_switch(), we can provide feedback to the task scheduler and architecture code on whether cpufreq supports FI. For this purpose provide an external function to expose whether the cpufreq drivers support FI, by using a static key. The logic behind the enablement of cpufreq-based invariance is as follows: - cpufreq-based invariance is disabled by default - cpufreq-based invariance is enabled if any of the callbacks above is implemented while the unsupported setpolicy() is not The cpufreq_supports_freq_invariance() function only returns whether cpufreq is instrumented with the arch_set_freq_scale() calls that result in support for frequency invariance. Due to the lack of knowledge on whether the implementation of arch_set_freq_scale() actually results in the setting of a scale factor based on cpufreq information, it is up to the architecture code to ensure the setting and provision of the scale factor to the scheduler. Signed-off-by: Ionela Voinescu Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- include/linux/cpufreq.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index a911e5d06845..e54767e2a68a 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -217,6 +217,7 @@ void refresh_frequency_limits(struct cpufreq_policy *policy); void cpufreq_update_policy(unsigned int cpu); void cpufreq_update_limits(unsigned int cpu); bool have_governor_per_policy(void); +bool cpufreq_supports_freq_invariance(void); struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy); void cpufreq_enable_fast_switch(struct cpufreq_policy *policy); void cpufreq_disable_fast_switch(struct cpufreq_policy *policy); @@ -237,6 +238,10 @@ static inline unsigned int cpufreq_get_hw_max_freq(unsigned int cpu) { return 0; } +static inline bool cpufreq_supports_freq_invariance(void) +{ + return false; +} static inline void disable_cpufreq(void) { } #endif -- cgit v1.2.3 From ecddc3a0d5d752071c627aa1a1d4d7b529ddae67 Mon Sep 17 00:00:00 2001 From: Valentin Schneider Date: Tue, 1 Sep 2020 21:55:48 +0100 Subject: arch_topology, cpufreq: constify arch_* cpumasks The passed cpumask arguments to arch_set_freq_scale() and arch_freq_counters_available() are only iterated over, so reflect this in the prototype. This also allows to pass system cpumasks like cpu_online_mask without getting a warning. Signed-off-by: Valentin Schneider Signed-off-by: Ionela Voinescu Acked-by: Catalin Marinas Acked-by: Viresh Kumar Reviewed-by: Sudeep Holla Signed-off-by: Rafael J. Wysocki --- include/linux/arch_topology.h | 2 +- include/linux/cpufreq.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index 69b1dabe39dc..810c83336257 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -30,7 +30,7 @@ static inline unsigned long topology_get_freq_scale(int cpu) return per_cpu(freq_scale, cpu); } -bool arch_freq_counters_available(struct cpumask *cpus); +bool arch_freq_counters_available(const struct cpumask *cpus); DECLARE_PER_CPU(unsigned long, thermal_pressure); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index e54767e2a68a..9f779fbdbe7b 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -1011,7 +1011,8 @@ static inline void sched_cpufreq_governor_change(struct cpufreq_policy *policy, extern void arch_freq_prepare_all(void); extern unsigned int arch_freq_get_on_cpu(int cpu); -extern void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq, +extern void arch_set_freq_scale(const struct cpumask *cpus, + unsigned long cur_freq, unsigned long max_freq); /* the following are really really optional */ -- cgit v1.2.3 From 15e5d5b45b2b7072214af519357a1c0af078c50b Mon Sep 17 00:00:00 2001 From: Valentin Schneider Date: Tue, 1 Sep 2020 21:55:49 +0100 Subject: arch_topology, arm, arm64: define arch_scale_freq_invariant() arch_scale_freq_invariant() is used by schedutil to determine whether the scheduler's load-tracking signals are frequency invariant. Its definition is overridable, though by default it is hardcoded to 'true' if arch_scale_freq_capacity() is defined ('false' otherwise). This behaviour is not overridden on arm, arm64 and other users of the generic arch topology driver, which is somewhat precarious: arch_scale_freq_capacity() will always be defined, yet not all cpufreq drivers are guaranteed to drive the frequency invariance scale factor setting. In other words, the load-tracking signals may very well *not* be frequency invariant. Now that cpufreq can be queried on whether the current driver is driving the Frequency Invariance (FI) scale setting, the current situation can be improved. This combines the query of whether cpufreq supports the setting of the frequency scale factor, with whether all online CPUs are counter-based FI enabled. While cpufreq FI enablement applies at system level, for all CPUs, counter-based FI support could also be used for only a subset of CPUs to set the invariance scale factor. Therefore, if cpufreq-based FI support is present, we consider the system to be invariant. If missing, we require all online CPUs to be counter-based FI enabled in order for the full system to be considered invariant. If the system ends up not being invariant, a new condition is needed in the counter initialization code that disables all scale factor setting based on counters. Precedence of counters over cpufreq use is not important here. The invariant status is only given to the system if all CPUs have at least one method of setting the frequency scale factor. Signed-off-by: Valentin Schneider Signed-off-by: Ionela Voinescu Acked-by: Catalin Marinas Acked-by: Viresh Kumar Reviewed-by: Sudeep Holla Signed-off-by: Rafael J. Wysocki --- include/linux/arch_topology.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index 810c83336257..083df331a3c9 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -30,6 +30,8 @@ static inline unsigned long topology_get_freq_scale(int cpu) return per_cpu(freq_scale, cpu); } +bool topology_scale_freq_invariant(void); + bool arch_freq_counters_available(const struct cpumask *cpus); DECLARE_PER_CPU(unsigned long, thermal_pressure); -- cgit v1.2.3 From 10942019040c5557556ec22aae0f771b2a1a1a6d Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 1 Sep 2020 16:28:58 +0200 Subject: firmware: psci: Extend psci_set_osi_mode() to allow reset to PC mode The current user (cpuidle-psci) of psci_set_osi_mode() only needs to enable the PSCI OSI mode. Although, as subsequent changes shows, there is a need to be able to reset back into the PSCI PC mode. Therefore, let's extend psci_set_osi_mode() to take a bool as in-parameter, to let the user indicate whether to enable OSI or to switch back to PC mode. Reviewed-by: Sudeep Holla Signed-off-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- include/linux/psci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/psci.h b/include/linux/psci.h index 14ad9b9ebcd6..2a1bfb890e58 100644 --- a/include/linux/psci.h +++ b/include/linux/psci.h @@ -18,7 +18,7 @@ bool psci_tos_resident_on(int cpu); int psci_cpu_suspend_enter(u32 state); bool psci_power_state_is_valid(u32 state); -int psci_set_osi_mode(void); +int psci_set_osi_mode(bool enable); bool psci_has_osi_support(void); struct psci_operations { -- cgit v1.2.3 From f49735f4978f479b0de4f50ab217d5a56bc83c55 Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Tue, 22 Sep 2020 12:34:16 -0600 Subject: cpuidle: record state entry rejection statistics CPUs may fail to enter the chosen idle state if there was a pending interrupt, causing the cpuidle driver to return an error value. Record that and export it via sysfs along with the other idle state statistics. This could prove useful in understanding behavior of the governor and the system during usecases that involve multiple CPUs. Signed-off-by: Lina Iyer [ rjw: Changelog and documentation edits ] Signed-off-by: Rafael J. Wysocki --- include/linux/cpuidle.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 6175c77bf25e..ed0da0e58e8b 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -38,6 +38,7 @@ struct cpuidle_state_usage { u64 time_ns; unsigned long long above; /* Number of times it's been too deep */ unsigned long long below; /* Number of times it's been too shallow */ + unsigned long long rejected; /* Number of times idle entry was rejected */ #ifdef CONFIG_SUSPEND unsigned long long s2idle_usage; unsigned long long s2idle_time; /* in US */ -- cgit v1.2.3 From 6b61d49a55796dbbc479eeb4465e59fd656c719c Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 18 Sep 2020 19:55:18 +0300 Subject: PM: runtime: Fix timer_expires data type on 32-bit arches Commit 8234f6734c5d ("PM-runtime: Switch autosuspend over to using hrtimers") switched PM runtime autosuspend to use hrtimers and all related time accounting in ns, but missed to update the timer_expires data type in struct dev_pm_info to u64. This causes the timer_expires value to be truncated on 32-bit architectures when assignment is done from u64 values: rpm_suspend() |- dev->power.timer_expires = expires; Fix it by changing the timer_expires type to u64. Fixes: 8234f6734c5d ("PM-runtime: Switch autosuspend over to using hrtimers") Signed-off-by: Grygorii Strashko Acked-by: Pavel Machek Acked-by: Vincent Guittot Cc: 5.0+ # 5.0+ [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki --- include/linux/pm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/pm.h b/include/linux/pm.h index a30a4b54df52..47aca6bac1d6 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -590,7 +590,7 @@ struct dev_pm_info { #endif #ifdef CONFIG_PM struct hrtimer suspend_timer; - unsigned long timer_expires; + u64 timer_expires; struct work_struct work; wait_queue_head_t wait_queue; struct wake_irq *wakeirq; -- cgit v1.2.3 From 7b38b7b0427df70237e3c9c73f2db6b99be2b4b9 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Tue, 8 Sep 2020 19:24:45 +0900 Subject: PM / devfreq: Add devfreq_get_devfreq_by_node function Split off part of devfreq_get_devfreq_by_phandle into a separate function. This allows callers to fetch devfreq instances by enumerating devicetree instead of explicit phandles. Acked-by: Krzysztof Kozlowski Reviewed-by: Lukasz Luba Signed-off-by: Leonard Crestez [cw00.choi: Export devfreq_get_devfreq_by_node function and add function to devfreq.h when CONFIG_PM_DEVFREQ is enabled.] Signed-off-by: Chanwoo Choi --- include/linux/devfreq.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index 12782fbb4c25..eb971b8e5051 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -261,6 +261,7 @@ void devm_devfreq_unregister_notifier(struct device *dev, struct devfreq *devfreq, struct notifier_block *nb, unsigned int list); +struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node); struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index); #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) @@ -414,6 +415,11 @@ static inline void devm_devfreq_unregister_notifier(struct device *dev, { } +static inline struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node) +{ + return ERR_PTR(-ENODEV); +} + static inline struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index) { -- cgit v1.2.3 From 86d90fd95bbc3b3fdc2ef0507b7324cd1d0a358b Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 8 Sep 2020 19:24:46 +0900 Subject: PM / devfreq: Change prototype of devfreq_get_devfreq_by_phandle function Previously, devfreq core support 'devfreq' property in order to get the devfreq device by phandle. But, 'devfreq' property name is not proper on devicetree binding because this name doesn't mean the any h/w attribute. The devfreq core hand over the right to decide the property name for getting the devfreq device on devicetree. Each devfreq driver will decide the property name on devicetree binding and pass the their own property name to devfreq_get_devfreq_by_phandle function. Acked-by: Krzysztof Kozlowski Signed-off-by: Chanwoo Choi --- include/linux/devfreq.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index eb971b8e5051..2f4a74efa6be 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -262,7 +262,8 @@ void devm_devfreq_unregister_notifier(struct device *dev, struct notifier_block *nb, unsigned int list); struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node); -struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index); +struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, + const char *phandle_name, int index); #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) /** @@ -421,7 +422,7 @@ static inline struct devfreq *devfreq_get_devfreq_by_node(struct device_node *no } static inline struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, - int index) + const char *phandle_name, int index) { return ERR_PTR(-ENODEV); } -- cgit v1.2.3 From 02bdbf7d09c059b16047e3d4a05e6d584dd993b6 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 8 Sep 2020 19:24:47 +0900 Subject: PM / devfreq: event: Change prototype of devfreq_event_get_edev_by_phandle function Previously, devfreq core support 'devfreq-events' property in order to get the devfreq-event device by phandle. But, 'devfreq-events' property name is not proper on devicetree binding because this name doesn't mean the any h/w attribute. The devfreq-event core hand over the rights to decide the property name for getting the devfreq-event device on devicetree. Each devfreq-event driver will decide the property name on devicetree binding and then pass the their own property name to devfreq_event_get_edev_by_phandle function. And change the prototype of devfreq_event_get_edev_count function because of used deprecated 'devfreq-events' property. Acked-by: Krzysztof Kozlowski Signed-off-by: Chanwoo Choi --- include/linux/devfreq-event.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/devfreq-event.h b/include/linux/devfreq-event.h index f14f17f8cb7f..4a50a5c71a5f 100644 --- a/include/linux/devfreq-event.h +++ b/include/linux/devfreq-event.h @@ -106,8 +106,11 @@ extern int devfreq_event_get_event(struct devfreq_event_dev *edev, struct devfreq_event_data *edata); extern int devfreq_event_reset_event(struct devfreq_event_dev *edev); extern struct devfreq_event_dev *devfreq_event_get_edev_by_phandle( - struct device *dev, int index); -extern int devfreq_event_get_edev_count(struct device *dev); + struct device *dev, + const char *phandle_name, + int index); +extern int devfreq_event_get_edev_count(struct device *dev, + const char *phandle_name); extern struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev, struct devfreq_event_desc *desc); extern int devfreq_event_remove_edev(struct devfreq_event_dev *edev); @@ -152,12 +155,15 @@ static inline int devfreq_event_reset_event(struct devfreq_event_dev *edev) } static inline struct devfreq_event_dev *devfreq_event_get_edev_by_phandle( - struct device *dev, int index) + struct device *dev, + const char *phandle_name, + int index) { return ERR_PTR(-EINVAL); } -static inline int devfreq_event_get_edev_count(struct device *dev) +static inline int devfreq_event_get_edev_count(struct device *dev, + const char *phandle_name) { return -EINVAL; } -- cgit v1.2.3 From 49f618e1b669ef0e26a8d8d7f8fafc7b8fd31531 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 24 Sep 2020 13:04:47 +0200 Subject: PM: domains: Rename power state enums for genpd To clarify the code a bit, let's rename GPD_STATE_ACTIVE into GENPD_STATE_ON and GPD_STATE_POWER_OFF to GENPD_STATE_OFF. Signed-off-by: Ulf Hansson [ rjw: Subject edit ] Signed-off-by: Rafael J. Wysocki --- include/linux/pm_domain.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index ee11502a575b..66f3c5d64d81 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -64,8 +64,8 @@ #define GENPD_FLAG_RPM_ALWAYS_ON (1U << 5) enum gpd_status { - GPD_STATE_ACTIVE = 0, /* PM domain is active */ - GPD_STATE_POWER_OFF, /* PM domain is off */ + GENPD_STATE_ON = 0, /* PM domain is on */ + GENPD_STATE_OFF, /* PM domain is off */ }; struct dev_power_governor { -- cgit v1.2.3 From a20b7053b5c47cd7de23288238ea4d23502f300a Mon Sep 17 00:00:00 2001 From: Ionela Voinescu Date: Thu, 24 Sep 2020 13:30:15 +0100 Subject: cpufreq,arm,arm64: restructure definitions of arch_set_freq_scale() Compared to other arch_* functions, arch_set_freq_scale() has an atypical weak definition that can be replaced by a strong architecture specific implementation. The more typical support for architectural functions involves defining an empty stub in a header file if the symbol is not already defined in architecture code. Some examples involve: - #define arch_scale_freq_capacity topology_get_freq_scale - #define arch_scale_freq_invariant topology_scale_freq_invariant - #define arch_scale_cpu_capacity topology_get_cpu_scale - #define arch_update_cpu_topology topology_update_cpu_topology - #define arch_scale_thermal_pressure topology_get_thermal_pressure - #define arch_set_thermal_pressure topology_set_thermal_pressure Bring arch_set_freq_scale() in line with these functions by renaming it to topology_set_freq_scale() in the arch topology driver, and by defining the arch_set_freq_scale symbol to point to the new function for arm and arm64. While there are other users of the arch_topology driver, this patch defines arch_set_freq_scale for arm and arm64 only, due to their existing definitions of arch_scale_freq_capacity. This is the getter function of the frequency invariance scale factor and without a getter function, the setter function - arch_set_freq_scale() has not purpose. Signed-off-by: Ionela Voinescu Acked-by: Viresh Kumar Acked-by: Catalin Marinas Acked-by: Sudeep Holla (BL_SWITCHER and topology parts) Signed-off-by: Rafael J. Wysocki --- include/linux/arch_topology.h | 2 ++ include/linux/cpufreq.h | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index 083df331a3c9..0f6cd6b73a61 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -30,6 +30,8 @@ static inline unsigned long topology_get_freq_scale(int cpu) return per_cpu(freq_scale, cpu); } +void topology_set_freq_scale(const struct cpumask *cpus, unsigned long cur_freq, + unsigned long max_freq); bool topology_scale_freq_invariant(void); bool arch_freq_counters_available(const struct cpumask *cpus); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 9f779fbdbe7b..fa37b1c66443 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -1011,9 +1011,14 @@ static inline void sched_cpufreq_governor_change(struct cpufreq_policy *policy, extern void arch_freq_prepare_all(void); extern unsigned int arch_freq_get_on_cpu(int cpu); -extern void arch_set_freq_scale(const struct cpumask *cpus, - unsigned long cur_freq, - unsigned long max_freq); +#ifndef arch_set_freq_scale +static __always_inline +void arch_set_freq_scale(const struct cpumask *cpus, + unsigned long cur_freq, + unsigned long max_freq) +{ +} +#endif /* the following are really really optional */ extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs; -- cgit v1.2.3