Skip to contentSkip to conversation

2.6.19 timer API changes

DISCUSSION Daniel Laird 4 participants 20 messages Dec 18, 2006 – Dec 20, 2006 MIPS

lore
Share & tools
lore
#0 lore raw

Hi All,

I am porting the Philips/PNX8550 kernel from 2.6.17.13 to 2.6.19. I am having some issues:
One issue I am having is with the new Timer API that replaced the board specific API.

I have made all of the important changes
board_timer_setup -> plat_timer_setup

When I run the kernel it hangs in the calibrate_delay function. Eventually the complete kernel does run but it runs very slow. This is usually an issue with the Timer Interuppt setup etc. But I have looked at the other MIPS ports and seem to have made the same changes.

On the PNX8550 it does not use the CP0 timer but use a different timer (the Custom MIPS core has 3 extra timers)

I replaced the arch/mips/kernel/time.c with a merge between 2.6.17.13 and 2.6.19 and I can get the kernel to boot at the correct speed straight through the calibrate_delay function and the entire system seems to be working correctly.

I was wondering if anyone might have any ideas on how to debug this problem as I would like a clean port to 2.6.19.
Maybe the new timer code will not work properly on the PNX8550 in which case maybe some patches are required.

I am continuing to debug at my end and once I have a working system with the smallest set of changes to the time.c file I will post them in the hope that someone will point out a silly error I have made in the CPU/board setup.

In the mean time any helpful ideas on debugging, tracing, even solving this issue would be really appreciated

Daniel

Signature · 2 lines
View this message in context: http://www.nabble.com/2.6.19-timer-API-changes-tf2838715.html#a7925588
Sent from the linux-mips main mailing list archive at Nabble.com.
#1 lore raw

Hi All,

I am porting the Philips/PNX8550 kernel from 2.6.17.13 to 2.6.19. I am having some issues:
One issue I am having is with the new Timer API that replaced the board specific API.

I have made all of the important changes
board_timer_setup -> plat_timer_setup

When I run the kernel it hangs in the calibrate_delay function. Eventually the complete kernel does run but it runs very slow. This is usually an issue with the Timer Interuppt setup etc. But I have looked at the other MIPS ports and seem to have made the same changes.

On the PNX8550 it does not use the CP0 timer but use a different timer (the Custom MIPS core has 3 extra timers)

I replaced the arch/mips/kernel/time.c with a merge between 2.6.17.13 and 2.6.19 and I can get the kernel to boot at the correct speed straight through the calibrate_delay function and the entire system seems to be working correctly.

I was wondering if anyone might have any ideas on how to debug this problem as I would like a clean port to 2.6.19.
Maybe the new timer code will not work properly on the PNX8550 in which case maybe some patches are required.

I am continuing to debug at my end and once I have a working system with the smallest set of changes to the time.c file I will post them in the hope that someone will point out a silly error I have made in the CPU/board setup.

In the mean time any helpful ideas on debugging, tracing, even solving this issue would be really appreciated

Daniel

Signature · 2 lines
View this message in context: http://www.nabble.com/2.6.19-timer-API-changes-tf2838715.html#a7943218
Sent from the linux-mips main mailing list archive at Nabble.com.
#2 lore raw
Quoted 7 lines · Daniel Laird

When I run the kernel it hangs in the calibrate_delay function. Eventually the complete kernel does run but it runs very slow. This is usually an issue with the Timer Interuppt setup etc. But I have looked at the other MIPS ports and seem to have made the same changes.

On the PNX8550 it does not use the CP0 timer but use a different timer (the Custom MIPS core has 3 extra timers)

Hmm, do the TIMER1 and CP0_COUNTER run at same speed? If no, the PNX8550 port should be broken (i.e. gettimeofday() did not work properly) even without the timer API changes. You should provide custom clocksource.mips_read (previously named mips_hpt_read) function which returns TIMER1 counter value. If the TIMER1 was not 32-bit free-run counter, some trick would be required. Refer sb1250 or jmr3927 for example.

---
Atsushi Nemoto

#3 lore raw
Quoted 9 lines · Atsushi Nemoto

Hmm, do the TIMER1 and CP0_COUNTER run at same speed? If no, the PNX8550 port should be broken (i.e. gettimeofday() did not work properly) even without the timer API changes. You should provide custom clocksource.mips_read (previously named mips_hpt_read) function which returns TIMER1 counter value. If the TIMER1 was not 32-bit free-run counter, some trick would be required. Refer sb1250 or jmr3927 for example.

Quoted 5 lines

---
Atsushi Nemoto

I am just starting to look into this (thankyou for your first comments). I have reduced the problem code, so if I change the following:
/* For use both as a high precision timer and an interrupt source. */ static void __init c0_hpt_timer_init(void)

{
	expirelo = read_c0_count() + cycles_per_jiffy;
	write_c0_compare(expirelo);
} (the 2.6.19 version)
to the following:
/* For use both as a high precision timer and an interrupt source.  */
static void __init c0_hpt_timer_init(void)
{
    unsigned int count = read_c0_count() - mips_hpt_read();
	expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
	write_c0_count(expirelo - cycles_per_jiffy);
	write_c0_compare(expirelo);
	write_c0_count(count);
}

Then i get the system to boot up and all seems well. I am new to this and am looking into why this change makes the system boot up. As always though any help is appreciated.

Cheers
Dan

Signature · 2 lines
View this message in context: http://www.nabble.com/2.6.19-timer-API-changes-tf2838715.html#a7948316
Sent from the linux-mips main mailing list archive at Nabble.com.
#5 lore raw
In reply to Atsushi Nemoto
Quoted 2 lines · Daniel Laird

On the PNX8550 it does not use the CP0 timer but use a different timer (the Custom MIPS core has 3 extra timers)

Do you know what this ifndef line mean?

#ifndef CONFIG_SOC_PNX8550	/* pnx8550 resets to zero */
	/* Ack this timer interrupt and set the next one.  */
	expirelo += cycles_per_jiffy;

#endif

If it means "On PNX8550, writing to COMPARE register resets COUNTER to zero", new time.c might be broken for PNX8550. Could you try this patch?

arch/mips/kernel/time.c +4 -0
index 11aab6d..4eb0741 100644
@@ -119,7 +119,11 @@ static cycle_t c0_hpt_read(void)
 /* For use both as a high precision timer and an interrupt source.  */
 static void __init c0_hpt_timer_init(void)
 {
+#ifdef CONFIG_SOC_PNX8550	/* pnx8550 resets to zero */
+	expirelo = cycles_per_jiffy;
+#else
 	expirelo = read_c0_count() + cycles_per_jiffy;
+#endif
 	write_c0_compare(expirelo);
 }
 
#6 lore raw
Quoted 27 lines · Atsushi Nemoto
Quoted 3 lines · Daniel Laird

On the PNX8550 it does not use the CP0 timer but use a different timer (the
Custom MIPS core has 3 extra timers)

Do you know what this ifndef line mean?

#ifndef CONFIG_SOC_PNX8550	/* pnx8550 resets to zero */
	/* Ack this timer interrupt and set the next one.  */
	expirelo += cycles_per_jiffy;

#endif

If it means "On PNX8550, writing to COMPARE register resets COUNTER to zero", new time.c might be broken for PNX8550. Could you try this patch?

arch/mips/kernel/time.c +0 -0
index 11aab6d..4eb0741 100644
@@ -119,7 +119,11 @@ static cycle_t c0_hpt_read(void)
 /* For use both as a high precision timer and an interrupt source.  */

arch/mips/kernel/time.c static cycle_t c0_hpt_read(void) · line 129

Quoted 10 lines
arch/mips/kernel/time.c +4 -0
 static void __init c0_hpt_timer_init(void)
 {
+#ifdef CONFIG_SOC_PNX8550	/* pnx8550 resets to zero */
+	expirelo = cycles_per_jiffy;
+#else
 	expirelo = read_c0_count() + cycles_per_jiffy;
+#endif
 	write_c0_compare(expirelo);
 }
 

I am just digging out the mips core user manual...
However I have tried this change you suggested, it still takes a long time to get past the calibrate delay function (~10seconds).
However after this it seems to run at full speed where as before it used to run very slow.
So an improvement, I think this does mean the new time.c has broken 8550 support hopefully I can find otu what the core does so it can be fixed.

Signature · 2 lines
View this message in context: http://www.nabble.com/2.6.19-timer-API-changes-tf2838715.html#a7949125
Sent from the linux-mips main mailing list archive at Nabble.com.
#18 lore raw
In reply to Atsushi Nemoto

Hello.

Quoted 6 lines · Atsushi Nemoto
Quoted 5 lines

When I run the kernel it hangs in the calibrate_delay function. Eventually the complete kernel does run but it runs very slow. This is usually an issue with the Timer Interuppt setup etc. But I have looked at the other MIPS ports and seem to have made the same changes.

On the PNX8550 it does not use the CP0 timer but use a different timer (the Custom MIPS core has 3 extra timers)

Quoted 7 lines

Hmm, do the TIMER1 and CP0_COUNTER run at same speed? If no, the PNX8550 port should be broken (i.e. gettimeofday() did not work properly) even without the timer API changes. You should provide custom clocksource.mips_read (previously named mips_hpt_read) function which returns TIMER1 counter value. If the TIMER1 was not 32-bit free-run counter, some trick would be required. Refer sb1250 or jmr3927 for example.

I would like to discourage you from repeating those JMR3927 clocksource
"tricks" when you have 3 spare count/compare regs. This will warrant troubles when clockevents support gets merged into mainline (in fact, it was not necessary even on JMR3927 which has 3 timers). Although, if the timer isn't auto-reloading (I assume it isn't), the trick shouldn't be needed.

Quoted 2 lines

---
Atsushi Nemoto

WBR, Sergei

#4 lore raw
In reply to Daniel Laird
Quoted 6 lines · Daniel Laird
Quoted 4 lines · Atsushi Nemoto

Hmm, do the TIMER1 and CP0_COUNTER run at same speed? If no, the PNX8550 port should be broken (i.e. gettimeofday() did not work properly) even without the timer API changes. You should provide custom clocksource.mips_read (previously named mips_hpt_read) function

Meaning clocksource_mips.read... :-)

Quoted 14 lines
Quoted 9 lines

which returns TIMER1 counter value. If the TIMER1 was not 32-bit free-run counter, some trick would be required. Refer sb1250 or jmr3927 for example.

---
Atsushi Nemoto

I am just starting to look into this (thankyou for your first comments). I have reduced the problem code, so if I change the following:
/* For use both as a high precision timer and an interrupt source. */ static void __init c0_hpt_timer_init(void)

Quoted 9 lines
{
	expirelo = read_c0_count() + cycles_per_jiffy;
	write_c0_compare(expirelo);
} (the 2.6.19 version)
to the following:
/* For use both as a high precision timer and an interrupt source.  */
static void __init c0_hpt_timer_init(void)
{
    unsigned int count = read_c0_count() - mips_hpt_read();

Doesn't make sense to me... Should be 0 or near.

Quoted 5 lines
	expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
	write_c0_count(expirelo - cycles_per_jiffy);
	write_c0_compare(expirelo);
	write_c0_count(count);
}

This code just shouldn't be executing at all, since the interrupts are
coming from the other source than standard CP0 count/compare registers (so, I'd assume mips_timer_state should need to be set -- but it doesn't)... and at the same time the handler writes to them... well, PNX8550 must have really weird timers...

Quoted 6 lines

Then i get the system to boot up and all seems well. I am new to this and am looking into why this change makes the system boot up. As always though any help is appreciated.

Cheers
Dan

WBR, Sergei

#19 lore raw
In reply to Sergei Shtylyov
Quoted 6 lines · Sergei Shtylyov

I would like to discourage you from repeating those JMR3927
clocksource "tricks" when you have 3 spare count/compare regs. This will warrant troubles when clockevents support gets merged into mainline (in fact, it was not necessary even on JMR3927 which has 3 timers). Although, if the timer isn't auto-reloading (I assume it isn't), the trick shouldn't be needed.

Indeed. JMR3927 is not good for reference on writing new code.

Though I do not know the PNX8550 timer details, if writing to the COMPARE reset the COUNTER or COUNTER wrapped to zero at a value in COMPARE, perhaps we can not use c0_hpt_read for clocksource.

---
Atsushi Nemoto

#7 lore raw
In reply to Daniel Laird
Quoted 7 lines · Daniel Laird

I am just digging out the mips core user manual...
However I have tried this change you suggested, it still takes a long time to get past the calibrate delay function (~10seconds).
However after this it seems to run at full speed where as before it used to run very slow.
So an improvement, I think this does mean the new time.c has broken 8550 support hopefully I can find otu what the core does so it can be fixed.

Hm, then it seems writing to COMPARE does not clear COUNT.

How about this? You should still fix pnx8550_hpt_read() anyway, but I suppose gettimeofday() on PNX8550 was broken long time.

Subject: [MIPS] Use custom timer_ack and clocksource_mips.read for PNX8550

---

arch/mips/kernel/time.c +0 -2
index 11aab6d..8aa544f 100644
@@ -94,10 +94,8 @@ static void c0_timer_ack(void)
 {
 	unsigned int count;
 
-#ifndef CONFIG_SOC_PNX8550	/* pnx8550 resets to zero */
 	/* Ack this timer interrupt and set the next one.  */
 	expirelo += cycles_per_jiffy;
-#endif
 	write_c0_compare(expirelo);
 
 	/* Check to see if we have missed any timer interrupts.  */
arch/mips/philips/pnx8550/common/time.c +17 -1
index 65c440e..e86905a 100644
@@ -33,7 +33,18 @@ #include <asm/debug.h>
 #include <int.h>
 #include <cm.h>
 
-extern unsigned int mips_hpt_frequency;
+static unsigned long cycles_per_jiffy __read_mostly;
+
+static void pnx8550_timer_ack(void)
+{
+	write_c0_compare(cycles_per_jiffy);
+}
+
+static cycle_t pnx8550_hpt_read(void)
+{
+	/* FIXME: we should use timer2 or timer3 as freerun counter */
+	return read_c0_count();
+}
 
 /*
  * pnx8550_time_init() - it does the following things:
@@ -68,6 +79,11 @@ void pnx8550_time_init(void)
 	 * HZ timer interrupts per second.
 	 */
 	mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p));
+	cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ;
+	clocksource_mips.read = pnx8550_hpt_read;
+	mips_timer_ack = pnx8550_timer_ack;
+	write_c0_count(0);
+	write_c0_compare(cycles_per_jiffy);
 }
 
 void __init plat_timer_setup(struct irqaction *irq)
#8 lore raw
Quoted 10 lines · Atsushi Nemoto

<snip>
Hm, then it seems writing to COMPARE does not clear COUNT.

How about this? You should still fix pnx8550_hpt_read() anyway, but I suppose gettimeofday() on PNX8550 was broken long time.

Subject: [MIPS] Use custom timer_ack and clocksource_mips.read for PNX8550

I have not tried the suggested change yet, but I have fiund the mips manual and here is what it says:

The 32-bit register is both readable and writable through the MTC0 and MFC0 instructions as CP0 register 9. Upon reset, the Count register is set to 0. Count and Compare together make up Timer_1 in the PR4450 (see Section 3.12). The timer is active by default. When active, Count register contains a free running
counter; on each processor clock-tick, the value in the register increments by one.
However, when bit ST1 bit[3] in the CP0 Configuration register is enabled, the timer is
stopped. When the ST1 bit is disabled, the timer returns to its default state.
Timer_1 is active when the PR4450 is in Sleep mode, but is switched off when the
PR4450 is in Coma mode.
When active, the register can be reset with the assertion of the Terminal Count
(TC_1) signal, which is asserted when the values in the Count and Compare registers
match. After the Count register is reset, it restarts its count on the next processor
clock-tick.
In the PR4450, the TC_1 signal is fed to the external hardware interrupt signal to
invoke an interrupt handler e.g., the timer interrupt. The TC_1 signal can only be
reset to 0 when the interrupt handler performs a write to the Compare register.
Consecutive writes to Count will result in undefined contents. At least one instruction
must be inserted between consecutive writes to Count.

This seems to suggest that writing to the compare register does in fact clear count.
If I do the following:
static void __init c0_hpt_timer_init(void)
{

#ifdef CONFIG_SOC_PNX8550 /* pnx8550 resets to zero */
    expirelo = cycles_per_jiffy;
#else
    expirelo = read_c0_count() + cycles_per_jiffy;

#endif
write_c0_compare(expirelo); write_c0_count(cycles_per_jiffy); //Added DJL
}
Then I get a normal startup. i.e it boots fast (no 10second hang). If I remove the write_c0_count then I get the 10 second hang.
I have no idea if gettimeofday is broken. ANy ideas on testing this? Is there a test package / application that will do this? Before I write my own

Thanks for the suggestions keep them coming!
Cheers
Dan

Signature · 2 lines
View this message in context: http://www.nabble.com/2.6.19-timer-API-changes-tf2838715.html#a7987092
Sent from the linux-mips main mailing list archive at Nabble.com.
#9 lore raw

Hello.

Quoted 41 lines · Daniel Laird
Quoted 6 lines

Hm, then it seems writing to COMPARE does not clear COUNT.

How about this? You should still fix pnx8550_hpt_read() anyway, but I suppose gettimeofday() on PNX8550 was broken long time.

Subject: [MIPS] Use custom timer_ack and clocksource_mips.read for PNX8550

I have not tried the suggested change yet, but I have fiund the mips manual and here is what it says:

The 32-bit register is both readable and writable through the MTC0 and MFC0 instructions as CP0 register 9. Upon reset, the Count register is set to 0. Count and Compare together make up Timer_1 in the PR4450 (see Section 3.12). The timer is active by default. When active, Count register contains a free running
counter; on each processor clock-tick, the value in the register increments by one.
However, when bit ST1 bit[3] in the CP0 Configuration register is enabled, the timer is
stopped. When the ST1 bit is disabled, the timer returns to its default state.
Timer_1 is active when the PR4450 is in Sleep mode, but is switched off when the
PR4450 is in Coma mode.
When active, the register can be reset with the assertion of the Terminal Count
(TC_1) signal, which is asserted when the values in the Count and Compare registers
match. After the Count register is reset, it restarts its count on the next processor
clock-tick.
In the PR4450, the TC_1 signal is fed to the external hardware interrupt signal to
invoke an interrupt handler e.g., the timer interrupt. The TC_1 signal can only be
reset to 0 when the interrupt handler performs a write to the Compare register.
Consecutive writes to Count will result in undefined contents. At least one instruction
must be inserted between consecutive writes to Count.

Quoted 2 lines

This seems to suggest that writing to the compare register does in fact clear count.

It actually doesn't suggest anything alike. All it says is that "the
register *can* be reset with the assertion of the Terminal Count (TC_1) signal which is asserted when the values in the Count and Compare registers match". Whtat it doesn't say is what determines if it's really reset by TC_1 assertion or not.

Quoted 11 lines

If I do the following:
static void __init c0_hpt_timer_init(void)
{

#ifdef CONFIG_SOC_PNX8550 /* pnx8550 resets to zero */
    expirelo = cycles_per_jiffy;
#else
    expirelo = read_c0_count() + cycles_per_jiffy;

#endif
write_c0_compare(expirelo);
write_c0_count(cycles_per_jiffy); //Added DJL
}

Hmm, all it actually should do is warrant missing of the first jiffy
interrupt... I'm even beginning to suspect the counter counts down, not up...
But well, after looking at some internal code, it seems that the Count register on PNX8550 always auto-reloads after mathing the Compare register.

Quoted 3 lines

Then I get a normal startup. i.e it boots fast (no 10second hang). If I remove the write_c0_count then I get the 10 second hang.
I have no idea if gettimeofday is broken. ANy ideas on testing this? Is

It surely is, if I'm correct in my assumption... I'd suggest to use
another PNX8550 timer as a clocksource (setting the its Compare register to all ones).

Quoted 5 lines

there a test package / application that will do this? Before I write my own

Thanks for the suggestions keep them coming!
Cheers
Dan

WBR, Sergei

#14 lore raw
In reply to Atsushi Nemoto

Hello.

Quoted 8 lines · Atsushi Nemoto
Quoted 6 lines

I am just digging out the mips core user manual... However I have tried this change you suggested, it still takes a long time to get past the calibrate delay function (~10seconds).
However after this it seems to run at full speed where as before it used to
run very slow.
So an improvement, I think this does mean the new time.c has broken 8550
support hopefully I can find otu what the core does so it can be fixed.

Hm, then it seems writing to COMPARE does not clear COUNT.

Looks like the count/compare match does this...

Quoted 2 lines

How about this? You should still fix pnx8550_hpt_read() anyway, but I suppose gettimeofday() on PNX8550 was broken long time.

And nobody noticed. :-)

Quoted 24 lines

Subject: [MIPS] Use custom timer_ack and clocksource_mips.read for PNX8550

---

arch/mips/kernel/time.c +0 -2
index 11aab6d..8aa544f 100644
@@ -94,10 +94,8 @@ static void c0_timer_ack(void)
 {
 	unsigned int count;
 
-#ifndef CONFIG_SOC_PNX8550	/* pnx8550 resets to zero */
 	/* Ack this timer interrupt and set the next one.  */
 	expirelo += cycles_per_jiffy;
-#endif
 	write_c0_compare(expirelo);
 
 	/* Check to see if we have missed any timer interrupts.  */
arch/mips/philips/pnx8550/common/time.c +0 -0
index 65c440e..e86905a 100644

arch/mips/philips/pnx8550/common/time.c #include <asm/debug.h> · line 36

Quoted 5 lines
arch/mips/philips/pnx8550/common/time.c +1 -1
@@ -33,7 +33,18 @@ #include <asm/debug.h>
 #include <int.h>
 #include <cm.h>
 
-extern unsigned int mips_hpt_frequency;
+static unsigned long cycles_per_jiffy __read_mostly;

I wonder shouldn't it be added to <asm-mips/time.h> just for such occasions..

arch/mips/philips/pnx8550/common/time.c #include <asm/debug.h> · line 47

Quoted 11 lines
arch/mips/philips/pnx8550/common/time.c +11 -0
+
+static void pnx8550_timer_ack(void)
+{
+	write_c0_compare(cycles_per_jiffy);
+}
+
+static cycle_t pnx8550_hpt_read(void)
+{
+	/* FIXME: we should use timer2 or timer3 as freerun counter */
+	return read_c0_count();
+}

I'd suggest read_c0_count2() here, possibly adding an interrupt handler
for it since it will interrupt upon hitting compare2 reg. value (but we could probably just mask the IRQ off), and enabling the timer 2, of course (the current code disables it)...

WBR, Sergei

#10 lore raw
In reply to Sergei Shtylyov
Quoted 20 lines
Quoted 19 lines

The 32-bit register is both readable and writable through the MTC0 and MFC0 instructions as CP0 register 9. Upon reset, the Count register is set to 0. Count and Compare together make up Timer_1 in the PR4450 (see Section 3.12). The timer is active by default. When active, Count register contains a free running counter; on each processor clock-tick, the value in the register increments by one. However, when bit ST1 bit[3] in the CP0 Configuration register is enabled, the timer is stopped. When the ST1 bit is disabled, the timer returns to its default state. Timer_1 is active when the PR4450 is in Sleep mode, but is switched off when the PR4450 is in Coma mode.
When active, the register can be reset with the assertion of the TerminalCount (TC_1) signal, which is asserted when the values in the Count and Compare registers match. After the Count register is reset, it restarts its count on the next processor clock-tick.
In the PR4450, the TC_1 signal is fed to the external hardware interrupt signal to invoke an interrupt handler e.g., the timer interrupt. The TC_1 signal can only be reset to 0 when the interrupt handler performs a write to the Compare register.
Consecutive writes to Count will result in undefined contents. At least one instruction must be inserted between consecutive writes to Count.

Quoted 8 lines
Quoted 2 lines

This seems to suggest that writing to the compare register does in fact clear count.

It actually doesn't suggest anything alike. All it says is that "the
register *can* be reset with the assertion of the Terminal Count (TC_1) signal which is asserted when the values in the Count and Compare registers match". Whtat it doesn't say is what determines if it's really reset by TC_1 assertion or not.

In all fairness, the spec can be read to state that the assertion of TC_1 clears the Count register. Or rather that it "can" - there seems to be some assumed mode of behavior that's not otherwise described. I wonder if they're not talking about behavior specifc to "Coma mode", which was perhaps what they are referring to when they begin the next sentence with "When active". I can see how someone might think it advantageous to have a mode where the Count register auto-resets on a timer tick, so that there's no need to recalcuate Compare values. But I've never seen that implemented on a MIPS processor. Free-running Count registers have other uses that can be shared with the timer interrupts, so long as it's Compare and not Count that gets reprogrammed on an interrupt. I have a hard time believing that the 8550 has the auto-reset as default behavior.

Quoted 11 lines
Quoted 11 lines

If I do the following:
static void __init c0_hpt_timer_init(void)
{

#ifdef CONFIG_SOC_PNX8550 /* pnx8550 resets to zero */
    expirelo = cycles_per_jiffy;
#else
    expirelo = read_c0_count() + cycles_per_jiffy;

#endif
write_c0_compare(expirelo);
write_c0_count(cycles_per_jiffy); //Added DJL
}

First of all, I think the conditional code is broken, even if you believe that Count is reset to zero on every interrupt. This is the *init* code, that's getting called once at boot time to set up the clock. It's not a clock interrupt handler.

It is highly likely that the Count register has already gone beyond the value of cycles_per_jiffy by the time this code gets hit. If that's true, programming Compare to zero+delta means waiting for the counter to wrap around before the first interrupt is delivered - a 10-second-ish hang. Writing the same value to Count that you just wrote to Compare will, on many cores, cause a Count=Compare state and a prompt interrupt.

But the real fix is almost certainly to get rid of the conditional.

Regards,

Kevin K.

#12 lore raw
In reply to Daniel Laird
Quoted 2 lines · Daniel Laird

Then I get a normal startup. i.e it boots fast (no 10second hang). If I remove the write_c0_count then I get the 10 second hang.

I think Kevin's analysis about this 10 second hang is correct. Then I think my last patch will work as well.

Quoted 2 lines

I have no idea if gettimeofday is broken. ANy ideas on testing this? Is there a test package / application that will do this? Before I write my own

Calling gettimeofday() continuously many times (at least some tick periods) and calculates times between each call. Those differences should be almost same. Of course you must run this program on very idle system (or you must raise its priority).

---
Atsushi Nemoto

#15 lore raw
In reply to Sergei Shtylyov
Quoted 4 lines · Sergei Shtylyov
Quoted 2 lines

How about this? You should still fix pnx8550_hpt_read() anyway, but I suppose gettimeofday() on PNX8550 was broken long time.

And nobody noticed. :-)

I changed my mind a bit. The pre-clocksource gettimeofday() might work well on PNX8550. There was timerlo variable which hold COUNT value on last timer interrupt and fixed_gettimeoffset() subtracted timerlo from COUNT value at the time.

Quoted 10 lines · Sergei Shtylyov

arch/mips/philips/pnx8550/common/time.c #include <asm/debug.h> · line 47

Quoted 5 lines
arch/mips/philips/pnx8550/common/time.c +5 -0
+static cycle_t pnx8550_hpt_read(void)
+{
+	/* FIXME: we should use timer2 or timer3 as freerun counter */
+	return read_c0_count();
+}

I'd suggest read_c0_count2() here, possibly adding an interrupt
handler for it since it will interrupt upon hitting compare2 reg. value (but we could probably just mask the IRQ off), and enabling the timer 2, of course (the current code disables it)...

It would be right direction. And we should set set count2 frequency to mips_hpt_frequency. But I cannot test it by myself so I'd like to leave it for others. Good exercise ;)

---
Atsushi Nemoto

#13 lore raw
In reply to Atsushi Nemoto

hello,

Quoted 14 lines · Atsushi Nemoto
Quoted 3 lines · Daniel Laird

Then I get a normal startup. i.e it boots fast (no 10second hang). If I
remove the write_c0_count then I get the 10 second hang.

I think Kevin's analysis about this 10 second hang is correct. Then I think my last patch will work as well.

Quoted 3 lines

I have no idea if gettimeofday is broken. ANy ideas on testing this? Is there a test package / application that will do this? Before I write my own

Quoted 8 lines

Calling gettimeofday() continuously many times (at least some tick periods) and calculates times between each call. Those differences should be almost same. Of course you must run this program on very idle system (or you must raise its priority).

---
Atsushi Nemoto

Thanks guys I can see how Kevin has come to his conclusion (On 10 secs And I think I agree)!
I will try your 2nd proposed solution, I gave it a very quick go but it did not work. I will give this some proper time, I think some mips_clocksource needed to be externed etc. (and add linux/clocksource.h ) to pnx8550/common/time.c.
Hopefullly this will make it compile, and then I can trace the problem a bit more. It might be after Christmas though before I come back to this Again cheers for the help.
Dan

Signature · 2 lines
View this message in context: http://www.nabble.com/2.6.19-timer-API-changes-tf2838715.html#a7992266
Sent from the linux-mips main mailing list archive at Nabble.com.
#17 lore raw
In reply to Sergei Shtylyov
Quoted 6 lines · Hello, I wrote:
Quoted 6 lines
arch/mips/philips/pnx8550/common/time.c +6 -0
+
+static void pnx8550_timer_ack(void)
+{
+    write_c0_compare(cycles_per_jiffy);
+}
+
Quoted 8 lines

arch/mips/philips/pnx8550/common/time.c #include <asm/debug.h> · line 47

Quoted 5 lines
arch/mips/philips/pnx8550/common/time.c +5 -0
+static cycle_t pnx8550_hpt_read(void)
+{
+    /* FIXME: we should use timer2 or timer3 as freerun counter */
+    return read_c0_count();
+}

I'd suggest read_c0_count2() here, possibly adding an interrupt
handler for it since it will interrupt upon hitting compare2 reg. value (but we could probably just mask the IRQ off), and enabling the timer 2, of course (the current code disables it)...

No, we'll have to handle IRQ it once the timer is enabled -- there seems
to be no provision to mask it off other than disabling the timer.

WBR, Sergei

#16 lore raw
In reply to Atsushi Nemoto
Quoted 27 lines · Atsushi Nemoto
Quoted 4 lines · Sergei Shtylyov
Quoted 2 lines

How about this? You should still fix pnx8550_hpt_read() anyway, but I suppose gettimeofday() on PNX8550 was broken long time.

And nobody noticed. :-)

I changed my mind a bit. The pre-clocksource gettimeofday() might work well on PNX8550. There was timerlo variable which hold COUNT value on last timer interrupt and fixed_gettimeoffset() subtracted timerlo from COUNT value at the time.

Quoted 10 lines · Sergei Shtylyov

arch/mips/philips/pnx8550/common/time.c #include <asm/debug.h> · line 47

Quoted 5 lines
arch/mips/philips/pnx8550/common/time.c +5 -0
+static cycle_t pnx8550_hpt_read(void)
+{
+	/* FIXME: we should use timer2 or timer3 as freerun counter */
+	return read_c0_count();
+}

I'd suggest read_c0_count2() here, possibly adding an interrupt
handler for it since it will interrupt upon hitting compare2 reg. value (but we could probably just mask the IRQ off), and enabling the timer 2, of course (the current code disables it)...

Quoted 9 lines

It would be right direction. And we should set set count2 frequency to mips_hpt_frequency. But I cannot test it by myself so I'd like to leave it for others. Good exercise ;)

---
Atsushi Nemoto

It seems likely that this did work in previous releases, however it will obviously need to work on this release and so once I have solved the startup issues by using your second proposed patch I will do some testing to see if I can get this to work (if it is indeed broken)
Cheers
Dan

Signature · 2 lines
View this message in context: http://www.nabble.com/2.6.19-timer-API-changes-tf2838715.html#a7992312
Sent from the linux-mips main mailing list archive at Nabble.com.
#11 lore raw
In reply to Kevin D. Kissell

Hello.

Quoted 5 lines · Kevin D. Kissell

they are referring to when they begin the next sentence with "When active". I can see how someone might think it advantageous to have a mode where the Count register auto-resets on a timer tick, so that there's no need to recalcuate Compare values. But I've never seen that implemented on a MIPS processor.

Toshiba TX3927 mentioned in that thread before is an example...

Quoted 4 lines

Free-running Count registers have other uses that can
be shared with the timer interrupts, so long as it's Compare and not Count that gets reprogrammed on an interrupt. I have a hard time believing that the 8550 has the auto-reset as default behavior.

Yet the code suggests that it does. PNX8550 seems to be a strange beast... :-)

Quoted 12 lines
Quoted 11 lines
Quoted 11 lines

If I do the following:
static void __init c0_hpt_timer_init(void)
{

#ifdef CONFIG_SOC_PNX8550 /* pnx8550 resets to zero */
   expirelo = cycles_per_jiffy;
#else
   expirelo = read_c0_count() + cycles_per_jiffy;

#endif
write_c0_compare(expirelo);
write_c0_count(cycles_per_jiffy); //Added DJL
}

Quoted 6 lines

First of all, I think the conditional code is broken, even if you believe that Count is reset to zero on every interrupt. This is the *init* code, that's getting called once at boot time to set up the clock. It's not a clock interrupt handler.

It is highly likely that the Count register has already gone

This is called why the count is disabled -- this is done in
arch_init_irq(). Only plat_timer_setup() re-enables it.

Quoted 8 lines

beyond the value of cycles_per_jiffy by the time this code gets hit. If that's true, programming Compare to zero+delta means waiting for the counter to wrap around before the first interrupt is delivered - a 10-second-ish hang. Writing the same value to Count that you just wrote to Compare will, on many cores, cause a Count=Compare state and a prompt interrupt.

But the real fix is almost certainly to get rid of the conditional.

That would be too simple... :-)
Moreover, with presumed auto-reload behavior it's likely to warrant the
wrong expirelo value (which in turn will cause jiffies to be longer than intended) -- all because of Count register possible being non-zero at this point...

Quoted 1 line

Kevin K.

WBR, Sergei