See comments inline. On 11 Aug 10, Mike Turquette wrote: > On some platforms it is possible to have some CPUs which support CPU > hotplug and some which do not. Currently the prescence of an 'online' > sysfs entry in userspace is adequate for applications to know that a CPU > supports hotplug, but there is no convenient way to make the same > determination in the kernel. > > To better model this relationship this patch introduces a new cpumask to > track CPUs that support CPU hotplug operations. > > This new cpumask is populated at boot-time and remains static for the > life of the machine. Bits set in the mask indicate a CPU which supports > hotplug, but make no guarantees about whether that CPU is currently > online or not. Likewise a cleared bit in the mask indicates either a > CPU which cannot hotplug or a lack of a populated CPU. > > The purpose of this new cpumask is to aid kernel code which uses CPU to > take CPUs online and offline. Possible uses are as a thermal event > mitigation technique or as a power capping mechanism. > > Signed-off-by: Mike Turquette <mturquette@xxxxxx> > --- > Change log: > v2: fixed missing parentheses in cpumask_test_cpu and improved grammar > in comments > > include/linux/cpumask.h | 27 ++++++++++++++++++++++----- > kernel/cpu.c | 18 ++++++++++++++++++ > 2 files changed, 40 insertions(+), 5 deletions(-) > > diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h > index b24ac56..52e64a7 100644 > --- a/include/linux/cpumask.h > +++ b/include/linux/cpumask.h > @@ -39,10 +39,11 @@ extern int nr_cpu_ids; > * The following particular system cpumasks and operations manage > * possible, present, active and online cpus. > * > - * cpu_possible_mask- has bit 'cpu' set iff cpu is populatable > - * cpu_present_mask - has bit 'cpu' set iff cpu is populated > - * cpu_online_mask - has bit 'cpu' set iff cpu available to scheduler > - * cpu_active_mask - has bit 'cpu' set iff cpu available to migration > + * cpu_possible_mask - has bit 'cpu' set iff cpu is populatable > + * cpu_hotpluggable_mask - has bit 'cpu' set iff cpu is hotpluggable > + * cpu_present_mask - has bit 'cpu' set iff cpu is populated > + * cpu_online_mask - has bit 'cpu' set iff cpu available to scheduler > + * cpu_active_mask - has bit 'cpu' set iff cpu available to migration > * > * If !CONFIG_HOTPLUG_CPU, present == possible, and active == online. > * > @@ -51,7 +52,11 @@ extern int nr_cpu_ids; > * life of that system boot. The cpu_present_mask is dynamic(*), > * representing which CPUs are currently plugged in. And > * cpu_online_mask is the dynamic subset of cpu_present_mask, > - * indicating those CPUs available for scheduling. > + * indicating those CPUs available for scheduling. The > + * cpu_hotpluggable_mask is also fixed at boot time as the set of CPU > + * id's which are possible AND can hotplug. Cleared bits in this mask > + * mean that either the CPU is not possible, or it is possible but does > + * not support CPU hotplug operations. > * > * If HOTPLUG is enabled, then cpu_possible_mask is forced to have > * all NR_CPUS bits set, otherwise it is just the set of CPUs that > @@ -61,6 +66,9 @@ extern int nr_cpu_ids; > * depending on what ACPI reports as currently plugged in, otherwise > * cpu_present_mask is just a copy of cpu_possible_mask. > * > + * If HOTPLUG is not enabled then cpu_hotpluggable_mask is the empty > + * set. > + * > * (*) Well, cpu_present_mask is dynamic in the hotplug case. If not > * hotplug, it's a copy of cpu_possible_mask, hence fixed at boot. > * > @@ -76,6 +84,7 @@ extern int nr_cpu_ids; > */ > > extern const struct cpumask *const cpu_possible_mask; > +extern const struct cpumask *const cpu_hotpluggable_mask; > extern const struct cpumask *const cpu_online_mask; > extern const struct cpumask *const cpu_present_mask; > extern const struct cpumask *const cpu_active_mask; > @@ -85,19 +94,23 @@ extern const struct cpumask *const cpu_active_mask; > #define num_possible_cpus() cpumask_weight(cpu_possible_mask) > #define num_present_cpus() cpumask_weight(cpu_present_mask) > #define num_active_cpus() cpumask_weight(cpu_active_mask) > +#define num_hotpluggable_cpus() cpumask_weight(cpu_hotpluggable_mask) > #define cpu_online(cpu) cpumask_test_cpu((cpu), cpu_online_mask) > #define cpu_possible(cpu) cpumask_test_cpu((cpu), cpu_possible_mask) > #define cpu_present(cpu) cpumask_test_cpu((cpu), cpu_present_mask) > #define cpu_active(cpu) cpumask_test_cpu((cpu), cpu_active_mask) > +#define cpu_hotpluggable(cpu) cpumask_test_cpu((cpu, cpu_hotpluggable_mask)) The bracket should be around cpu, like this (cpu) so that there are no side-effects when passing anything to the macro. See the other #defines above. > #else > #define num_online_cpus() 1U > #define num_possible_cpus() 1U > #define num_present_cpus() 1U > #define num_active_cpus() 1U > +#define num_hotpluggable_cpus() 0 > #define cpu_online(cpu) ((cpu) == 0) > #define cpu_possible(cpu) ((cpu) == 0) > #define cpu_present(cpu) ((cpu) == 0) > #define cpu_active(cpu) ((cpu) == 0) > +#define cpu_hotpluggable(cpu) 0 > #endif > > /* verify cpu argument to cpumask_* operators */ > @@ -678,16 +691,20 @@ extern const DECLARE_BITMAP(cpu_all_bits, NR_CPUS); > #define cpu_none_mask to_cpumask(cpu_bit_bitmap[0]) > > #define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask) > +#define for_each_hotpluggable_cpu(cpu) \ > + for_each_cpu((cpu), cpu_hotpluggable_mask) > #define for_each_online_cpu(cpu) for_each_cpu((cpu), cpu_online_mask) > #define for_each_present_cpu(cpu) for_each_cpu((cpu), cpu_present_mask) > > /* Wrappers for arch boot code to manipulate normally-constant masks */ > void set_cpu_possible(unsigned int cpu, bool possible); > +void set_cpu_hotpluggable(unsigned int cpu, bool hotpluggable); > void set_cpu_present(unsigned int cpu, bool present); > void set_cpu_online(unsigned int cpu, bool online); > void set_cpu_active(unsigned int cpu, bool active); > void init_cpu_present(const struct cpumask *src); > void init_cpu_possible(const struct cpumask *src); > +void init_cpu_hotpluggable(const struct cpumask *src); > void init_cpu_online(const struct cpumask *src); > > /** > diff --git a/kernel/cpu.c b/kernel/cpu.c > index 12b7458..8c397c9 100644 > --- a/kernel/cpu.c > +++ b/kernel/cpu.c > @@ -536,6 +536,11 @@ static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly; > const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits); > EXPORT_SYMBOL(cpu_possible_mask); > > +static DECLARE_BITMAP(cpu_hotpluggable_bits, CONFIG_NR_CPUS) __read_mostly; > +const struct cpumask *const cpu_hotpluggable_mask = > + to_cpumask(cpu_hotpluggable_bits); > +EXPORT_SYMBOL(cpu_hotpluggable_mask); > + > static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly; > const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits); > EXPORT_SYMBOL(cpu_online_mask); > @@ -556,6 +561,14 @@ void set_cpu_possible(unsigned int cpu, bool possible) > cpumask_clear_cpu(cpu, to_cpumask(cpu_possible_bits)); > } > > +void set_cpu_hotpluggable(unsigned int cpu, bool hotpluggable) > +{ > + if (hotpluggable) > + cpumask_set_cpu(cpu, to_cpumask(cpu_hotpluggable_bits)); > + else > + cpumask_clear_cpu(cpu, to_cpumask(cpu_hotpluggable_bits)); > +} > + > void set_cpu_present(unsigned int cpu, bool present) > { > if (present) > @@ -590,6 +603,11 @@ void init_cpu_possible(const struct cpumask *src) > cpumask_copy(to_cpumask(cpu_possible_bits), src); > } > > +void init_cpu_hotpluggable(const struct cpumask *src) > +{ > + cpumask_copy(to_cpumask(cpu_hotpluggable_bits), src); > +} > + Just to be clear I understand this code, init_cpu_hotpluggable will be called in arch code, right? e.g. arch/arm/kernel/smp.c or do you intend for it to be called in platform-specific code? > void init_cpu_online(const struct cpumask *src) > { > cpumask_copy(to_cpumask(cpu_online_bits), src); > -- > 1.7.4.1 _______________________________________________ linux-pm mailing list linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/linux-pm