diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2014-02-08 07:34:09 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-18 15:38:37 -0500 |
commit | 67bad2fdb754dbef14596c0b5d28b3a12c8dfe84 (patch) | |
tree | 05c3cd5f809618319346f9642549460f95149f02 /drivers | |
parent | 91219a3b20325689eb80f7598cce2dc745db171d (diff) |
cpu: add generic support for CPU feature based module autoloading
This patch adds support for advertising optional CPU features over udev
using the modalias, and for declaring compatibility with/dependency upon
such a feature in a module.
The mapping between feature numbers and actual features should be provided
by the architecture in a file called <asm/cpufeature.h> which exports the
following functions/macros:
- cpu_feature(FEAT), a preprocessor macro that maps token FEAT to a
numeric index;
- bool cpu_have_feature(n), returning whether this CPU has support for
feature #n;
- MAX_CPU_FEATURES, an upper bound for 'n' in the previous function.
The feature can then be enabled by setting CONFIG_GENERIC_CPU_AUTOPROBE
for the architecture.
For instance, a module that registers its module init function using
module_cpu_feature_match(FEAT_X, module_init_function)
will be probed automatically when the CPU's support for the 'FEAT_X'
feature is advertised over udev, and will only allow the module to be
loaded by hand if the 'FEAT_X' feature is supported.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/base/Kconfig | 8 | ||||
-rw-r--r-- | drivers/base/cpu.c | 50 |
2 files changed, 53 insertions, 5 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index ec36e7772e57..3f0d3732df7f 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
@@ -185,6 +185,14 @@ config GENERIC_CPU_DEVICES | |||
185 | bool | 185 | bool |
186 | default n | 186 | default n |
187 | 187 | ||
188 | config HAVE_CPU_AUTOPROBE | ||
189 | def_bool ARCH_HAS_CPU_AUTOPROBE | ||
190 | |||
191 | config GENERIC_CPU_AUTOPROBE | ||
192 | bool | ||
193 | depends on !ARCH_HAS_CPU_AUTOPROBE | ||
194 | select HAVE_CPU_AUTOPROBE | ||
195 | |||
188 | config SOC_BUS | 196 | config SOC_BUS |
189 | bool | 197 | bool |
190 | 198 | ||
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index f48370dfc908..8a38bf8c792f 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/percpu.h> | 15 | #include <linux/percpu.h> |
16 | #include <linux/acpi.h> | 16 | #include <linux/acpi.h> |
17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
18 | #include <linux/cpufeature.h> | ||
18 | 19 | ||
19 | #include "base.h" | 20 | #include "base.h" |
20 | 21 | ||
@@ -286,6 +287,45 @@ static void cpu_device_release(struct device *dev) | |||
286 | */ | 287 | */ |
287 | } | 288 | } |
288 | 289 | ||
290 | #ifdef CONFIG_HAVE_CPU_AUTOPROBE | ||
291 | #ifdef CONFIG_GENERIC_CPU_AUTOPROBE | ||
292 | static ssize_t print_cpu_modalias(struct device *dev, | ||
293 | struct device_attribute *attr, | ||
294 | char *buf) | ||
295 | { | ||
296 | ssize_t n; | ||
297 | u32 i; | ||
298 | |||
299 | n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:", | ||
300 | CPU_FEATURE_TYPEVAL); | ||
301 | |||
302 | for (i = 0; i < MAX_CPU_FEATURES; i++) | ||
303 | if (cpu_have_feature(i)) { | ||
304 | if (PAGE_SIZE < n + sizeof(",XXXX\n")) { | ||
305 | WARN(1, "CPU features overflow page\n"); | ||
306 | break; | ||
307 | } | ||
308 | n += sprintf(&buf[n], ",%04X", i); | ||
309 | } | ||
310 | buf[n++] = '\n'; | ||
311 | return n; | ||
312 | } | ||
313 | #else | ||
314 | #define print_cpu_modalias arch_print_cpu_modalias | ||
315 | #endif | ||
316 | |||
317 | static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
318 | { | ||
319 | char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
320 | if (buf) { | ||
321 | print_cpu_modalias(NULL, NULL, buf); | ||
322 | add_uevent_var(env, "MODALIAS=%s", buf); | ||
323 | kfree(buf); | ||
324 | } | ||
325 | return 0; | ||
326 | } | ||
327 | #endif | ||
328 | |||
289 | /* | 329 | /* |
290 | * register_cpu - Setup a sysfs device for a CPU. | 330 | * register_cpu - Setup a sysfs device for a CPU. |
291 | * @cpu - cpu->hotpluggable field set to 1 will generate a control file in | 331 | * @cpu - cpu->hotpluggable field set to 1 will generate a control file in |
@@ -306,8 +346,8 @@ int register_cpu(struct cpu *cpu, int num) | |||
306 | cpu->dev.offline_disabled = !cpu->hotpluggable; | 346 | cpu->dev.offline_disabled = !cpu->hotpluggable; |
307 | cpu->dev.offline = !cpu_online(num); | 347 | cpu->dev.offline = !cpu_online(num); |
308 | cpu->dev.of_node = of_get_cpu_node(num, NULL); | 348 | cpu->dev.of_node = of_get_cpu_node(num, NULL); |
309 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | 349 | #ifdef CONFIG_HAVE_CPU_AUTOPROBE |
310 | cpu->dev.bus->uevent = arch_cpu_uevent; | 350 | cpu->dev.bus->uevent = cpu_uevent; |
311 | #endif | 351 | #endif |
312 | cpu->dev.groups = common_cpu_attr_groups; | 352 | cpu->dev.groups = common_cpu_attr_groups; |
313 | if (cpu->hotpluggable) | 353 | if (cpu->hotpluggable) |
@@ -330,8 +370,8 @@ struct device *get_cpu_device(unsigned cpu) | |||
330 | } | 370 | } |
331 | EXPORT_SYMBOL_GPL(get_cpu_device); | 371 | EXPORT_SYMBOL_GPL(get_cpu_device); |
332 | 372 | ||
333 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | 373 | #ifdef CONFIG_HAVE_CPU_AUTOPROBE |
334 | static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL); | 374 | static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL); |
335 | #endif | 375 | #endif |
336 | 376 | ||
337 | static struct attribute *cpu_root_attrs[] = { | 377 | static struct attribute *cpu_root_attrs[] = { |
@@ -344,7 +384,7 @@ static struct attribute *cpu_root_attrs[] = { | |||
344 | &cpu_attrs[2].attr.attr, | 384 | &cpu_attrs[2].attr.attr, |
345 | &dev_attr_kernel_max.attr, | 385 | &dev_attr_kernel_max.attr, |
346 | &dev_attr_offline.attr, | 386 | &dev_attr_offline.attr, |
347 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | 387 | #ifdef CONFIG_HAVE_CPU_AUTOPROBE |
348 | &dev_attr_modalias.attr, | 388 | &dev_attr_modalias.attr, |
349 | #endif | 389 | #endif |
350 | NULL | 390 | NULL |