* 2.6.19 timer API changes
@ 2006-12-18 9:15 Daniel Laird
2006-12-19 8:17 ` Daniel Laird
0 siblings, 1 reply; 21+ messages in thread
From: Daniel Laird @ 2006-12-18 9:15 UTC (permalink / raw)
To: linux-mips
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
--
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.
^ permalink raw reply [flat|nested] 21+ messages in thread
* 2.6.19 timer API changes
2006-12-18 9:15 2.6.19 timer API changes Daniel Laird
@ 2006-12-19 8:17 ` Daniel Laird
2006-12-19 14:34 ` Atsushi Nemoto
0 siblings, 1 reply; 21+ messages in thread
From: Daniel Laird @ 2006-12-19 8:17 UTC (permalink / raw)
To: linux-mips
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
--
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.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-19 8:17 ` Daniel Laird
@ 2006-12-19 14:34 ` Atsushi Nemoto
2006-12-19 14:51 ` Daniel Laird
` (2 more replies)
0 siblings, 3 replies; 21+ messages in thread
From: Atsushi Nemoto @ 2006-12-19 14:34 UTC (permalink / raw)
To: danieljlaird; +Cc: linux-mips
On Tue, 19 Dec 2006 00:17:24 -0800 (PST), Daniel Laird <danieljlaird@hotmail.com> wrote:
> 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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-19 14:34 ` Atsushi Nemoto
@ 2006-12-19 14:51 ` Daniel Laird
2006-12-19 16:23 ` Sergei Shtylyov
2006-12-19 15:01 ` Atsushi Nemoto
2006-12-19 15:52 ` Sergei Shtylyov
2 siblings, 1 reply; 21+ messages in thread
From: Daniel Laird @ 2006-12-19 14:51 UTC (permalink / raw)
To: linux-mips
Atsushi Nemoto wrote:
>
> 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
>
>
>
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
--
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.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-19 14:34 ` Atsushi Nemoto
2006-12-19 14:51 ` Daniel Laird
@ 2006-12-19 15:01 ` Atsushi Nemoto
2006-12-19 15:34 ` Daniel Laird
2006-12-19 15:52 ` Sergei Shtylyov
2 siblings, 1 reply; 21+ messages in thread
From: Atsushi Nemoto @ 2006-12-19 15:01 UTC (permalink / raw)
To: danieljlaird; +Cc: linux-mips
On Tue, 19 Dec 2006 00:17:24 -0800 (PST), Daniel Laird <danieljlaird@hotmail.com> wrote:
> 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?
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 11aab6d..4eb0741 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -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);
}
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-19 15:01 ` Atsushi Nemoto
@ 2006-12-19 15:34 ` Daniel Laird
2006-12-19 17:15 ` Atsushi Nemoto
0 siblings, 1 reply; 21+ messages in thread
From: Daniel Laird @ 2006-12-19 15:34 UTC (permalink / raw)
To: linux-mips
Atsushi Nemoto wrote:
>
> On Tue, 19 Dec 2006 00:17:24 -0800 (PST), Daniel Laird
> <danieljlaird@hotmail.com> wrote:
>> 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?
>
> diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
> index 11aab6d..4eb0741 100644
> --- a/arch/mips/kernel/time.c
> +++ b/arch/mips/kernel/time.c
> @@ -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);
> }
>
>
>
>
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.
--
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.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-19 14:34 ` Atsushi Nemoto
2006-12-19 14:51 ` Daniel Laird
2006-12-19 15:01 ` Atsushi Nemoto
@ 2006-12-19 15:52 ` Sergei Shtylyov
2006-12-19 16:29 ` Atsushi Nemoto
2 siblings, 1 reply; 21+ messages in thread
From: Sergei Shtylyov @ 2006-12-19 15:52 UTC (permalink / raw)
To: Atsushi Nemoto; +Cc: danieljlaird, linux-mips, Vitaly Wool
Hello.
Atsushi Nemoto wrote:
>>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.
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.
> ---
> Atsushi Nemoto
WBR, Sergei
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-19 14:51 ` Daniel Laird
@ 2006-12-19 16:23 ` Sergei Shtylyov
0 siblings, 0 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2006-12-19 16:23 UTC (permalink / raw)
To: Daniel Laird; +Cc: linux-mips, Vitaly Wool
Daniel Laird wrote:
> Atsushi Nemoto wrote:
>>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... :-)
>>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)
> {
> 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.
> 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...
> 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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-19 15:52 ` Sergei Shtylyov
@ 2006-12-19 16:29 ` Atsushi Nemoto
0 siblings, 0 replies; 21+ messages in thread
From: Atsushi Nemoto @ 2006-12-19 16:29 UTC (permalink / raw)
To: sshtylyov; +Cc: danieljlaird, linux-mips, vwool
On Tue, 19 Dec 2006 18:52:36 +0300, Sergei Shtylyov <sshtylyov@ru.mvista.com> wrote:
> 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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-19 15:34 ` Daniel Laird
@ 2006-12-19 17:15 ` Atsushi Nemoto
2006-12-20 9:37 ` Daniel Laird
2006-12-20 14:29 ` Sergei Shtylyov
0 siblings, 2 replies; 21+ messages in thread
From: Atsushi Nemoto @ 2006-12-19 17:15 UTC (permalink / raw)
To: danieljlaird; +Cc: linux-mips, ralf
On Tue, 19 Dec 2006 07:34:54 -0800 (PST), Daniel Laird <danieljlaird@hotmail.com> wrote:
> 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
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
---
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 11aab6d..8aa544f 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -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. */
diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c
index 65c440e..e86905a 100644
--- a/arch/mips/philips/pnx8550/common/time.c
+++ b/arch/mips/philips/pnx8550/common/time.c
@@ -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)
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-19 17:15 ` Atsushi Nemoto
@ 2006-12-20 9:37 ` Daniel Laird
2006-12-20 14:12 ` Sergei Shtylyov
2006-12-20 15:24 ` Atsushi Nemoto
2006-12-20 14:29 ` Sergei Shtylyov
1 sibling, 2 replies; 21+ messages in thread
From: Daniel Laird @ 2006-12-20 9:37 UTC (permalink / raw)
To: linux-mips
Atsushi Nemoto wrote:
>
> <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
--
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.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-20 9:37 ` Daniel Laird
@ 2006-12-20 14:12 ` Sergei Shtylyov
2006-12-20 14:50 ` Kevin D. Kissell
2006-12-20 15:24 ` Atsushi Nemoto
1 sibling, 1 reply; 21+ messages in thread
From: Sergei Shtylyov @ 2006-12-20 14:12 UTC (permalink / raw)
To: Daniel Laird; +Cc: linux-mips, Vitaly Wool
Hello.
Daniel Laird wrote:
>>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.
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.
> 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.
> 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).
> 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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-19 17:15 ` Atsushi Nemoto
2006-12-20 9:37 ` Daniel Laird
@ 2006-12-20 14:29 ` Sergei Shtylyov
2006-12-20 15:40 ` Atsushi Nemoto
2006-12-20 15:48 ` Sergei Shtylyov
1 sibling, 2 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2006-12-20 14:29 UTC (permalink / raw)
To: Atsushi Nemoto; +Cc: danieljlaird, linux-mips, ralf
Hello.
Atsushi Nemoto wrote:
>>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...
> How about this? You should still fix pnx8550_hpt_read() anyway, but I
> suppose gettimeofday() on PNX8550 was broken long time.
And nobody noticed. :-)
> Subject: [MIPS] Use custom timer_ack and clocksource_mips.read for PNX8550
>
> Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
> ---
> diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
> index 11aab6d..8aa544f 100644
> --- a/arch/mips/kernel/time.c
> +++ b/arch/mips/kernel/time.c
> @@ -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. */
> diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c
> index 65c440e..e86905a 100644
> --- a/arch/mips/philips/pnx8550/common/time.c
> +++ b/arch/mips/philips/pnx8550/common/time.c
> @@ -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..
> +
> +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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
@ 2006-12-20 14:50 ` Kevin D. Kissell
0 siblings, 0 replies; 21+ messages in thread
From: Kevin D. Kissell @ 2006-12-20 14:50 UTC (permalink / raw)
To: Sergei Shtylyov, Daniel Laird; +Cc: linux-mips, Vitaly Wool
> > 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.
>
> > 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.
> > 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.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
@ 2006-12-20 14:50 ` Kevin D. Kissell
0 siblings, 0 replies; 21+ messages in thread
From: Kevin D. Kissell @ 2006-12-20 14:50 UTC (permalink / raw)
To: Sergei Shtylyov, Daniel Laird; +Cc: linux-mips, Vitaly Wool
> > 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.
>
> > 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.
> > 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.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-20 9:37 ` Daniel Laird
2006-12-20 14:12 ` Sergei Shtylyov
@ 2006-12-20 15:24 ` Atsushi Nemoto
2006-12-20 15:46 ` Daniel Laird
1 sibling, 1 reply; 21+ messages in thread
From: Atsushi Nemoto @ 2006-12-20 15:24 UTC (permalink / raw)
To: danieljlaird; +Cc: linux-mips
On Wed, 20 Dec 2006 01:37:17 -0800 (PST), Daniel Laird <danieljlaird@hotmail.com> wrote:
> 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.
> 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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-20 14:29 ` Sergei Shtylyov
@ 2006-12-20 15:40 ` Atsushi Nemoto
2006-12-20 15:48 ` Daniel Laird
2006-12-20 15:48 ` Sergei Shtylyov
1 sibling, 1 reply; 21+ messages in thread
From: Atsushi Nemoto @ 2006-12-20 15:40 UTC (permalink / raw)
To: sshtylyov; +Cc: danieljlaird, linux-mips, ralf
On Wed, 20 Dec 2006 17:29:25 +0300, Sergei Shtylyov <sshtylyov@ru.mvista.com> wrote:
> > 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.
On Wed, 20 Dec 2006 17:29:25 +0300, Sergei Shtylyov <sshtylyov@ru.mvista.com> wrote:
> > +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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-20 15:24 ` Atsushi Nemoto
@ 2006-12-20 15:46 ` Daniel Laird
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Laird @ 2006-12-20 15:46 UTC (permalink / raw)
To: linux-mips
hello,
Atsushi Nemoto wrote:
>
> On Wed, 20 Dec 2006 01:37:17 -0800 (PST), Daniel Laird
> <danieljlaird@hotmail.com> wrote:
>> 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.
>
>> 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
>
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
--
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.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-20 14:29 ` Sergei Shtylyov
2006-12-20 15:40 ` Atsushi Nemoto
@ 2006-12-20 15:48 ` Sergei Shtylyov
1 sibling, 0 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2006-12-20 15:48 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: Atsushi Nemoto, danieljlaird, linux-mips, ralf, Vitaly Wool
Hello, I wrote:
>> +
>> +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)...
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
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-20 15:40 ` Atsushi Nemoto
@ 2006-12-20 15:48 ` Daniel Laird
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Laird @ 2006-12-20 15:48 UTC (permalink / raw)
To: linux-mips
Atsushi Nemoto wrote:
>
> On Wed, 20 Dec 2006 17:29:25 +0300, Sergei Shtylyov
> <sshtylyov@ru.mvista.com> wrote:
>> > 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.
>
> On Wed, 20 Dec 2006 17:29:25 +0300, Sergei Shtylyov
> <sshtylyov@ru.mvista.com> wrote:
>
>> > +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
>
>
>
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
--
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.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: 2.6.19 timer API changes
2006-12-20 14:50 ` Kevin D. Kissell
(?)
@ 2006-12-20 18:01 ` Sergei Shtylyov
-1 siblings, 0 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2006-12-20 18:01 UTC (permalink / raw)
To: Kevin D. Kissell; +Cc: Daniel Laird, linux-mips, Vitaly Wool
Hello.
Kevin D. Kissell wrote:
> 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...
> 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... :-)
>>>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
This is called why the count is disabled -- this is done in
arch_init_irq(). Only plat_timer_setup() re-enables it.
> 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...
> Kevin K.
WBR, Sergei
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2006-12-20 18:02 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-12-18 9:15 2.6.19 timer API changes Daniel Laird
2006-12-19 8:17 ` Daniel Laird
2006-12-19 14:34 ` Atsushi Nemoto
2006-12-19 14:51 ` Daniel Laird
2006-12-19 16:23 ` Sergei Shtylyov
2006-12-19 15:01 ` Atsushi Nemoto
2006-12-19 15:34 ` Daniel Laird
2006-12-19 17:15 ` Atsushi Nemoto
2006-12-20 9:37 ` Daniel Laird
2006-12-20 14:12 ` Sergei Shtylyov
2006-12-20 14:50 ` Kevin D. Kissell
2006-12-20 14:50 ` Kevin D. Kissell
2006-12-20 18:01 ` Sergei Shtylyov
2006-12-20 15:24 ` Atsushi Nemoto
2006-12-20 15:46 ` Daniel Laird
2006-12-20 14:29 ` Sergei Shtylyov
2006-12-20 15:40 ` Atsushi Nemoto
2006-12-20 15:48 ` Daniel Laird
2006-12-20 15:48 ` Sergei Shtylyov
2006-12-19 15:52 ` Sergei Shtylyov
2006-12-19 16:29 ` Atsushi Nemoto
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.