All of lore.kernel.org
 help / color / mirror / Atom feed
* patch for P4 TSC problem
@ 2003-12-04  8:47 Li, Shaohua
  2003-12-04 18:23 ` Dominik Brodowski
  0 siblings, 1 reply; 2+ messages in thread
From: Li, Shaohua @ 2003-12-04  8:47 UTC (permalink / raw)
  To: cpufreq

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

Hi,

TSC frequency doesn't change under P4 and above when CPU frequency
changes, which caused some problems. Attached patch will handle this
problem. How about it?

 

Thanks,

Shaohua

 


[-- Attachment #2: tsc.patch --]
[-- Type: application/octet-stream, Size: 1394 bytes --]

--- a/arch/i386/timers/timer_tsc.c	2003-11-25 17:54:06.000000000 +0800
+++ b/arch/i386/timers/timer_tsc.c	2003-11-27 13:15:32.000000000 +0800
@@ -33,6 +33,7 @@
 extern volatile unsigned long jiffies;
 
 static int use_tsc;
+static int variable_tsc_freq = 1;
 /* Number of usecs that the last interrupt was delayed */
 static int delay_at_last_interrupt;
 
@@ -336,7 +337,8 @@
 		cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
 #ifndef CONFIG_SMP
 		if (use_tsc) {
-			fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq);
+			if (variable_tsc_freq)
+				fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq);
 			cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
 			set_cyc2ns_scale(cpu_khz/1000);
 		}
@@ -352,6 +354,13 @@
 };
 #endif
 
+static void __init init_variable_tsc(void)
+{
+	/* P4 and above CPU TSC freq doesn't change when CPU frequency changes*/
+	if ((boot_cpu_data.x86 >= 15) && (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
+		variable_tsc_freq = 0;
+	/* Add support for CPU from non-intel vendor */
+}
 
 static int __init init_tsc(char* override)
 {
@@ -442,6 +451,7 @@
 				printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
 			}
 			set_cyc2ns_scale(cpu_khz/1000);
+			init_variable_tsc();
 			return 0;
 		}
 	}

[-- Attachment #3: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Cpufreq mailing list
Cpufreq@www.linux.org.uk
http://www.linux.org.uk/mailman/listinfo/cpufreq

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

* Re: patch for P4 TSC problem
  2003-12-04  8:47 patch for P4 TSC problem Li, Shaohua
@ 2003-12-04 18:23 ` Dominik Brodowski
  0 siblings, 0 replies; 2+ messages in thread
From: Dominik Brodowski @ 2003-12-04 18:23 UTC (permalink / raw)
  To: Li, Shaohua; +Cc: johnstul, cpufreq

Hi,

On Thu, Dec 04, 2003 at 04:47:30PM +0800, Li, Shaohua wrote:
> TSC frequency doesn't change under P4 and above when CPU frequency
> changes, which caused some problems. Attached patch will handle this
> problem. How about it?

That information is fantastic. Finally the cause of the "lost-ticks" 
which appears on P4 processors is known. 

About the patch: Because of a few, partly unrelated reasons, namely
- cpufreq_register_notifier() shouldn't be called during time_init() 
	because it shouldn't be called while we're in atomic context
- the p4 detection code should only be used when cpufreq is used
- also cyc2us and loops_per_jiffy are affected (I think)
- the patch had an invalid header
I'd prefer the patch posted below.

	Dominik


--- linux/arch/i386/kernel/timers/timer_tsc.c.original	2003-12-04 19:12:23.386582200 +0100
+++ linux/arch/i386/kernel/timers/timer_tsc.c	2003-12-04 19:21:07.494905624 +0100
@@ -306,9 +306,17 @@
 }
 #endif
 
+
 #ifdef CONFIG_CPU_FREQ
+/* If the CPU frequency is scaled, TSC-based delays will need a different
+ * loops_per_jiffy value to function properly. An exception to this
+ * are modern Intel Pentium 4 processors, where the TSC runs at a constant
+ * speed independent of frequency scaling. 
+ */
+
 static unsigned int  ref_freq = 0;
 static unsigned long loops_per_jiffy_ref = 0;
+static unsigned int  variable_tsc = 1;
 
 #ifndef CONFIG_SMP
 static unsigned long fast_gettimeoffset_ref = 0;
@@ -333,12 +341,15 @@
 
 	if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
 	    (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
-		cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
+		if (variable_tsc)
+			cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
 #ifndef CONFIG_SMP
 		if (use_tsc) {
-			fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq);
 			cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
-			set_cyc2ns_scale(cpu_khz/1000);
+			if (variable_tsc) {
+				fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq);
+				set_cyc2ns_scale(cpu_khz/1000);
+			}
 		}
 #endif
 	}
@@ -350,7 +361,19 @@
 static struct notifier_block time_cpufreq_notifier_block = {
 	.notifier_call	= time_cpufreq_notifier
 };
-#endif
+
+
+static int __init cpufreq_tsc(void)
+{
+	/* P4 and above CPU TSC freq doesn't change when CPU frequency changes*/
+	if ((boot_cpu_data.x86 >= 15) && (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
+		variable_tsc_freq = 0;
+
+	return cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+}
+core_initcall(cpufreq_tsc);
+
+#endif 
 
 
 static int __init init_tsc(char* override)
@@ -392,10 +415,6 @@
  	 *	some CPU's have a TSC. Thats never worked and nobody has
  	 *	moaned if you have the only one in the world - you fix it!
  	 */
- 
-#ifdef CONFIG_CPU_FREQ
-	cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
-#endif
 
 	count2 = LATCH; /* initialize counter for mark_offset_tsc() */

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

end of thread, other threads:[~2003-12-04 18:23 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-12-04  8:47 patch for P4 TSC problem Li, Shaohua
2003-12-04 18:23 ` Dominik Brodowski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.