public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [2.5. PATCH] cpufreq: update HyperThreading support in p4-clockmod.c driver
@ 2002-11-01  8:22 Dominik Brodowski
  0 siblings, 0 replies; 3+ messages in thread
From: Dominik Brodowski @ 2002-11-01  8:22 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel, cpufreq

[-- Attachment #1: Type: text/plain, Size: 4482 bytes --]

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);

[-- Attachment #2: Type: application/pgp-signature, Size: 240 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [2.5. PATCH] cpufreq: update HyperThreading support in  p4-clockmod.c driver
@ 2002-11-01 16:03 James Bottomley
  0 siblings, 0 replies; 3+ messages in thread
From: James Bottomley @ 2002-11-01 16:03 UTC (permalink / raw)
  To: Dominik Brodowski; +Cc: linux-kernel, James.Bottomley

the #define for hyperthreading should be #ifdef CONFIG_X86_HT.

Could you also make the symbol export conditional on this so that subarch's 
which don't have hyperthreading will still compile?

Thanks,

James Bottomley





^ permalink raw reply	[flat|nested] 3+ messages in thread

* [2.5. PATCH] cpufreq: update HyperThreading support in p4-clockmod.c driver
@ 2002-11-03 12:16 Dominik Brodowski
  0 siblings, 0 replies; 3+ messages in thread
From: Dominik Brodowski @ 2002-11-03 12:16 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel, cpufreq

[-- Attachment #1: Type: text/plain, Size: 5152 bytes --]

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

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 - thanks to Venkatesh Pallipadi for
explaining cpu_sibling_map to me. 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	Fri Nov  1 21:12:23 2002
+++ linux/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	Sun Nov  3 12:30:34 2002
@@ -50,32 +50,55 @@
 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)
 {
 	u32 l, h;
 	unsigned long cpus_allowed;
-	struct cpufreq_freqs    freqs;
+	struct cpufreq_freqs freqs;
+	int hyperthreading = 0;
+	int affected_cpu_map = 0;
+	int sibling = 0;
 
 	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;
+
+	/* only run on CPU to be set, or on its sibling */
+	affected_cpu_map = 1 << cpu;
+#ifdef CONFIG_X86_HT
+	hyperthreading = ((cpu_has_ht) && (smp_num_siblings == 2));
+	if (hyperthreading) {
+		sibling = cpu_sibling_map[cpu];
+		affected_cpu_map |= (1 << sibling);
+	}
+#endif
+	set_cpus_allowed(current, affected_cpu_map);
+	BUG_ON(!(smp_processor_id() & affected_cpu_map));
+
+	/* 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 = sibling;
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	}
 
 	rdmsr(MSR_IA32_THERM_STATUS, l, h);
 	if (l & 0x01)
@@ -86,10 +109,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 +127,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 = cpu;
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	}
 
 	return 0;
 }
@@ -123,7 +147,7 @@
 
 	if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
 	{
-		for (i=8; i>0; i++)
+		for (i=8; i>0; i--)
 			if ((policy->min <= ((stock_freq / 8) * i)) &&
 			    (policy->max >= ((stock_freq / 8) * i))) 
 			{
@@ -131,7 +155,7 @@
 				number_states++;
 			}
 	} else {
-		for (i=0; i<=8; i--)
+		for (i=1; i<=8; i++)
 			if ((policy->min <= ((stock_freq / 8) * i)) &&
 			    (policy->max >= ((stock_freq / 8) * i))) 
 			{
@@ -143,9 +167,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 +259,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	Fri Nov  1 21:12:23 2002
+++ linux/arch/i386/kernel/i386_ksyms.c	Fri Nov  1 21:08:44 2002
@@ -143,6 +143,11 @@
 EXPORT_SYMBOL(mmx_copy_page);
 #endif
 
+#ifdef CONFIG_X86_HT
+EXPORT_SYMBOL(smp_num_siblings);
+EXPORT_SYMBOL(cpu_sibling_map);
+#endif
+
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(cpu_data);
 EXPORT_SYMBOL(cpu_online_map);

[-- Attachment #2: Type: application/pgp-signature, Size: 240 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2002-11-03 12:11 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-11-01  8:22 [2.5. PATCH] cpufreq: update HyperThreading support in p4-clockmod.c driver Dominik Brodowski
  -- strict thread matches above, loose matches on Subject: below --
2002-11-01 16:03 James Bottomley
2002-11-03 12:16 Dominik Brodowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox