alpha timer patch [Re: reporting 2.2 kernel bugs]

Richard Henderson (rth@cygnus.com)
Thu, 7 Jan 1999 22:54:59 -0800


On Fri, Jan 08, 1999 at 07:13:48AM +0100, Willem Boschman wrote:
> I don't have any explainations for you but i do know it works. Have
> been using this since 2.1.125 every normal kernel gets the clock
> wrong while with patch its fine.I did think mayby its an error in egcs
> (1.0.3 or 1.1a ?) which does't occur if you move the code so i tried
> gcc-2.8.1 and now egcs-1.1.1. No change.

I have trouble beliveing in compiler bugs in this case
because in either case the compiled code should be the
same, isolated as it is in its own function.

I am willing to believe in mysterious interactions with
the rest of the boot process. To that end, would the
several folks that have been having Alpha timer problems
try out the following patch?

r~

diff -rup 2.2.0-pre5/arch/alpha/kernel/irq.c 2.2.0-pre5-axp/arch/alpha/kernel/irq.c
--- 2.2.0-pre5/arch/alpha/kernel/irq.c Thu Jan 7 15:51:29 1999
+++ 2.2.0-pre5-axp/arch/alpha/kernel/irq.c Thu Jan 7 22:06:16 1999
@@ -314,14 +314,14 @@ free_irq(unsigned int irq, void *dev_id)

int get_irq_list(char *buf)
{
- int i, j;
+ int i;
struct irqaction * action;
char *p = buf;

#ifdef __SMP__
p += sprintf(p, " ");
- for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "CPU%d ", j);
+ for (i = 0; j < smp_num_cpus; i++)
+ p += sprintf(p, "CPU%d ", i);
*p++ = '\n';
#endif

diff -rup 2.2.0-pre5/arch/alpha/kernel/proto.h 2.2.0-pre5-axp/arch/alpha/kernel/proto.h
--- 2.2.0-pre5/arch/alpha/kernel/proto.h Mon Oct 12 11:40:12 1998
+++ 2.2.0-pre5-axp/arch/alpha/kernel/proto.h Thu Jan 7 22:53:10 1999
@@ -129,8 +129,6 @@ extern void tsunami_init_arch(unsigned l
extern void tsunami_machine_check(u64, u64, struct pt_regs *);

/* setup.c */
-extern void init_pit_rest(void);
-extern void generic_init_pit (void);
extern unsigned long srm_hae;

/* smp.c */
@@ -143,6 +141,8 @@ extern void reset_for_srm(void);

/* time.c */
extern void timer_interrupt(int irq, void *dev, struct pt_regs * regs);
+extern void rtc_init_pit(void);
+extern void generic_init_pit(void);
extern unsigned long est_cycle_freq;

/* smc37c93x.c */
diff -rup 2.2.0-pre5/arch/alpha/kernel/setup.c 2.2.0-pre5-axp/arch/alpha/kernel/setup.c
--- 2.2.0-pre5/arch/alpha/kernel/setup.c Mon Dec 28 16:15:31 1998
+++ 2.2.0-pre5-axp/arch/alpha/kernel/setup.c Thu Jan 7 22:03:01 1999
@@ -275,6 +275,16 @@ setup_arch(char **cmdline_p, unsigned lo
if (alpha_mv.init_arch)
alpha_mv.init_arch(memory_start_p, memory_end_p);

+ /* Initialize the timers. */
+ /* ??? There is some circumstantial evidence that this needs
+ to be done now rather than later in time_init, which would
+ be more natural. Someone please explain or refute. */
+#if defined(CONFIG_RTC)
+ rtc_init_pit();
+#else
+ alpha_mv.init_pit();
+#endif
+
/*
* Give us a default console. TGA users will see nothing until
* chr_dev_init is called, rather late in the boot sequence.
diff -rup 2.2.0-pre5/arch/alpha/kernel/sys_ruffian.c 2.2.0-pre5-axp/arch/alpha/kernel/sys_ruffian.c
--- 2.2.0-pre5/arch/alpha/kernel/sys_ruffian.c Mon Dec 28 16:16:03 1998
+++ 2.2.0-pre5-axp/arch/alpha/kernel/sys_ruffian.c Thu Jan 7 22:52:40 1999
@@ -82,7 +82,7 @@ ruffian_device_interrupt(unsigned long v
* then all the PCI slots/INTXs (12-31)
* flash(5) :DWH:
*/
- pld &= 0x00000000ffffff9fUL; /* was ffff7f */
+ pld &= 0x00000000ffffff9fUL; /* was ffff7f */

/*
* Now for every possible bit set, work through them and call
@@ -118,12 +118,12 @@ ruffian_device_interrupt(unsigned long v
} else {
handle_irq(j, j, regs);
}
- } else { /* if not an ISA int */
+ } else { /* if not an ISA int */
handle_irq(16 + i, 16 + i, regs);
}

- *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
- *(vulp)PYXIS_INT_REQ; /* read to force the write */
+ *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
+ *(vulp)PYXIS_INT_REQ; /* read to force the write */
}
}

@@ -222,7 +222,7 @@ ruffian_init_arch(unsigned long *mem_sta

pyxis_enable_errors();
if (!pyxis_srm_window_setup()) {
- printk("ruffian_init_arch: Skipping window register rewrites."
+ printk("ruffian_init_arch: Skipping window register rewrites."
"\n... Trust DeskStation firmware!\n");
}
pyxis_finish_init_arch();
@@ -233,7 +233,10 @@ ruffian_init_pit (void)
{
/* Ruffian depends on the system timer established in MILO! */
request_region(0x70, 0x10, "timer");
- init_pit_rest();
+
+ outb(0xb6, 0x43); /* pit counter 2: speaker */
+ outb(0x31, 0x42);
+ outb(0x13, 0x42);
}

static void
diff -rup 2.2.0-pre5/arch/alpha/kernel/time.c 2.2.0-pre5-axp/arch/alpha/kernel/time.c
--- 2.2.0-pre5/arch/alpha/kernel/time.c Mon Dec 28 16:16:03 1998
+++ 2.2.0-pre5-axp/arch/alpha/kernel/time.c Thu Jan 7 22:23:29 1999
@@ -158,43 +158,28 @@ static inline unsigned long mktime(unsig
* drivers depend on them being initialized (e.g., joystick driver).
*/

-/* It is (normally) only counter 0 that presents config problems, so
- provide this support function to do the rest of the job. */
-
-void inline
-init_pit_rest(void)
-{
-#if 0
- /* Leave refresh timer alone---nobody should depend on a
- particular value anyway. */
- outb(0x54, 0x43); /* counter 1: refresh timer */
- outb(0x18, 0x41);
-#endif
-
- outb(0xb6, 0x43); /* counter 2: speaker */
- outb(0x31, 0x42);
- outb(0x13, 0x42);
-}
-
#ifdef CONFIG_RTC
-static inline void
+void
rtc_init_pit (void)
{
unsigned char control;

- /* Setup interval timer if /dev/rtc is being used */
+ /* Turn off RTC interrupts before /dev/rtc is initialized */
+ control = CMOS_READ(RTC_CONTROL);
+ control &= ~(RTC_PIE | RTC_AIE | RTC_UIE);
+ CMOS_WRITE(control, RTC_CONTROL);
+ (void) CMOS_READ(RTC_INTR_FLAGS);
+
+ request_region(0x40, 0x20, "timer"); /* reserve pit */
+
+ /* Setup interval timer. */
outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
outb(LATCH & 0xff, 0x40); /* LSB */
outb(LATCH >> 8, 0x40); /* MSB */
- request_region(0x40, 0x20, "timer"); /* reserve pit */

- /* Turn off RTC interrupts before /dev/rtc is initialized */
- control = CMOS_READ(RTC_CONTROL);
- control &= ~(RTC_PIE | RTC_AIE | RTC_UIE);
- CMOS_WRITE(control, RTC_CONTROL);
- CMOS_READ(RTC_INTR_FLAGS);
-
- init_pit_rest();
+ outb(0xb6, 0x43); /* pit counter 2: speaker */
+ outb(0x31, 0x42);
+ outb(0x13, 0x42);
}
#endif

@@ -203,7 +188,7 @@ generic_init_pit (void)
{
unsigned char x;

- /* Reset periodic interrupt frequency. */
+ /* Reset periodic interrupt frequency. */
x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f;
if (x != 0x26 && x != 0x19 && x != 0x06) {
printk("Setting RTC_FREQ to 1024 Hz (%x)\n", x);
@@ -218,36 +203,26 @@ generic_init_pit (void)
x &= ~(RTC_AIE | RTC_UIE);
CMOS_WRITE(x, RTC_CONTROL);
}
- CMOS_READ(RTC_INTR_FLAGS);
+ (void) CMOS_READ(RTC_INTR_FLAGS);

request_region(RTC_PORT(0), 0x10, "timer"); /* reserve rtc */

- /* Turn off the PIT. */
- outb(0x36, 0x43); /* counter 0: system timer */
+ outb(0x36, 0x43); /* pit counter 0: system timer */
outb(0x00, 0x40);
outb(0x00, 0x40);

- init_pit_rest();
+ outb(0xb6, 0x43); /* pit counter 2: speaker */
+ outb(0x31, 0x42);
+ outb(0x13, 0x42);
}

-/* This probably isn't Right, but it is what the old code did. */
-#if defined(CONFIG_RTC)
-# define init_pit rtc_init_pit
-#else
-# define init_pit alpha_mv.init_pit
-#endif
-
-
void
time_init(void)
{
- void (*irq_handler)(int, void *, struct pt_regs *);
+ void (*irq_handler)(int, void *, struct pt_regs *);
unsigned int year, mon, day, hour, min, sec, cc1, cc2;
unsigned long cycle_freq;

- /* Initialize the timers. */
- init_pit();
-
/*
* The Linux interpretation of the CMOS clock register contents:
* When the Update-In-Progress (UIP) flag goes from 1 to 0, the
@@ -322,8 +297,8 @@ time_init(void)
state.partial_tick = 0L;

/* setup timer */
- irq_handler = timer_interrupt;
- if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL))
+ irq_handler = timer_interrupt;
+ if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL))
panic("Could not allocate timer IRQ!");
}

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