[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

rusty old patches and smp behaviour



hi,

i brought my nautilus system back online and decided to update an old
patch of mine that switches the system timer to the programmable
interval timer. that allows you to use the real-time clock for other
purposes besides the timer tick. on my system, everything except the
alarm functionality works. the patch does the following:
    1) adds a CONFIG_ALPHA_PIT that configures the pit to generate
       timer interrupts.
    2) moves all of the timing code into the timer_interrupt as
       opposed to being called directly from the entInt vector. 
    3) make the entInt vector just trigger an rtc interrupt.

that way, toggling between use of the rtc or the pit for timer
interrupts is soley dependent upon what's passed to setup_irq. oh
yeah, it also exports plat_node_data as a bunch of modules don't build
without it exported.

however, i'm not sure if i'm doing the right thing for an smp system.
so, could i get someone using an smp system to do the following for
me?
    1) send me /proc/interrupts on pre-patched system.
    2) apply patch. tell me if the system still works for both
       CONFIG_ALPHA_PIT=y and n.
    3) send me /proc/interrupts for both options.
    4) try using /dev/rtc with _PIT=y and see what parts work.

thanks,

-a

here's the patch against 2.4.20:
--- kernel-source-2.4.20/Documentation/Configure.help.save	2003-02-05 23:40:11.000000000 -0800
+++ kernel-source-2.4.20/Documentation/Configure.help	2003-02-07 00:01:09.000000000 -0800
@@ -26347,6 +26347,12 @@
 
   If unsure, say N.
 
+Alpha programmable interval timer (EXPERIMENTAL)
+CONFIG_ALPHA_PIT
+  Say Y to use the programmable interval timer instead of the real-time 
+  clock for the timer interrupt. You may not want to do this on an SMP
+  system.
+
 #
 # A couple of things I keep forgetting:
 #   capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
--- kernel-source-2.4.20/arch/alpha/kernel/time.c.save	2003-02-06 00:01:14.000000000 -0800
+++ kernel-source-2.4.20/arch/alpha/kernel/time.c	2003-02-06 23:51:50.000000000 -0800
@@ -95,8 +95,10 @@
 	__u32 now;
 	long nticks;
 
-#ifndef CONFIG_SMP
-	/* Not SMP, do kernel PC profiling here.  */
+#ifdef CONFIG_SMP
+	if (smp_percpu_timer_interrupt(regs) < 0)
+		return;
+#else
 	if (!user_mode(regs))
 		alpha_do_profile(regs->pc);
 #endif
@@ -141,6 +143,7 @@
 {
 	unsigned char x;
 
+#ifndef CONFIG_ALPHA_PIT
 	/* Reset periodic interrupt frequency.  */
 	x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f;
 	if (x != 0x26 && x != 0x19 && x != 0x06) {
@@ -161,6 +164,19 @@
 	outb(0x36, 0x43);	/* pit counter 0: system timer */
 	outb(0x00, 0x40);
 	outb(0x00, 0x40);
+#else
+	/* Turn off periodic interrupts.  */
+	x = CMOS_READ(RTC_CONTROL);
+	if (x & RTC_PIE) {
+		x &= ~(RTC_UIE | RTC_PIE);
+		CMOS_WRITE(x, RTC_CONTROL);
+	}
+	(void) CMOS_READ(RTC_INTR_FLAGS);
+
+	outb(0x34, 0x43);       /* binary, mode 2, LSB/MSB, ch 0 */
+	outb_p(LATCH & 0xff, 0x40);
+	outb_p(LATCH >> 8, 0x40);
+#endif
 
 	outb(0xb6, 0x43);	/* pit counter 2: speaker */
 	outb(0x31, 0x42);
--- kernel-source-2.4.20/arch/alpha/kernel/smp.c.save	2003-02-06 00:06:39.000000000 -0800
+++ kernel-source-2.4.20/arch/alpha/kernel/smp.c	2003-02-07 00:57:17.000000000 -0800
@@ -684,7 +684,7 @@
 }
 
 
-void
+int
 smp_percpu_timer_interrupt(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
@@ -696,19 +696,16 @@
 		alpha_do_profile(regs->pc);
 
 	if (!--data->prof_counter) {
-		/* We need to make like a normal interrupt -- otherwise
-		   timer interrupts ignore the global interrupt lock,
-		   which would be a Bad Thing.  */
-		irq_enter(cpu, RTC_IRQ);
-
 		update_process_times(user);
-
 		data->prof_counter = data->prof_multiplier;
-		irq_exit(cpu, RTC_IRQ);
+	}
 
-		if (softirq_pending(cpu))
-			do_softirq();
+	if (cpu != boot_cpuid) {
+		irq_attempt(cpu, TIMER_IRQ)++;
+		kstat.irqs[cpu][TIMER_IRQ]++;
+		return -1;
 	}
+	return 0;
 }
 
 int __init
--- kernel-source-2.4.20/arch/alpha/kernel/irq_alpha.c.save	2003-02-06 00:48:14.000000000 -0800
+++ kernel-source-2.4.20/arch/alpha/kernel/irq_alpha.c	2003-02-06 23:55:12.000000000 -0800
@@ -57,21 +57,7 @@
 #endif
 		break;
 	case 1:
-#ifdef CONFIG_SMP
-	  {
-		long cpu;
-		smp_percpu_timer_interrupt(&regs);
-		cpu = smp_processor_id();
-		if (cpu != boot_cpuid) {
-		        irq_attempt(cpu, RTC_IRQ)++;
-		        kstat.irqs[cpu][RTC_IRQ]++;
-		} else {
-			handle_irq(RTC_IRQ, &regs);
-		}
-	  }
-#else
 		handle_irq(RTC_IRQ, &regs);
-#endif
 		return;
 	case 2:
 		alpha_mv.machine_check(vector, la_ptr, &regs);
@@ -214,15 +200,10 @@
  * processed by PALcode, and comes in via entInt vector 1.
  */
 
+#ifndef CONFIG_ALPHA_PIT
 static void rtc_enable_disable(unsigned int irq) { }
 static unsigned int rtc_startup(unsigned int irq) { return 0; }
 
-struct irqaction timer_irqaction = {
-	handler:	timer_interrupt,
-	flags:		SA_INTERRUPT,
-	name:		"timer",
-};
-
 static struct hw_interrupt_type rtc_irq_type = {
 	typename:	"RTC",
 	startup:	rtc_startup,
@@ -232,13 +213,22 @@
 	ack:		rtc_enable_disable,
 	end:		rtc_enable_disable,
 };
+#endif
+
+struct irqaction timer_irqaction = {
+	handler:	timer_interrupt,
+	flags:		SA_INTERRUPT,
+	name:		"timer",
+};
 
 void __init
 init_rtc_irq(void)
 {
+#ifndef CONFIG_ALPHA_PIT
 	irq_desc[RTC_IRQ].status = IRQ_DISABLED;
 	irq_desc[RTC_IRQ].handler = &rtc_irq_type;
-	setup_irq(RTC_IRQ, &timer_irqaction);
+#endif
+	setup_irq(TIMER_IRQ, &timer_irqaction);
 }
 
 /* Dummy irqactions.  */
--- kernel-source-2.4.20/arch/alpha/kernel/irq_impl.h.save	2003-02-06 00:05:56.000000000 -0800
+++ kernel-source-2.4.20/arch/alpha/kernel/irq_impl.h	2003-02-07 00:50:09.000000000 -0800
@@ -8,12 +8,18 @@
  * with the IRQ handling routines in irq.c.
  */
 
+#include <linux/config.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 
-
 #define RTC_IRQ    8
 
+#ifdef CONFIG_ALPHA_PIT
+#define TIMER_IRQ  0
+#else
+#define TIMER_IRQ  RTC_IRQ 
+#endif
+
 extern void isa_device_interrupt(unsigned long, struct pt_regs *);
 extern void isa_no_iack_sc_device_interrupt(unsigned long, struct pt_regs *);
 extern void srm_device_interrupt(unsigned long, struct pt_regs *);
--- kernel-source-2.4.20/arch/alpha/kernel/alpha_ksyms.c.save	2003-02-06 09:40:56.000000000 -0800
+++ kernel-source-2.4.20/arch/alpha/kernel/alpha_ksyms.c	2003-02-06 09:46:14.000000000 -0800
@@ -238,6 +238,7 @@
 #endif /* CONFIG_SMP */
 
 EXPORT_SYMBOL(rtc_lock);
+EXPORT_SYMBOL(plat_node_data);
 
 /*
  * The following are special because they're not called
--- kernel-source-2.4.20/arch/alpha/kernel/proto.h.save	2003-02-07 00:02:44.000000000 -0800
+++ kernel-source-2.4.20/arch/alpha/kernel/proto.h	2003-02-07 00:49:53.000000000 -0800
@@ -92,7 +92,7 @@
 /* smp.c */
 extern void setup_smp(void);
 extern void handle_ipi(struct pt_regs *);
-extern void smp_percpu_timer_interrupt(struct pt_regs *);
+extern int smp_percpu_timer_interrupt(struct pt_regs *);
 
 /* bios32.c */
 /* extern void reset_for_srm(void); */
--- kernel-source-2.4.20/arch/alpha/config.in.save	2003-02-05 23:39:57.000000000 -0800
+++ kernel-source-2.4.20/arch/alpha/config.in	2003-02-06 01:51:16.000000000 -0800
@@ -254,6 +254,7 @@
    if [ "$CONFIG_DISCONTIGMEM" = "y" ]; then
       bool ' NUMA Support (EXPERIMENTAL)' CONFIG_NUMA
    fi
+   bool 'Alpha programmable interval timer (EXPERIMENTAL)' CONFIG_ALPHA_PIT
 fi
 
 # LARGE_VMALLOC is racy, if you *really* need it then fix it first
--- kernel-source-2.4.20/include/asm-alpha/mc146818rtc.h.save	2003-02-05 23:37:23.000000000 -0800
+++ kernel-source-2.4.20/include/asm-alpha/mc146818rtc.h	2003-02-07 00:18:11.000000000 -0800
@@ -4,6 +4,7 @@
 #ifndef __ASM_ALPHA_MC146818RTC_H
 #define __ASM_ALPHA_MC146818RTC_H
 
+#include <linux/config.h>
 #include <asm/io.h>
 
 #ifndef RTC_PORT
@@ -24,4 +25,8 @@
 outb_p((val),RTC_PORT(1)); \
 })
 
+#ifdef CONFIG_ALPHA_PIT
+#define RTC_IRQ 8
+#endif
+
 #endif /* __ASM_ALPHA_MC146818RTC_H */
 



Reply to: