public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* RE: IO-APIC on nforce2 [PATCH]
@ 2004-04-15 18:33 Allen Martin
  2004-04-15 19:20 ` Craig Bradney
  2004-04-15 19:50 ` Len Brown
  0 siblings, 2 replies; 27+ messages in thread
From: Allen Martin @ 2004-04-15 18:33 UTC (permalink / raw)
  To: ross, Len Brown, Christian Kröner, Linux-Nforce-Bugs
  Cc: linux-kernel, Maciej W. Rozycki

> True it is a bios thing but I have yet to see an nforce2 MOBO 
> that is not 
> routed in this way. I am thinking it is internal to the 
> chipset. I have seen
> none route it into io-apic pin2.

It was a bug in our original nForce reference BIOS that we gave out to vendors.  Since then we fixed the reference BIOS, but since it was after products shipped, most of the motherboard vendors won't pick up the change unless they get complaints from customers.

We've fixed it for our reference BIOS for future products though.


-Allen

^ permalink raw reply	[flat|nested] 27+ messages in thread
* RE: IO-APIC on nforce2 [PATCH]
@ 2004-04-23  1:23 Allen Martin
  2004-04-23 15:39 ` Maciej W. Rozycki
  0 siblings, 1 reply; 27+ messages in thread
From: Allen Martin @ 2004-04-23  1:23 UTC (permalink / raw)
  To: Maciej W. Rozycki, Len Brown
  Cc: Jamie Lokier, ross, Christian Kröner, Linux-Nforce-Bugs,
	linux-kernel

>  Allen, is there a possibility to get a clarification from 
> Nvidia on that?  
> Specifically, assuming both an 8254 and an I/O APIC core are 
> integrated
> into the chip, whether OUT0 of the 8254 is unconditionally routed to
> INTIN0 of the I/O APIC or is it configurable somehow.

The 8254 PIT is hardwared to IRQ0 on all nForce chipsets, it can't be routed.

-Allen

^ permalink raw reply	[flat|nested] 27+ messages in thread
* RE: IO-APIC on nforce2 [PATCH]
@ 2004-04-16 16:41 Allen Martin
  0 siblings, 0 replies; 27+ messages in thread
From: Allen Martin @ 2004-04-16 16:41 UTC (permalink / raw)
  To: Len Brown
  Cc: ross, Christian Kröner, Linux-Nforce-Bugs, linux-kernel,
	Maciej W. Rozycki

> I'm also excited to see a linux-nforce-bugs@exchange.nvidia.com alias
> on your note.  Perhaps you can explain how we should use it.  Should
> this alias be included on discussions of the more important issue --
> the system hang that seems to be related to HALT in idle/C1?

Yes, any issues that are relevant to linux operation on nForce boards can go there.  That list gets a lot of volume though, so any pressing issue that needs a response you can cc me directly.

-Allen

^ permalink raw reply	[flat|nested] 27+ messages in thread
* Re: IO-APIC on nforce2 [PATCH]
@ 2004-04-14 21:01 Christian Kröner
  2004-04-15  0:35 ` Peter Clifton
  2004-04-15  0:41 ` Ross Dickson
  0 siblings, 2 replies; 27+ messages in thread
From: Christian Kröner @ 2004-04-14 21:01 UTC (permalink / raw)
  To: linux-kernel; +Cc: Len Brown, Maciej W. Rozycki, ross

> Just would like to add that if we cannot get Maciej's 8259 ack patch
> back into the distro then we need an if statement in the check_timer()
> to turn off timer_ack for nforce2 or Christian might get his hi-load back
> and certainly nmi_debug=1 won't work.
>
> e.g. for 2.4.26-rc2 io_apic.c line 1613 or 2.6.5 line 2180
>       if (pin1 != -1) {
>               /*
>                * Ok, does IRQ0 through the IOAPIC work?
>                */
> +             if(acpi_skip_timer_override)
> +                     timer_ack=0;
>               unmask_IO_APIC_irq(0);
>

Also on mainline 2.6.5 this if-statement doesn't seem to be necessary. Len's 
patch worked on this kernel as well, setting the timer interrupt to 
IO-APIC-edge and there is no strange hi-load anymore too.

thanks, christian.

^ permalink raw reply	[flat|nested] 27+ messages in thread
* Re: IO-APIC on nforce2
@ 2004-04-13  1:17 Ross Dickson
  2004-04-13  5:08 ` Len Brown
  0 siblings, 1 reply; 27+ messages in thread
From: Ross Dickson @ 2004-04-13  1:17 UTC (permalink / raw)
  To: christian.kroener; +Cc: linux-kernel, Maciej W. Rozycki, Len Brown

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

Christian Kröner wrote

> I got a problem using LOCAL APIC and IO-APIC on my uniprocessor nforce2 board. 
> With recent kernels (latest -mm and 2.6.5-linus) the timer irq gets set to 
> XT-PIC, which results in having a constant hi-load of 15% (after booting) to 
> about 25% (after having the system run about 12 h). Earlier versions of -mm 
> set the timer-irq to IO-APIC-level (or edge, i dont remember it well) and i 
> never had any constant hi-load with these versions. Since mainline kernel 
> versions never ever set the timer irq to IO-APIC-{level,edge} i used to patch 
> them with the ross' nforce-patches, so that the timer-irq gets to be 
> IO-APCI-edge, which worked even though the patch applied with offset. Anyways 
> with the latest mm-kernels these patches dont work anymore. I could apply 
> them with offset but it seems the code isn't used or something else is wrong 
> since the timer-irq stays XT-PIC, which results in the problems above. Could 
> anyone point out, how to resolve this problem or tell me what I could do, to 
> get my timer-irq right? I'm sure willing to test patches... 
> Thanks in advance, christian. 
> - 


Hi Christian

I don't know why the high load on xtpic except maybe heaps of spurious irq's 
under the hood.

I am working with 2.4.26-rc2 and have noticed a change with the the recent acpi?
update. The recent fix to stop unnecessary ioapic irq routing entries puts the 
following if statement into io_apic.c, io_apic_set_pci_routing()

	/*
	 * IRQs < 16 are already in the irq_2_pin[] map
	 */
	if (irq >= 16)
		add_pin_to_irq(irq, ioapic, pin);

which prevents my io-apic patch from using that function to reprogram the
io-apic pin on irq0 from pin2 to pin0. 

As a quick fix you could drop the "if (irq >= 16)".
I don't know what harm if any that would do other than create unwanted
irq mapping entries as in the past.

As a better solution to work with the new code I have created a function to
change the pin an irq comes into the io-apic on and also re-initialise the 
io-apic to deal with the change. 

Here is the function for 2.4.26-rc2.

/*
 * reroute irq to different pin clearing old and enabling new
 */
static void __init replace_IO_APIC_pin_at_irq(unsigned int irq,
						int oldapic, int oldpin,
						int newapic, int newpin)
{
	struct IO_APIC_route_entry entry;
	unsigned long flags;
	/*
	 * read oldapic entry
	 */
	spin_lock_irqsave(&ioapic_lock, flags);
	*(((int*)&entry) + 0) = io_apic_read(oldapic, 0x10 + 2 * oldpin);
	*(((int*)&entry) + 1) = io_apic_read(oldapic, 0x11 + 2 * oldpin);
	spin_unlock_irqrestore(&ioapic_lock, flags);
	/*
	 * Check delivery_mode to be sure we're not clearing an SMI pin
	 */
	if (entry.delivery_mode == dest_SMI)
		return;
	/*
	 * clear oldpin on oldapic
	 */
	clear_IO_APIC_pin(oldapic, oldpin);
	/*
	 * reroute irq to newpin on newapic
	 */
	replace_pin_at_irq(irq, oldapic, oldpin, newapic, newpin);
	/*
	 * Enable newpin on newapic
	*/
	spin_lock_irqsave(&ioapic_lock, flags);
	io_apic_write(newapic, 0x10 + 2*newpin, *(((int *)&entry) + 0));
	io_apic_write(newapic, 0x11 + 2*newpin, *(((int *)&entry) + 1));
	spin_unlock_irqrestore(&ioapic_lock, flags);
}

I am now using this instead of the io_apic_set_pci_routing().
My modified check_timer() to work with it is as follows.

/*
 * This code may look a bit paranoid, but it's supposed to cooperate with
 * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
 * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
 * fanatically on his truly buggy board.
 */
static inline void check_timer(void)
{
	extern int timer_ack;
	int pin1, pin2;
	int vector, i;

	/*
	 * get/set the timer IRQ vector:
	 */
	disable_8259A_irq(0);
	vector = assign_irq_vector(0);
	set_intr_gate(vector, interrupt[0]);

	/*
	 * Subtle, code in do_timer_interrupt() expects an AEOI
	 * mode for the 8259A whenever interrupts are routed
	 * through I/O APICs.  Also IRQ0 has to be enabled in
	 * the 8259A which implies the virtual wire has to be
	 * disabled in the local APIC.
	 */
	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
	init_8259A(1);
	timer_ack = 1;
	enable_8259A_irq(0);

	pin1 = find_isa_irq_pin(0, mp_INT);
	pin2 = find_isa_irq_pin(0, mp_ExtINT);

	printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);

	if (pin1 != -1) {
		for(i=0;i<2;i++) {
			/*
			 * Ok, does IRQ0 through the IOAPIC work?
			 */
			unmask_IO_APIC_irq(0);
			if (timer_irq_works()) {
				if (nmi_watchdog == NMI_IO_APIC) {
					disable_8259A_irq(0);
					setup_nmi();
					enable_8259A_irq(0);
					check_nmi_watchdog();
				}
				printk(KERN_INFO "..TIMER: works OK on IO-APIC irq0\n" );
				return;
			}
			mask_IO_APIC_irq(0);
			if(!i) { /* try INTIN0 if INTIN2 failed */
				printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC INTIN%d\n",pin1);
				printk(KERN_INFO "..TIMER: Check if 8254 timer connected to IO-APIC INTIN0? ...\n");
				replace_IO_APIC_pin_at_irq(0, 0, pin1, 0, 0);
				timer_ack=0;
				disable_8259A_irq(0);
			} else { /* restore settings */
				clear_IO_APIC_pin(0, 0);
				printk(KERN_ERR "..TIMER: 8254 timer not connected to IO-APIC INTIN0\n");
				timer_ack=1;
				enable_8259A_irq(0);
			}
		}
	}

	printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
	if (pin2 != -1) {
		printk("\n..... (found pin %d) ...", pin2);
		/*
		 * legacy devices should be connected to IO APIC #0
		 */
		setup_ExtINT_IRQ0_pin(pin2, vector);
		if (timer_irq_works()) {
			printk("works.\n");
			if (pin1 != -1)
				replace_pin_at_irq(0, 0, pin1, 0, pin2);
			else
				add_pin_to_irq(0, 0, pin2);
			if (nmi_watchdog == NMI_IO_APIC) {
				setup_nmi();
				check_nmi_watchdog();
			}
			return;
		}
		/*
		 * Cleanup, just in case ...
		 */
		clear_IO_APIC_pin(0, pin2);
	}
	printk(" failed.\n");

	if (nmi_watchdog) {
		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
		nmi_watchdog = 0;
	}

	printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");

	disable_8259A_irq(0);
	irq_desc[0].handler = &lapic_irq_type;
	apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
	enable_8259A_irq(0);

	if (timer_irq_works()) {
		printk(" works.\n");
		return;
	}
	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
	printk(" failed.\n");

	printk(KERN_INFO "...trying to set up timer as ExtINT IRQ...");

	init_8259A(0);
	make_8259A_irq(0);
	apic_write_around(APIC_LVT0, APIC_DM_EXTINT);

	unlock_ExtINT_logic();

	if (timer_irq_works()) {
		printk(" works.\n");
		return;
	}
	printk(" failed :(.\n");
	panic("IO-APIC + timer doesn't work! pester mingo@redhat.com");
}

This version loops twice on the "pin1" attempt, firstly trying the bios assigned
pin, then trying pin0 with no timer acks and the 8259 xtpic disabled.

I have not as yet downloaded 2.6.5xxx
From memory this 2.4.26-rc2 code should be very similar to the (2.6.5-linus)
but a bit different to the -mm series. For the -mm series I think you can drop
the "timer_ack=" lines from my changes as it still has Maciej Rozycki's 8259 
ack patch? The timer ack should already have been correctly set to off by it's
checking if the apic is an integrated one.

Here are the changes as a diff on the io_apic.c in 2.4.26-rc2

--- io_apic.c.orig	2004-04-08 15:56:53.000000000 +1000
+++ io_apic.c	2004-04-10 02:33:02.000000000 +1000
@@ -197,10 +197,48 @@ static void clear_IO_APIC (void)
 		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
 			clear_IO_APIC_pin(apic, pin);
 }

 /*
+ * reroute irq to different pin clearing old and enabling new
+ */
+static void __init replace_IO_APIC_pin_at_irq(unsigned int irq,
+						int oldapic, int oldpin,
+						int newapic, int newpin)
+{
+	struct IO_APIC_route_entry entry;
+	unsigned long flags;
+	/*
+	 * read oldapic entry
+	 */
+	spin_lock_irqsave(&ioapic_lock, flags);
+	*(((int*)&entry) + 0) = io_apic_read(oldapic, 0x10 + 2 * oldpin);
+	*(((int*)&entry) + 1) = io_apic_read(oldapic, 0x11 + 2 * oldpin);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+	/*
+	 * Check delivery_mode to be sure we're not clearing an SMI pin
+	 */
+	if (entry.delivery_mode == dest_SMI)
+		return;
+	/*
+	 * clear oldpin on oldapic
+	 */
+	clear_IO_APIC_pin(oldapic, oldpin);
+	/*
+	 * reroute irq to newpin on newapic
+	 */
+	replace_pin_at_irq(irq, oldapic, oldpin, newapic, newpin);
+	/*
+	 * Enable newpin on newapic
+	*/
+	spin_lock_irqsave(&ioapic_lock, flags);
+	io_apic_write(newapic, 0x10 + 2*newpin, *(((int *)&entry) + 0));
+	io_apic_write(newapic, 0x11 + 2*newpin, *(((int *)&entry) + 1));
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+/*
  * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
  * specific CPU-side IRQs.
  */

 #define MAX_PIRQS 8
@@ -1582,11 +1620,11 @@ static inline void unlock_ExtINT_logic(v
  */
 static inline void check_timer(void)
 {
 	extern int timer_ack;
 	int pin1, pin2;
-	int vector;
+	int vector, i;

 	/*
 	 * get/set the timer IRQ vector:
 	 */
 	disable_8259A_irq(0);
@@ -1609,25 +1647,39 @@ static inline void check_timer(void)
 	pin2 = find_isa_irq_pin(0, mp_ExtINT);

 	printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);

 	if (pin1 != -1) {
-		/*
-		 * Ok, does IRQ0 through the IOAPIC work?
-		 */
-		unmask_IO_APIC_irq(0);
-		if (timer_irq_works()) {
-			if (nmi_watchdog == NMI_IO_APIC) {
+		for(i=0;i<2;i++) {
+			/*
+			 * Ok, does IRQ0 through the IOAPIC work?
+			 */
+			unmask_IO_APIC_irq(0);
+			if (timer_irq_works()) {
+				if (nmi_watchdog == NMI_IO_APIC) {
+					disable_8259A_irq(0);
+					setup_nmi();
+					enable_8259A_irq(0);
+					check_nmi_watchdog();
+				}
+				printk(KERN_INFO "..TIMER: works OK on IO-APIC irq0\n" );
+				return;
+			}
+			mask_IO_APIC_irq(0);
+			if(!i) { /* try INTIN0 if INTIN2 failed */
+				printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC INTIN%d\n",pin1);
+				printk(KERN_INFO "..TIMER: Check if 8254 timer connected to IO-APIC INTIN0? ...\n");
+				replace_IO_APIC_pin_at_irq(0, 0, pin1, 0, 0);
+				timer_ack=0;
 				disable_8259A_irq(0);
-				setup_nmi();
+			} else { /* restore settings */
+				clear_IO_APIC_pin(0, 0);
+				printk(KERN_ERR "..TIMER: 8254 timer not connected to IO-APIC INTIN0\n");
+				timer_ack=1;
 				enable_8259A_irq(0);
-				check_nmi_watchdog();
 			}
-			return;
 		}
-		clear_IO_APIC_pin(0, pin1);
-		printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
 	}

 	printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
 	if (pin2 != -1) {
 		printk("\n..... (found pin %d) ...", pin2);

Also attached as tarball if whitespace problems,
Hope this helps, Please cc me on responses,
Ross Dickson


[-- Attachment #2: nforce2-ioapic-rd-2.4.26-rc2.patch.tgz --]
[-- Type: application/x-tgz, Size: 1420 bytes --]

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

end of thread, other threads:[~2004-04-23 15:39 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-15 18:33 IO-APIC on nforce2 [PATCH] Allen Martin
2004-04-15 19:20 ` Craig Bradney
2004-04-15 19:50 ` Len Brown
2004-04-16  8:27   ` Jamie Lokier
2004-04-22  4:00     ` Len Brown
2004-04-22 13:22       ` Maciej W. Rozycki
2004-04-22 13:53         ` Christian Kröner
2004-04-22 15:27           ` Len Brown
2004-04-22 15:40             ` Maciej W. Rozycki
2004-04-22 16:15             ` Christian Kröner
  -- strict thread matches above, loose matches on Subject: below --
2004-04-23  1:23 Allen Martin
2004-04-23 15:39 ` Maciej W. Rozycki
2004-04-16 16:41 Allen Martin
2004-04-14 21:01 Christian Kröner
2004-04-15  0:35 ` Peter Clifton
2004-04-15  0:29   ` Craig Bradney
2004-04-15  0:41 ` Ross Dickson
2004-04-13  1:17 IO-APIC on nforce2 Ross Dickson
2004-04-13  5:08 ` Len Brown
2004-04-13  7:03   ` Ross Dickson
2004-04-14  1:02     ` IO-APIC on nforce2 [PATCH] Len Brown
2004-04-14  5:02       ` Ross Dickson
2004-04-14  6:30         ` Jamie Lokier
2004-04-14 10:37         ` Maciej W. Rozycki
2004-04-15 19:28           ` Len Brown
2004-04-14 19:57         ` Christian Kröner
2004-04-15  0:17           ` Len Brown
2004-04-15  1:48             ` Ross Dickson
2004-04-15 17:09               ` Christian Kröner
2004-04-15 15:21       ` Zwane Mwaikambo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox