summaryrefslogtreecommitdiff
path: root/drivers/powercap
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-02-21 12:32:05 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2023-02-21 12:32:05 -0800
commit1b72607d7321e66829e11148712b3a2ba1dc83e7 (patch)
tree7fa9633b99a12104605792f60166ce86a1ab082c /drivers/powercap
parent88af9b164c7a25a71b1a1a699872b869e2e84c77 (diff)
parent6828e402d06f7c574430b61c05db784cd847b19f (diff)
downloadlwn-1b72607d7321e66829e11148712b3a2ba1dc83e7.tar.gz
lwn-1b72607d7321e66829e11148712b3a2ba1dc83e7.zip
Merge tag 'thermal-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull thermal control updates from Rafael Wysocki: "The majority of changes here are related to the general switch-over to using arrays of generic trip point structures registered along with a thermal zone instead of trip point callbacks (this has been done mostly by Daniel Lezcano with some help from yours truly on the Intel drivers front). Apart from that and the related reorganization of code, there are some enhancements of the existing driver and a new Mediatek Low Voltage Thermal Sensor (LVTS) driver. The Intel powerclamp undergoes a major rework so it will use the generic idle_inject facility for CPU idle time injection going forward and it will take additional module parameters for specifying the subset of CPUs to be affected by it (work done by Srinivas Pandruvada). Also included are assorted fixes and a whole bunch of cleanups. Specifics: - Rework a large bunch of drivers to use the generic thermal trip structure and use the opportunity to do more cleanups by removing unused functions from the OF code (Daniel Lezcano) - Remove core header inclusion from drivers (Daniel Lezcano) - Fix some locking issues related to the generic thermal trip rework (Johan Hovold) - Fix a crash when requesting the critical temperature on tegra, which is related to the generic trip point work (Jon Hunter) - Clean up thermal device unregistration code (Viresh Kumar) - Fix and clean up thermal control core initialization error code paths (Daniel Lezcano) - Relocate the trip points handling code into a separate file (Daniel Lezcano) - Make the thermal core fail registration of thermal zones and cooling devices if the thermal class has not been registered (Rafael Wysocki) - Add trip point initialization helper functions for ACPI-defined trip points and modify two thermal drivers to use them (Rafael Wysocki, Daniel Lezcano) - Make the core thermal control code use sysfs_emit_at() instead of scnprintf() where applicable (ye xingchen) - Consolidate code accessing the Intel TCC (Thermal Control Circuitry) MSRs by introducing library functions for that and making the TCC-related code in thermal drivers use them (Zhang Rui) - Enhance the x86_pkg_temp_thermal driver to support dynamic tjmax changes (Zhang Rui) - Address an "unsigned expression compared with zero" warning in the intel_soc_dts_iosf thermal driver (Yang Li) - Update comments regarding two functions in the Intel Menlow thermal driver (Deming Wang) - Use sysfs_emit_at() instead of scnprintf() in the int340x thermal driver (ye xingchen) - Make the intel_pch thermal driver support the Wellsburg PCH (Tim Zimmermann) - Modify the intel_pch and processor_thermal_device_pci thermal drivers use generic trip point tables instead of thermal zone trip point callbacks (Daniel Lezcano) - Add production mode attribute sysfs attribute to the int340x thermal driver (Srinivas Pandruvada) - Rework dynamic trip point updates handling and locking in the int340x thermal driver (Rafael Wysocki) - Make the int340x thermal driver use a generic trip points table instead of thermal zone trip point callbacks (Rafael Wysocki, Daniel Lezcano) - Clean up and improve the int340x thermal driver (Rafael Wysocki) - Simplify and clean up the intel_pch thermal driver (Rafael Wysocki) - Fix the Intel powerclamp thermal driver and make it use the common idle injection framework (Srinivas Pandruvada) - Add two module parameters, cpumask and max_idle, to the Intel powerclamp thermal driver to allow it to affect only a specific subset of CPUs instead of all of them (Srinivas Pandruvada) - Make the Intel quark_dts thermal driver Use generic trip point objects instead of its own trip point representation (Daniel Lezcano) - Add toctree entry for thermal documents and fix two issues in the Intel powerclamp driver documentation (Bagas Sanjaya) - Use strscpy() to instead of strncpy() in the thermal core (Xu Panda) - Fix thermal_sampling_exit() (Vincent Guittot) - Add Mediatek Low Voltage Thermal Sensor (LVTS) driver (Balsam Chihi) - Add r8a779g0 RCar support to the rcar_gen3 thermal driver (Geert Uytterhoeven) - Fix useless call to set_trips() when resuming in the rcar_gen3 thermal control driver and add interrupt support detection at init time to it (Niklas Söderlund) - Fix memory corruption in the hi3660 thermal driver (Yongqin Liu) - Fix include path for libnl3 in pkg-config file for libthermal (Vibhav Pant) - Remove syscfg-based driver for st as the platform is not supported any more (Alain Volmat)" * tag 'thermal-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (135 commits) thermal/drivers/st: Remove syscfg based driver thermal: Remove core header inclusion from drivers tools/lib/thermal: Fix include path for libnl3 in pkg-config file. thermal/drivers/hisi: Drop second sensor hi3660 thermal/drivers/rcar_gen3_thermal: Fix device initialization thermal/drivers/rcar_gen3_thermal: Create device local ops struct thermal/drivers/rcar_gen3_thermal: Do not call set_trips() when resuming thermal/drivers/rcar_gen3: Add support for R-Car V4H dt-bindings: thermal: rcar-gen3-thermal: Add r8a779g0 support thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver dt-bindings: thermal: mediatek: Add LVTS thermal controllers thermal/drivers/mediatek: Relocate driver to mediatek folder tools/lib/thermal: Fix thermal_sampling_exit() Documentation: powerclamp: Fix numbered lists formatting Documentation: powerclamp: Escape wildcard in cpumask description Documentation: admin-guide: Add toctree entry for thermal docs thermal: intel: powerclamp: Add two module parameters Documentation: admin-guide: Move intel_powerclamp documentation thermal: core: Use sysfs_emit_at() instead of scnprintf() thermal: intel: powerclamp: Fix duration module parameter ...
Diffstat (limited to 'drivers/powercap')
-rw-r--r--drivers/powercap/idle_inject.c59
1 files changed, 53 insertions, 6 deletions
diff --git a/drivers/powercap/idle_inject.c b/drivers/powercap/idle_inject.c
index c03b5402c03b..e18a2cc4e46a 100644
--- a/drivers/powercap/idle_inject.c
+++ b/drivers/powercap/idle_inject.c
@@ -63,13 +63,29 @@ struct idle_inject_thread {
* @idle_duration_us: duration of CPU idle time to inject
* @run_duration_us: duration of CPU run time to allow
* @latency_us: max allowed latency
+ * @update: Optional callback deciding whether or not to skip idle
+ * injection in the given cycle.
* @cpumask: mask of CPUs affected by idle injection
+ *
+ * This structure is used to define per instance idle inject device data. Each
+ * instance has an idle duration, a run duration and mask of CPUs to inject
+ * idle.
+ *
+ * Actual CPU idle time is injected by calling kernel scheduler interface
+ * play_idle_precise(). There is one optional callback that can be registered
+ * by calling idle_inject_register_full():
+ *
+ * update() - This callback is invoked just before waking up CPUs to inject
+ * idle. If it returns false, CPUs are not woken up to inject idle in the given
+ * cycle. It also allows the caller to readjust the idle and run duration by
+ * calling idle_inject_set_duration() for the next cycle.
*/
struct idle_inject_device {
struct hrtimer timer;
unsigned int idle_duration_us;
unsigned int run_duration_us;
unsigned int latency_us;
+ bool (*update)(void);
unsigned long cpumask[];
};
@@ -111,11 +127,12 @@ static enum hrtimer_restart idle_inject_timer_fn(struct hrtimer *timer)
struct idle_inject_device *ii_dev =
container_of(timer, struct idle_inject_device, timer);
+ if (!ii_dev->update || (ii_dev->update && ii_dev->update()))
+ idle_inject_wakeup(ii_dev);
+
duration_us = READ_ONCE(ii_dev->run_duration_us);
duration_us += READ_ONCE(ii_dev->idle_duration_us);
- idle_inject_wakeup(ii_dev);
-
hrtimer_forward_now(timer, ns_to_ktime(duration_us * NSEC_PER_USEC));
return HRTIMER_RESTART;
@@ -162,6 +179,7 @@ void idle_inject_set_duration(struct idle_inject_device *ii_dev,
if (!run_duration_us)
pr_debug("CPU is forced to 100 percent idle\n");
}
+EXPORT_SYMBOL_NS_GPL(idle_inject_set_duration, IDLE_INJECT);
/**
* idle_inject_get_duration - idle and run duration retrieval helper
@@ -176,6 +194,7 @@ void idle_inject_get_duration(struct idle_inject_device *ii_dev,
*run_duration_us = READ_ONCE(ii_dev->run_duration_us);
*idle_duration_us = READ_ONCE(ii_dev->idle_duration_us);
}
+EXPORT_SYMBOL_NS_GPL(idle_inject_get_duration, IDLE_INJECT);
/**
* idle_inject_set_latency - set the maximum latency allowed
@@ -187,6 +206,7 @@ void idle_inject_set_latency(struct idle_inject_device *ii_dev,
{
WRITE_ONCE(ii_dev->latency_us, latency_us);
}
+EXPORT_SYMBOL_NS_GPL(idle_inject_set_latency, IDLE_INJECT);
/**
* idle_inject_start - start idle injections
@@ -218,6 +238,7 @@ int idle_inject_start(struct idle_inject_device *ii_dev)
return 0;
}
+EXPORT_SYMBOL_NS_GPL(idle_inject_start, IDLE_INJECT);
/**
* idle_inject_stop - stops idle injections
@@ -264,6 +285,7 @@ void idle_inject_stop(struct idle_inject_device *ii_dev)
cpu_hotplug_enable();
}
+EXPORT_SYMBOL_NS_GPL(idle_inject_stop, IDLE_INJECT);
/**
* idle_inject_setup - prepare the current task for idle injection
@@ -292,17 +314,22 @@ static int idle_inject_should_run(unsigned int cpu)
}
/**
- * idle_inject_register - initialize idle injection on a set of CPUs
+ * idle_inject_register_full - initialize idle injection on a set of CPUs
* @cpumask: CPUs to be affected by idle injection
+ * @update: This callback is called just before waking up CPUs to inject
+ * idle
*
* This function creates an idle injection control device structure for the
- * given set of CPUs and initializes the timer associated with it. It does not
- * start any injection cycles.
+ * given set of CPUs and initializes the timer associated with it. This
+ * function also allows to register update()callback.
+ * It does not start any injection cycles.
*
* Return: NULL if memory allocation fails, idle injection control device
* pointer on success.
*/
-struct idle_inject_device *idle_inject_register(struct cpumask *cpumask)
+
+struct idle_inject_device *idle_inject_register_full(struct cpumask *cpumask,
+ bool (*update)(void))
{
struct idle_inject_device *ii_dev;
int cpu, cpu_rb;
@@ -315,6 +342,7 @@ struct idle_inject_device *idle_inject_register(struct cpumask *cpumask)
hrtimer_init(&ii_dev->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
ii_dev->timer.function = idle_inject_timer_fn;
ii_dev->latency_us = UINT_MAX;
+ ii_dev->update = update;
for_each_cpu(cpu, to_cpumask(ii_dev->cpumask)) {
@@ -339,6 +367,24 @@ out_rollback:
return NULL;
}
+EXPORT_SYMBOL_NS_GPL(idle_inject_register_full, IDLE_INJECT);
+
+/**
+ * idle_inject_register - initialize idle injection on a set of CPUs
+ * @cpumask: CPUs to be affected by idle injection
+ *
+ * This function creates an idle injection control device structure for the
+ * given set of CPUs and initializes the timer associated with it. It does not
+ * start any injection cycles.
+ *
+ * Return: NULL if memory allocation fails, idle injection control device
+ * pointer on success.
+ */
+struct idle_inject_device *idle_inject_register(struct cpumask *cpumask)
+{
+ return idle_inject_register_full(cpumask, NULL);
+}
+EXPORT_SYMBOL_NS_GPL(idle_inject_register, IDLE_INJECT);
/**
* idle_inject_unregister - unregister idle injection control device
@@ -359,6 +405,7 @@ void idle_inject_unregister(struct idle_inject_device *ii_dev)
kfree(ii_dev);
}
+EXPORT_SYMBOL_NS_GPL(idle_inject_unregister, IDLE_INJECT);
static struct smp_hotplug_thread idle_inject_threads = {
.store = &idle_inject_thread.tsk,