[2.5. PATCH] cpufreq: update HyperThreading support in p4-clockmod.c driver

From: Dominik Brodowski (linux@brodo.de)
Date: Fri Nov 01 2002 - 03:22:49 EST


This patch updates the p4-clockmod.c driver to correctly manage
HyperThreading-enabled Pentium IVs as well as those models which do
not support HyperThreading. Additionally, an EXPORT_SYMBOL was
missing. (spotted by Marc-Christian Petersen - thanks!)

         Dominik

diff -ruN linux-2545original/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c linux/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
--- linux-2545original/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Thu Oct 31 12:00:00 2002
+++ linux/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Thu Oct 31 20:00:00 2002
@@ -50,7 +50,6 @@
 MODULE_PARM(stock_freq, "i");
 
 static struct cpufreq_driver *cpufreq_p4_driver;
-static unsigned int cpufreq_p4_old_state = 0;
 
 
 static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
@@ -58,24 +57,50 @@
         u32 l, h;
         unsigned long cpus_allowed;
         struct cpufreq_freqs freqs;
+ int hyperthreading;
+
 
         if (!cpu_online(cpu) || (newstate > DC_DISABLE) ||
                 (newstate == DC_RESV))
                 return -EINVAL;
- cpu = cpu >> 1; /* physical CPU #nr */
+
+ /* switch to physical CPU where state is to be changed*/
+ cpus_allowed = current->cpus_allowed;
+
+ /* hyperthreading? */
+#ifdef CONFIG_SMP
+ hyperthreading = ((cpu_has_ht) && (smp_num_siblings == 2));
+#else
+ hyperthreading = 0;
+#endif
+ if (hyperthreading) {
+ unsigned int phys_cpu = cpu / 2;
+ set_cpus_allowed(current, 3 << (phys_cpu));
+ BUG_ON((cpu & ~1) != (smp_processor_id() & ~1));
+ cpu = phys_cpu * 2;
+ } else {
+ set_cpus_allowed(current, 1 << cpu);
+ BUG_ON(cpu != smp_processor_id());
+ }
+ /* get current state */
+ rdmsr(MSR_IA32_THERM_CONTROL, l, h);
+ l = l >> 1;
+ l &= 0x7;
+
+ if (l == newstate) {
+ set_cpus_allowed(current, cpus_allowed);
+ return 0;
+ }
 
         /* notifiers */
- freqs.old = stock_freq * cpufreq_p4_old_state / 8;
+ freqs.old = stock_freq * l / 8;
         freqs.new = stock_freq * newstate / 8;
- freqs.cpu = 2*cpu;
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- freqs.cpu++;
+ freqs.cpu = cpu;
         cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
- /* switch to physical CPU where state is to be changed*/
- cpus_allowed = current->cpus_allowed;
- set_cpus_allowed(current, 3 << (2 * cpu));
- BUG_ON(cpu != (smp_processor_id() >> 1));
+ if (hyperthreading) {
+ freqs.cpu++;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ }
 
         rdmsr(MSR_IA32_THERM_STATUS, l, h);
         if (l & 0x01)
@@ -86,10 +111,10 @@
 
         rdmsr(MSR_IA32_THERM_CONTROL, l, h);
         if (newstate == DC_DISABLE) {
- printk(KERN_INFO PFX "CPU#%d,%d disabling modulation\n", cpu, (cpu + 1));
+ printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu);
                 wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h);
         } else {
- printk(KERN_INFO PFX "CPU#%d,%d setting duty cycle to %d%%\n", cpu, (cpu + 1), ((125 * newstate) / 10));
+ printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", cpu, ((125 * newstate) / 10));
                 /* bits 63 - 5 : reserved
                  * bit 4 : enable/disable
                  * bits 3-1 : duty cycle
@@ -104,9 +129,10 @@
 
         /* notifiers */
         cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- freqs.cpu--;
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- cpufreq_p4_old_state = newstate;
+ if (hyperthreading) {
+ freqs.cpu--;
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
 
         return 0;
 }
@@ -143,9 +169,9 @@
         /* if (number_states == 1) */
         {
                 if (policy->cpu == CPUFREQ_ALL_CPUS) {
- for (i=0; i<(NR_CPUS/2); i++)
- if (cpu_online(2*i))
- cpufreq_p4_setdc((2*i), newstate);
+ for (i=0; i<NR_CPUS; i++)
+ if (cpu_online(i))
+ cpufreq_p4_setdc(i, newstate);
                 } else {
                         cpufreq_p4_setdc(policy->cpu, newstate);
                 }
@@ -235,7 +261,6 @@
         for (i=0;i<NR_CPUS;i++)
                 driver->cpu_cur_freq[i] = stock_freq;
 #endif
- cpufreq_p4_old_state = DC_DISABLE;
 
         driver->verify = &cpufreq_p4_verify;
         driver->setpolicy = &cpufreq_p4_setpolicy;
diff -ruN linux-2545original/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- linux-2545original/arch/i386/kernel/i386_ksyms.c.original Thu Oct 31 12:00:00 2002
+++ linux/arch/i386/kernel/i386_ksyms.c Thu Oct 31 20:00:00 2002
@@ -145,6 +145,7 @@
 
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(cpu_data);
+EXPORT_SYMBOL(smp_num_siblings);
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL(cpu_callout_map);
 EXPORT_SYMBOL_NOVERS(__write_lock_failed);



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Nov 07 2002 - 22:00:19 EST