Commit b66b8b9a4a79087dde1b358a016e5c8739ccf186
Committed by
Greg Kroah-Hartman
1 parent
3bd391f056
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
intel-idle: convert to x86_cpu_id auto probing
With this it should be automatically loaded on suitable systems by udev. The old switch () is replaced with a table based approach, this also cleans up the code. Cc: Len Brown <lenb@kernel.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>
Showing 1 changed file with 66 additions and 50 deletions Side-by-side Diff
drivers/idle/intel_idle.c
... | ... | @@ -62,6 +62,7 @@ |
62 | 62 | #include <linux/notifier.h> |
63 | 63 | #include <linux/cpu.h> |
64 | 64 | #include <linux/module.h> |
65 | +#include <asm/cpu_device_id.h> | |
65 | 66 | #include <asm/mwait.h> |
66 | 67 | #include <asm/msr.h> |
67 | 68 | |
... | ... | @@ -81,6 +82,17 @@ |
81 | 82 | /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ |
82 | 83 | static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */ |
83 | 84 | |
85 | +struct idle_cpu { | |
86 | + struct cpuidle_state *state_table; | |
87 | + | |
88 | + /* | |
89 | + * Hardware C-state auto-demotion may not always be optimal. | |
90 | + * Indicate which enable bits to clear here. | |
91 | + */ | |
92 | + unsigned long auto_demotion_disable_flags; | |
93 | +}; | |
94 | + | |
95 | +static const struct idle_cpu *icpu; | |
84 | 96 | static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; |
85 | 97 | static int intel_idle(struct cpuidle_device *dev, |
86 | 98 | struct cpuidle_driver *drv, int index); |
... | ... | @@ -88,12 +100,6 @@ |
88 | 100 | static struct cpuidle_state *cpuidle_state_table; |
89 | 101 | |
90 | 102 | /* |
91 | - * Hardware C-state auto-demotion may not always be optimal. | |
92 | - * Indicate which enable bits to clear here. | |
93 | - */ | |
94 | -static unsigned long long auto_demotion_disable_flags; | |
95 | - | |
96 | -/* | |
97 | 103 | * Set this flag for states where the HW flushes the TLB for us |
98 | 104 | * and so we don't need cross-calls to keep it consistent. |
99 | 105 | * If this flag is set, SW flushes the TLB, so even if the |
100 | 106 | |
101 | 107 | |
102 | 108 | |
103 | 109 | |
104 | 110 | |
... | ... | @@ -319,28 +325,73 @@ |
319 | 325 | unsigned long long msr_bits; |
320 | 326 | |
321 | 327 | rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); |
322 | - msr_bits &= ~auto_demotion_disable_flags; | |
328 | + msr_bits &= ~(icpu->auto_demotion_disable_flags); | |
323 | 329 | wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); |
324 | 330 | } |
325 | 331 | |
332 | +static const struct idle_cpu idle_cpu_nehalem = { | |
333 | + .state_table = nehalem_cstates, | |
334 | +}; | |
335 | + | |
336 | +static const struct idle_cpu idle_cpu_westmere = { | |
337 | + .state_table = nehalem_cstates, | |
338 | + .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, | |
339 | +}; | |
340 | + | |
341 | +static const struct idle_cpu idle_cpu_atom = { | |
342 | + .state_table = atom_cstates, | |
343 | +}; | |
344 | + | |
345 | +static const struct idle_cpu idle_cpu_lincroft = { | |
346 | + .state_table = atom_cstates, | |
347 | + .auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE, | |
348 | +}; | |
349 | + | |
350 | +static const struct idle_cpu idle_cpu_snb = { | |
351 | + .state_table = snb_cstates, | |
352 | +}; | |
353 | + | |
354 | +#define ICPU(model, cpu) \ | |
355 | + { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } | |
356 | + | |
357 | +static const struct x86_cpu_id intel_idle_ids[] = { | |
358 | + ICPU(0x1a, idle_cpu_nehalem), | |
359 | + ICPU(0x1e, idle_cpu_nehalem), | |
360 | + ICPU(0x1f, idle_cpu_nehalem), | |
361 | + ICPU(0x25, idle_cpu_westmere), | |
362 | + ICPU(0x2c, idle_cpu_westmere), | |
363 | + ICPU(0x2f, idle_cpu_westmere), | |
364 | + ICPU(0x1c, idle_cpu_atom), | |
365 | + ICPU(0x26, idle_cpu_lincroft), | |
366 | + ICPU(0x2f, idle_cpu_westmere), | |
367 | + ICPU(0x2a, idle_cpu_snb), | |
368 | + ICPU(0x2d, idle_cpu_snb), | |
369 | + {} | |
370 | +}; | |
371 | +MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); | |
372 | + | |
326 | 373 | /* |
327 | 374 | * intel_idle_probe() |
328 | 375 | */ |
329 | 376 | static int intel_idle_probe(void) |
330 | 377 | { |
331 | 378 | unsigned int eax, ebx, ecx; |
379 | + const struct x86_cpu_id *id; | |
332 | 380 | |
333 | 381 | if (max_cstate == 0) { |
334 | 382 | pr_debug(PREFIX "disabled\n"); |
335 | 383 | return -EPERM; |
336 | 384 | } |
337 | 385 | |
338 | - if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) | |
386 | + id = x86_match_cpu(intel_idle_ids); | |
387 | + if (!id) { | |
388 | + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && | |
389 | + boot_cpu_data.x86 == 6) | |
390 | + pr_debug(PREFIX "does not run on family %d model %d\n", | |
391 | + boot_cpu_data.x86, boot_cpu_data.x86_model); | |
339 | 392 | return -ENODEV; |
393 | + } | |
340 | 394 | |
341 | - if (!boot_cpu_has(X86_FEATURE_MWAIT)) | |
342 | - return -ENODEV; | |
343 | - | |
344 | 395 | if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) |
345 | 396 | return -ENODEV; |
346 | 397 | |
347 | 398 | |
... | ... | @@ -353,44 +404,9 @@ |
353 | 404 | |
354 | 405 | pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); |
355 | 406 | |
407 | + icpu = (const struct idle_cpu *)id->driver_data; | |
408 | + cpuidle_state_table = icpu->state_table; | |
356 | 409 | |
357 | - if (boot_cpu_data.x86 != 6) /* family 6 */ | |
358 | - return -ENODEV; | |
359 | - | |
360 | - switch (boot_cpu_data.x86_model) { | |
361 | - | |
362 | - case 0x1A: /* Core i7, Xeon 5500 series */ | |
363 | - case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */ | |
364 | - case 0x1F: /* Core i7 and i5 Processor - Nehalem */ | |
365 | - case 0x2E: /* Nehalem-EX Xeon */ | |
366 | - case 0x2F: /* Westmere-EX Xeon */ | |
367 | - case 0x25: /* Westmere */ | |
368 | - case 0x2C: /* Westmere */ | |
369 | - cpuidle_state_table = nehalem_cstates; | |
370 | - auto_demotion_disable_flags = | |
371 | - (NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE); | |
372 | - break; | |
373 | - | |
374 | - case 0x1C: /* 28 - Atom Processor */ | |
375 | - cpuidle_state_table = atom_cstates; | |
376 | - break; | |
377 | - | |
378 | - case 0x26: /* 38 - Lincroft Atom Processor */ | |
379 | - cpuidle_state_table = atom_cstates; | |
380 | - auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE; | |
381 | - break; | |
382 | - | |
383 | - case 0x2A: /* SNB */ | |
384 | - case 0x2D: /* SNB Xeon */ | |
385 | - cpuidle_state_table = snb_cstates; | |
386 | - break; | |
387 | - | |
388 | - default: | |
389 | - pr_debug(PREFIX "does not run on family %d model %d\n", | |
390 | - boot_cpu_data.x86, boot_cpu_data.x86_model); | |
391 | - return -ENODEV; | |
392 | - } | |
393 | - | |
394 | 410 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ |
395 | 411 | lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE; |
396 | 412 | else { |
... | ... | @@ -470,7 +486,7 @@ |
470 | 486 | drv->state_count += 1; |
471 | 487 | } |
472 | 488 | |
473 | - if (auto_demotion_disable_flags) | |
489 | + if (icpu->auto_demotion_disable_flags) | |
474 | 490 | on_each_cpu(auto_demotion_disable, NULL, 1); |
475 | 491 | |
476 | 492 | return 0; |
... | ... | @@ -522,7 +538,7 @@ |
522 | 538 | return -EIO; |
523 | 539 | } |
524 | 540 | |
525 | - if (auto_demotion_disable_flags) | |
541 | + if (icpu->auto_demotion_disable_flags) | |
526 | 542 | smp_call_function_single(cpu, auto_demotion_disable, NULL, 1); |
527 | 543 | |
528 | 544 | return 0; |