diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig b/arch/x86/kernel/cpu/cpufreq/Kconfig index 151eda0a23fc40be379c71b409b6cf846d0d3e2f..cb7a5715596dfa448e56eef69c92125afc9f0f77 100644 --- a/arch/x86/kernel/cpu/cpufreq/Kconfig +++ b/arch/x86/kernel/cpu/cpufreq/Kconfig @@ -29,7 +29,7 @@ config X86_ACPI_CPUFREQ config ELAN_CPUFREQ tristate "AMD Elan SC400 and SC410" select CPU_FREQ_TABLE - depends on X86_32 && X86_ELAN + depends on X86_ELAN ---help--- This adds the CPUFreq driver for AMD Elan SC400 and SC410 processors. @@ -45,7 +45,7 @@ config ELAN_CPUFREQ config SC520_CPUFREQ tristate "AMD Elan SC520" select CPU_FREQ_TABLE - depends on X86_32 && X86_ELAN + depends on X86_ELAN ---help--- This adds the CPUFreq driver for AMD Elan SC520 processor. diff --git a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c index 326a4c81f68493cd8802ce13093689858577ad63..39f8cb18296c68fc74fa999a195f0d1fa20a9787 100644 --- a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c +++ b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c @@ -23,6 +23,7 @@ #define EPS_BRAND_C7 1 #define EPS_BRAND_EDEN 2 #define EPS_BRAND_C3 3 +#define EPS_BRAND_C7D 4 struct eps_cpu_data { u32 fsb; @@ -54,6 +55,7 @@ static int eps_set_state(struct eps_cpu_data *centaur, { struct cpufreq_freqs freqs; u32 lo, hi; + u8 current_multiplier, current_voltage; int err = 0; int i; @@ -93,6 +95,15 @@ static int eps_set_state(struct eps_cpu_data *centaur, rdmsr(MSR_IA32_PERF_STATUS, lo, hi); freqs.new = centaur->fsb * ((lo >> 8) & 0xff); + /* Print voltage and multiplier */ + rdmsr(MSR_IA32_PERF_STATUS, lo, hi); + current_voltage = lo & 0xff; + printk(KERN_INFO "eps: Current voltage = %dmV\n", + current_voltage * 16 + 700); + current_multiplier = (lo >> 8) & 0xff; + printk(KERN_INFO "eps: Current multiplier = %d\n", + current_multiplier); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return err; } @@ -141,9 +152,10 @@ static int eps_cpu_init(struct cpufreq_policy *policy) u8 current_multiplier, current_voltage; u8 max_multiplier, max_voltage; u8 min_multiplier, min_voltage; - u8 brand; + u8 brand = 0; u32 fsb; struct eps_cpu_data *centaur; + struct cpuinfo_x86 *c = &cpu_data(0); struct cpufreq_frequency_table *f_table; int k, step, voltage; int ret; @@ -153,21 +165,36 @@ static int eps_cpu_init(struct cpufreq_policy *policy) return -ENODEV; /* Check brand */ - printk("eps: Detected VIA "); - rdmsr(0x1153, lo, hi); - brand = (((lo >> 2) ^ lo) >> 18) & 3; + printk(KERN_INFO "eps: Detected VIA "); + + switch (c->x86_model) { + case 10: + rdmsr(0x1153, lo, hi); + brand = (((lo >> 2) ^ lo) >> 18) & 3; + printk(KERN_CONT "Model A "); + break; + case 13: + rdmsr(0x1154, lo, hi); + brand = (((lo >> 4) ^ (lo >> 2))) & 0x000000ff; + printk(KERN_CONT "Model D "); + break; + } + switch(brand) { case EPS_BRAND_C7M: - printk("C7-M\n"); + printk(KERN_CONT "C7-M\n"); break; case EPS_BRAND_C7: - printk("C7\n"); + printk(KERN_CONT "C7\n"); break; case EPS_BRAND_EDEN: - printk("Eden\n"); + printk(KERN_CONT "Eden\n"); + break; + case EPS_BRAND_C7D: + printk(KERN_CONT "C7-D\n"); break; case EPS_BRAND_C3: - printk("C3\n"); + printk(KERN_CONT "C3\n"); return -ENODEV; break; } @@ -179,7 +206,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Can be locked at 0 */ rdmsrl(MSR_IA32_MISC_ENABLE, val); if (!(val & 1 << 16)) { - printk("eps: Can't enable Enhanced PowerSaver\n"); + printk(KERN_INFO "eps: Can't enable Enhanced PowerSaver\n"); return -ENODEV; } } @@ -187,19 +214,19 @@ static int eps_cpu_init(struct cpufreq_policy *policy) /* Print voltage and multiplier */ rdmsr(MSR_IA32_PERF_STATUS, lo, hi); current_voltage = lo & 0xff; - printk("eps: Current voltage = %dmV\n", current_voltage * 16 + 700); + printk(KERN_INFO "eps: Current voltage = %dmV\n", current_voltage * 16 + 700); current_multiplier = (lo >> 8) & 0xff; - printk("eps: Current multiplier = %d\n", current_multiplier); + printk(KERN_INFO "eps: Current multiplier = %d\n", current_multiplier); /* Print limits */ max_voltage = hi & 0xff; - printk("eps: Highest voltage = %dmV\n", max_voltage * 16 + 700); + printk(KERN_INFO "eps: Highest voltage = %dmV\n", max_voltage * 16 + 700); max_multiplier = (hi >> 8) & 0xff; - printk("eps: Highest multiplier = %d\n", max_multiplier); + printk(KERN_INFO "eps: Highest multiplier = %d\n", max_multiplier); min_voltage = (hi >> 16) & 0xff; - printk("eps: Lowest voltage = %dmV\n", min_voltage * 16 + 700); + printk(KERN_INFO "eps: Lowest voltage = %dmV\n", min_voltage * 16 + 700); min_multiplier = (hi >> 24) & 0xff; - printk("eps: Lowest multiplier = %d\n", min_multiplier); + printk(KERN_INFO "eps: Lowest multiplier = %d\n", min_multiplier); /* Sanity checks */ if (current_multiplier == 0 || max_multiplier == 0 @@ -208,7 +235,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) if (current_multiplier > max_multiplier || max_multiplier <= min_multiplier) return -EINVAL; - if (current_voltage > 0x1c || max_voltage > 0x1c) + if (current_voltage > 0x1f || max_voltage > 0x1f) return -EINVAL; if (max_voltage < min_voltage) return -EINVAL; @@ -310,7 +337,7 @@ static int __init eps_init(void) /* 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) + || c->x86 != 6 || c->x86_model < 10) return -ENODEV; if (!cpu_has(c, X86_FEATURE_EST)) return -ENODEV; diff --git a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c index 2ed7db2fd257b3a25c78dd61dd48683bb60a49f7..9d9eae82e60fae3baec7333269ddb6c46b7d1d27 100644 --- a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c +++ b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c @@ -181,8 +181,8 @@ 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 ((current_cpu_data.x86_vendor != X86_VENDOR_NSC) && - (current_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) { + if ((boot_cpu_data.x86_vendor != X86_VENDOR_NSC) && + (boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) { dprintk("error: no MediaGX/Geode processor found!\n"); return NULL; } diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c index b5a9863d6cdc336ce7b13f5c9d797944b179cbc6..0a61159d7b71389c8e8bcdbae7b913463b0f318c 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c @@ -460,7 +460,7 @@ static int powernow_decode_bios (int maxfid, int startvid) latency = psb->settlingtime; if (latency < 100) { - printk (KERN_INFO PFX "BIOS set settling time to %d microseconds." + printk(KERN_INFO PFX "BIOS set settling time to %d microseconds. " "Should be at least 100. Correcting.\n", latency); latency = 100; } diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 5affe91ca1e5964ff9bd309c78c3619f04379c7b..c99d59d8ef2ea46694ac8b3da1cb07de2714cf10 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -578,10 +578,9 @@ static void print_basics(struct powernow_k8_data *data) for (j = 0; j < data->numps; j++) { if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) { if (cpu_family == CPU_HW_PSTATE) { - printk(KERN_INFO PFX " %d : fid 0x%x did 0x%x (%d MHz)\n", + printk(KERN_INFO PFX " %d : pstate %d (%d MHz)\n", j, - (data->powernow_table[j].index & 0xff00) >> 8, - (data->powernow_table[j].index & 0xff0000) >> 16, + data->powernow_table[j].index, data->powernow_table[j].frequency/1000); } else { printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", @@ -1235,8 +1234,10 @@ static unsigned int powernowk8_get (unsigned int cpu) struct powernow_k8_data *data; cpumask_t oldmask = current->cpus_allowed; unsigned int khz = 0; + unsigned int first; - data = per_cpu(powernow_data, first_cpu(per_cpu(cpu_core_map, cpu))); + first = first_cpu(per_cpu(cpu_core_map, cpu)); + data = per_cpu(powernow_data, first); if (!data) return -EINVAL; diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h index afd2b520d35c6258a25a2bc0f804279b647ae430..ab48cfed4d96ce5629e29f3a21ffd9c3e25d8a21 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h @@ -47,7 +47,7 @@ struct powernow_k8_data { #define CPUID_XFAM 0x0ff00000 /* extended family */ #define CPUID_XFAM_K8 0 #define CPUID_XMOD 0x000f0000 /* extended model */ -#define CPUID_XMOD_REV_MASK 0x00080000 +#define CPUID_XMOD_REV_MASK 0x000c0000 #define CPUID_XFAM_10H 0x00100000 /* family 0x10 */ #define CPUID_USE_XFAM_XMOD 0x00000f00 #define CPUID_GET_MAX_CAPABILITIES 0x80000000 diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 721f86f4f0085d3a4caf11c7365ae18643825c84..c159ae64eeb2cf791d8aa36036e0480b8d3cf487 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -9,9 +9,6 @@ config CPU_FREQ clock speed, you need to either enable a dynamic cpufreq governor (see below) after boot, or use a userspace tool. - To compile this driver as a module, choose M here: the - module will be called cpufreq. - For details, take a look at . If in doubt, say N. diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b730d670952957871f2eecf3f35989e673c70855..64926aa990dbc024b46aeaca71c76c8d7a1ee7a5 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -287,7 +287,7 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) if (!l_p_j_ref_freq) { l_p_j_ref = loops_per_jiffy; l_p_j_ref_freq = ci->old; - dprintk("saving %lu as reference value for loops_per_jiffy;" + dprintk("saving %lu as reference value for loops_per_jiffy; " "freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq); } if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || @@ -295,7 +295,7 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) { loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); - dprintk("scaling loops_per_jiffy to %lu" + dprintk("scaling loops_per_jiffy to %lu " "for frequency %u kHz\n", loops_per_jiffy, ci->new); } } @@ -601,6 +601,31 @@ static ssize_t show_affected_cpus (struct cpufreq_policy * policy, char *buf) return i; } +static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + unsigned int freq = 0; + unsigned int ret; + + if (!policy->governor->store_setspeed) + return -EINVAL; + + ret = sscanf(buf, "%u", &freq); + if (ret != 1) + return -EINVAL; + + policy->governor->store_setspeed(policy, freq); + + return count; +} + +static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf) +{ + if (!policy->governor->show_setspeed) + return sprintf(buf, "\n"); + + return policy->governor->show_setspeed(policy, buf); +} #define define_one_ro(_name) \ static struct freq_attr _name = \ @@ -624,6 +649,7 @@ define_one_ro(affected_cpus); define_one_rw(scaling_min_freq); define_one_rw(scaling_max_freq); define_one_rw(scaling_governor); +define_one_rw(scaling_setspeed); static struct attribute * default_attrs[] = { &cpuinfo_min_freq.attr, @@ -634,6 +660,7 @@ static struct attribute * default_attrs[] = { &scaling_governor.attr, &scaling_driver.attr, &scaling_available_governors.attr, + &scaling_setspeed.attr, NULL }; @@ -1313,7 +1340,7 @@ static int cpufreq_resume(struct sys_device * sysdev) struct cpufreq_freqs freqs; if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN)) - dprintk("Warning: CPU frequency" + dprintk("Warning: CPU frequency " "is %u, cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur); diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index f8cdde4bf6cd86030a8f829d00fdac862d5847f2..cb2ac01a41a1c55a0faa2480d823aa91b7b3b001 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -65,12 +65,12 @@ static struct notifier_block userspace_cpufreq_notifier_block = { /** * cpufreq_set - set the CPU frequency + * @policy: pointer to policy struct where freq is being set * @freq: target frequency in kHz - * @cpu: CPU for which the frequency is to be set * * Sets the CPU frequency to freq. */ -static int cpufreq_set(unsigned int freq, struct cpufreq_policy *policy) +static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq) { int ret = -EINVAL; @@ -102,34 +102,11 @@ static int cpufreq_set(unsigned int freq, struct cpufreq_policy *policy) } -/************************** sysfs interface ************************/ -static ssize_t show_speed (struct cpufreq_policy *policy, char *buf) +static ssize_t show_speed(struct cpufreq_policy *policy, char *buf) { - return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]); + return sprintf(buf, "%u\n", cpu_cur_freq[policy->cpu]); } -static ssize_t -store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) -{ - unsigned int freq = 0; - unsigned int ret; - - ret = sscanf (buf, "%u", &freq); - if (ret != 1) - return -EINVAL; - - cpufreq_set(freq, policy); - - return count; -} - -static struct freq_attr freq_attr_scaling_setspeed = -{ - .attr = { .name = "scaling_setspeed", .mode = 0644 }, - .show = show_speed, - .store = store_speed, -}; - static int cpufreq_governor_userspace(struct cpufreq_policy *policy, unsigned int event) { @@ -142,10 +119,6 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, return -EINVAL; BUG_ON(!policy->cur); mutex_lock(&userspace_mutex); - rc = sysfs_create_file (&policy->kobj, - &freq_attr_scaling_setspeed.attr); - if (rc) - goto start_out; if (cpus_using_userspace_governor == 0) { cpufreq_register_notifier( @@ -160,7 +133,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, cpu_cur_freq[cpu] = policy->cur; cpu_set_freq[cpu] = policy->cur; dprintk("managing cpu %u started (%u - %u kHz, currently %u kHz)\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]); -start_out: + mutex_unlock(&userspace_mutex); break; case CPUFREQ_GOV_STOP: @@ -176,7 +149,6 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, cpu_min_freq[cpu] = 0; cpu_max_freq[cpu] = 0; cpu_set_freq[cpu] = 0; - sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); dprintk("managing cpu %u stopped\n", cpu); mutex_unlock(&userspace_mutex); break; @@ -211,6 +183,8 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, struct cpufreq_governor cpufreq_gov_userspace = { .name = "userspace", .governor = cpufreq_governor_userspace, + .store_setspeed = cpufreq_set, + .show_setspeed = show_speed, .owner = THIS_MODULE, }; EXPORT_SYMBOL(cpufreq_gov_userspace); diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 5409f3afb3f85fab2a0b7e160c2972805b0a374d..ae6cd60d5c148979ddf4e911510db24b60e163d5 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -171,7 +171,7 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); static struct cpufreq_frequency_table *show_table[NR_CPUS]; /** - * show_scaling_governor - show the current policy for the specified CPU + * show_available_freqs - show available frequencies for the specified CPU */ static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf) { diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 23932d7741a996721162dc264290adbed5248f6a..ddd8652fc3f38a91d5f471fd70a534e21337ba12 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -167,6 +167,10 @@ struct cpufreq_governor { char name[CPUFREQ_NAME_LEN]; int (*governor) (struct cpufreq_policy *policy, unsigned int event); + ssize_t (*show_setspeed) (struct cpufreq_policy *policy, + char *buf); + int (*store_setspeed) (struct cpufreq_policy *policy, + unsigned int freq); unsigned int max_transition_latency; /* HW must be able to switch to next freq faster than this value in nano secs or we will fallback to performance governor */