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. 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 > -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html