- Add driver auto probing for x86 features v4
authorThomas Renninger <trenn@suse.de>
Sun, 12 Feb 2012 17:15:10 +0000 (18:15 +0100)
committerThomas Renninger <trenn@suse.de>
Sun, 12 Feb 2012 17:15:10 +0000 (18:15 +0100)
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- x86/cpu: Fix overrun check in arch_print_cpu_modalias()
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- crypto: Add support for x86 cpuid
  auto loading for x86 crypto drivers
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- x86/cpu: Clean up modalias feature matching
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- intel-idle: convert to x86_cpu_id auto probing
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- intel_idle: Fix ID for Nehalem-EX Xeon in device ID table
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- HWMON: Convert via-cputemp to x86 cpuid autoprobing
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- powernow-k7: Fix CPU family number
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- ACPI: Load acpi-cpufreq from processor driver automatically
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- intel_idle: Revert change of auto_demotion_flags for Nehalem
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- HWMON: Convert coretemp to x86 cpuid autoprobing
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- powernow-k6: Really enable auto-loading
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- X86: Introduce HW-Pstate scattered cpuid feature
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- cpufreq: Add support for x86 cpuinfo auto loading v4
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- x86: autoload microcode driver on Intel and AMD systems v2
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- CPU: Introduce ARCH_HAS_CPU_AUTOPROBE and X86 parts
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- ACPI: remove duplicated lines of merging
  problems with acpi_processor_start
  (http://lists.opensuse.org/opensuse-kernel/2011-11/msg00075.html).
- Update config files.

suse-commit: 6efe9b5949513b33987e51400da8c75e7225970d

37 files changed:
arch/x86/Kconfig
arch/x86/crypto/aesni-intel_glue.c
arch/x86/crypto/crc32c-intel.c
arch/x86/crypto/ghash-clmulni-intel_glue.c
arch/x86/include/asm/cpu_device_id.h [new file with mode: 0644]
arch/x86/include/asm/cpufeature.h
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/match.c [new file with mode: 0644]
arch/x86/kernel/cpu/scattered.c
arch/x86/kernel/microcode_core.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_perflib.c
drivers/base/cpu.c
drivers/cpufreq/cpufreq-nforce2.c
drivers/cpufreq/e_powersaver.c
drivers/cpufreq/elanfreq.c
drivers/cpufreq/gx-suspmod.c
drivers/cpufreq/longhaul.c
drivers/cpufreq/longrun.c
drivers/cpufreq/p4-clockmod.c
drivers/cpufreq/powernow-k6.c
drivers/cpufreq/powernow-k7.c
drivers/cpufreq/powernow-k8.c
drivers/cpufreq/sc520_freq.c
drivers/cpufreq/speedstep-centrino.c
drivers/cpufreq/speedstep-ich.c
drivers/cpufreq/speedstep-lib.c
drivers/cpufreq/speedstep-smi.c
drivers/crypto/padlock-aes.c
drivers/crypto/padlock-sha.c
drivers/hwmon/coretemp.c
drivers/hwmon/via-cputemp.c
drivers/idle/intel_idle.c
include/acpi/processor.h
include/linux/cpu.h
include/linux/mod_devicetable.h
scripts/mod/file2alias.c

index 734a120..ffcb80b 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 545d0ce..b3350bd 100644 (file)
@@ -28,6 +28,7 @@
 #include <crypto/aes.h>
 #include <crypto/cryptd.h>
 #include <crypto/ctr.h>
+#include <asm/cpu_device_id.h>
 #include <asm/i387.h>
 #include <asm/aes.h>
 #include <crypto/scatterwalk.h>
@@ -1253,14 +1254,19 @@ static struct crypto_alg __rfc4106_alg = {
 };
 #endif
 
+
+static const struct x86_cpu_id aesni_cpu_id[] = {
+       X86_FEATURE_MATCH(X86_FEATURE_AES),
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, aesni_cpu_id);
+
 static int __init aesni_init(void)
 {
        int err;
 
-       if (!cpu_has_aes) {
-               printk(KERN_INFO "Intel AES-NI instructions are not detected.\n");
+       if (!x86_match_cpu(aesni_cpu_id))
                return -ENODEV;
-       }
 
        if ((err = crypto_fpu_init()))
                goto fpu_err;
index b9d0026..493f959 100644 (file)
@@ -31,6 +31,7 @@
 #include <crypto/internal/hash.h>
 
 #include <asm/cpufeature.h>
+#include <asm/cpu_device_id.h>
 
 #define CHKSUM_BLOCK_SIZE      1
 #define CHKSUM_DIGEST_SIZE     4
@@ -173,13 +174,17 @@ static struct shash_alg alg = {
        }
 };
 
+static const struct x86_cpu_id crc32c_cpu_id[] = {
+       X86_FEATURE_MATCH(X86_FEATURE_XMM4_2),
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, crc32c_cpu_id);
 
 static int __init crc32c_intel_mod_init(void)
 {
-       if (cpu_has_xmm4_2)
-               return crypto_register_shash(&alg);
-       else
+       if (!x86_match_cpu(crc32c_cpu_id))
                return -ENODEV;
+       return crypto_register_shash(&alg);
 }
 
 static void __exit crc32c_intel_mod_fini(void)
index 976aa64..b4bf0a6 100644 (file)
@@ -20,6 +20,7 @@
 #include <crypto/gf128mul.h>
 #include <crypto/internal/hash.h>
 #include <asm/i387.h>
+#include <asm/cpu_device_id.h>
 
 #define GHASH_BLOCK_SIZE       16
 #define GHASH_DIGEST_SIZE      16
@@ -294,15 +295,18 @@ static struct ahash_alg ghash_async_alg = {
        },
 };
 
+static const struct x86_cpu_id pcmul_cpu_id[] = {
+       X86_FEATURE_MATCH(X86_FEATURE_PCLMULQDQ), /* Pickle-Mickle-Duck */
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, pcmul_cpu_id);
+
 static int __init ghash_pclmulqdqni_mod_init(void)
 {
        int err;
 
-       if (!cpu_has_pclmulqdq) {
-               printk(KERN_INFO "Intel PCLMULQDQ-NI instructions are not"
-                      " detected.\n");
+       if (!x86_match_cpu(pcmul_cpu_id))
                return -ENODEV;
-       }
 
        err = crypto_register_shash(&ghash_alg);
        if (err)
diff --git a/arch/x86/include/asm/cpu_device_id.h b/arch/x86/include/asm/cpu_device_id.h
new file mode 100644 (file)
index 0000000..ff501e5
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _CPU_DEVICE_ID
+#define _CPU_DEVICE_ID 1
+
+/*
+ * Declare drivers belonging to specific x86 CPUs
+ * Similar in spirit to pci_device_id and related PCI functions
+ */
+
+#include <linux/mod_devicetable.h>
+
+extern const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match);
+
+#endif
index 8d67d42..dcb839e 100644 (file)
 #define X86_FEATURE_PLN                (7*32+ 5) /* Intel Power Limit Notification */
 #define X86_FEATURE_PTS                (7*32+ 6) /* Intel Package Thermal Status */
 #define X86_FEATURE_DTS                (7*32+ 7) /* Digital Thermal Sensor */
+#define X86_FEATURE_HW_PSTATE  (7*32+ 8) /* AMD HW-PState */
 
 /* Virtualization flags: Linux defined, word 8 */
 #define X86_FEATURE_TPR_SHADOW  (8*32+ 0) /* Intel TPR Shadow */
index 25f24dc..6ab6aa2 100644 (file)
@@ -16,6 +16,7 @@ obj-y                 := intel_cacheinfo.o scattered.o topology.o
 obj-y                  += proc.o capflags.o powerflags.o common.o
 obj-y                  += vmware.o hypervisor.o sched.o mshyperv.o
 obj-y                  += rdrand.o
+obj-y                  += match.o
 
 obj-$(CONFIG_X86_32)   += bugs.o
 obj-$(CONFIG_X86_64)   += bugs_64.o
diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c
new file mode 100644 (file)
index 0000000..5502b28
--- /dev/null
@@ -0,0 +1,91 @@
+#include <asm/cpu_device_id.h>
+#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
+ * @match: Pointer to array of x86_cpu_ids. Last entry terminated with
+ *         {}.
+ *
+ * Return the entry if the current CPU matches the entries in the
+ * passed x86_cpu_id match table. Otherwise NULL.  The match table
+ * contains vendor (X86_VENDOR_*), family, model and feature bits or
+ * respective wildcard entries.
+ *
+ * A typical table entry would be to match a specific CPU
+ * { X86_VENDOR_INTEL, 6, 0x12 }
+ * or to match a specific CPU feature
+ * { X86_FEATURE_MATCH(X86_FEATURE_FOOBAR) }
+ *
+ * Fields can be wildcarded with %X86_VENDOR_ANY, %X86_FAMILY_ANY,
+ * %X86_MODEL_ANY, %X86_FEATURE_ANY or 0 (except for vendor)
+ *
+ * Arrays used to match for this should also be declared using
+ * MODULE_DEVICE_TABLE(x86_cpu, ...)
+ *
+ * This always matches against the boot cpu, assuming models and features are
+ * consistent over all CPUs.
+ */
+const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
+{
+       const struct x86_cpu_id *m;
+       struct cpuinfo_x86 *c = &boot_cpu_data;
+
+       for (m = match; m->vendor | m->family | m->model | m->feature; m++) {
+               if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor)
+                       continue;
+               if (m->family != X86_FAMILY_ANY && c->x86 != m->family)
+                       continue;
+               if (m->model != X86_MODEL_ANY && c->x86_model != m->model)
+                       continue;
+               if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature))
+                       continue;
+               return m;
+       }
+       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 -= 1;
+       for (i = 0; i < NCAPINTS*32; i++) {
+               if (boot_cpu_has(i)) {
+                       n = snprintf(buf, size, ",%04X", i);
+                       if (n >= size) {
+                               WARN(1, "x86 features overflow page\n");
+                               break;
+                       }
+                       size -= n;
+                       buf += n;
+               }
+       }
+       *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 c7f64e6..addf9e8 100644 (file)
@@ -40,6 +40,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
                { X86_FEATURE_EPB,              CR_ECX, 3, 0x00000006, 0 },
                { X86_FEATURE_XSAVEOPT,         CR_EAX, 0, 0x0000000d, 1 },
                { X86_FEATURE_CPB,              CR_EDX, 9, 0x80000007, 0 },
+               { X86_FEATURE_HW_PSTATE,        CR_EDX, 7, 0x80000007, 0 },
                { X86_FEATURE_NPT,              CR_EDX, 0, 0x8000000a, 0 },
                { X86_FEATURE_LBRV,             CR_EDX, 1, 0x8000000a, 0 },
                { X86_FEATURE_SVML,             CR_EDX, 2, 0x8000000a, 0 },
index fda91c3..87a0f86 100644 (file)
@@ -86,6 +86,7 @@
 
 #include <asm/microcode.h>
 #include <asm/processor.h>
+#include <asm/cpu_device_id.h>
 
 MODULE_DESCRIPTION("Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
@@ -504,6 +505,20 @@ static struct notifier_block __refdata mc_cpu_notifier = {
        .notifier_call  = mc_cpu_callback,
 };
 
+#ifdef MODULE
+/* Autoload on Intel and AMD systems */
+static const struct x86_cpu_id microcode_id[] = {
+#ifdef CONFIG_MICROCODE_INTEL
+       { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, },
+#endif
+#ifdef CONFIG_MICROCODE_AMD
+       { X86_VENDOR_AMD, X86_FAMILY_ANY, X86_MODEL_ANY, },
+#endif
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, microcode_id);
+#endif
+
 static int __init microcode_init(void)
 {
        struct cpuinfo_x86 *c = &cpu_data(0);
index 8ae05ce..2801b41 100644 (file)
@@ -474,6 +474,7 @@ static __ref int acpi_processor_start(struct acpi_processor *pr)
 
 #ifdef CONFIG_CPU_FREQ
        acpi_processor_ppc_has_changed(pr, 0);
+       acpi_processor_load_module(pr);
 #endif
        acpi_processor_get_throttling_info(pr);
        acpi_processor_get_limit_info(pr);
index 85b3237..0af48a8 100644 (file)
@@ -240,6 +240,28 @@ void acpi_processor_ppc_exit(void)
        acpi_processor_ppc_status &= ~PPC_REGISTERED;
 }
 
+/*
+ * Do a quick check if the systems looks like it should use ACPI
+ * cpufreq. We look at a _PCT method being available, but don't
+ * do a whole lot of sanity checks.
+ */
+void acpi_processor_load_module(struct acpi_processor *pr)
+{
+       static int requested;
+       acpi_status status = 0;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+       if (!arch_has_acpi_pdc() || requested)
+               return;
+       status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
+       if (!ACPI_FAILURE(status)) {
+               printk(KERN_INFO PREFIX "Requesting acpi_cpufreq\n");
+               request_module_nowait("acpi_cpufreq");
+               requested = 1;
+       }
+       kfree(buffer.pointer);
+}
+
 static int acpi_processor_get_performance_control(struct acpi_processor *pr)
 {
        int result = 0;
index db87e78..2a0c670 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 7bac808..13d311e 100644 (file)
@@ -385,6 +385,14 @@ static struct cpufreq_driver nforce2_driver = {
        .owner = THIS_MODULE,
 };
 
+#ifdef MODULE
+static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = {
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2 },
+       {}
+};
+MODULE_DEVICE_TABLE(pci, nforce2_ids);
+#endif
+
 /**
  * nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic
  *
index 4bd6815..3fffbe6 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 
+#include <asm/cpu_device_id.h>
 #include <asm/msr.h>
 #include <asm/tsc.h>
 
@@ -437,18 +438,19 @@ static struct cpufreq_driver eps_driver = {
        .attr           = eps_attr,
 };
 
+
+/* This driver will work only on Centaur C7 processors with
+ * Enhanced SpeedStep/PowerSaver registers */
+static const struct x86_cpu_id eps_cpu_id[] = {
+       { X86_VENDOR_CENTAUR, 6, X86_MODEL_ANY, X86_FEATURE_EST },
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, eps_cpu_id);
+
 static int __init eps_init(void)
 {
-       struct cpuinfo_x86 *c = &cpu_data(0);
-
-       /* This driver will work only on Centaur C7 processors with
-        * Enhanced SpeedStep/PowerSaver registers */
-       if (c->x86_vendor != X86_VENDOR_CENTAUR
-           || c->x86 != 6 || c->x86_model < 10)
-               return -ENODEV;
-       if (!cpu_has(c, X86_FEATURE_EST))
+       if (!x86_match_cpu(eps_cpu_id) || boot_cpu_data.x86_model < 10)
                return -ENODEV;
-
        if (cpufreq_register_driver(&eps_driver))
                return -EINVAL;
        return 0;
index c587db4..960671f 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/cpufreq.h>
 
+#include <asm/cpu_device_id.h>
 #include <asm/msr.h>
 #include <linux/timex.h>
 #include <linux/io.h>
@@ -277,17 +278,16 @@ static struct cpufreq_driver elanfreq_driver = {
        .attr           = elanfreq_attr,
 };
 
+static const struct x86_cpu_id elan_id[] = {
+       { X86_VENDOR_AMD, 4, 10, },
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, elan_id);
 
 static int __init elanfreq_init(void)
 {
-       struct cpuinfo_x86 *c = &cpu_data(0);
-
-       /* Test if we have the right hardware */
-       if ((c->x86_vendor != X86_VENDOR_AMD) ||
-               (c->x86 != 4) || (c->x86_model != 10)) {
-               printk(KERN_INFO "elanfreq: error: no Elan processor found!\n");
+       if (!x86_match_cpu(elan_id))
                return -ENODEV;
-       }
        return cpufreq_register_driver(&elanfreq_driver);
 }
 
index ffe1f2c..5a06c0b 100644 (file)
@@ -82,6 +82,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 
+#include <asm/cpu_device_id.h>
 #include <asm/processor-cyrix.h>
 
 /* PCI config registers, all at F0 */
@@ -171,6 +172,7 @@ static struct pci_device_id gx_chipset_tbl[] __initdata = {
        { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), },
        { 0, },
 };
+MODULE_DEVICE_TABLE(gx_chipset_tbl);
 
 static void gx_write_byte(int reg, int value)
 {
@@ -185,13 +187,6 @@ static __init struct pci_dev *gx_detect_chipset(void)
 {
        struct pci_dev *gx_pci = NULL;
 
-       /* check if CPU is a MediaGX or a Geode. */
-       if ((boot_cpu_data.x86_vendor != X86_VENDOR_NSC) &&
-           (boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) {
-               pr_debug("error: no MediaGX/Geode processor found!\n");
-               return NULL;
-       }
-
        /* detect which companion chip is used */
        for_each_pci_dev(gx_pci) {
                if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL)
index f47d26e..53ddbc7 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/acpi.h>
 
 #include <asm/msr.h>
+#include <asm/cpu_device_id.h>
 #include <acpi/processor.h>
 
 #include "longhaul.h"
@@ -951,12 +952,17 @@ static struct cpufreq_driver longhaul_driver = {
        .attr   = longhaul_attr,
 };
 
+static const struct x86_cpu_id longhaul_id[] = {
+       { X86_VENDOR_CENTAUR, 6 },
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, longhaul_id);
 
 static int __init longhaul_init(void)
 {
        struct cpuinfo_x86 *c = &cpu_data(0);
 
-       if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6)
+       if (!x86_match_cpu(longhaul_id))
                return -ENODEV;
 
 #ifdef CONFIG_SMP
index 34ea359..8bc9f5f 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <asm/msr.h>
 #include <asm/processor.h>
+#include <asm/cpu_device_id.h>
 
 static struct cpufreq_driver   longrun_driver;
 
@@ -288,6 +289,12 @@ static struct cpufreq_driver longrun_driver = {
        .owner          = THIS_MODULE,
 };
 
+static const struct x86_cpu_id longrun_ids[] = {
+       { X86_VENDOR_TRANSMETA, X86_FAMILY_ANY, X86_MODEL_ANY,
+         X86_FEATURE_LONGRUN },
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, longrun_ids);
 
 /**
  * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver
@@ -296,12 +303,8 @@ static struct cpufreq_driver longrun_driver = {
  */
 static int __init longrun_init(void)
 {
-       struct cpuinfo_x86 *c = &cpu_data(0);
-
-       if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
-           !cpu_has(c, X86_FEATURE_LONGRUN))
+       if (!x86_match_cpu(longrun_ids))
                return -ENODEV;
-
        return cpufreq_register_driver(&longrun_driver);
 }
 
index 6be3e07..827629c 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/processor.h>
 #include <asm/msr.h>
 #include <asm/timer.h>
+#include <asm/cpu_device_id.h>
 
 #include "speedstep-lib.h"
 
@@ -289,21 +290,25 @@ static struct cpufreq_driver p4clockmod_driver = {
        .attr           = p4clockmod_attr,
 };
 
+static const struct x86_cpu_id cpufreq_p4_id[] = {
+       { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_ACC },
+       {}
+};
+
+/*
+ * Intentionally no MODULE_DEVICE_TABLE here: this driver should not
+ * be auto loaded.  Please don't add one.
+ */
 
 static int __init cpufreq_p4_init(void)
 {
-       struct cpuinfo_x86 *c = &cpu_data(0);
        int ret;
 
        /*
         * THERM_CONTROL is architectural for IA32 now, so
         * we can rely on the capability checks
         */
-       if (c->x86_vendor != X86_VENDOR_INTEL)
-               return -ENODEV;
-
-       if (!test_cpu_cap(c, X86_FEATURE_ACPI) ||
-                               !test_cpu_cap(c, X86_FEATURE_ACC))
+       if (!x86_match_cpu(cpufreq_p4_id) || !boot_cpu_has(X86_FEATURE_ACPI))
                return -ENODEV;
 
        ret = cpufreq_register_driver(&p4clockmod_driver);
index b3379d6..af23e0b 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/timex.h>
 #include <linux/io.h>
 
+#include <asm/cpu_device_id.h>
 #include <asm/msr.h>
 
 #define POWERNOW_IOPORT 0xfff0          /* it doesn't matter where, as long
@@ -210,6 +211,12 @@ static struct cpufreq_driver powernow_k6_driver = {
        .attr           = powernow_k6_attr,
 };
 
+static const struct x86_cpu_id powernow_k6_ids[] = {
+       { X86_VENDOR_AMD, 5, 12 },
+       { X86_VENDOR_AMD, 5, 13 },
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, powernow_k6_ids);
 
 /**
  * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver
@@ -220,10 +227,7 @@ static struct cpufreq_driver powernow_k6_driver = {
  */
 static int __init powernow_k6_init(void)
 {
-       struct cpuinfo_x86 *c = &cpu_data(0);
-
-       if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
-               ((c->x86_model != 12) && (c->x86_model != 13)))
+       if (!x86_match_cpu(powernow_k6_ids))
                return -ENODEV;
 
        if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) {
index d71d9f3..cf7e1ee 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/timer.h>         /* Needed for recalibrate_cpu_khz() */
 #include <asm/msr.h>
 #include <asm/system.h>
+#include <asm/cpu_device_id.h>
 
 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
 #include <linux/acpi.h>
@@ -110,18 +111,19 @@ static int check_fsb(unsigned int fsbspeed)
        return delta < 5;
 }
 
+static const struct x86_cpu_id powernow_k7_cpuids[] = {
+       { X86_VENDOR_AMD, 6, },
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids);
+
 static int check_powernow(void)
 {
        struct cpuinfo_x86 *c = &cpu_data(0);
        unsigned int maxei, eax, ebx, ecx, edx;
 
-       if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 6)) {
-#ifdef MODULE
-               printk(KERN_INFO PFX "This module only works with "
-                               "AMD K7 CPUs\n");
-#endif
+       if (!x86_match_cpu(powernow_k7_cpuids))
                return 0;
-       }
 
        /* Get maximum capabilities */
        maxei = cpuid_eax(0x80000000);
index 8f9b2ce..c0e8164 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/delay.h>
 
 #include <asm/msr.h>
+#include <asm/cpu_device_id.h>
 
 #include <linux/acpi.h>
 #include <linux/mutex.h>
@@ -520,6 +521,15 @@ static int core_voltage_post_transition(struct powernow_k8_data *data,
        return 0;
 }
 
+static const struct x86_cpu_id powernow_k8_ids[] = {
+       /* IO based frequency switching */
+       { X86_VENDOR_AMD, 0xf },
+       /* MSR based frequency switching supported */
+       X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE),
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, powernow_k8_ids);
+
 static void check_supported_cpu(void *_rc)
 {
        u32 eax, ebx, ecx, edx;
@@ -527,13 +537,7 @@ static void check_supported_cpu(void *_rc)
 
        *rc = -ENODEV;
 
-       if (__this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_AMD)
-               return;
-
        eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
-       if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) &&
-           ((eax & CPUID_XFAM) < CPUID_XFAM_10H))
-               return;
 
        if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) {
                if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
@@ -1553,6 +1557,9 @@ static int __cpuinit powernowk8_init(void)
        unsigned int i, supported_cpus = 0, cpu;
        int rv;
 
+       if (!x86_match_cpu(powernow_k8_ids))
+               return -ENODEV;
+
        for_each_online_cpu(i) {
                int rc;
                smp_call_function_single(i, check_supported_cpu, &rc, 1);
index 1e205e6..e42e073 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/timex.h>
 #include <linux/io.h>
 
+#include <asm/cpu_device_id.h>
 #include <asm/msr.h>
 
 #define MMCR_BASE      0xfffef000      /* The default base address */
@@ -150,18 +151,19 @@ static struct cpufreq_driver sc520_freq_driver = {
        .attr   = sc520_freq_attr,
 };
 
+static const struct x86_cpu_id sc520_ids[] = {
+       { X86_VENDOR_AMD, 4, 9 },
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, sc520_ids);
 
 static int __init sc520_freq_init(void)
 {
-       struct cpuinfo_x86 *c = &cpu_data(0);
        int err;
 
-       /* Test if we have the right hardware */
-       if (c->x86_vendor != X86_VENDOR_AMD ||
-           c->x86 != 4 || c->x86_model != 9) {
-               pr_debug("no Elan SC520 processor found!\n");
+       if (!x86_match_cpu(sc520_ids))
                return -ENODEV;
-       }
+
        cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
        if (!cpuctl) {
                printk(KERN_ERR "sc520_freq: error: failed to remap memory\n");
index 6ea3455..3a953d5 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/msr.h>
 #include <asm/processor.h>
 #include <asm/cpufeature.h>
+#include <asm/cpu_device_id.h>
 
 #define PFX            "speedstep-centrino: "
 #define MAINTAINER     "cpufreq@vger.kernel.org"
@@ -595,6 +596,24 @@ static struct cpufreq_driver centrino_driver = {
        .owner          = THIS_MODULE,
 };
 
+/*
+ * This doesn't replace the detailed checks above because
+ * the generic CPU IDs don't have a way to match for steppings
+ * or ASCII model IDs.
+ */
+static const struct x86_cpu_id centrino_ids[] = {
+       { X86_VENDOR_INTEL, 6, 9, X86_FEATURE_EST },
+       { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST },
+       { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST },
+       { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST },
+       { X86_VENDOR_INTEL, 15, 3, X86_FEATURE_EST },
+       { X86_VENDOR_INTEL, 15, 4, X86_FEATURE_EST },
+       {}
+};
+#if 0
+/* Autoload or not? Do not for now. */
+MODULE_DEVICE_TABLE(x86cpu, centrino_ids);
+#endif
 
 /**
  * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver
@@ -612,11 +631,8 @@ static struct cpufreq_driver centrino_driver = {
  */
 static int __init centrino_init(void)
 {
-       struct cpuinfo_x86 *cpu = &cpu_data(0);
-
-       if (!cpu_has(cpu, X86_FEATURE_EST))
+       if (!x86_match_cpu(centrino_ids))
                return -ENODEV;
-
        return cpufreq_register_driver(&centrino_driver);
 }
 
index a748ce7..7432b3a 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/pci.h>
 #include <linux/sched.h>
 
+#include <asm/cpu_device_id.h>
+
 #include "speedstep-lib.h"
 
 
@@ -388,6 +390,16 @@ static struct cpufreq_driver speedstep_driver = {
        .attr   = speedstep_attr,
 };
 
+static const struct x86_cpu_id ss_smi_ids[] = {
+       { X86_VENDOR_INTEL, 6, 0xb, },
+       { X86_VENDOR_INTEL, 6, 0x8, },
+       { X86_VENDOR_INTEL, 15, 2 },
+       {}
+};
+#if 0
+/* Autoload or not? Do not for now. */
+MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids);
+#endif
 
 /**
  * speedstep_init - initializes the SpeedStep CPUFreq driver
@@ -398,6 +410,9 @@ static struct cpufreq_driver speedstep_driver = {
  */
 static int __init speedstep_init(void)
 {
+       if (!x86_match_cpu(ss_smi_ids))
+               return -ENODEV;
+
        /* detect processor */
        speedstep_processor = speedstep_detect_processor();
        if (!speedstep_processor) {
index 8af2d2f..7047821 100644 (file)
@@ -249,6 +249,7 @@ EXPORT_SYMBOL_GPL(speedstep_get_frequency);
  *                 DETECT SPEEDSTEP-CAPABLE PROCESSOR                *
  *********************************************************************/
 
+/* Keep in sync with the x86_cpu_id tables in the different modules */
 unsigned int speedstep_detect_processor(void)
 {
        struct cpuinfo_x86 *c = &cpu_data(0);
index c76ead3..6a457fc 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <asm/ist.h>
+#include <asm/cpu_device_id.h>
 
 #include "speedstep-lib.h"
 
@@ -379,6 +380,17 @@ static struct cpufreq_driver speedstep_driver = {
        .attr           = speedstep_attr,
 };
 
+static const struct x86_cpu_id ss_smi_ids[] = {
+       { X86_VENDOR_INTEL, 6, 0xb, },
+       { X86_VENDOR_INTEL, 6, 0x8, },
+       { X86_VENDOR_INTEL, 15, 2 },
+       {}
+};
+#if 0
+/* Not auto loaded currently */
+MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids);
+#endif
+
 /**
  * speedstep_init - initializes the SpeedStep CPUFreq driver
  *
@@ -388,6 +400,9 @@ static struct cpufreq_driver speedstep_driver = {
  */
 static int __init speedstep_init(void)
 {
+       if (!x86_match_cpu(ss_smi_ids))
+               return -ENODEV;
+
        speedstep_processor = speedstep_detect_processor();
 
        switch (speedstep_processor) {
index 29b9469..37b2e94 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/percpu.h>
 #include <linux/smp.h>
 #include <linux/slab.h>
+#include <asm/cpu_device_id.h>
 #include <asm/byteorder.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
@@ -503,12 +504,18 @@ static struct crypto_alg cbc_aes_alg = {
        }
 };
 
+static struct x86_cpu_id padlock_cpu_id[] = {
+       X86_FEATURE_MATCH(X86_FEATURE_XCRYPT),
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, padlock_cpu_id);
+
 static int __init padlock_init(void)
 {
        int ret;
        struct cpuinfo_x86 *c = &cpu_data(0);
 
-       if (!cpu_has_xcrypt)
+       if (!x86_match_cpu(padlock_cpu_id))
                return -ENODEV;
 
        if (!cpu_has_xcrypt_enabled) {
index 06bdb4b..9266c0e 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/scatterlist.h>
+#include <asm/cpu_device_id.h>
 #include <asm/i387.h>
 
 struct padlock_sha_desc {
@@ -526,6 +527,12 @@ static struct shash_alg sha256_alg_nano = {
        }
 };
 
+static struct x86_cpu_id padlock_sha_ids[] = {
+       X86_FEATURE_MATCH(X86_FEATURE_PHE),
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, padlock_sha_ids);
+
 static int __init padlock_init(void)
 {
        int rc = -ENODEV;
@@ -533,15 +540,8 @@ static int __init padlock_init(void)
        struct shash_alg *sha1;
        struct shash_alg *sha256;
 
-       if (!cpu_has_phe) {
-               printk(KERN_NOTICE PFX "VIA PadLock Hash Engine not detected.\n");
-               return -ENODEV;
-       }
-
-       if (!cpu_has_phe_enabled) {
-               printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
+       if (!x86_match_cpu(padlock_sha_ids) || !cpu_has_phe_enabled)
                return -ENODEV;
-       }
 
        /* Register the newly added algorithm module if on *
        * VIA Nano processor, or else just do as before */
index a6c6ec3..249ac46 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/moduleparam.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
+#include <asm/cpu_device_id.h>
 
 #define DRVNAME        "coretemp"
 
@@ -759,13 +760,23 @@ static struct notifier_block coretemp_cpu_notifier __refdata = {
        .notifier_call = coretemp_cpu_callback,
 };
 
+static const struct x86_cpu_id coretemp_ids[] = {
+       { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTS },
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, coretemp_ids);
+
 static int __init coretemp_init(void)
 {
        int i, err = -ENODEV;
 
-       /* quick check if we run Intel */
-       if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
-               goto exit;
+       /*
+        * CPUID.06H.EAX[0] indicates whether the CPU has thermal
+        * sensors. We check this bit only, all the early CPUs
+        * without thermal sensors will be filtered out.
+        */
+       if (!x86_match_cpu(coretemp_ids))
+               return -ENODEV;
 
        err = platform_driver_register(&coretemp_driver);
        if (err)
index 8eac67d..8689664 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/cpu.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
+#include <asm/cpu_device_id.h>
 
 #define DRVNAME        "via_cputemp"
 
@@ -308,15 +309,20 @@ static struct notifier_block via_cputemp_cpu_notifier __refdata = {
        .notifier_call = via_cputemp_cpu_callback,
 };
 
+static const struct x86_cpu_id cputemp_ids[] = {
+       { X86_VENDOR_CENTAUR, 6, 0xa, }, /* C7 A */
+       { X86_VENDOR_CENTAUR, 6, 0xd, }, /* C7 D */
+       { X86_VENDOR_CENTAUR, 6, 0xf, }, /* Nano */
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, cputemp_ids);
+
 static int __init via_cputemp_init(void)
 {
        int i, err;
 
-       if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) {
-               printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n");
-               err = -ENODEV;
-               goto exit;
-       }
+       if (!x86_match_cpu(cputemp_ids))
+               return -ENODEV;
 
        err = platform_driver_register(&via_cputemp_driver);
        if (err)
index 54ab97b..1c15e9b 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/notifier.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
+#include <asm/cpu_device_id.h>
 #include <asm/mwait.h>
 #include <asm/msr.h>
 
@@ -81,6 +82,17 @@ static unsigned int mwait_substates;
 /* Reliable LAPIC Timer States, bit 1 for C1 etc.  */
 static unsigned int lapic_timer_reliable_states = (1 << 1);     /* Default to only C1 */
 
+struct idle_cpu {
+       struct cpuidle_state *state_table;
+
+       /*
+        * Hardware C-state auto-demotion may not always be optimal.
+        * Indicate which enable bits to clear here.
+        */
+       unsigned long auto_demotion_disable_flags;
+};
+
+static const struct idle_cpu *icpu;
 static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
 static int intel_idle(struct cpuidle_device *dev,
                        struct cpuidle_driver *drv, int index);
@@ -88,12 +100,6 @@ static int intel_idle(struct cpuidle_device *dev,
 static struct cpuidle_state *cpuidle_state_table;
 
 /*
- * Hardware C-state auto-demotion may not always be optimal.
- * Indicate which enable bits to clear here.
- */
-static unsigned long long auto_demotion_disable_flags;
-
-/*
  * Set this flag for states where the HW flushes the TLB for us
  * and so we don't need cross-calls to keep it consistent.
  * If this flag is set, SW flushes the TLB, so even if the
@@ -319,27 +325,68 @@ static void auto_demotion_disable(void *dummy)
        unsigned long long msr_bits;
 
        rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
-       msr_bits &= ~auto_demotion_disable_flags;
+       msr_bits &= ~(icpu->auto_demotion_disable_flags);
        wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
 }
 
+static const struct idle_cpu idle_cpu_nehalem = {
+       .state_table = nehalem_cstates,
+       .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
+};
+
+static const struct idle_cpu idle_cpu_atom = {
+       .state_table = atom_cstates,
+};
+
+static const struct idle_cpu idle_cpu_lincroft = {
+       .state_table = atom_cstates,
+       .auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE,
+};
+
+static const struct idle_cpu idle_cpu_snb = {
+       .state_table = snb_cstates,
+};
+
+#define ICPU(model, cpu) \
+       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu }
+
+static const struct x86_cpu_id intel_idle_ids[] = {
+       ICPU(0x1a, idle_cpu_nehalem),
+       ICPU(0x1e, idle_cpu_nehalem),
+       ICPU(0x1f, idle_cpu_nehalem),
+       ICPU(0x25, idle_cpu_nehalem),
+       ICPU(0x2c, idle_cpu_nehalem),
+       ICPU(0x2e, idle_cpu_nehalem),
+       ICPU(0x1c, idle_cpu_atom),
+       ICPU(0x26, idle_cpu_lincroft),
+       ICPU(0x2f, idle_cpu_nehalem),
+       ICPU(0x2a, idle_cpu_snb),
+       ICPU(0x2d, idle_cpu_snb),
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
+
 /*
  * intel_idle_probe()
  */
 static int intel_idle_probe(void)
 {
        unsigned int eax, ebx, ecx;
+       const struct x86_cpu_id *id;
 
        if (max_cstate == 0) {
                pr_debug(PREFIX "disabled\n");
                return -EPERM;
        }
 
-       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
-               return -ENODEV;
-
-       if (!boot_cpu_has(X86_FEATURE_MWAIT))
+       id = x86_match_cpu(intel_idle_ids);
+       if (!id) {
+               if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+                   boot_cpu_data.x86 == 6)
+                       pr_debug(PREFIX "does not run on family %d model %d\n",
+                               boot_cpu_data.x86, boot_cpu_data.x86_model);
                return -ENODEV;
+       }
 
        if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
                return -ENODEV;
@@ -353,43 +400,8 @@ static int intel_idle_probe(void)
 
        pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates);
 
-
-       if (boot_cpu_data.x86 != 6)     /* family 6 */
-               return -ENODEV;
-
-       switch (boot_cpu_data.x86_model) {
-
-       case 0x1A:      /* Core i7, Xeon 5500 series */
-       case 0x1E:      /* Core i7 and i5 Processor - Lynnfield Jasper Forest */
-       case 0x1F:      /* Core i7 and i5 Processor - Nehalem */
-       case 0x2E:      /* Nehalem-EX Xeon */
-       case 0x2F:      /* Westmere-EX Xeon */
-       case 0x25:      /* Westmere */
-       case 0x2C:      /* Westmere */
-               cpuidle_state_table = nehalem_cstates;
-               auto_demotion_disable_flags =
-                       (NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE);
-               break;
-
-       case 0x1C:      /* 28 - Atom Processor */
-               cpuidle_state_table = atom_cstates;
-               break;
-
-       case 0x26:      /* 38 - Lincroft Atom Processor */
-               cpuidle_state_table = atom_cstates;
-               auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE;
-               break;
-
-       case 0x2A:      /* SNB */
-       case 0x2D:      /* SNB Xeon */
-               cpuidle_state_table = snb_cstates;
-               break;
-
-       default:
-               pr_debug(PREFIX "does not run on family %d model %d\n",
-                       boot_cpu_data.x86, boot_cpu_data.x86_model);
-               return -ENODEV;
-       }
+       icpu = (const struct idle_cpu *)id->driver_data;
+       cpuidle_state_table = icpu->state_table;
 
        if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
                lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
@@ -470,7 +482,7 @@ static int intel_idle_cpuidle_driver_init(void)
                drv->state_count += 1;
        }
 
-       if (auto_demotion_disable_flags)
+       if (icpu->auto_demotion_disable_flags)
                on_each_cpu(auto_demotion_disable, NULL, 1);
 
        return 0;
@@ -522,7 +534,7 @@ int intel_idle_cpu_init(int cpu)
                return -EIO;
        }
 
-       if (auto_demotion_disable_flags)
+       if (icpu->auto_demotion_disable_flags)
                smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
 
        return 0;
index 8cf7e98..9d65047 100644 (file)
@@ -225,6 +225,7 @@ struct acpi_processor_errata {
        } piix4;
 };
 
+extern void acpi_processor_load_module(struct acpi_processor *pr);
 extern int acpi_processor_preregister_performance(struct
                                                  acpi_processor_performance
                                                  __percpu *performance);
index 1f65875..6e53b48 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.
  */
index 83ac071..fb69ad1 100644 (file)
@@ -560,4 +560,25 @@ struct amba_id {
 #endif
 };
 
+/*
+ * Match x86 CPUs for CPU specific drivers.
+ * See documentation of "x86_match_cpu" for details.
+ */
+
+struct x86_cpu_id {
+       __u16 vendor;
+       __u16 family;
+       __u16 model;
+       __u16 feature;  /* bit index */
+       kernel_ulong_t driver_data;
+};
+
+#define X86_FEATURE_MATCH(x) \
+       { X86_VENDOR_ANY, X86_FAMILY_ANY, X86_MODEL_ANY, x }
+
+#define X86_VENDOR_ANY 0xffff
+#define X86_FAMILY_ANY 0
+#define X86_MODEL_ANY  0
+#define X86_FEATURE_ANY 0      /* Same as FPU, you can't test for that */
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
index e8c9695..78fd81f 100644 (file)
@@ -1003,6 +1003,31 @@ static int do_amba_entry(const char *filename,
 }
 ADD_TO_DEVTABLE("amba", struct amba_id, do_amba_entry);
 
+/* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,*
+ * All fields are numbers. It would be nicer to use strings for vendor
+ * and feature, but getting those out of the build system here is too
+ * complicated.
+ */
+
+static int do_x86cpu_entry(const char *filename, struct x86_cpu_id *id,
+                          char *alias)
+{
+       id->feature = TO_NATIVE(id->feature);
+       id->family = TO_NATIVE(id->family);
+       id->model = TO_NATIVE(id->model);
+       id->vendor = TO_NATIVE(id->vendor);
+
+       strcpy(alias, "x86cpu:");
+       ADD(alias, "vendor:",  id->vendor != X86_VENDOR_ANY, id->vendor);
+       ADD(alias, ":family:", id->family != X86_FAMILY_ANY, id->family);
+       ADD(alias, ":model:",  id->model  != X86_MODEL_ANY,  id->model);
+       strcat(alias, ":feature:*");
+       if (id->feature != X86_FEATURE_ANY)
+               sprintf(alias + strlen(alias), "%04X*", id->feature);
+       return 1;
+}
+ADD_TO_DEVTABLE("x86cpu", struct x86_cpu_id, do_x86cpu_entry);
+
 /* Does namelen bytes of name exactly match the symbol? */
 static bool sym_is(const char *name, unsigned namelen, const char *symbol)
 {