CPU: Introduce ARCH_HAS_CPU_AUTOPROBE and X86 parts
authorThomas Renninger <trenn@suse.de>
Wed, 25 Jan 2012 23:09:14 +0000 (00:09 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 27 Jan 2012 00:49:08 +0000 (16:49 -0800)
This patch is based on Andi Kleen's work:
Implement autoprobing/loading of modules serving CPU
specific features (x86cpu autoloading).

And Kay Siever's work to get rid of sysdev cpu structures
and making use of struct device instead.

Before, the cpuid driver had to be loaded to get the x86cpu
autoloading feature. With this patch autoloading works through
the /sys/devices/system/cpu object

Cc: Kay Sievers <kay.sievers@vrfy.org>
Cc: Dave Jones <davej@redhat.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Huang Ying <ying.huang@intel.com>
Cc: Len Brown <lenb@kernel.org>
Acked-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Thomas Renninger <trenn@suse.de>
Acked-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
arch/x86/Kconfig
arch/x86/kernel/cpu/match.c
arch/x86/kernel/cpuid.c
drivers/base/cpu.c
include/linux/cpu.h

index 864cc6e6ac8e300d35b45c6b749f2ee93555c891..6baa1e66e1bc7599e9f0acac2cecba73f5166ef8 100644 (file)
@@ -179,6 +179,9 @@ config ARCH_HAS_DEFAULT_IDLE
 config ARCH_HAS_CACHE_LINE_SIZE
        def_bool y
 
+config ARCH_HAS_CPU_AUTOPROBE
+       def_bool y
+
 config HAVE_SETUP_PER_CPU_AREA
        def_bool y
 
index 7acc961422e7dfff5a0978a5b6fff50d600e5f2f..940e2d483076a67410939970648c81306b9c3bd5 100644 (file)
@@ -2,6 +2,7 @@
 #include <asm/processor.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 
 /**
  * x86_match_cpu - match current CPU again an array of x86_cpu_ids
@@ -46,3 +47,46 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
        return NULL;
 }
 EXPORT_SYMBOL(x86_match_cpu);
+
+ssize_t arch_print_cpu_modalias(struct device *dev,
+                               struct device_attribute *attr,
+                               char *bufptr)
+{
+       int size = PAGE_SIZE;
+       int i, n;
+       char *buf = bufptr;
+
+       n = snprintf(buf, size, "x86cpu:vendor:%04X:family:%04X:"
+                    "model:%04X:feature:",
+               boot_cpu_data.x86_vendor,
+               boot_cpu_data.x86,
+               boot_cpu_data.x86_model);
+       size -= n;
+       buf += n;
+       size -= 2;
+       for (i = 0; i < NCAPINTS*32; i++) {
+               if (boot_cpu_has(i)) {
+                       n = snprintf(buf, size, ",%04X", i);
+                       if (n < 0) {
+                               WARN(1, "x86 features overflow page\n");
+                               break;
+                       }
+                       size -= n;
+                       buf += n;
+               }
+       }
+       *buf++ = ',';
+       *buf++ = '\n';
+       return buf - bufptr;
+}
+
+int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (buf) {
+               arch_print_cpu_modalias(NULL, NULL, buf);
+               add_uevent_var(env, "MODALIAS=%s", buf);
+               kfree(buf);
+       }
+       return 0;
+}
index 7c89880eefd04af78aa736902e553b008204fbdd..a524353d93f21181e5998b592e7c39072ad1f182 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/notifier.h>
 #include <linux/uaccess.h>
 #include <linux/gfp.h>
-#include <linux/slab.h>
 
 #include <asm/processor.h>
 #include <asm/msr.h>
@@ -139,57 +138,13 @@ static const struct file_operations cpuid_fops = {
        .open = cpuid_open,
 };
 
-static ssize_t print_cpu_modalias(struct device *dev,
-                                 struct device_attribute *attr,
-                                 char *bufptr)
-{
-       int size = PAGE_SIZE;
-       int i, n;
-       char *buf = bufptr;
-
-       n = snprintf(buf, size, "x86cpu:vendor:%04X:family:"
-                    "%04X:model:%04X:feature:",
-               boot_cpu_data.x86_vendor,
-               boot_cpu_data.x86,
-               boot_cpu_data.x86_model);
-       size -= n;
-       buf += n;
-       size -= 2;
-       for (i = 0; i < NCAPINTS*32; i++) {
-               if (boot_cpu_has(i)) {
-                       n = snprintf(buf, size, ",%04X", i);
-                       if (n < 0) {
-                               WARN(1, "x86 features overflow page\n");
-                               break;
-                       }
-                       size -= n;
-                       buf += n;
-               }
-       }
-       *buf++ = ',';
-       *buf++ = '\n';
-       return buf - bufptr;
-}
-
-static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
-
 static __cpuinit int cpuid_device_create(int cpu)
 {
        struct device *dev;
-       int err;
 
        dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), NULL,
                            "cpu%d", cpu);
-       if (IS_ERR(dev))
-               return PTR_ERR(dev);
-
-       err = device_create_file(dev, &dev_attr_modalias);
-       if (err) {
-               /* keep device around on error. attribute is optional. */
-               err = 0;
-       }
-
-       return 0;
+       return IS_ERR(dev) ? PTR_ERR(dev) : 0;
 }
 
 static void cpuid_device_destroy(int cpu)
@@ -227,17 +182,6 @@ static char *cpuid_devnode(struct device *dev, umode_t *mode)
        return kasprintf(GFP_KERNEL, "cpu/%u/cpuid", MINOR(dev->devt));
 }
 
-static int cpuid_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-       char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
-       if (buf) {
-               print_cpu_modalias(NULL, NULL, buf);
-               add_uevent_var(env, "MODALIAS=%s", buf);
-               kfree(buf);
-       }
-       return 0;
-}
-
 static int __init cpuid_init(void)
 {
        int i, err = 0;
@@ -256,7 +200,6 @@ static int __init cpuid_init(void)
                goto out_chrdev;
        }
        cpuid_class->devnode = cpuid_devnode;
-       cpuid_class->dev_uevent = cpuid_dev_uevent;
        for_each_online_cpu(i) {
                err = cpuid_device_create(i);
                if (err != 0)
index db87e78d745940a3ba19332799930057edfd0615..2a0c670c281d14e01725e579da40406b47cda7db 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/device.h>
 #include <linux/node.h>
 #include <linux/gfp.h>
+#include <linux/slab.h>
 #include <linux/percpu.h>
 
 #include "base.h"
@@ -223,6 +224,9 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
        cpu->node_id = cpu_to_node(num);
        cpu->dev.id = num;
        cpu->dev.bus = &cpu_subsys;
+#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
+       cpu->dev.bus->uevent = arch_cpu_uevent;
+#endif
        error = device_register(&cpu->dev);
        if (!error && cpu->hotpluggable)
                register_cpu_control(cpu);
@@ -247,6 +251,10 @@ struct device *get_cpu_device(unsigned cpu)
 }
 EXPORT_SYMBOL_GPL(get_cpu_device);
 
+#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
+static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
+#endif
+
 static struct attribute *cpu_root_attrs[] = {
 #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
        &dev_attr_probe.attr,
@@ -257,6 +265,9 @@ static struct attribute *cpu_root_attrs[] = {
        &cpu_attrs[2].attr.attr,
        &dev_attr_kernel_max.attr,
        &dev_attr_offline.attr,
+#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
+       &dev_attr_modalias.attr,
+#endif
        NULL
 };
 
index 1f6587590a1afedf4a8c7478fde3d41a7de9d4e0..6e53b4823d7f10fc79809f83828d6a4759584b8a 100644 (file)
@@ -44,6 +44,13 @@ extern ssize_t arch_cpu_release(const char *, size_t);
 #endif
 struct notifier_block;
 
+#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
+extern int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env);
+extern ssize_t arch_print_cpu_modalias(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *bufptr);
+#endif
+
 /*
  * CPU notifier priorities.
  */