On 02-12-2013 19:05, Zoran Markovic wrote: > Hi Eduardo, > I have some graphs created for Broadcom's Capri (Cortex-A9x2) device. > I do a full temperature ramp using ARM-proprietary test, which heats > it up to ~48C. By hot-unplugging CPU1 I can cool it down to ~40C > within seconds. Let me know if you'd like to see the graphs. Yeah, I would like to see it. But what I was more interested in seeing is how long does it take to offline a CPU? > Regards, Zoran > > On 29 November 2013 06:08, Eduardo Valentin <eduardo.valentin@xxxxxx> wrote: >> Hello Zoran, >> >> On 27-11-2013 17:56, Zoran Markovic wrote: >>> Pinging again... Does anyone have any opinion on this feature? >> >> Sorry for not answering you. Yes there is interest in such work. >> Besides, your patch is not the very first attempt to do so. If I >> remember correctly, when Amit D. K was originally sending the current >> cpu cooling device, it included a hotplug part. That is why it was named >> cpucooling and not cpufreqcooling. Anyways, the major concerns by that >> time was the latencies to off line a CPU, mainly due to task and >> structure migration. >> >> Thus the question is, have you measure the behavior of your system when >> using this cooling device? Does it present any cooling effectiveness >> during high system load scenarios for instance? In case you have data, >> would you be able to share them? >> >> >>> Thanks, >>> Zoran >>> >>> On 4 October 2013 15:52, Zoran Markovic <zoran.markovic@xxxxxxxxxx> wrote: >>>> Any comments on this proposed feature and implementation? Apparently >>>> it's also useful for server systems. >> >> >> >> >>>> Thanks, >>>> Zoran >>>> >>>> On 20 September 2013 15:15, Zoran Markovic <zoran.markovic@xxxxxxxxxx> wrote: >>>>> This patch implements a generic CPU hotplug cooling device. The >>>>> implementation scales down the number of running CPUs when temperature >>>>> increases through a thermal trip point and prevents booting CPUs >>>>> until thermal conditions are restored. Upon restoration, the action >>>>> of starting up a CPU is left to another entity (e.g. CPU offline >>>>> governor, for which a patch is in the works). >>>>> >>>>> In the past two years, ARM considerably reduced the time required for >>>>> CPUs to boot and shutdown; this time is now measured in microseconds. >>>>> This patch is predominantly intended for ARM big.LITTLE architectures >>>>> where big cores are expected to have a much bigger impact on thermal >>>>> budget than little cores, resulting in fast temperature ramps to a trip >>>>> point, i.e. thermal runaways. Switching off the big core(s) may be one >>>>> of the recovery mechanisms to restore system temperature, but the actual >>>>> strategy is left to the thermal governor. >>>>> >>>>> The assumption is that CPU shutdown/startup is a rare event, so no >>>>> attempt was made to make the code atomic, i.e. the code evidently races >>>>> with CPU hotplug driver. The set_cur_state() function offlines CPUs >>>>> iteratively one at a time, checking the cooling state before each CPU >>>>> shutdown. A hotplug notifier callback validates any CPU boot requests >>>>> against current cooling state and approves/denies accordingly. This >>>>> mechanism guarantees that the desired cooling state could be reached in a >>>>> maximum of d-c iterations, where d and c are the "desired" and "current" >>>>> cooling states expressed in the number of offline CPUs. >>>>> >>>>> Credits to Amit Daniel Kachhap for initial attempt to upstream this feature. >>>>> >>>>> Cc: Zhang Rui <rui.zhang@xxxxxxxxx> >>>>> Cc: Eduardo Valentin <eduardo.valentin@xxxxxx> >>>>> Cc: Rob Landley <rob@xxxxxxxxxxx> >>>>> Cc: Amit Daniel Kachhap <amit.daniel@xxxxxxxxxxx> >>>>> Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> >>>>> Cc: Durgadoss R <durgadoss.r@xxxxxxxxx> >>>>> Cc: Christian Daudt <bcm@xxxxxxxxxxxxx> >>>>> Cc: James King <james.king@xxxxxxxxxx> >>>>> Signed-off-by: Zoran Markovic <zoran.markovic@xxxxxxxxxx> >>>>> --- >>>>> Documentation/thermal/cpu-cooling-api.txt | 17 ++ >>>>> drivers/thermal/Kconfig | 10 + >>>>> drivers/thermal/Makefile | 1 + >>>>> drivers/thermal/cpu_hotplug.c | 362 +++++++++++++++++++++++++++++ >>>>> include/linux/cpuhp_cooling.h | 57 +++++ >>>>> 5 files changed, 447 insertions(+) >>>>> create mode 100644 drivers/thermal/cpu_hotplug.c >>>>> create mode 100644 include/linux/cpuhp_cooling.h >>>>> >>>>> diff --git a/Documentation/thermal/cpu-cooling-api.txt b/Documentation/thermal/cpu-cooling-api.txt >>>>> index fca24c9..2f94f68 100644 >>>>> --- a/Documentation/thermal/cpu-cooling-api.txt >>>>> +++ b/Documentation/thermal/cpu-cooling-api.txt >>>>> @@ -30,3 +30,20 @@ the user. The registration APIs returns the cooling device pointer. >>>>> This interface function unregisters the "thermal-cpufreq-%x" cooling device. >>>>> >>>>> cdev: Cooling device pointer which has to be unregistered. >>>>> + >>>>> +1.2 cpu hotplug registration/unregistration APIs >>>>> +1.2.1 struct thermal_cooling_device *cpuhp_cooling_register( >>>>> + struct cpumask *cpus, const char *ext) >>>>> + >>>>> + This function creates and registers a cpu hotplug cooling device with >>>>> + the name "cpu-hotplug-%s". >>>>> + >>>>> + cpus: cpumask of cpu cores participating in cooling. >>>>> + ext: instance-specific name of device >>>>> + >>>>> +1.2.2 void cpuhotplug_cooling_unregister(struct thermal_cooling_device *cdev) >>>>> + >>>>> + This function unregisters and frees the cpu hotplug cooling device cdev. >>>>> + >>>>> + cdev: Pointer to cooling device to unregister. >>>>> + >>>>> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig >>>>> index 52b6ed7..3509100 100644 >>>>> --- a/drivers/thermal/Kconfig >>>>> +++ b/drivers/thermal/Kconfig >>>>> @@ -79,6 +79,16 @@ config CPU_THERMAL >>>>> >>>>> If you want this support, you should say Y here. >>>>> >>>>> +config CPU_THERMAL_HOTPLUG >>>>> + bool "Generic CPU hotplug cooling" >>>>> + depends on HOTPLUG_CPU >>>>> + help >>>>> + Shutdown CPUs to prevent the device from overheating. This feature >>>>> + uses generic CPU hot-unplug capabilities to control device >>>>> + temperature. When the temperature increases over a trip point, a >>>>> + random subset of CPUs is shut down to reach the desired cooling >>>>> + state. >>>>> + >>>>> config THERMAL_EMULATION >>>>> bool "Thermal emulation mode support" >>>>> help >>>>> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile >>>>> index 5ee0db0..0bd08be 100644 >>>>> --- a/drivers/thermal/Makefile >>>>> +++ b/drivers/thermal/Makefile >>>>> @@ -12,6 +12,7 @@ thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o >>>>> >>>>> # cpufreq cooling >>>>> thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o >>>>> +thermal_sys-$(CONFIG_CPU_THERMAL_HOTPLUG) += cpu_hotplug.o >>>>> >>>>> # platform thermal drivers >>>>> obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o >>>>> diff --git a/drivers/thermal/cpu_hotplug.c b/drivers/thermal/cpu_hotplug.c >>>>> new file mode 100644 >>>>> index 0000000..8c3021e >>>>> --- /dev/null >>>>> +++ b/drivers/thermal/cpu_hotplug.c >>>>> @@ -0,0 +1,362 @@ >>>>> +/* >>>>> + * drivers/thermal/cpu_hotplug.c >>>>> + * >>>>> + * Copyright (C) 2013 Broadcom Corporation Ltd. >>>>> + * Copyright (C) 2013 Zoran Markovic <zoran.markovic@xxxxxxxxxx> >>>>> + * >>>>> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >>>>> + * This program is free software; you can redistribute it and/or modify >>>>> + * it under the terms of the GNU General Public License as published by >>>>> + * the Free Software Foundation; version 2 of the License. >>>>> + * >>>>> + * This program is distributed in the hope that it will be useful, but >>>>> + * WITHOUT ANY WARRANTY; without even the implied warranty of >>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >>>>> + * General Public License for more details. >>>>> + * >>>>> + * You should have received a copy of the GNU General Public License along >>>>> + * with this program; if not, write to the Free Software Foundation, Inc., >>>>> + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. >>>>> + * >>>>> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >>>>> + */ >>>>> +#include <linux/module.h> >>>>> +#include <linux/thermal.h> >>>>> +#include <linux/workqueue.h> >>>>> +#include <linux/cpu.h> >>>>> +#include <linux/err.h> >>>>> +#include <linux/slab.h> >>>>> +#include <linux/cpuhp_cooling.h> >>>>> + >>>>> +/** >>>>> + * struct cpuhotplug_cooling_device - cpu hotplug cooling device data >>>>> + * @cpus: cpu mask representing cpus that can be hot-unplugged for cooling >>>>> + * @cdev: pointer to generic cooling device >>>>> + */ >>>>> +struct cpuhotplug_cooling_device { >>>>> + unsigned int target; >>>>> + struct cpumask cpus; >>>>> + struct thermal_cooling_device *cdev; >>>>> + struct list_head list; >>>>> +}; >>>>> + >>>>> +/** >>>>> + * cpuhotplug_list - list of all cpu hotplug cooling devices. Traversed >>>>> + * by cpu hotplug notifier to check constraints on booting cpus. Locked >>>>> + * by cpuhotplug_cooling_lock mutex. >>>>> + */ >>>>> +static LIST_HEAD(cpuhotplug_list); >>>>> +static DEFINE_MUTEX(cpuhotplug_cooling_lock); >>>>> + >>>>> +/** >>>>> + * boot_cpu - return index of boot CPU; same criteria as in >>>>> + * disable_nonboot_cpus() >>>>> + */ >>>>> +static inline int boot_cpu(void) >>>>> +{ >>>>> + int cpu; >>>>> + get_online_cpus(); >>>>> + cpu = cpumask_first(cpu_online_mask); >>>>> + put_online_cpus(); >>>>> + return cpu; >>>>> +} >>>>> + >>>>> +/** >>>>> + * random_online_cpu - pick any online hot-unpluggable cpu >>>>> + * @d: pointer to cpuhotplug_cooling_device containing hot-pluggable cpu mask >>>>> + */ >>>>> +static inline int random_online_cpu(struct cpuhotplug_cooling_device *d) >>>>> +{ >>>>> + int cpu; >>>>> + >>>>> + get_online_cpus(); >>>>> + cpu = any_online_cpu(d->cpus); >>>>> + put_online_cpus(); >>>>> + >>>>> + return cpu; >>>>> +} >>>>> + >>>>> +/** >>>>> + * _num_offline_cpus - number of hot-pluggable cpus currently offline >>>>> + * @d: pointer to cpuhotplug_cooling_device containing hot-pluggable cpu mask >>>>> + */ >>>>> +static inline int _num_offline_cpus(struct cpuhotplug_cooling_device *d) >>>>> +{ >>>>> + struct cpumask offline; >>>>> + >>>>> + cpumask_andnot(&offline, &(d->cpus), cpu_online_mask); >>>>> + return cpumask_weight(&offline); >>>>> +} >>>>> + >>>>> +/** >>>>> + * num_offline_cpus - same as _num_offline_cpus, but safe from background >>>>> + * hotplug events. >>>>> + * @d: pointer to cpuhotplug_cooling_device containing hot-pluggable cpu mask >>>>> + */ >>>>> +static inline int num_offline_cpus(struct cpuhotplug_cooling_device *d) >>>>> +{ >>>>> + int num; >>>>> + >>>>> + get_online_cpus(); >>>>> + num = _num_offline_cpus(d); >>>>> + put_online_cpus(); >>>>> + >>>>> + return num; >>>>> +} >>>>> + >>>>> +/** >>>>> + * cpuhotplug_get_max_state - get maximum cooling state of device >>>>> + * @cdev: pointer to generic cooling device >>>>> + * @state: returned maximum cooling state >>>>> + * >>>>> + * Thermal framework callback to get the maximum cooling state of cpu >>>>> + * hotplug cooling device. >>>>> + * >>>>> + * Return: always 0. >>>>> + */ >>>>> +static int cpuhotplug_get_max_state(struct thermal_cooling_device *cdev, >>>>> + unsigned long *state) >>>>> +{ >>>>> + struct cpuhotplug_cooling_device *d = cdev->devdata; >>>>> + >>>>> + /* defined as number of CPUs in hot-pluggable mask: this is invariant */ >>>>> + *state = cpumask_weight(&(d->cpus)); >>>>> + >>>>> + return 0; >>>>> +} >>>>> + >>>>> +/** >>>>> + * cpuhotplug_get_cur_state - get current cooling state of device >>>>> + * @cdev: pointer to generic cooling device >>>>> + * @state: current cooling state >>>>> + * >>>>> + * Thermal framework callback to get the current cooling state of cpu >>>>> + * hotplug cooling device. >>>>> + * >>>>> + * Return: always 0. >>>>> + */ >>>>> +static int cpuhotplug_get_cur_state(struct thermal_cooling_device *cdev, >>>>> + unsigned long *state) >>>>> +{ >>>>> + struct cpuhotplug_cooling_device *d = cdev->devdata; >>>>> + >>>>> + *state = d->target; >>>>> + >>>>> + return 0; >>>>> +} >>>>> + >>>>> +/** >>>>> + * cpuhotplug_get_cur_state - set cooling state of device >>>>> + * @cdev: pointer to generic cooling device >>>>> + * @state: cooling state >>>>> + * >>>>> + * Thermal framework callback to set/change cooling state of cpu hotplug >>>>> + * cooling device. >>>>> + * >>>>> + * Return: 0 on success, or error code otherwise >>>>> + */ >>>>> +static int cpuhotplug_set_cur_state(struct thermal_cooling_device *cdev, >>>>> + unsigned long state) >>>>> +{ >>>>> + struct cpuhotplug_cooling_device *d = cdev->devdata; >>>>> + unsigned long cstate; >>>>> + unsigned int cpu; >>>>> + int err = 0; >>>>> + >>>>> + if (state > cpumask_weight(&(d->cpus))) >>>>> + return -EINVAL; /* out of allowed range */ >>>>> + >>>>> + /* >>>>> + * Set target state here; hot-unplug CPUs if we are too hot, but >>>>> + * don't attempt to hot-plug CPUs if we're cold. Starting CPUs >>>>> + * should be left to CPUOffline governor. >>>>> + * >>>>> + * There is a chance that CPU hotplug driver is racing with this >>>>> + * code. Rather than trying to make the procedure atomic, iterate >>>>> + * until we reach the desired state, or signal error if the state >>>>> + * cannot be reached. >>>>> + * >>>>> + * Neither CPU hotplug nor this code is expected to run too often. >>>>> + */ >>>>> + d->target = state; >>>>> + >>>>> + /* compare desired cooling state to current cooling state */ >>>>> + while ((cstate = num_offline_cpus(d)) < state && !err) { >>>>> + /* cstate < cstate: we're too hot, unplug any cpu */ >>>>> + cpu = random_online_cpu(d); >>>>> + if (cpu < nr_cpu_ids) >>>>> + err = work_on_cpu(boot_cpu(), >>>>> + (long(*)(void *))cpu_down, >>>>> + (void *)cpu); >>>>> + /* on error, message would come from cpu_down() */ >>>>> + else { >>>>> + pr_warn("cpuhotplug: CPUs already down\n"); >>>>> + err = -EAGAIN; >>>>> + } >>>>> + } >>>>> + >>>>> + return err; >>>>> +} >>>>> + >>>>> +/* cpu hotplug cooling device ops */ >>>>> +static struct thermal_cooling_device_ops const cpuhotplug_cooling_ops = { >>>>> + .get_max_state = cpuhotplug_get_max_state, >>>>> + .get_cur_state = cpuhotplug_get_cur_state, >>>>> + .set_cur_state = cpuhotplug_set_cur_state, >>>>> +}; >>>>> + >>>>> +/** >>>>> + * _cpu_startup_allowed - traverse list of hotplug cooling devices to >>>>> + * check if startup of cpu violates thermal constraints >>>>> + */ >>>>> +static inline int _cpu_startup_allowed(int cpu) >>>>> +{ >>>>> + struct cpuhotplug_cooling_device *d; >>>>> + int ret = 1; >>>>> + >>>>> + /* >>>>> + * Prevent starting CPU if it violates any cooling >>>>> + * device's constraint. Called from hotplug notifier, so >>>>> + * cpu_up()/cpu_down() already holds a lock on hotplug >>>>> + * events. >>>>> + */ >>>>> + mutex_lock(&cpuhotplug_cooling_lock); >>>>> + list_for_each_entry(d, &cpuhotplug_list, list) { >>>>> + if (cpumask_test_cpu(cpu, &(d->cpus)) && >>>>> + d->target >= _num_offline_cpus(d)) { >>>>> + pr_warn("%s: CPU%d startup prevented\n", >>>>> + dev_name(&(d->cdev->device)), cpu); >>>>> + ret = 0; >>>>> + break; >>>>> + } >>>>> + } >>>>> + mutex_unlock(&cpuhotplug_cooling_lock); >>>>> + return ret; >>>>> +} >>>>> + >>>>> +/** >>>>> + * cpuhotplug_thermal_notifier - notifier callback for CPU hotplug events. >>>>> + * @nb: struct notifier_block >>>>> + * @event: cpu hotplug event for which callback is invoked. >>>>> + * @data: context data, in this particular case CPU index. >>>>> + * >>>>> + * Callback intercepting CPU hotplug events. Compares CPU hotplug action >>>>> + * with current thermal state and allows/denies accordingly. >>>>> + * >>>>> + * Return: 0 (allow) or error (deny). >>>>> + */ >>>>> +static int cpuhotplug_thermal_notifier(struct notifier_block *nb, >>>>> + unsigned long event, void *data) >>>>> +{ >>>>> + int cpu = (int)data; >>>>> + >>>>> + switch (event) { >>>>> + case CPU_UP_PREPARE: >>>>> + case CPU_UP_PREPARE_FROZEN: >>>>> + /* _cpu_up() only cares about result from CPU_UP_PREPAREs */ >>>>> + if (!_cpu_startup_allowed(cpu)) >>>>> + return notifier_from_errno(-EAGAIN); >>>>> + break; >>>>> + default: >>>>> + /* allow all other actions */ >>>>> + break; >>>>> + } >>>>> + return 0; >>>>> +} >>>>> + >>>>> +static struct notifier_block cpuhotplug_thermal_notifier_block = { >>>>> + .notifier_call = cpuhotplug_thermal_notifier, >>>>> +}; >>>>> + >>>>> +/** >>>>> + * cpuhotplug_cooling_register - create cpu hotplug cooling device >>>>> + * @cpus: cpumask of cpu cores participating in cooling >>>>> + * @ext: instance-specific name of device >>>>> + * >>>>> + * Creates and registers a cpu hotplug cooling device with the name >>>>> + * "cpu-hotplug-<ext>". >>>>> + * >>>>> + * Return: valid pointer to cpuhotplug_cooling_device struct on success, >>>>> + * corresponding ERR_PTR() on failure. >>>>> + */ >>>>> +struct thermal_cooling_device * >>>>> +cpuhotplug_cooling_register(const struct cpumask *cpus, const char *ext) >>>>> +{ >>>>> + struct thermal_cooling_device *cdev; >>>>> + struct cpuhotplug_cooling_device *cpuhotplug_cdev; >>>>> + struct cpumask test; >>>>> + char name[THERMAL_NAME_LENGTH]; >>>>> + int err; >>>>> + >>>>> + /* test if we passed in a good cpumask */ >>>>> + cpu_maps_update_begin(); >>>>> + cpumask_and(&test, cpus, cpu_possible_mask); >>>>> + cpu_maps_update_done(); >>>>> + >>>>> + if (cpumask_test_cpu(boot_cpu(), &test)) { >>>>> + pr_warn("cannot hot-plug boot CPU%d\n", boot_cpu()); >>>>> + cpumask_clear_cpu(boot_cpu(), &test); >>>>> + } >>>>> + if (cpumask_empty(&test)) { >>>>> + pr_err("CPUs unavailable for hot-plug cooling\n"); >>>>> + err = -EINVAL; >>>>> + goto out; >>>>> + } >>>>> + >>>>> + cpuhotplug_cdev = kzalloc(sizeof(struct cpuhotplug_cooling_device), >>>>> + GFP_KERNEL); >>>>> + if (!cpuhotplug_cdev) { >>>>> + err = -ENOMEM; >>>>> + goto out; >>>>> + } >>>>> + >>>>> + cpumask_copy(&cpuhotplug_cdev->cpus, &test); >>>>> + >>>>> + snprintf(name, sizeof(name), "cpu-hotplug-%s", ext); >>>>> + >>>>> + cpuhotplug_cdev->target = 0; >>>>> + cdev = thermal_cooling_device_register(name, cpuhotplug_cdev, >>>>> + &cpuhotplug_cooling_ops); >>>>> + if (!cdev) { >>>>> + pr_err("%s: cooling device registration failed.\n", name); >>>>> + err = -EINVAL; >>>>> + goto out_free; >>>>> + } >>>>> + cpuhotplug_cdev->cdev = cdev; >>>>> + >>>>> + mutex_lock(&cpuhotplug_cooling_lock); >>>>> + if (list_empty(&cpuhotplug_list)) >>>>> + register_cpu_notifier(&cpuhotplug_thermal_notifier_block); >>>>> + list_add(&(cpuhotplug_cdev->list), &cpuhotplug_list); >>>>> + mutex_unlock(&cpuhotplug_cooling_lock); >>>>> + >>>>> + return cdev; >>>>> + >>>>> +out_free: >>>>> + kfree(cpuhotplug_cdev); >>>>> +out: >>>>> + return ERR_PTR(err); >>>>> +} >>>>> +EXPORT_SYMBOL_GPL(cpuhotplug_cooling_register); >>>>> + >>>>> +/** >>>>> + * cpuhotplug_cooling_unregister - remove cpu hotplug cooling device >>>>> + * @cdev: cooling device to remove >>>>> + * >>>>> + * Unregisters and frees the cpu hotplug cooling device. >>>>> + */ >>>>> +void cpuhotplug_cooling_unregister(struct thermal_cooling_device *cdev) >>>>> +{ >>>>> + struct cpuhotplug_cooling_device *cpuhotplug_cdev = cdev->devdata; >>>>> + >>>>> + mutex_lock(&cpuhotplug_cooling_lock); >>>>> + list_del(&(cpuhotplug_cdev->list)); >>>>> + if (list_empty(&cpuhotplug_list)) >>>>> + unregister_cpu_notifier(&cpuhotplug_thermal_notifier_block); >>>>> + mutex_unlock(&cpuhotplug_cooling_lock); >>>>> + >>>>> + thermal_cooling_device_unregister(cpuhotplug_cdev->cdev); >>>>> + kfree(cpuhotplug_cdev); >>>>> +} >>>>> +EXPORT_SYMBOL_GPL(cpuhotplug_cooling_unregister); >>>>> + >>>>> diff --git a/include/linux/cpuhp_cooling.h b/include/linux/cpuhp_cooling.h >>>>> new file mode 100644 >>>>> index 0000000..ace1d5b >>>>> --- /dev/null >>>>> +++ b/include/linux/cpuhp_cooling.h >>>>> @@ -0,0 +1,57 @@ >>>>> +/* >>>>> + * linux/include/linux/cpuhp_cooling.h >>>>> + * >>>>> + * Copyright (C) 2013 Broadcom Corporation Ltd. >>>>> + * Copyright (C) 2013 Zoran Markovic <zoran.markovic@xxxxxxxxxx> >>>>> + * >>>>> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >>>>> + * This program is free software; you can redistribute it and/or modify >>>>> + * it under the terms of the GNU General Public License as published by >>>>> + * the Free Software Foundation; version 2 of the License. >>>>> + * >>>>> + * This program is distributed in the hope that it will be useful, but >>>>> + * WITHOUT ANY WARRANTY; without even the implied warranty of >>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >>>>> + * General Public License for more details. >>>>> + * >>>>> + * You should have received a copy of the GNU General Public License along >>>>> + * with this program; if not, write to the Free Software Foundation, Inc., >>>>> + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. >>>>> + * >>>>> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >>>>> + */ >>>>> + >>>>> +#ifndef __CPUHP_COOLING_H__ >>>>> +#define __CPUHP_COOLING_H__ >>>>> + >>>>> +#include <linux/thermal.h> >>>>> +#include <linux/cpumask.h> >>>>> + >>>>> +#ifdef CONFIG_CPU_THERMAL_HOTPLUG >>>>> +/** >>>>> + * cpuhotplug_cooling_register - create cpu hotplug cooling device. >>>>> + * @cpus: cpumask of hot-pluggable cpus >>>>> + * @ext: instance-specific device name >>>>> + */ >>>>> +struct thermal_cooling_device * >>>>> +cpuhotplug_cooling_register(const struct cpumask *cpus, const char *ext); >>>>> + >>>>> +/** >>>>> + * cpuhotplug_cooling_unregister - remove cpu hoptlug cooling device. >>>>> + * @cdev: thermal cooling device pointer. >>>>> + */ >>>>> +void cpuhotplug_cooling_unregister(struct thermal_cooling_device *cdev); >>>>> +#else /* !CONFIG_CPU_THERMAL_HOTPLUG */ >>>>> +static inline struct thermal_cooling_device * >>>>> +cpuhotplug_cooling_register(const struct cpumask *cpus, const char *ext) >>>>> +{ >>>>> + return NULL; >>>>> +} >>>>> +static inline >>>>> +void cpuhotplug_cooling_unregister(struct thermal_cooling_device *cdev) >>>>> +{ >>>>> + return; >>>>> +} >>>>> +#endif /* CONFIG_CPU_THERMAL_HOTPLUG */ >>>>> + >>>>> +#endif /* __CPU_COOLING_H__ */ >>>>> -- >>>>> 1.7.9.5 >>>>> >>> >>> >> >> >> -- >> You have got to be excited about what you are doing. (L. Lamport) >> >> Eduardo Valentin >> > > -- You have got to be excited about what you are doing. (L. Lamport) Eduardo Valentin
Attachment:
signature.asc
Description: OpenPGP digital signature