Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpufreq: Add support for x86 cpuinfo auto loading v4

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>

authored by

Andi Kleen and committed by
Greg Kroah-Hartman
fa8031ae 2f1e097e

+142 -61
+8
drivers/cpufreq/cpufreq-nforce2.c
··· 385 385 .owner = THIS_MODULE, 386 386 }; 387 387 388 + #ifdef MODULE 389 + static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = { 390 + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2 }, 391 + {} 392 + }; 393 + MODULE_DEVICE_TABLE(pci, nforce2_ids); 394 + #endif 395 + 388 396 /** 389 397 * nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic 390 398 *
+11 -9
drivers/cpufreq/e_powersaver.c
··· 16 16 #include <linux/io.h> 17 17 #include <linux/delay.h> 18 18 19 + #include <asm/cpu_device_id.h> 19 20 #include <asm/msr.h> 20 21 #include <asm/tsc.h> 21 22 ··· 438 437 .attr = eps_attr, 439 438 }; 440 439 440 + 441 + /* This driver will work only on Centaur C7 processors with 442 + * Enhanced SpeedStep/PowerSaver registers */ 443 + static const struct x86_cpu_id eps_cpu_id[] = { 444 + { X86_VENDOR_CENTAUR, 6, X86_MODEL_ANY, X86_FEATURE_EST }, 445 + {} 446 + }; 447 + MODULE_DEVICE_TABLE(x86cpu, eps_cpu_id); 448 + 441 449 static int __init eps_init(void) 442 450 { 443 - struct cpuinfo_x86 *c = &cpu_data(0); 444 - 445 - /* This driver will work only on Centaur C7 processors with 446 - * Enhanced SpeedStep/PowerSaver registers */ 447 - if (c->x86_vendor != X86_VENDOR_CENTAUR 448 - || c->x86 != 6 || c->x86_model < 10) 451 + if (!x86_match_cpu(eps_cpu_id) || boot_cpu_data.x86_model < 10) 449 452 return -ENODEV; 450 - if (!cpu_has(c, X86_FEATURE_EST)) 451 - return -ENODEV; 452 - 453 453 if (cpufreq_register_driver(&eps_driver)) 454 454 return -EINVAL; 455 455 return 0;
+7 -7
drivers/cpufreq/elanfreq.c
··· 23 23 #include <linux/delay.h> 24 24 #include <linux/cpufreq.h> 25 25 26 + #include <asm/cpu_device_id.h> 26 27 #include <asm/msr.h> 27 28 #include <linux/timex.h> 28 29 #include <linux/io.h> ··· 278 277 .attr = elanfreq_attr, 279 278 }; 280 279 280 + static const struct x86_cpu_id elan_id[] = { 281 + { X86_VENDOR_AMD, 4, 10, }, 282 + {} 283 + }; 284 + MODULE_DEVICE_TABLE(x86cpu, elan_id); 281 285 282 286 static int __init elanfreq_init(void) 283 287 { 284 - struct cpuinfo_x86 *c = &cpu_data(0); 285 - 286 - /* Test if we have the right hardware */ 287 - if ((c->x86_vendor != X86_VENDOR_AMD) || 288 - (c->x86 != 4) || (c->x86_model != 10)) { 289 - printk(KERN_INFO "elanfreq: error: no Elan processor found!\n"); 288 + if (!x86_match_cpu(elan_id)) 290 289 return -ENODEV; 291 - } 292 290 return cpufreq_register_driver(&elanfreq_driver); 293 291 } 294 292
+2 -7
drivers/cpufreq/gx-suspmod.c
··· 82 82 #include <linux/errno.h> 83 83 #include <linux/slab.h> 84 84 85 + #include <asm/cpu_device_id.h> 85 86 #include <asm/processor-cyrix.h> 86 87 87 88 /* PCI config registers, all at F0 */ ··· 172 171 { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), }, 173 172 { 0, }, 174 173 }; 174 + MODULE_DEVICE_TABLE(gx_chipset_tbl); 175 175 176 176 static void gx_write_byte(int reg, int value) 177 177 { ··· 186 184 static __init struct pci_dev *gx_detect_chipset(void) 187 185 { 188 186 struct pci_dev *gx_pci = NULL; 189 - 190 - /* check if CPU is a MediaGX or a Geode. */ 191 - if ((boot_cpu_data.x86_vendor != X86_VENDOR_NSC) && 192 - (boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) { 193 - pr_debug("error: no MediaGX/Geode processor found!\n"); 194 - return NULL; 195 - } 196 187 197 188 /* detect which companion chip is used */ 198 189 for_each_pci_dev(gx_pci) {
+7 -1
drivers/cpufreq/longhaul.c
··· 35 35 #include <linux/acpi.h> 36 36 37 37 #include <asm/msr.h> 38 + #include <asm/cpu_device_id.h> 38 39 #include <acpi/processor.h> 39 40 40 41 #include "longhaul.h" ··· 952 951 .attr = longhaul_attr, 953 952 }; 954 953 954 + static const struct x86_cpu_id longhaul_id[] = { 955 + { X86_VENDOR_CENTAUR, 6 }, 956 + {} 957 + }; 958 + MODULE_DEVICE_TABLE(x86cpu, longhaul_id); 955 959 956 960 static int __init longhaul_init(void) 957 961 { 958 962 struct cpuinfo_x86 *c = &cpu_data(0); 959 963 960 - if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6) 964 + if (!x86_match_cpu(longhaul_id)) 961 965 return -ENODEV; 962 966 963 967 #ifdef CONFIG_SMP
+8 -5
drivers/cpufreq/longrun.c
··· 14 14 15 15 #include <asm/msr.h> 16 16 #include <asm/processor.h> 17 + #include <asm/cpu_device_id.h> 17 18 18 19 static struct cpufreq_driver longrun_driver; 19 20 ··· 289 288 .owner = THIS_MODULE, 290 289 }; 291 290 291 + static const struct x86_cpu_id longrun_ids[] = { 292 + { X86_VENDOR_TRANSMETA, X86_FAMILY_ANY, X86_MODEL_ANY, 293 + X86_FEATURE_LONGRUN }, 294 + {} 295 + }; 296 + MODULE_DEVICE_TABLE(x86cpu, longrun_ids); 292 297 293 298 /** 294 299 * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver ··· 303 296 */ 304 297 static int __init longrun_init(void) 305 298 { 306 - struct cpuinfo_x86 *c = &cpu_data(0); 307 - 308 - if (c->x86_vendor != X86_VENDOR_TRANSMETA || 309 - !cpu_has(c, X86_FEATURE_LONGRUN)) 299 + if (!x86_match_cpu(longrun_ids)) 310 300 return -ENODEV; 311 - 312 301 return cpufreq_register_driver(&longrun_driver); 313 302 } 314 303
+11 -6
drivers/cpufreq/p4-clockmod.c
··· 31 31 #include <asm/processor.h> 32 32 #include <asm/msr.h> 33 33 #include <asm/timer.h> 34 + #include <asm/cpu_device_id.h> 34 35 35 36 #include "speedstep-lib.h" 36 37 ··· 290 289 .attr = p4clockmod_attr, 291 290 }; 292 291 292 + static const struct x86_cpu_id cpufreq_p4_id[] = { 293 + { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_ACC }, 294 + {} 295 + }; 296 + 297 + /* 298 + * Intentionally no MODULE_DEVICE_TABLE here: this driver should not 299 + * be auto loaded. Please don't add one. 300 + */ 293 301 294 302 static int __init cpufreq_p4_init(void) 295 303 { 296 - struct cpuinfo_x86 *c = &cpu_data(0); 297 304 int ret; 298 305 299 306 /* 300 307 * THERM_CONTROL is architectural for IA32 now, so 301 308 * we can rely on the capability checks 302 309 */ 303 - if (c->x86_vendor != X86_VENDOR_INTEL) 304 - return -ENODEV; 305 - 306 - if (!test_cpu_cap(c, X86_FEATURE_ACPI) || 307 - !test_cpu_cap(c, X86_FEATURE_ACC)) 310 + if (!x86_match_cpu(cpufreq_p4_id) || !boot_cpu_has(X86_FEATURE_ACPI)) 308 311 return -ENODEV; 309 312 310 313 ret = cpufreq_register_driver(&p4clockmod_driver);
+8 -4
drivers/cpufreq/powernow-k6.c
··· 16 16 #include <linux/timex.h> 17 17 #include <linux/io.h> 18 18 19 + #include <asm/cpu_device_id.h> 19 20 #include <asm/msr.h> 20 21 21 22 #define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long ··· 211 210 .attr = powernow_k6_attr, 212 211 }; 213 212 213 + static const struct x86_cpu_id powernow_k6_ids[] = { 214 + { X86_VENDOR_AMD, 5, 12 }, 215 + { X86_VENDOR_AMD, 5, 13 }, 216 + {} 217 + }; 218 + 214 219 215 220 /** 216 221 * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver ··· 227 220 */ 228 221 static int __init powernow_k6_init(void) 229 222 { 230 - struct cpuinfo_x86 *c = &cpu_data(0); 231 - 232 - if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) || 233 - ((c->x86_model != 12) && (c->x86_model != 13))) 223 + if (!x86_match_cpu(powernow_k6_ids)) 234 224 return -ENODEV; 235 225 236 226 if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) {
+8 -6
drivers/cpufreq/powernow-k7.c
··· 28 28 #include <asm/timer.h> /* Needed for recalibrate_cpu_khz() */ 29 29 #include <asm/msr.h> 30 30 #include <asm/system.h> 31 + #include <asm/cpu_device_id.h> 31 32 32 33 #ifdef CONFIG_X86_POWERNOW_K7_ACPI 33 34 #include <linux/acpi.h> ··· 111 110 return delta < 5; 112 111 } 113 112 113 + static const struct x86_cpu_id powernow_k7_cpuids[] = { 114 + { X86_VENDOR_AMD, 7, }, 115 + {} 116 + }; 117 + MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids); 118 + 114 119 static int check_powernow(void) 115 120 { 116 121 struct cpuinfo_x86 *c = &cpu_data(0); 117 122 unsigned int maxei, eax, ebx, ecx, edx; 118 123 119 - if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 6)) { 120 - #ifdef MODULE 121 - printk(KERN_INFO PFX "This module only works with " 122 - "AMD K7 CPUs\n"); 123 - #endif 124 + if (!x86_match_cpu(powernow_k7_cpuids)) 124 125 return 0; 125 - } 126 126 127 127 /* Get maximum capabilities */ 128 128 maxei = cpuid_eax(0x80000000);
+13 -6
drivers/cpufreq/powernow-k8.c
··· 40 40 #include <linux/delay.h> 41 41 42 42 #include <asm/msr.h> 43 + #include <asm/cpu_device_id.h> 43 44 44 45 #include <linux/acpi.h> 45 46 #include <linux/mutex.h> ··· 521 520 return 0; 522 521 } 523 522 523 + static const struct x86_cpu_id powernow_k8_ids[] = { 524 + /* IO based frequency switching */ 525 + { X86_VENDOR_AMD, 0xf }, 526 + /* MSR based frequency switching supported */ 527 + X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE), 528 + {} 529 + }; 530 + MODULE_DEVICE_TABLE(x86cpu, powernow_k8_ids); 531 + 524 532 static void check_supported_cpu(void *_rc) 525 533 { 526 534 u32 eax, ebx, ecx, edx; ··· 537 527 538 528 *rc = -ENODEV; 539 529 540 - if (__this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_AMD) 541 - return; 542 - 543 530 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); 544 - if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) && 545 - ((eax & CPUID_XFAM) < CPUID_XFAM_10H)) 546 - return; 547 531 548 532 if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) { 549 533 if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || ··· 1556 1552 { 1557 1553 unsigned int i, supported_cpus = 0, cpu; 1558 1554 int rv; 1555 + 1556 + if (!x86_match_cpu(powernow_k8_ids)) 1557 + return -ENODEV; 1559 1558 1560 1559 for_each_online_cpu(i) { 1561 1560 int rc;
+8 -6
drivers/cpufreq/sc520_freq.c
··· 22 22 #include <linux/timex.h> 23 23 #include <linux/io.h> 24 24 25 + #include <asm/cpu_device_id.h> 25 26 #include <asm/msr.h> 26 27 27 28 #define MMCR_BASE 0xfffef000 /* The default base address */ ··· 151 150 .attr = sc520_freq_attr, 152 151 }; 153 152 153 + static const struct x86_cpu_id sc520_ids[] = { 154 + { X86_VENDOR_AMD, 4, 9 }, 155 + {} 156 + }; 157 + MODULE_DEVICE_TABLE(x86cpu, sc520_ids); 154 158 155 159 static int __init sc520_freq_init(void) 156 160 { 157 - struct cpuinfo_x86 *c = &cpu_data(0); 158 161 int err; 159 162 160 - /* Test if we have the right hardware */ 161 - if (c->x86_vendor != X86_VENDOR_AMD || 162 - c->x86 != 4 || c->x86_model != 9) { 163 - pr_debug("no Elan SC520 processor found!\n"); 163 + if (!x86_match_cpu(sc520_ids)) 164 164 return -ENODEV; 165 - } 165 + 166 166 cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1); 167 167 if (!cpuctl) { 168 168 printk(KERN_ERR "sc520_freq: error: failed to remap memory\n");
+20 -4
drivers/cpufreq/speedstep-centrino.c
··· 25 25 #include <asm/msr.h> 26 26 #include <asm/processor.h> 27 27 #include <asm/cpufeature.h> 28 + #include <asm/cpu_device_id.h> 28 29 29 30 #define PFX "speedstep-centrino: " 30 31 #define MAINTAINER "cpufreq@vger.kernel.org" ··· 596 595 .owner = THIS_MODULE, 597 596 }; 598 597 598 + /* 599 + * This doesn't replace the detailed checks above because 600 + * the generic CPU IDs don't have a way to match for steppings 601 + * or ASCII model IDs. 602 + */ 603 + static const struct x86_cpu_id centrino_ids[] = { 604 + { X86_VENDOR_INTEL, 6, 9, X86_FEATURE_EST }, 605 + { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, 606 + { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, 607 + { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, 608 + { X86_VENDOR_INTEL, 15, 3, X86_FEATURE_EST }, 609 + { X86_VENDOR_INTEL, 15, 4, X86_FEATURE_EST }, 610 + {} 611 + }; 612 + #if 0 613 + /* Autoload or not? Do not for now. */ 614 + MODULE_DEVICE_TABLE(x86cpu, centrino_ids); 615 + #endif 599 616 600 617 /** 601 618 * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver ··· 631 612 */ 632 613 static int __init centrino_init(void) 633 614 { 634 - struct cpuinfo_x86 *cpu = &cpu_data(0); 635 - 636 - if (!cpu_has(cpu, X86_FEATURE_EST)) 615 + if (!x86_match_cpu(centrino_ids)) 637 616 return -ENODEV; 638 - 639 617 return cpufreq_register_driver(&centrino_driver); 640 618 } 641 619
+15
drivers/cpufreq/speedstep-ich.c
··· 25 25 #include <linux/pci.h> 26 26 #include <linux/sched.h> 27 27 28 + #include <asm/cpu_device_id.h> 29 + 28 30 #include "speedstep-lib.h" 29 31 30 32 ··· 390 388 .attr = speedstep_attr, 391 389 }; 392 390 391 + static const struct x86_cpu_id ss_smi_ids[] = { 392 + { X86_VENDOR_INTEL, 6, 0xb, }, 393 + { X86_VENDOR_INTEL, 6, 0x8, }, 394 + { X86_VENDOR_INTEL, 15, 2 }, 395 + {} 396 + }; 397 + #if 0 398 + /* Autoload or not? Do not for now. */ 399 + MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids); 400 + #endif 393 401 394 402 /** 395 403 * speedstep_init - initializes the SpeedStep CPUFreq driver ··· 410 398 */ 411 399 static int __init speedstep_init(void) 412 400 { 401 + if (!x86_match_cpu(ss_smi_ids)) 402 + return -ENODEV; 403 + 413 404 /* detect processor */ 414 405 speedstep_processor = speedstep_detect_processor(); 415 406 if (!speedstep_processor) {
+1
drivers/cpufreq/speedstep-lib.c
··· 249 249 * DETECT SPEEDSTEP-CAPABLE PROCESSOR * 250 250 *********************************************************************/ 251 251 252 + /* Keep in sync with the x86_cpu_id tables in the different modules */ 252 253 unsigned int speedstep_detect_processor(void) 253 254 { 254 255 struct cpuinfo_x86 *c = &cpu_data(0);
+15
drivers/cpufreq/speedstep-smi.c
··· 20 20 #include <linux/delay.h> 21 21 #include <linux/io.h> 22 22 #include <asm/ist.h> 23 + #include <asm/cpu_device_id.h> 23 24 24 25 #include "speedstep-lib.h" 25 26 ··· 380 379 .attr = speedstep_attr, 381 380 }; 382 381 382 + static const struct x86_cpu_id ss_smi_ids[] = { 383 + { X86_VENDOR_INTEL, 6, 0xb, }, 384 + { X86_VENDOR_INTEL, 6, 0x8, }, 385 + { X86_VENDOR_INTEL, 15, 2 }, 386 + {} 387 + }; 388 + #if 0 389 + /* Not auto loaded currently */ 390 + MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids); 391 + #endif 392 + 383 393 /** 384 394 * speedstep_init - initializes the SpeedStep CPUFreq driver 385 395 * ··· 400 388 */ 401 389 static int __init speedstep_init(void) 402 390 { 391 + if (!x86_match_cpu(ss_smi_ids)) 392 + return -ENODEV; 393 + 403 394 speedstep_processor = speedstep_detect_processor(); 404 395 405 396 switch (speedstep_processor) {