linux/drivers/thermal/cpufreq_cooling.c

687 lines
20 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
/*
* linux/drivers/thermal/cpufreq_cooling.c
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
*
* Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
*
* Copyright (C) 2012-2018 Linaro Limited.
*
* Authors: Amit Daniel <amit.kachhap@linaro.org>
* Viresh Kumar <viresh.kumar@linaro.org>
*
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
*/
#include <linux/cpu.h>
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
#include <linux/cpufreq.h>
#include <linux/cpu_cooling.h>
#include <linux/energy_model.h>
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
#include <linux/err.h>
#include <linux/export.h>
#include <linux/idr.h>
#include <linux/pm_opp.h>
#include <linux/pm_qos.h>
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
#include <linux/slab.h>
#include <linux/thermal.h>
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
#include <trace/events/thermal.h>
/*
* Cooling state <-> CPUFreq frequency
*
* Cooling states are translated to frequencies throughout this driver and this
* is the relation between them.
*
* Highest cooling state corresponds to lowest possible frequency.
*
* i.e.
* level 0 --> 1st Max Freq
* level 1 --> 2nd Max Freq
* ...
*/
/**
* struct time_in_idle - Idle time stats
* @time: previous reading of the absolute time that this cpu was idle
* @timestamp: wall time of the last invocation of get_cpu_idle_time_us()
*/
struct time_in_idle {
u64 time;
u64 timestamp;
};
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
/**
* struct cpufreq_cooling_device - data for cooling device with cpufreq
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
* @id: unique integer value corresponding to each cpufreq_cooling_device
* registered.
* @last_load: load measured by the latest call to cpufreq_get_requested_power()
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
* @cpufreq_state: integer value representing the current state of cpufreq
* cooling devices.
* @max_level: maximum cooling level. One less than total number of valid
* cpufreq frequencies.
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
* @em: Reference on the Energy Model of the device
* @cdev: thermal_cooling_device pointer to keep track of the
* registered cooling device.
* @policy: cpufreq policy.
* @node: list_head to link all cpufreq_cooling_device together.
* @idle_time: idle time stats
* @qos_req: PM QoS contraint to apply
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
*
* This structure is required for keeping information of each registered
* cpufreq_cooling_device.
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
*/
struct cpufreq_cooling_device {
int id;
u32 last_load;
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
unsigned int cpufreq_state;
unsigned int max_level;
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
struct em_perf_domain *em;
struct cpufreq_policy *policy;
thermal: cpu_cooling: Update always cpufreq policy with thermal constraints Existing code updates cupfreq policy only while executing cpufreq_apply_cooling() function (i.e. when notify_device != NOTIFY_INVALID). It doesn't apply constraints when cpufreq policy update happens from any other place but it should update the cpufreq policy with thermal constraints every time when there is a cpufreq policy update, to keep state of cpufreq_cooling_device and max_feq of cpufreq policy in sync. For instance while resuming cpufreq updates cpufreq_policy and it restores default policy->usr_policy values irrespective of cooling device's cpufreq_state since notification gets missed because (notify_device == NOTIFY_INVALID). Another problem, is that userspace is able to change max_freq irrespective of cooling device's state, as notification gets missed. This patch modifies code to maintain a global cpufreq_dev_list and applies constraints of all matching cooling devices for policy's cpu when there is any policy update(ends up applying the lowest max_freq among the matching cpu cooling devices). This patch also removes redundant check (max_freq > policy->user_policy.max), as cpufreq framework takes care of user_policy constraints already where ever required, otherwise its causing an issue while increasing max_freq in normal scenerio as it restores max_freq with policy->user_policy.max which is old (smaller) value. Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
2014-11-07 21:42:29 +08:00
struct list_head node;
struct time_in_idle *idle_time;
cpufreq: Use per-policy frequency QoS Replace the CPU device PM QoS used for the management of min and max frequency constraints in cpufreq (and its users) with per-policy frequency QoS to avoid problems with cpufreq policies covering more then one CPU. Namely, a cpufreq driver is registered with the subsys interface which calls cpufreq_add_dev() for each CPU, starting from CPU0, so currently the PM QoS notifiers are added to the first CPU in the policy (i.e. CPU0 in the majority of cases). In turn, when the cpufreq driver is unregistered, the subsys interface doing that calls cpufreq_remove_dev() for each CPU, starting from CPU0, and the PM QoS notifiers are only removed when cpufreq_remove_dev() is called for the last CPU in the policy, say CPUx, which as a rule is not CPU0 if the policy covers more than one CPU. Then, the PM QoS notifiers cannot be removed, because CPUx does not have them, and they are still there in the device PM QoS notifiers list of CPU0, which prevents new PM QoS notifiers from being registered for CPU0 on the next attempt to register the cpufreq driver. The same issue occurs when the first CPU in the policy goes offline before unregistering the driver. After this change it does not matter which CPU is the policy CPU at the driver registration time and whether or not it is online all the time, because the frequency QoS is per policy and not per CPU. Fixes: 67d874c3b2c6 ("cpufreq: Register notifiers with the PM QoS framework") Reported-by: Dmitry Osipenko <digetx@gmail.com> Tested-by: Dmitry Osipenko <digetx@gmail.com> Reported-by: Sudeep Holla <sudeep.holla@arm.com> Tested-by: Sudeep Holla <sudeep.holla@arm.com> Diagnosed-by: Viresh Kumar <viresh.kumar@linaro.org> Link: https://lore.kernel.org/linux-pm/5ad2624194baa2f53acc1f1e627eb7684c577a19.1562210705.git.viresh.kumar@linaro.org/T/#md2d89e95906b8c91c15f582146173dce2e86e99f Link: https://lore.kernel.org/linux-pm/20191017094612.6tbkwoq4harsjcqv@vireshk-i7/T/#m30d48cc23b9a80467fbaa16e30f90b3828a5a29b Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
2019-10-16 18:47:06 +08:00
struct freq_qos_request qos_req;
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
};
static DEFINE_IDA(cpufreq_ida);
thermal: cpu_cooling: fix lockdep problems in cpu_cooling A recent change to the cpu_cooling code introduced a AB-BA deadlock scenario between the cpufreq_policy_notifier_list rwsem and the cooling_cpufreq_lock. This is caused by cooling_cpufreq_lock being held before the registration/removal of the notifier block (an operation which takes the rwsem), and the notifier code itself which takes the locks in the reverse order: ====================================================== [ INFO: possible circular locking dependency detected ] 3.18.0+ #1453 Not tainted ------------------------------------------------------- rc.local/770 is trying to acquire lock: (cooling_cpufreq_lock){+.+.+.}, at: [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc but task is already holding lock: ((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 ((cpufreq_policy_notifier_list).rwsem){++++.+}: [<c06bc3b0>] down_write+0x44/0x9c [<c0043444>] blocking_notifier_chain_register+0x28/0xd8 [<c04ad610>] cpufreq_register_notifier+0x68/0x90 [<c04abe4c>] __cpufreq_cooling_register.part.1+0x120/0x180 [<c04abf44>] __cpufreq_cooling_register+0x98/0xa4 [<c04abf8c>] cpufreq_cooling_register+0x18/0x1c [<bf0046f8>] imx_thermal_probe+0x1c0/0x470 [imx_thermal] [<c037cef8>] platform_drv_probe+0x50/0xac [<c037b710>] driver_probe_device+0x114/0x234 [<c037b8cc>] __driver_attach+0x9c/0xa0 [<c0379d68>] bus_for_each_dev+0x5c/0x90 [<c037b204>] driver_attach+0x24/0x28 [<c037ae7c>] bus_add_driver+0xe0/0x1d8 [<c037c0cc>] driver_register+0x80/0xfc [<c037cd80>] __platform_driver_register+0x50/0x64 [<bf007018>] 0xbf007018 [<c0008a5c>] do_one_initcall+0x88/0x1d8 [<c0095da4>] load_module+0x1768/0x1ef8 [<c0096614>] SyS_init_module+0xe0/0xf4 [<c000ec00>] ret_fast_syscall+0x0/0x48 -> #0 (cooling_cpufreq_lock){+.+.+.}: [<c00619f8>] lock_acquire+0xb0/0x124 [<c06ba3b4>] mutex_lock_nested+0x5c/0x3d8 [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc [<c0042bf4>] notifier_call_chain+0x4c/0x8c [<c0042f20>] __blocking_notifier_call_chain+0x50/0x68 [<c0042f58>] blocking_notifier_call_chain+0x20/0x28 [<c04ae62c>] cpufreq_set_policy+0x7c/0x1d0 [<c04af3cc>] store_scaling_governor+0x74/0x9c [<c04ad418>] store+0x90/0xc0 [<c0175384>] sysfs_kf_write+0x54/0x58 [<c01746b4>] kernfs_fop_write+0xdc/0x190 [<c010dcc0>] vfs_write+0xac/0x1b4 [<c010dfec>] SyS_write+0x44/0x90 [<c000ec00>] ret_fast_syscall+0x0/0x48 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock((cpufreq_policy_notifier_list).rwsem); lock(cooling_cpufreq_lock); lock((cpufreq_policy_notifier_list).rwsem); lock(cooling_cpufreq_lock); *** DEADLOCK *** 7 locks held by rc.local/770: #0: (sb_writers#6){.+.+.+}, at: [<c010dda0>] vfs_write+0x18c/0x1b4 #1: (&of->mutex){+.+.+.}, at: [<c0174678>] kernfs_fop_write+0xa0/0x190 #2: (s_active#52){.+.+.+}, at: [<c0174680>] kernfs_fop_write+0xa8/0x190 #3: (cpu_hotplug.lock){++++++}, at: [<c0026a60>] get_online_cpus+0x34/0x90 #4: (cpufreq_rwsem){.+.+.+}, at: [<c04ad3e0>] store+0x58/0xc0 #5: (&policy->rwsem){+.+.+.}, at: [<c04ad3f8>] store+0x70/0xc0 #6: ((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68 stack backtrace: CPU: 0 PID: 770 Comm: rc.local Not tainted 3.18.0+ #1453 Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree) Backtrace: [<c00121c8>] (dump_backtrace) from [<c0012360>] (show_stack+0x18/0x1c) r6:c0b85a80 r5:c0b75630 r4:00000000 r3:00000000 [<c0012348>] (show_stack) from [<c06b6c48>] (dump_stack+0x7c/0x98) [<c06b6bcc>] (dump_stack) from [<c06b42a4>] (print_circular_bug+0x28c/0x2d8) r4:c0b85a80 r3:d0071d40 [<c06b4018>] (print_circular_bug) from [<c00613b0>] (__lock_acquire+0x1acc/0x1bb0) r10:c0b50660 r8:c09e6d80 r7:d0071d40 r6:c11d0f0c r5:00000007 r4:d0072240 [<c005f8e4>] (__lock_acquire) from [<c00619f8>] (lock_acquire+0xb0/0x124) r10:00000000 r9:c04abfc4 r8:00000000 r7:00000000 r6:00000000 r5:c0a06f0c r4:00000000 [<c0061948>] (lock_acquire) from [<c06ba3b4>] (mutex_lock_nested+0x5c/0x3d8) r10:ec853800 r9:c0a06ed4 r8:d0071d40 r7:c0a06ed4 r6:c11d0f0c r5:00000000 r4:c04abfc4 [<c06ba358>] (mutex_lock_nested) from [<c04abfc4>] (cpufreq_thermal_notifier+0x34/0xfc) r10:ec853800 r9:ec85380c r8:d00d7d3c r7:c0a06ed4 r6:d00d7d3c r5:00000000 r4:fffffffe [<c04abf90>] (cpufreq_thermal_notifier) from [<c0042bf4>] (notifier_call_chain+0x4c/0x8c) r7:00000000 r6:00000000 r5:00000000 r4:fffffffe [<c0042ba8>] (notifier_call_chain) from [<c0042f20>] (__blocking_notifier_call_chain+0x50/0x68) r8:c0a072a4 r7:00000000 r6:d00d7d3c r5:ffffffff r4:c0a06fc8 r3:ffffffff [<c0042ed0>] (__blocking_notifier_call_chain) from [<c0042f58>] (blocking_notifier_call_chain+0x20/0x28) r7:ec98b540 r6:c13ebc80 r5:ed76e600 r4:d00d7d3c [<c0042f38>] (blocking_notifier_call_chain) from [<c04ae62c>] (cpufreq_set_policy+0x7c/0x1d0) [<c04ae5b0>] (cpufreq_set_policy) from [<c04af3cc>] (store_scaling_governor+0x74/0x9c) r7:ec98b540 r6:0000000c r5:ec98b540 r4:ed76e600 [<c04af358>] (store_scaling_governor) from [<c04ad418>] (store+0x90/0xc0) r6:0000000c r5:ed76e6d4 r4:ed76e600 [<c04ad388>] (store) from [<c0175384>] (sysfs_kf_write+0x54/0x58) r8:0000000c r7:d00d7f78 r6:ec98b540 r5:0000000c r4:ec853800 r3:0000000c [<c0175330>] (sysfs_kf_write) from [<c01746b4>] (kernfs_fop_write+0xdc/0x190) r6:ec98b540 r5:00000000 r4:00000000 r3:c0175330 [<c01745d8>] (kernfs_fop_write) from [<c010dcc0>] (vfs_write+0xac/0x1b4) r10:0162aa70 r9:d00d6000 r8:0000000c r7:d00d7f78 r6:0162aa70 r5:0000000c r4:eccde500 [<c010dc14>] (vfs_write) from [<c010dfec>] (SyS_write+0x44/0x90) r10:0162aa70 r8:0000000c r7:eccde500 r6:eccde500 r5:00000000 r4:00000000 [<c010dfa8>] (SyS_write) from [<c000ec00>] (ret_fast_syscall+0x0/0x48) r10:00000000 r8:c000edc4 r7:00000004 r6:000216cc r5:0000000c r4:0162aa70 Solve this by moving to finer grained locking - use one mutex to protect the cpufreq_dev_list as a whole, and a separate lock to ensure correct ordering of cpufreq notifier registration and removal. cooling_list_lock is taken within cooling_cpufreq_lock on (un)registration to preserve the behavior of the code, i.e. to atomically add/remove to the list and (un)register the notifier. Fixes: 2dcd851fe4b4 ("thermal: cpu_cooling: Update always cpufreq policy with Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
2015-08-12 17:52:16 +08:00
static DEFINE_MUTEX(cooling_list_lock);
static LIST_HEAD(cpufreq_cdev_list);
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
/**
* get_level: Find the level for a particular frequency
* @cpufreq_cdev: cpufreq_cdev for which the property is required
* @freq: Frequency
*
* Return: level corresponding to the frequency.
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
*/
static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_cdev,
unsigned int freq)
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
{
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
int i;
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
for (i = cpufreq_cdev->max_level - 1; i >= 0; i--) {
if (freq > cpufreq_cdev->em->table[i].frequency)
break;
}
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
return cpufreq_cdev->max_level - i - 1;
}
static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_cdev,
u32 freq)
{
int i;
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
for (i = cpufreq_cdev->max_level - 1; i >= 0; i--) {
if (freq > cpufreq_cdev->em->table[i].frequency)
break;
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
}
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
return cpufreq_cdev->em->table[i + 1].power;
}
static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_cdev,
u32 power)
{
int i;
for (i = cpufreq_cdev->max_level; i >= 0; i--) {
if (power >= cpufreq_cdev->em->table[i].power)
break;
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
}
return cpufreq_cdev->em->table[i].frequency;
}
/**
* get_load() - get load for a cpu since last updated
* @cpufreq_cdev: &struct cpufreq_cooling_device for this cpu
* @cpu: cpu number
* @cpu_idx: index of the cpu in time_in_idle*
*
* Return: The average load of cpu @cpu in percentage since this
* function was last called.
*/
static u32 get_load(struct cpufreq_cooling_device *cpufreq_cdev, int cpu,
int cpu_idx)
{
u32 load;
u64 now, now_idle, delta_time, delta_idle;
struct time_in_idle *idle_time = &cpufreq_cdev->idle_time[cpu_idx];
now_idle = get_cpu_idle_time(cpu, &now, 0);
delta_idle = now_idle - idle_time->time;
delta_time = now - idle_time->timestamp;
if (delta_time <= delta_idle)
load = 0;
else
load = div64_u64(100 * (delta_time - delta_idle), delta_time);
idle_time->time = now_idle;
idle_time->timestamp = now;
return load;
}
/**
* get_dynamic_power() - calculate the dynamic power
* @cpufreq_cdev: &cpufreq_cooling_device for this cdev
* @freq: current frequency
*
* Return: the dynamic power consumed by the cpus described by
* @cpufreq_cdev.
*/
static u32 get_dynamic_power(struct cpufreq_cooling_device *cpufreq_cdev,
unsigned long freq)
{
u32 raw_cpu_power;
raw_cpu_power = cpu_freq_to_power(cpufreq_cdev, freq);
return (raw_cpu_power * cpufreq_cdev->last_load) / 100;
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
}
/**
* cpufreq_get_requested_power() - get the current power
* @cdev: &thermal_cooling_device pointer
* @tz: a valid thermal zone device pointer
* @power: pointer in which to store the resulting power
*
* Calculate the current power consumption of the cpus in milliwatts
* and store it in @power. This function should actually calculate
* the requested power, but it's hard to get the frequency that
* cpufreq would have assigned if there were no thermal limits.
* Instead, we calculate the current power on the assumption that the
* immediate future will look like the immediate past.
*
* We use the current frequency and the average load since this
* function was last called. In reality, there could have been
* multiple opps since this function was last called and that affects
* the load calculation. While it's not perfectly accurate, this
* simplification is good enough and works. REVISIT this, as more
* complex code may be needed if experiments show that it's not
* accurate enough.
*
* Return: 0 on success, -E* if getting the static power failed.
*/
static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz,
u32 *power)
{
unsigned long freq;
int i = 0, cpu;
u32 total_load = 0;
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
struct cpufreq_policy *policy = cpufreq_cdev->policy;
u32 *load_cpu = NULL;
freq = cpufreq_quick_get(policy->cpu);
if (trace_thermal_power_cpu_get_power_enabled()) {
u32 ncpus = cpumask_weight(policy->related_cpus);
load_cpu = kcalloc(ncpus, sizeof(*load_cpu), GFP_KERNEL);
}
for_each_cpu(cpu, policy->related_cpus) {
u32 load;
if (cpu_online(cpu))
load = get_load(cpufreq_cdev, cpu, i);
else
load = 0;
total_load += load;
if (load_cpu)
load_cpu[i] = load;
i++;
}
cpufreq_cdev->last_load = total_load;
*power = get_dynamic_power(cpufreq_cdev, freq);
if (load_cpu) {
trace_thermal_power_cpu_get_power(policy->related_cpus, freq,
load_cpu, i, *power);
kfree(load_cpu);
}
return 0;
}
/**
* cpufreq_state2power() - convert a cpu cdev state to power consumed
* @cdev: &thermal_cooling_device pointer
* @tz: a valid thermal zone device pointer
* @state: cooling device state to be converted
* @power: pointer in which to store the resulting power
*
* Convert cooling device state @state into power consumption in
* milliwatts assuming 100% load. Store the calculated power in
* @power.
*
* Return: 0 on success, -EINVAL if the cooling device state could not
* be converted into a frequency or other -E* if there was an error
* when calculating the static power.
*/
static int cpufreq_state2power(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz,
unsigned long state, u32 *power)
{
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
unsigned int freq, num_cpus, idx;
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
/* Request state should be less than max_level */
if (state > cpufreq_cdev->max_level)
return -EINVAL;
num_cpus = cpumask_weight(cpufreq_cdev->policy->cpus);
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
idx = cpufreq_cdev->max_level - state;
freq = cpufreq_cdev->em->table[idx].frequency;
*power = cpu_freq_to_power(cpufreq_cdev, freq) * num_cpus;
return 0;
}
/**
* cpufreq_power2state() - convert power to a cooling device state
* @cdev: &thermal_cooling_device pointer
* @tz: a valid thermal zone device pointer
* @power: power in milliwatts to be converted
* @state: pointer in which to store the resulting state
*
* Calculate a cooling device state for the cpus described by @cdev
* that would allow them to consume at most @power mW and store it in
* @state. Note that this calculation depends on external factors
* such as the cpu load or the current static power. Calling this
* function with the same power as input can yield different cooling
* device states depending on those external factors.
*
* Return: 0 on success, -ENODEV if no cpus are online or -EINVAL if
* the calculated frequency could not be converted to a valid state.
* The latter should not happen unless the frequencies available to
* cpufreq have changed since the initialization of the cpu cooling
* device.
*/
static int cpufreq_power2state(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz, u32 power,
unsigned long *state)
{
unsigned int target_freq;
u32 last_load, normalised_power;
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
struct cpufreq_policy *policy = cpufreq_cdev->policy;
last_load = cpufreq_cdev->last_load ?: 1;
normalised_power = (power * 100) / last_load;
target_freq = cpu_power_to_freq(cpufreq_cdev, normalised_power);
*state = get_level(cpufreq_cdev, target_freq);
trace_thermal_power_cpu_limit(policy->related_cpus, target_freq, *state,
power);
return 0;
}
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
static inline bool em_is_sane(struct cpufreq_cooling_device *cpufreq_cdev,
struct em_perf_domain *em) {
struct cpufreq_policy *policy;
unsigned int nr_levels;
if (!em)
return false;
policy = cpufreq_cdev->policy;
if (!cpumask_equal(policy->related_cpus, em_span_cpus(em))) {
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
pr_err("The span of pd %*pbl is misaligned with cpufreq policy %*pbl\n",
cpumask_pr_args(em_span_cpus(em)),
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
cpumask_pr_args(policy->related_cpus));
return false;
}
nr_levels = cpufreq_cdev->max_level + 1;
if (em_pd_nr_perf_states(em) != nr_levels) {
pr_err("The number of performance states in pd %*pbl (%u) doesn't match the number of cooling levels (%u)\n",
cpumask_pr_args(em_span_cpus(em)),
em_pd_nr_perf_states(em), nr_levels);
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
return false;
}
return true;
}
#endif /* CONFIG_THERMAL_GOV_POWER_ALLOCATOR */
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
static unsigned int get_state_freq(struct cpufreq_cooling_device *cpufreq_cdev,
unsigned long state)
{
struct cpufreq_policy *policy;
unsigned long idx;
#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
/* Use the Energy Model table if available */
if (cpufreq_cdev->em) {
idx = cpufreq_cdev->max_level - state;
return cpufreq_cdev->em->table[idx].frequency;
}
#endif
/* Otherwise, fallback on the CPUFreq table */
policy = cpufreq_cdev->policy;
if (policy->freq_table_sorted == CPUFREQ_TABLE_SORTED_ASCENDING)
idx = cpufreq_cdev->max_level - state;
else
idx = state;
return policy->freq_table[idx].frequency;
}
/* cpufreq cooling device callback functions are defined below */
/**
* cpufreq_get_max_state - callback function to get the max cooling state.
* @cdev: thermal cooling device pointer.
* @state: fill this variable with the max cooling state.
*
* Callback for the thermal cooling device to return the cpufreq
* max cooling state.
*
* Return: 0 on success, an error code otherwise.
*/
static int cpufreq_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
*state = cpufreq_cdev->max_level;
return 0;
}
/**
* cpufreq_get_cur_state - callback function to get the current cooling state.
* @cdev: thermal cooling device pointer.
* @state: fill this variable with the current cooling state.
*
* Callback for the thermal cooling device to return the cpufreq
* current cooling state.
*
* Return: 0 on success, an error code otherwise.
*/
static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
*state = cpufreq_cdev->cpufreq_state;
return 0;
}
/**
* cpufreq_set_cur_state - callback function to set the current cooling state.
* @cdev: thermal cooling device pointer.
* @state: set this variable to the current cooling state.
*
* Callback for the thermal cooling device to change the cpufreq
* current cooling state.
*
* Return: 0 on success, an error code otherwise.
*/
static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
unsigned long state)
{
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
struct cpumask *cpus;
unsigned int frequency;
unsigned long max_capacity, capacity;
int ret;
/* Request state should be less than max_level */
if (state > cpufreq_cdev->max_level)
return -EINVAL;
/* Check if the old cooling action is same as new cooling action */
if (cpufreq_cdev->cpufreq_state == state)
return 0;
cpufreq_cdev->cpufreq_state = state;
frequency = get_state_freq(cpufreq_cdev, state);
ret = freq_qos_update_request(&cpufreq_cdev->qos_req, frequency);
if (ret > 0) {
cpus = cpufreq_cdev->policy->cpus;
max_capacity = arch_scale_cpu_capacity(cpumask_first(cpus));
capacity = frequency * max_capacity;
capacity /= cpufreq_cdev->policy->cpuinfo.max_freq;
arch_set_thermal_pressure(cpus, max_capacity - capacity);
- Convert tsens configuration DT binding to yaml (Rajeshwari) - Add interrupt support on the rcar sensor (Niklas Söderlund) - Add a new Spreadtrum thermal driver (Baolin Wang) - Add thermal binding for the fsl scu board, a new API to retrieve the sensor id bound to the thermal zone and i.MX system controller sensor (Anson Huang)) - Remove warning log when a deferred probe is requested on Exynos (Marek Szyprowski) - Add the thermal monitoring unit support for imx8mm with its DT bindings (Anson Huang) - Rephrase the Kconfig text for clarity (Linus Walleij) - Use the gpio descriptor for the ti-soc-thermal (Linus Walleij) - Align msg structure to 4 bytes for i.MX SC, fix the Kconfig dependency, add the __may_be unused annotation for PM functions and the COMPILE_TEST option for imx8mm (Anson Huang) - Fix a dependency on regmap in Kconfig for qoriq (Yuantian Tang) - Add DT binding and support for the rcar gen3 r8a77961 and improve the error path on the rcar init function (Niklas Söderlund) - Cleanup and improvements for the tsens Qcom sensor (Amit Kucheria) - Improve code by removing lock and caching values in the rcar thermal sensor (Niklas Söderlund) - Cleanup in the qoriq drivers and add a call to imx_thermal_unregister_legacy_cooling in the removal function (Anson Huang) - Remove redundant 'maxItems' in tsens and sprd DT bindings (Rob Herring) - Change the thermal DT bindings by making the cooling-maps optional (Yuantian Tang) - Add Tiger Lake support (Sumeet Pawnikar) - Use scnprintf() for avoiding potential buffer overflow (Takashi Iwai) - Make pkg_temp_lock a raw_spinlock_t(Clark Williams) - Fix incorrect data types by changing them to signed on i.MX SC (Anson Huang) - Replace zero-length array with flexible-array member (Gustavo A. R. Silva) - Add support for i.MX8MP in the driver and in the DT bindings (Anson Huang) - Fix return value of the cpufreq_set_cur_state() function (Willy Wolff) - Remove abusing and scary WARN_ON in the cpufreq cooling device (Daniel Lezcano) - Fix build warning of incorrect argument type reported by sparse on imx8mm (Anson Huang) - Fix stub for the devfreq cooling device (Martin Blumenstingl) - Fix cpu idle cooling documentation (Sergey Vidishev) -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEGn3N4YVz0WNVyHskqDIjiipP6E8FAl6MXkEACgkQqDIjiipP 6E+BIggAh52YBU8D8GthsvCPTgka95+wAIaZtx4Y7UnhvshHhM2w+m97TQOXK373 95mwO9mwQuAoksSmLo7pBQYJ7HItQ26Yoq9akpOL6EiT+BEWiqoHJgl+afVVtoKa n67d3Pa6coup1+PQNIA8kpTIOmUQTP8THtwpZ3HlChWsg22NTd0QUGpGJ1TtBD/q KqMdQjxahFJ4RTYsnECWBkw3EMkczMNMgdrXEvm4rMkcaJzv9g2ZPqerOShK/RzP 8sejWczt6jaRwu4hLpd/lLikTSHZoXMFJ8ylAiQXFELCPAQIrMS/ae+dTGJ4qP7x hkjsewPbeA1Z+al/IBVHiCtOzKkICQ== =XDYl -----END PGP SIGNATURE----- Merge tag 'thermal-v5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux Pull thermal updates from Daniel Lezcano: - Convert tsens configuration DT binding to yaml (Rajeshwari) - Add interrupt support on the rcar sensor (Niklas Söderlund) - Add a new Spreadtrum thermal driver (Baolin Wang) - Add thermal binding for the fsl scu board, a new API to retrieve the sensor id bound to the thermal zone and i.MX system controller sensor (Anson Huang)) - Remove warning log when a deferred probe is requested on Exynos (Marek Szyprowski) - Add the thermal monitoring unit support for imx8mm with its DT bindings (Anson Huang) - Rephrase the Kconfig text for clarity (Linus Walleij) - Use the gpio descriptor for the ti-soc-thermal (Linus Walleij) - Align msg structure to 4 bytes for i.MX SC, fix the Kconfig dependency, add the __may_be unused annotation for PM functions and the COMPILE_TEST option for imx8mm (Anson Huang) - Fix a dependency on regmap in Kconfig for qoriq (Yuantian Tang) - Add DT binding and support for the rcar gen3 r8a77961 and improve the error path on the rcar init function (Niklas Söderlund) - Cleanup and improvements for the tsens Qcom sensor (Amit Kucheria) - Improve code by removing lock and caching values in the rcar thermal sensor (Niklas Söderlund) - Cleanup in the qoriq drivers and add a call to imx_thermal_unregister_legacy_cooling in the removal function (Anson Huang) - Remove redundant 'maxItems' in tsens and sprd DT bindings (Rob Herring) - Change the thermal DT bindings by making the cooling-maps optional (Yuantian Tang) - Add Tiger Lake support (Sumeet Pawnikar) - Use scnprintf() for avoiding potential buffer overflow (Takashi Iwai) - Make pkg_temp_lock a raw_spinlock_t(Clark Williams) - Fix incorrect data types by changing them to signed on i.MX SC (Anson Huang) - Replace zero-length array with flexible-array member (Gustavo A. R. Silva) - Add support for i.MX8MP in the driver and in the DT bindings (Anson Huang) - Fix return value of the cpufreq_set_cur_state() function (Willy Wolff) - Remove abusing and scary WARN_ON in the cpufreq cooling device (Daniel Lezcano) - Fix build warning of incorrect argument type reported by sparse on imx8mm (Anson Huang) - Fix stub for the devfreq cooling device (Martin Blumenstingl) - Fix cpu idle cooling documentation (Sergey Vidishev) * tag 'thermal-v5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux: (52 commits) Documentation: cpu-idle-cooling: Fix diagram for 33% duty cycle thermal: devfreq_cooling: inline all stubs for CONFIG_DEVFREQ_THERMAL=n thermal: imx8mm: Fix build warning of incorrect argument type thermal/drivers/cpufreq_cooling: Remove abusing WARN_ON thermal/drivers/cpufreq_cooling: Fix return of cpufreq_set_cur_state thermal: imx8mm: Add i.MX8MP support dt-bindings: thermal: imx8mm-thermal: Add support for i.MX8MP thermal: qcom: tsens.h: Replace zero-length array with flexible-array member thermal: imx_sc_thermal: Fix incorrect data type thermal: int340x_thermal: Use scnprintf() for avoiding potential buffer overflow thermal: int340x: processor_thermal: Add Tiger Lake support thermal/x86_pkg_temp: Make pkg_temp_lock a raw_spinlock_t dt-bindings: thermal: make cooling-maps property optional dt-bindings: thermal: qcom-tsens: Remove redundant 'maxItems' dt-bindings: thermal: sprd: Remove redundant 'maxItems' thermal: imx: Calling imx_thermal_unregister_legacy_cooling() in .remove thermal: qoriq: Sort includes alphabetically thermal: qoriq: Use devm_add_action_or_reset() to handle all cleanups thermal: rcar_thermal: Remove lock in rcar_thermal_get_current_temp() thermal: rcar_thermal: Do not store ctemp in rcar_thermal_priv ...
2020-04-08 11:00:16 +08:00
ret = 0;
}
return ret;
}
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
/* Bind cpufreq callbacks to thermal cooling device ops */
static struct thermal_cooling_device_ops cpufreq_cooling_ops = {
.get_max_state = cpufreq_get_max_state,
.get_cur_state = cpufreq_get_cur_state,
.set_cur_state = cpufreq_set_cur_state,
};
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
/**
* __cpufreq_cooling_register - helper function to create cpufreq cooling device
* @np: a valid struct device_node to the cooling device device tree node
* @policy: cpufreq policy
* Normally this should be same as cpufreq policy->related_cpus.
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
* @em: Energy Model of the cpufreq policy
*
* This interface function registers the cpufreq cooling device with the name
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
* cooling devices. It also gives the opportunity to link the cooling device
* with a device tree node, in order to bind it via the thermal DT code.
*
* Return: a valid struct thermal_cooling_device pointer on success,
* on failure, it returns a corresponding ERR_PTR().
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
*/
static struct thermal_cooling_device *
__cpufreq_cooling_register(struct device_node *np,
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
struct cpufreq_policy *policy,
struct em_perf_domain *em)
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
{
struct thermal_cooling_device *cdev;
struct cpufreq_cooling_device *cpufreq_cdev;
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
char dev_name[THERMAL_NAME_LENGTH];
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
unsigned int i, num_cpus;
struct device *dev;
int ret;
struct thermal_cooling_device_ops *cooling_ops;
dev = get_cpu_device(policy->cpu);
if (unlikely(!dev)) {
pr_warn("No cpu device for cpu %d\n", policy->cpu);
return ERR_PTR(-ENODEV);
}
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
if (IS_ERR_OR_NULL(policy)) {
pr_err("%s: cpufreq policy isn't valid: %p\n", __func__, policy);
return ERR_PTR(-EINVAL);
}
i = cpufreq_table_count_valid_entries(policy);
if (!i) {
pr_debug("%s: CPUFreq table not found or has no valid entries\n",
__func__);
return ERR_PTR(-ENODEV);
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
}
cpufreq_cdev = kzalloc(sizeof(*cpufreq_cdev), GFP_KERNEL);
if (!cpufreq_cdev)
return ERR_PTR(-ENOMEM);
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
cpufreq_cdev->policy = policy;
num_cpus = cpumask_weight(policy->related_cpus);
cpufreq_cdev->idle_time = kcalloc(num_cpus,
sizeof(*cpufreq_cdev->idle_time),
GFP_KERNEL);
if (!cpufreq_cdev->idle_time) {
cdev = ERR_PTR(-ENOMEM);
goto free_cdev;
}
/* max_level is an index, not a counter */
cpufreq_cdev->max_level = i - 1;
ret = ida_simple_get(&cpufreq_ida, 0, 0, GFP_KERNEL);
if (ret < 0) {
cdev = ERR_PTR(ret);
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
goto free_idle_time;
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
}
cpufreq_cdev->id = ret;
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
cpufreq_cdev->id);
cooling_ops = &cpufreq_cooling_ops;
#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
if (em_is_sane(cpufreq_cdev, em)) {
cpufreq_cdev->em = em;
cooling_ops->get_requested_power = cpufreq_get_requested_power;
cooling_ops->state2power = cpufreq_state2power;
cooling_ops->power2state = cpufreq_power2state;
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
} else
#endif
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
if (policy->freq_table_sorted == CPUFREQ_TABLE_UNSORTED) {
pr_err("%s: unsorted frequency tables are not supported\n",
__func__);
cdev = ERR_PTR(-EINVAL);
goto remove_ida;
}
cpufreq: Use per-policy frequency QoS Replace the CPU device PM QoS used for the management of min and max frequency constraints in cpufreq (and its users) with per-policy frequency QoS to avoid problems with cpufreq policies covering more then one CPU. Namely, a cpufreq driver is registered with the subsys interface which calls cpufreq_add_dev() for each CPU, starting from CPU0, so currently the PM QoS notifiers are added to the first CPU in the policy (i.e. CPU0 in the majority of cases). In turn, when the cpufreq driver is unregistered, the subsys interface doing that calls cpufreq_remove_dev() for each CPU, starting from CPU0, and the PM QoS notifiers are only removed when cpufreq_remove_dev() is called for the last CPU in the policy, say CPUx, which as a rule is not CPU0 if the policy covers more than one CPU. Then, the PM QoS notifiers cannot be removed, because CPUx does not have them, and they are still there in the device PM QoS notifiers list of CPU0, which prevents new PM QoS notifiers from being registered for CPU0 on the next attempt to register the cpufreq driver. The same issue occurs when the first CPU in the policy goes offline before unregistering the driver. After this change it does not matter which CPU is the policy CPU at the driver registration time and whether or not it is online all the time, because the frequency QoS is per policy and not per CPU. Fixes: 67d874c3b2c6 ("cpufreq: Register notifiers with the PM QoS framework") Reported-by: Dmitry Osipenko <digetx@gmail.com> Tested-by: Dmitry Osipenko <digetx@gmail.com> Reported-by: Sudeep Holla <sudeep.holla@arm.com> Tested-by: Sudeep Holla <sudeep.holla@arm.com> Diagnosed-by: Viresh Kumar <viresh.kumar@linaro.org> Link: https://lore.kernel.org/linux-pm/5ad2624194baa2f53acc1f1e627eb7684c577a19.1562210705.git.viresh.kumar@linaro.org/T/#md2d89e95906b8c91c15f582146173dce2e86e99f Link: https://lore.kernel.org/linux-pm/20191017094612.6tbkwoq4harsjcqv@vireshk-i7/T/#m30d48cc23b9a80467fbaa16e30f90b3828a5a29b Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
2019-10-16 18:47:06 +08:00
ret = freq_qos_add_request(&policy->constraints,
&cpufreq_cdev->qos_req, FREQ_QOS_MAX,
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
get_state_freq(cpufreq_cdev, 0));
if (ret < 0) {
pr_err("%s: Failed to add freq constraint (%d)\n", __func__,
ret);
cdev = ERR_PTR(ret);
goto remove_ida;
}
cdev = thermal_of_cooling_device_register(np, dev_name, cpufreq_cdev,
cooling_ops);
if (IS_ERR(cdev))
goto remove_qos_req;
thermal: cpu_cooling: fix lockdep problems in cpu_cooling A recent change to the cpu_cooling code introduced a AB-BA deadlock scenario between the cpufreq_policy_notifier_list rwsem and the cooling_cpufreq_lock. This is caused by cooling_cpufreq_lock being held before the registration/removal of the notifier block (an operation which takes the rwsem), and the notifier code itself which takes the locks in the reverse order: ====================================================== [ INFO: possible circular locking dependency detected ] 3.18.0+ #1453 Not tainted ------------------------------------------------------- rc.local/770 is trying to acquire lock: (cooling_cpufreq_lock){+.+.+.}, at: [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc but task is already holding lock: ((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 ((cpufreq_policy_notifier_list).rwsem){++++.+}: [<c06bc3b0>] down_write+0x44/0x9c [<c0043444>] blocking_notifier_chain_register+0x28/0xd8 [<c04ad610>] cpufreq_register_notifier+0x68/0x90 [<c04abe4c>] __cpufreq_cooling_register.part.1+0x120/0x180 [<c04abf44>] __cpufreq_cooling_register+0x98/0xa4 [<c04abf8c>] cpufreq_cooling_register+0x18/0x1c [<bf0046f8>] imx_thermal_probe+0x1c0/0x470 [imx_thermal] [<c037cef8>] platform_drv_probe+0x50/0xac [<c037b710>] driver_probe_device+0x114/0x234 [<c037b8cc>] __driver_attach+0x9c/0xa0 [<c0379d68>] bus_for_each_dev+0x5c/0x90 [<c037b204>] driver_attach+0x24/0x28 [<c037ae7c>] bus_add_driver+0xe0/0x1d8 [<c037c0cc>] driver_register+0x80/0xfc [<c037cd80>] __platform_driver_register+0x50/0x64 [<bf007018>] 0xbf007018 [<c0008a5c>] do_one_initcall+0x88/0x1d8 [<c0095da4>] load_module+0x1768/0x1ef8 [<c0096614>] SyS_init_module+0xe0/0xf4 [<c000ec00>] ret_fast_syscall+0x0/0x48 -> #0 (cooling_cpufreq_lock){+.+.+.}: [<c00619f8>] lock_acquire+0xb0/0x124 [<c06ba3b4>] mutex_lock_nested+0x5c/0x3d8 [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc [<c0042bf4>] notifier_call_chain+0x4c/0x8c [<c0042f20>] __blocking_notifier_call_chain+0x50/0x68 [<c0042f58>] blocking_notifier_call_chain+0x20/0x28 [<c04ae62c>] cpufreq_set_policy+0x7c/0x1d0 [<c04af3cc>] store_scaling_governor+0x74/0x9c [<c04ad418>] store+0x90/0xc0 [<c0175384>] sysfs_kf_write+0x54/0x58 [<c01746b4>] kernfs_fop_write+0xdc/0x190 [<c010dcc0>] vfs_write+0xac/0x1b4 [<c010dfec>] SyS_write+0x44/0x90 [<c000ec00>] ret_fast_syscall+0x0/0x48 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock((cpufreq_policy_notifier_list).rwsem); lock(cooling_cpufreq_lock); lock((cpufreq_policy_notifier_list).rwsem); lock(cooling_cpufreq_lock); *** DEADLOCK *** 7 locks held by rc.local/770: #0: (sb_writers#6){.+.+.+}, at: [<c010dda0>] vfs_write+0x18c/0x1b4 #1: (&of->mutex){+.+.+.}, at: [<c0174678>] kernfs_fop_write+0xa0/0x190 #2: (s_active#52){.+.+.+}, at: [<c0174680>] kernfs_fop_write+0xa8/0x190 #3: (cpu_hotplug.lock){++++++}, at: [<c0026a60>] get_online_cpus+0x34/0x90 #4: (cpufreq_rwsem){.+.+.+}, at: [<c04ad3e0>] store+0x58/0xc0 #5: (&policy->rwsem){+.+.+.}, at: [<c04ad3f8>] store+0x70/0xc0 #6: ((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68 stack backtrace: CPU: 0 PID: 770 Comm: rc.local Not tainted 3.18.0+ #1453 Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree) Backtrace: [<c00121c8>] (dump_backtrace) from [<c0012360>] (show_stack+0x18/0x1c) r6:c0b85a80 r5:c0b75630 r4:00000000 r3:00000000 [<c0012348>] (show_stack) from [<c06b6c48>] (dump_stack+0x7c/0x98) [<c06b6bcc>] (dump_stack) from [<c06b42a4>] (print_circular_bug+0x28c/0x2d8) r4:c0b85a80 r3:d0071d40 [<c06b4018>] (print_circular_bug) from [<c00613b0>] (__lock_acquire+0x1acc/0x1bb0) r10:c0b50660 r8:c09e6d80 r7:d0071d40 r6:c11d0f0c r5:00000007 r4:d0072240 [<c005f8e4>] (__lock_acquire) from [<c00619f8>] (lock_acquire+0xb0/0x124) r10:00000000 r9:c04abfc4 r8:00000000 r7:00000000 r6:00000000 r5:c0a06f0c r4:00000000 [<c0061948>] (lock_acquire) from [<c06ba3b4>] (mutex_lock_nested+0x5c/0x3d8) r10:ec853800 r9:c0a06ed4 r8:d0071d40 r7:c0a06ed4 r6:c11d0f0c r5:00000000 r4:c04abfc4 [<c06ba358>] (mutex_lock_nested) from [<c04abfc4>] (cpufreq_thermal_notifier+0x34/0xfc) r10:ec853800 r9:ec85380c r8:d00d7d3c r7:c0a06ed4 r6:d00d7d3c r5:00000000 r4:fffffffe [<c04abf90>] (cpufreq_thermal_notifier) from [<c0042bf4>] (notifier_call_chain+0x4c/0x8c) r7:00000000 r6:00000000 r5:00000000 r4:fffffffe [<c0042ba8>] (notifier_call_chain) from [<c0042f20>] (__blocking_notifier_call_chain+0x50/0x68) r8:c0a072a4 r7:00000000 r6:d00d7d3c r5:ffffffff r4:c0a06fc8 r3:ffffffff [<c0042ed0>] (__blocking_notifier_call_chain) from [<c0042f58>] (blocking_notifier_call_chain+0x20/0x28) r7:ec98b540 r6:c13ebc80 r5:ed76e600 r4:d00d7d3c [<c0042f38>] (blocking_notifier_call_chain) from [<c04ae62c>] (cpufreq_set_policy+0x7c/0x1d0) [<c04ae5b0>] (cpufreq_set_policy) from [<c04af3cc>] (store_scaling_governor+0x74/0x9c) r7:ec98b540 r6:0000000c r5:ec98b540 r4:ed76e600 [<c04af358>] (store_scaling_governor) from [<c04ad418>] (store+0x90/0xc0) r6:0000000c r5:ed76e6d4 r4:ed76e600 [<c04ad388>] (store) from [<c0175384>] (sysfs_kf_write+0x54/0x58) r8:0000000c r7:d00d7f78 r6:ec98b540 r5:0000000c r4:ec853800 r3:0000000c [<c0175330>] (sysfs_kf_write) from [<c01746b4>] (kernfs_fop_write+0xdc/0x190) r6:ec98b540 r5:00000000 r4:00000000 r3:c0175330 [<c01745d8>] (kernfs_fop_write) from [<c010dcc0>] (vfs_write+0xac/0x1b4) r10:0162aa70 r9:d00d6000 r8:0000000c r7:d00d7f78 r6:0162aa70 r5:0000000c r4:eccde500 [<c010dc14>] (vfs_write) from [<c010dfec>] (SyS_write+0x44/0x90) r10:0162aa70 r8:0000000c r7:eccde500 r6:eccde500 r5:00000000 r4:00000000 [<c010dfa8>] (SyS_write) from [<c000ec00>] (ret_fast_syscall+0x0/0x48) r10:00000000 r8:c000edc4 r7:00000004 r6:000216cc r5:0000000c r4:0162aa70 Solve this by moving to finer grained locking - use one mutex to protect the cpufreq_dev_list as a whole, and a separate lock to ensure correct ordering of cpufreq notifier registration and removal. cooling_list_lock is taken within cooling_cpufreq_lock on (un)registration to preserve the behavior of the code, i.e. to atomically add/remove to the list and (un)register the notifier. Fixes: 2dcd851fe4b4 ("thermal: cpu_cooling: Update always cpufreq policy with Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
2015-08-12 17:52:16 +08:00
mutex_lock(&cooling_list_lock);
list_add(&cpufreq_cdev->node, &cpufreq_cdev_list);
mutex_unlock(&cooling_list_lock);
thermal: cpu_cooling: fix lockdep problems in cpu_cooling A recent change to the cpu_cooling code introduced a AB-BA deadlock scenario between the cpufreq_policy_notifier_list rwsem and the cooling_cpufreq_lock. This is caused by cooling_cpufreq_lock being held before the registration/removal of the notifier block (an operation which takes the rwsem), and the notifier code itself which takes the locks in the reverse order: ====================================================== [ INFO: possible circular locking dependency detected ] 3.18.0+ #1453 Not tainted ------------------------------------------------------- rc.local/770 is trying to acquire lock: (cooling_cpufreq_lock){+.+.+.}, at: [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc but task is already holding lock: ((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 ((cpufreq_policy_notifier_list).rwsem){++++.+}: [<c06bc3b0>] down_write+0x44/0x9c [<c0043444>] blocking_notifier_chain_register+0x28/0xd8 [<c04ad610>] cpufreq_register_notifier+0x68/0x90 [<c04abe4c>] __cpufreq_cooling_register.part.1+0x120/0x180 [<c04abf44>] __cpufreq_cooling_register+0x98/0xa4 [<c04abf8c>] cpufreq_cooling_register+0x18/0x1c [<bf0046f8>] imx_thermal_probe+0x1c0/0x470 [imx_thermal] [<c037cef8>] platform_drv_probe+0x50/0xac [<c037b710>] driver_probe_device+0x114/0x234 [<c037b8cc>] __driver_attach+0x9c/0xa0 [<c0379d68>] bus_for_each_dev+0x5c/0x90 [<c037b204>] driver_attach+0x24/0x28 [<c037ae7c>] bus_add_driver+0xe0/0x1d8 [<c037c0cc>] driver_register+0x80/0xfc [<c037cd80>] __platform_driver_register+0x50/0x64 [<bf007018>] 0xbf007018 [<c0008a5c>] do_one_initcall+0x88/0x1d8 [<c0095da4>] load_module+0x1768/0x1ef8 [<c0096614>] SyS_init_module+0xe0/0xf4 [<c000ec00>] ret_fast_syscall+0x0/0x48 -> #0 (cooling_cpufreq_lock){+.+.+.}: [<c00619f8>] lock_acquire+0xb0/0x124 [<c06ba3b4>] mutex_lock_nested+0x5c/0x3d8 [<c04abfc4>] cpufreq_thermal_notifier+0x34/0xfc [<c0042bf4>] notifier_call_chain+0x4c/0x8c [<c0042f20>] __blocking_notifier_call_chain+0x50/0x68 [<c0042f58>] blocking_notifier_call_chain+0x20/0x28 [<c04ae62c>] cpufreq_set_policy+0x7c/0x1d0 [<c04af3cc>] store_scaling_governor+0x74/0x9c [<c04ad418>] store+0x90/0xc0 [<c0175384>] sysfs_kf_write+0x54/0x58 [<c01746b4>] kernfs_fop_write+0xdc/0x190 [<c010dcc0>] vfs_write+0xac/0x1b4 [<c010dfec>] SyS_write+0x44/0x90 [<c000ec00>] ret_fast_syscall+0x0/0x48 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock((cpufreq_policy_notifier_list).rwsem); lock(cooling_cpufreq_lock); lock((cpufreq_policy_notifier_list).rwsem); lock(cooling_cpufreq_lock); *** DEADLOCK *** 7 locks held by rc.local/770: #0: (sb_writers#6){.+.+.+}, at: [<c010dda0>] vfs_write+0x18c/0x1b4 #1: (&of->mutex){+.+.+.}, at: [<c0174678>] kernfs_fop_write+0xa0/0x190 #2: (s_active#52){.+.+.+}, at: [<c0174680>] kernfs_fop_write+0xa8/0x190 #3: (cpu_hotplug.lock){++++++}, at: [<c0026a60>] get_online_cpus+0x34/0x90 #4: (cpufreq_rwsem){.+.+.+}, at: [<c04ad3e0>] store+0x58/0xc0 #5: (&policy->rwsem){+.+.+.}, at: [<c04ad3f8>] store+0x70/0xc0 #6: ((cpufreq_policy_notifier_list).rwsem){++++.+}, at: [<c0042f04>] __blocking_notifier_call_chain+0x34/0x68 stack backtrace: CPU: 0 PID: 770 Comm: rc.local Not tainted 3.18.0+ #1453 Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree) Backtrace: [<c00121c8>] (dump_backtrace) from [<c0012360>] (show_stack+0x18/0x1c) r6:c0b85a80 r5:c0b75630 r4:00000000 r3:00000000 [<c0012348>] (show_stack) from [<c06b6c48>] (dump_stack+0x7c/0x98) [<c06b6bcc>] (dump_stack) from [<c06b42a4>] (print_circular_bug+0x28c/0x2d8) r4:c0b85a80 r3:d0071d40 [<c06b4018>] (print_circular_bug) from [<c00613b0>] (__lock_acquire+0x1acc/0x1bb0) r10:c0b50660 r8:c09e6d80 r7:d0071d40 r6:c11d0f0c r5:00000007 r4:d0072240 [<c005f8e4>] (__lock_acquire) from [<c00619f8>] (lock_acquire+0xb0/0x124) r10:00000000 r9:c04abfc4 r8:00000000 r7:00000000 r6:00000000 r5:c0a06f0c r4:00000000 [<c0061948>] (lock_acquire) from [<c06ba3b4>] (mutex_lock_nested+0x5c/0x3d8) r10:ec853800 r9:c0a06ed4 r8:d0071d40 r7:c0a06ed4 r6:c11d0f0c r5:00000000 r4:c04abfc4 [<c06ba358>] (mutex_lock_nested) from [<c04abfc4>] (cpufreq_thermal_notifier+0x34/0xfc) r10:ec853800 r9:ec85380c r8:d00d7d3c r7:c0a06ed4 r6:d00d7d3c r5:00000000 r4:fffffffe [<c04abf90>] (cpufreq_thermal_notifier) from [<c0042bf4>] (notifier_call_chain+0x4c/0x8c) r7:00000000 r6:00000000 r5:00000000 r4:fffffffe [<c0042ba8>] (notifier_call_chain) from [<c0042f20>] (__blocking_notifier_call_chain+0x50/0x68) r8:c0a072a4 r7:00000000 r6:d00d7d3c r5:ffffffff r4:c0a06fc8 r3:ffffffff [<c0042ed0>] (__blocking_notifier_call_chain) from [<c0042f58>] (blocking_notifier_call_chain+0x20/0x28) r7:ec98b540 r6:c13ebc80 r5:ed76e600 r4:d00d7d3c [<c0042f38>] (blocking_notifier_call_chain) from [<c04ae62c>] (cpufreq_set_policy+0x7c/0x1d0) [<c04ae5b0>] (cpufreq_set_policy) from [<c04af3cc>] (store_scaling_governor+0x74/0x9c) r7:ec98b540 r6:0000000c r5:ec98b540 r4:ed76e600 [<c04af358>] (store_scaling_governor) from [<c04ad418>] (store+0x90/0xc0) r6:0000000c r5:ed76e6d4 r4:ed76e600 [<c04ad388>] (store) from [<c0175384>] (sysfs_kf_write+0x54/0x58) r8:0000000c r7:d00d7f78 r6:ec98b540 r5:0000000c r4:ec853800 r3:0000000c [<c0175330>] (sysfs_kf_write) from [<c01746b4>] (kernfs_fop_write+0xdc/0x190) r6:ec98b540 r5:00000000 r4:00000000 r3:c0175330 [<c01745d8>] (kernfs_fop_write) from [<c010dcc0>] (vfs_write+0xac/0x1b4) r10:0162aa70 r9:d00d6000 r8:0000000c r7:d00d7f78 r6:0162aa70 r5:0000000c r4:eccde500 [<c010dc14>] (vfs_write) from [<c010dfec>] (SyS_write+0x44/0x90) r10:0162aa70 r8:0000000c r7:eccde500 r6:eccde500 r5:00000000 r4:00000000 [<c010dfa8>] (SyS_write) from [<c000ec00>] (ret_fast_syscall+0x0/0x48) r10:00000000 r8:c000edc4 r7:00000004 r6:000216cc r5:0000000c r4:0162aa70 Solve this by moving to finer grained locking - use one mutex to protect the cpufreq_dev_list as a whole, and a separate lock to ensure correct ordering of cpufreq notifier registration and removal. cooling_list_lock is taken within cooling_cpufreq_lock on (un)registration to preserve the behavior of the code, i.e. to atomically add/remove to the list and (un)register the notifier. Fixes: 2dcd851fe4b4 ("thermal: cpu_cooling: Update always cpufreq policy with Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
2015-08-12 17:52:16 +08:00
return cdev;
remove_qos_req:
cpufreq: Use per-policy frequency QoS Replace the CPU device PM QoS used for the management of min and max frequency constraints in cpufreq (and its users) with per-policy frequency QoS to avoid problems with cpufreq policies covering more then one CPU. Namely, a cpufreq driver is registered with the subsys interface which calls cpufreq_add_dev() for each CPU, starting from CPU0, so currently the PM QoS notifiers are added to the first CPU in the policy (i.e. CPU0 in the majority of cases). In turn, when the cpufreq driver is unregistered, the subsys interface doing that calls cpufreq_remove_dev() for each CPU, starting from CPU0, and the PM QoS notifiers are only removed when cpufreq_remove_dev() is called for the last CPU in the policy, say CPUx, which as a rule is not CPU0 if the policy covers more than one CPU. Then, the PM QoS notifiers cannot be removed, because CPUx does not have them, and they are still there in the device PM QoS notifiers list of CPU0, which prevents new PM QoS notifiers from being registered for CPU0 on the next attempt to register the cpufreq driver. The same issue occurs when the first CPU in the policy goes offline before unregistering the driver. After this change it does not matter which CPU is the policy CPU at the driver registration time and whether or not it is online all the time, because the frequency QoS is per policy and not per CPU. Fixes: 67d874c3b2c6 ("cpufreq: Register notifiers with the PM QoS framework") Reported-by: Dmitry Osipenko <digetx@gmail.com> Tested-by: Dmitry Osipenko <digetx@gmail.com> Reported-by: Sudeep Holla <sudeep.holla@arm.com> Tested-by: Sudeep Holla <sudeep.holla@arm.com> Diagnosed-by: Viresh Kumar <viresh.kumar@linaro.org> Link: https://lore.kernel.org/linux-pm/5ad2624194baa2f53acc1f1e627eb7684c577a19.1562210705.git.viresh.kumar@linaro.org/T/#md2d89e95906b8c91c15f582146173dce2e86e99f Link: https://lore.kernel.org/linux-pm/20191017094612.6tbkwoq4harsjcqv@vireshk-i7/T/#m30d48cc23b9a80467fbaa16e30f90b3828a5a29b Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
2019-10-16 18:47:06 +08:00
freq_qos_remove_request(&cpufreq_cdev->qos_req);
remove_ida:
ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id);
free_idle_time:
kfree(cpufreq_cdev->idle_time);
free_cdev:
kfree(cpufreq_cdev);
return cdev;
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
}
/**
* cpufreq_cooling_register - function to create cpufreq cooling device.
* @policy: cpufreq policy
*
* This interface function registers the cpufreq cooling device with the name
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
* cooling devices.
*
* Return: a valid struct thermal_cooling_device pointer on success,
* on failure, it returns a corresponding ERR_PTR().
*/
struct thermal_cooling_device *
cpufreq_cooling_register(struct cpufreq_policy *policy)
{
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
return __cpufreq_cooling_register(NULL, policy, NULL);
}
EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
/**
* of_cpufreq_cooling_register - function to create cpufreq cooling device.
* @policy: cpufreq policy
*
* This interface function registers the cpufreq cooling device with the name
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
* cooling devices. Using this API, the cpufreq cooling device will be
* linked to the device tree node provided.
*
* Using this function, the cooling device will implement the power
* extensions by using a simple cpu power model. The cpus must have
* registered their OPPs using the OPP library.
*
* It also takes into account, if property present in policy CPU node, the
* static power consumed by the cpu.
*
* Return: a valid struct thermal_cooling_device pointer on success,
* and NULL on failure.
*/
struct thermal_cooling_device *
of_cpufreq_cooling_register(struct cpufreq_policy *policy)
{
struct device_node *np = of_get_cpu_node(policy->cpu, NULL);
struct thermal_cooling_device *cdev = NULL;
if (!np) {
pr_err("cpufreq_cooling: OF node not available for cpu%d\n",
policy->cpu);
return NULL;
}
if (of_find_property(np, "#cooling-cells", NULL)) {
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
struct em_perf_domain *em = em_cpu_get(policy->cpu);
thermal: cpu_cooling: Migrate to using the EM framework The newly introduced Energy Model framework manages power cost tables in a generic way. Moreover, it supports several types of models since the tables can come from DT or firmware (through SCMI) for example. On the other hand, the cpu_cooling subsystem manages its own power cost tables using only DT data. In order to avoid the duplication of data in the kernel, and in order to enable IPA with EMs coming from more than just DT, remove the private tables from cpu_cooling.c and migrate it to using the centralized EM framework. Doing so should have no visible functional impact for existing users of IPA since: - recent extenstions to the the PM_OPP infrastructure enable the registration of EMs in PM_EM using the DT property used by IPA; - the existing upstream cpufreq drivers marked with the 'CPUFREQ_IS_COOLING_DEV' flag all use the aforementioned PM_OPP infrastructure, which means they all support PM_EM. The only two exceptions are qoriq-cpufreq which doesn't in fact use an EM and scmi-cpufreq which doesn't use DT for power costs. For existing users of cpu_cooling, PM_EM tables will contain the exact same power values that IPA used to compute on its own until now. The only new dependency for them is to compile in CONFIG_ENERGY_MODEL. The case where the thermal subsystem is used without an Energy Model (cpufreq_cooling_ops) is handled by looking directly at CPUFreq's frequency table which is already a dependency for cpu_cooling.c anyway. Since the thermal framework expects the cooling states in a particular order, bail out whenever the CPUFreq table is unsorted, since that is fairly uncommon in general, and there are currently no users of cpu_cooling for this use-case. Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Quentin Perret <qperret@google.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20191030151451.7961-5-qperret@google.com
2019-10-30 23:14:51 +08:00
cdev = __cpufreq_cooling_register(np, policy, em);
if (IS_ERR(cdev)) {
pr_err("cpufreq_cooling: cpu%d failed to register as cooling device: %ld\n",
policy->cpu, PTR_ERR(cdev));
cdev = NULL;
}
}
of_node_put(np);
return cdev;
}
EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
/**
* cpufreq_cooling_unregister - function to remove cpufreq cooling device.
* @cdev: thermal cooling device pointer.
*
* This interface function unregisters the "thermal-cpufreq-%x" cooling device.
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
*/
void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
{
struct cpufreq_cooling_device *cpufreq_cdev;
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
if (!cdev)
return;
cpufreq_cdev = cdev->devdata;
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
mutex_lock(&cooling_list_lock);
list_del(&cpufreq_cdev->node);
mutex_unlock(&cooling_list_lock);
thermal_cooling_device_unregister(cdev);
cpufreq: Use per-policy frequency QoS Replace the CPU device PM QoS used for the management of min and max frequency constraints in cpufreq (and its users) with per-policy frequency QoS to avoid problems with cpufreq policies covering more then one CPU. Namely, a cpufreq driver is registered with the subsys interface which calls cpufreq_add_dev() for each CPU, starting from CPU0, so currently the PM QoS notifiers are added to the first CPU in the policy (i.e. CPU0 in the majority of cases). In turn, when the cpufreq driver is unregistered, the subsys interface doing that calls cpufreq_remove_dev() for each CPU, starting from CPU0, and the PM QoS notifiers are only removed when cpufreq_remove_dev() is called for the last CPU in the policy, say CPUx, which as a rule is not CPU0 if the policy covers more than one CPU. Then, the PM QoS notifiers cannot be removed, because CPUx does not have them, and they are still there in the device PM QoS notifiers list of CPU0, which prevents new PM QoS notifiers from being registered for CPU0 on the next attempt to register the cpufreq driver. The same issue occurs when the first CPU in the policy goes offline before unregistering the driver. After this change it does not matter which CPU is the policy CPU at the driver registration time and whether or not it is online all the time, because the frequency QoS is per policy and not per CPU. Fixes: 67d874c3b2c6 ("cpufreq: Register notifiers with the PM QoS framework") Reported-by: Dmitry Osipenko <digetx@gmail.com> Tested-by: Dmitry Osipenko <digetx@gmail.com> Reported-by: Sudeep Holla <sudeep.holla@arm.com> Tested-by: Sudeep Holla <sudeep.holla@arm.com> Diagnosed-by: Viresh Kumar <viresh.kumar@linaro.org> Link: https://lore.kernel.org/linux-pm/5ad2624194baa2f53acc1f1e627eb7684c577a19.1562210705.git.viresh.kumar@linaro.org/T/#md2d89e95906b8c91c15f582146173dce2e86e99f Link: https://lore.kernel.org/linux-pm/20191017094612.6tbkwoq4harsjcqv@vireshk-i7/T/#m30d48cc23b9a80467fbaa16e30f90b3828a5a29b Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
2019-10-16 18:47:06 +08:00
freq_qos_remove_request(&cpufreq_cdev->qos_req);
ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id);
kfree(cpufreq_cdev->idle_time);
kfree(cpufreq_cdev);
thermal: add generic cpufreq cooling implementation This patchset introduces a new generic cooling device based on cpufreq that can be used on non-ACPI platforms. As a proof of concept, we have drivers for the following platforms using this mechanism now: * Samsung Exynos (Exynos4 and Exynos5) in the current patchset. * Freescale i.MX (git://git.linaro.org/people/amitdanielk/linux.git imx6q_thermal) There is a small change in cpufreq cooling registration APIs, so a minor change is needed for Freescale platforms. Brief Description: 1) The generic cooling devices code is placed inside driver/thermal/* as placing inside acpi folder will need un-necessary enabling of acpi code. This code is architecture independent. 2) This patchset adds generic cpu cooling low level implementation through frequency clipping. In future, other cpu related cooling devices may be added here. An ACPI version of this already exists (drivers/acpi/processor_thermal.c) .But this will be useful for platforms like ARM using the generic thermal interface along with the generic cpu cooling devices. The cooling device registration API's return cooling device pointers which can be easily binded with the thermal zone trip points. The important APIs exposed are, a) struct thermal_cooling_device *cpufreq_cooling_register( struct cpumask *clip_cpus) b) void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 3) Samsung exynos platform thermal implementation is done using the generic cpu cooling APIs and the new trip type. The temperature sensor driver present in the hwmon folder(registered as hwmon driver) is moved to thermal folder and registered as a thermal driver. A simple data/control flow diagrams is shown below, Core Linux thermal <-----> Exynos thermal interface <----- Temperature Sensor | | \|/ | Cpufreq cooling device <--------------- TODO: *Will send the DT enablement patches later after the driver is merged. This patch: Add support for generic cpu thermal cooling low level implementations using frequency scaling up/down based on the registration parameters. Different cpu related cooling devices can be registered by the user and the binding of these cooling devices to the corresponding trip points can be easily done as the registration APIs return the cooling device pointer. The user of these APIs are responsible for passing clipping frequency . The drivers can also register to recieve notification about any cooling action called. [akpm@linux-foundation.org: fix comment layout] Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org> Cc: Guenter Roeck <guenter.roeck@ericsson.com> Cc: SangWook Ju <sw.ju@samsung.com> Cc: Durgadoss <durgadoss.r@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Jean Delvare <khali@linux-fr.org> Cc: Kyungmin Park <kmpark@infradead.org> Cc: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
2012-08-16 19:41:40 +08:00
}
EXPORT_SYMBOL_GPL(cpufreq_cooling_unregister);