From b66b8b9a4a79087dde1b358a016e5c8739ccf186 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 26 Jan 2012 00:09:07 +0100 Subject: 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 Signed-off-by: Andi Kleen Signed-off-by: Thomas Renninger Acked-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- drivers/idle/intel_idle.c | 116 ++++++++++++++++++++++++++-------------------- 1 file changed, 66 insertions(+), 50 deletions(-) (limited to 'drivers/idle/intel_idle.c') diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 20bce51c2e8..ef6a409ff1a 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -81,18 +82,23 @@ 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); 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. @@ -319,27 +325,72 @@ 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, +}; + +static const struct idle_cpu idle_cpu_westmere = { + .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_westmere), + ICPU(0x2c, idle_cpu_westmere), + ICPU(0x2f, idle_cpu_westmere), + ICPU(0x1c, idle_cpu_atom), + ICPU(0x26, idle_cpu_lincroft), + ICPU(0x2f, idle_cpu_westmere), + 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 +404,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 +486,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 +538,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; -- cgit v1.2.3-70-g09d2 From e668505c9811411c6096888b43ba104f35c9e9c3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 11 Feb 2012 22:57:38 +0000 Subject: intel_idle: Fix ID for Nehalem-EX Xeon in device ID table Commit b66b8b9a4a79087dde1b358a016e5c8739ccf186 ('intel-idle: convert to x86_cpu_id auto probing') put two entries for model 0x2f (Westmere-EX Xeon) in the device ID table and left out model 0x2e (Nehalem-EX Xeon). Signed-off-by: Ben Hutchings Acked-by: Thomas Renninger Acked-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- drivers/idle/intel_idle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/idle/intel_idle.c') diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 237fe5785f0..a238649e746 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -360,7 +360,7 @@ static const struct x86_cpu_id intel_idle_ids[] = { ICPU(0x1f, idle_cpu_nehalem), ICPU(0x25, idle_cpu_westmere), ICPU(0x2c, idle_cpu_westmere), - ICPU(0x2f, idle_cpu_westmere), + ICPU(0x2e, idle_cpu_westmere), ICPU(0x1c, idle_cpu_atom), ICPU(0x26, idle_cpu_lincroft), ICPU(0x2f, idle_cpu_westmere), -- cgit v1.2.3-70-g09d2 From 8bf11938459ff8ceb8643258d0a35e0f2bc9be17 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 16 Feb 2012 04:13:14 +0000 Subject: intel_idle: Revert change of auto_demotion_disable_flags for Nehalem Commit b66b8b9a4a79087dde1b358a016e5c8739ccf186 ('intel-idle: convert to x86_cpu_id auto probing') added a distinction between Nehalem and Westemere processors and changed auto_demotion_disable_flags for the former to 0. This was not explained in the commit message, so change it back. Signed-off-by: Ben Hutchings Acked-by: Thomas Renninger Acked-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- drivers/idle/intel_idle.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/idle/intel_idle.c') diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index a238649e746..1c15e9b3357 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -331,10 +331,6 @@ static void auto_demotion_disable(void *dummy) static const struct idle_cpu idle_cpu_nehalem = { .state_table = nehalem_cstates, -}; - -static const struct idle_cpu idle_cpu_westmere = { - .state_table = nehalem_cstates, .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, }; @@ -358,12 +354,12 @@ 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_westmere), - ICPU(0x2c, idle_cpu_westmere), - ICPU(0x2e, idle_cpu_westmere), + 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_westmere), + ICPU(0x2f, idle_cpu_nehalem), ICPU(0x2a, idle_cpu_snb), ICPU(0x2d, idle_cpu_snb), {} -- cgit v1.2.3-70-g09d2 From dc716e96f5a467835e8121e1caaf25d66a901cb3 Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Wed, 21 Mar 2012 16:33:43 -0700 Subject: drivers/idle/intel_idle.c: fix confusing code identation Fix a code indentation in the function intel_idle_cpu_init that looks confusing.o Suggested-by: Srivatsa S. Bhat Reviewed-by: Srivatsa S. Bhat Signed-off-by: Marcos Paulo de Souza Cc: "Brown, Len" Cc: Len Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/idle/intel_idle.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/idle/intel_idle.c') diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 1c15e9b3357..d0f59c3f87e 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -507,8 +507,7 @@ int intel_idle_cpu_init(int cpu) int num_substates; if (cstate > max_cstate) { - printk(PREFIX "max_cstate %d reached\n", - max_cstate); + printk(PREFIX "max_cstate %d reached\n", max_cstate); break; } @@ -524,8 +523,9 @@ int intel_idle_cpu_init(int cpu) dev->states_usage[dev->state_count].driver_data = (void *)get_driver_data(cstate); - dev->state_count += 1; - } + dev->state_count += 1; + } + dev->cpu = cpu; if (cpuidle_register_device(dev)) { -- cgit v1.2.3-70-g09d2