cpufreq: Add support for x86 cpuinfo auto loading v4
authorAndi Kleen <ak@linux.intel.com>
Wed, 25 Jan 2012 23:09:12 +0000 (00:09 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 27 Jan 2012 00:49:06 +0000 (16:49 -0800)
This marks all the x86 cpuinfo tables to the CPU specific device drivers,
to allow auto loading by udev. This should simplify the distribution
startup scripts for this greatly.

I didn't add MODULE_DEVICE_IDs to the centrino and p4-clockmod drivers,
because those probably shouldn't be auto loaded and the acpi driver
be used instead (not fully sure on that, would appreciate feedback)

The old nforce drivers autoload based on the PCI ID.

ACPI cpufreq is autoloaded in another patch.

v3: Autoload gx based on PCI IDs only. Remove cpu check (Dave Jones)
v4: Use newly introduce HW_PSTATE feature for powernow-k8 loading

Cc: Dave Jones <davej@redhat.com>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-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>
15 files changed:
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

index 7bac808804f3ad61bce2643c5c00665777f98afd..13d311ee08b3723ca422d6f9b1cf485b011f2ea9 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 4bd6815d317bb86631dc3713a7e2e3eebc7332ac..3fffbe6025cd34e9dc2ee9cbfd893c6f1eff9f68 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 c587db472a75a21eeabb0c52a1df3b7f48b549f4..960671fd3d7e8c236a5f31f6577b7d174047b01a 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 ffe1f2c92ed3f6c10da0749b087b39eb4bd9c390..5a06c0ba24526a8426708fcab7b2ebf7e586c752 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 f47d26e2a13566d870a54ad6f284736f9ffa0209..53ddbc760af7be17d91b1c383fe2e4e62ab2e0a2 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 34ea359b370ebca7c74b6470d78bc0731d521c57..8bc9f5fbbaeb25a07b29c3ea27245afac0e75d4b 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 6be3e0760c26f0d7b0b3750d165d527b64aaff88..827629c9aad76a0a9a6a549e658160c18b5a4d53 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 b3379d6a5c57214cadb73f8f6dffc37b83ccb6e9..54dd031394f6d49e1229ff003b9b54abbcffa899 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 },
+       {}
+};
+
 
 /**
  * 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 d71d9f3723590cd659323e58338ca0c2a7ee9319..501d167368d2f22636d460ee7cf9f6b5973276c1 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, 7, },
+       {}
+};
+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 8f9b2ceeec850305feae1b8fefef0f7a166cc265..c0e816468e300f242735f4825d09b9d291a9b522 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 1e205e6b1727e5e1f78260b7baa1faa1ca27d2b3..e42e073cd9b87d8789b08fa0e5804289d1405ebf 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 6ea3455def2165e970ee3e35e6910f2598af8218..3a953d519f4610d3d84b80e031a2d2410bb80d3d 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 a748ce782fee7bbb7da944d4a76dec63c472cf37..7432b3a72cd475d48421344fe3240cf6a77c1262 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 8af2d2fd9d511913f4648f9f13e90f21d09b36d3..7047821a7f8a5fd966521ba5a8d48bf7664d2d54 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 c76ead3490bf73bc1a831508f8a3e826de256c04..6a457fcaaad5f2c75bca49c818db20a55a91306c 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) {