[PATCH 2.6.11.7 1/1] x86 reboot: Add reboot fixup for gx1/cs5530a

2005-04-11 Thread jayalk
Hi Peter, 

As per your suggestion, I switched do {} while(0) to ((void)(0))
for the dummy define, since it's an argumentless function.

Please let me know if it's okay now.

Thanks,
Jaya Kumar

--- 

I ran into a problem getting reboot working with 2.6.11 on an embedded
board. The board has a Geode GX1 with a CS5530A companion. What I observe on
reboot is the "Restarting system" printk, and then a cpu stall/hang. I think
the problem arises because the keyboard controller is disabled by the BIOS,
so the traditional mach_reboot()'s output to port 0x64 is ignored. Then the
386 triple fault issued after mach_reboot() results in a shutdown (because
the hardware doesn't have to detect the triple fault and issue a reset).
That then gives the end result of a stalled cpu/hang. 

I found that the CS5530A in question has a "issue system wide reset" bit.
The reboot works cleanly if I write that bit rather than do mach_reboot().
So the following patch is my attempt to incorporate that change into 2.6.11
by adding a X86_REBOOTFIXUPS option. In order to keep reboot.c free of hw
specific fixups, I put it in another file, reboot_fixups.c. I tried to make
it a bit generic so that if there are other reboot related fixups for other
chipsets/boards, there'd be a clean place to put it. Please let me know what
you think.

Thanks,
Jaya Kumar

---

Signed-off-by:  Jaya Kumar  <[EMAIL PROTECTED]>

diff -uprN -X dontdiff linux-2.6.11.7-vanilla/arch/i386/Kconfig 
linux-2.6.11.7/arch/i386/Kconfig
--- linux-2.6.11.7-vanilla/arch/i386/Kconfig2005-04-08 02:57:18.0 
+0800
+++ linux-2.6.11.7/arch/i386/Kconfig2005-04-11 14:21:05.0 +0800
@@ -645,6 +645,24 @@ config I8K
  Say Y if you intend to run this kernel on a Dell Inspiron 8000.
  Say N otherwise.
 
+config X86_REBOOTFIXUPS
+   bool "Enable X86 board specific fixups for reboot"
+   depends on X86 
+   default n
+   ---help---
+ This enables chipset and/or board specific fixups to be done
+ in order to get reboot to work correctly. This is only needed on
+ some combinations of hardware and BIOS. The symptom, for which 
+ this config is intended, is when reboot ends with a stalled/hung 
+ system. 
+
+ Currently, the only fixup is for the Geode GX1/CS5530A/TROM2.1. 
+ combination.
+
+ Say Y if you want to enable the fixup. Currently, it's safe to
+ enable this option even if you don't need it.
+ Say N otherwise.
+
 config MICROCODE
tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
---help---
diff -uprN -X dontdiff linux-2.6.11.7-vanilla/arch/i386/kernel/Makefile 
linux-2.6.11.7/arch/i386/kernel/Makefile
--- linux-2.6.11.7-vanilla/arch/i386/kernel/Makefile2005-04-08 
02:57:22.0 +0800
+++ linux-2.6.11.7/arch/i386/kernel/Makefile2005-04-11 13:10:31.0 
+0800
@@ -23,6 +23,7 @@ obj-$(CONFIG_X86_TRAMPOLINE)  += trampoli
 obj-$(CONFIG_X86_MPPARSE)  += mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)   += apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)  += io_apic.o
+obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o
 obj-$(CONFIG_X86_NUMAQ)+= numaq.o
 obj-$(CONFIG_X86_SUMMIT_NUMA)  += summit.o
 obj-$(CONFIG_KPROBES)  += kprobes.o
diff -uprN -X dontdiff linux-2.6.11.7-vanilla/arch/i386/kernel/reboot.c 
linux-2.6.11.7/arch/i386/kernel/reboot.c
--- linux-2.6.11.7-vanilla/arch/i386/kernel/reboot.c2005-04-08 
02:57:27.0 +0800
+++ linux-2.6.11.7/arch/i386/kernel/reboot.c2005-04-11 13:10:31.0 
+0800
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include "mach_reboot.h"
+#include 
 
 /*
  * Power off function, if any
@@ -348,6 +349,7 @@ void machine_restart(char * __unused)
/* rebooting needs to touch the page at absolute addr 0 */
*((unsigned short *)__va(0x472)) = reboot_mode;
for (;;) {
+   mach_reboot_fixups(); /* for board specific fixups */
mach_reboot();
/* That didn't work - force a triple fault.. */
__asm__ __volatile__("lidt %0": :"m" (no_idt));
diff -uprN -X dontdiff linux-2.6.11.7-vanilla/arch/i386/kernel/reboot_fixups.c 
linux-2.6.11.7/arch/i386/kernel/reboot_fixups.c
--- linux-2.6.11.7-vanilla/arch/i386/kernel/reboot_fixups.c 1970-01-01 
07:30:00.0 +0730
+++ linux-2.6.11.7/arch/i386/kernel/reboot_fixups.c 2005-04-11 
14:09:02.0 +0800
@@ -0,0 +1,56 @@
+/*
+ * linux/arch/i386/kernel/reboot_fixups.c
+ * 
+ * This is a good place to put board specific reboot fixups.
+ *
+ * List of supported fixups:
+ * geode-gx1/cs5530a - Jaya Kumar <[EMAIL PROTECTED]>
+ *
+ */
+
+#include 
+#include 
+
+static void cs5530a_warm_reset(struct pci_dev *dev)
+{
+   /* writing 1 to the reset control register, 0x44 causes the 
+   cs5530a to perform a system warm reset */
+   pci_write_config_byte(dev, 0x44, 0x1);
+   

[PATCH 2.6.11.7 1/1] x86 reboot: Add reboot fixup for gx1/cs5530a

2005-04-11 Thread jayalk
Hi Riley, Dave, Peter, i386 boot/workaround maintainers,

I'm resending this patch (from March 28). 

This patch incorporates the suggestions from the previous thread and also
switches to using pci_get_device since pci_find_device is deprecated, and
made some of the variables static.

Please let me know if it's okay.

Thanks,
Jaya Kumar

--- 

I ran into a problem getting reboot working with 2.6.11 on an embedded
board. The board has a Geode GX1 with a CS5530A companion. What I observe on
reboot is the "Restarting system" printk, and then a cpu stall/hang. I think
the problem arises because the keyboard controller is disabled by the BIOS,
so the traditional mach_reboot()'s output to port 0x64 is ignored. Then the
386 triple fault issued after mach_reboot() results in a shutdown (because
the hardware doesn't have to detect the triple fault and issue a reset).
That then gives the end result of a stalled cpu/hang. 

I found that the CS5530A in question has a "issue system wide reset" bit.
The reboot works cleanly if I write that bit rather than do mach_reboot().
So the following patch is my attempt to incorporate that change into 2.6.11
by adding a X86_REBOOTFIXUPS option. In order to keep reboot.c free of hw
specific fixups, I put it in another file, reboot_fixups.c. I tried to make
it a bit generic so that if there are other reboot related fixups for other
chipsets/boards, there'd be a clean place to put it. Please let me know what
you think.

Thanks,
Jaya Kumar

---

Signed-off-by:  Jaya Kumar  <[EMAIL PROTECTED]>

diff -uprN -X dontdiff linux-2.6.11.7-vanilla/arch/i386/Kconfig 
linux-2.6.11.7/arch/i386/Kconfig
--- linux-2.6.11.7-vanilla/arch/i386/Kconfig2005-04-08 02:57:18.0 
+0800
+++ linux-2.6.11.7/arch/i386/Kconfig2005-04-11 14:21:05.0 +0800
@@ -645,6 +645,24 @@ config I8K
  Say Y if you intend to run this kernel on a Dell Inspiron 8000.
  Say N otherwise.
 
+config X86_REBOOTFIXUPS
+   bool "Enable X86 board specific fixups for reboot"
+   depends on X86 
+   default n
+   ---help---
+ This enables chipset and/or board specific fixups to be done
+ in order to get reboot to work correctly. This is only needed on
+ some combinations of hardware and BIOS. The symptom, for which 
+ this config is intended, is when reboot ends with a stalled/hung 
+ system. 
+
+ Currently, the only fixup is for the Geode GX1/CS5530A/TROM2.1. 
+ combination.
+
+ Say Y if you want to enable the fixup. Currently, it's safe to
+ enable this option even if you don't need it.
+ Say N otherwise.
+
 config MICROCODE
tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
---help---
diff -uprN -X dontdiff linux-2.6.11.7-vanilla/arch/i386/kernel/Makefile 
linux-2.6.11.7/arch/i386/kernel/Makefile
--- linux-2.6.11.7-vanilla/arch/i386/kernel/Makefile2005-04-08 
02:57:22.0 +0800
+++ linux-2.6.11.7/arch/i386/kernel/Makefile2005-04-11 13:10:31.0 
+0800
@@ -23,6 +23,7 @@ obj-$(CONFIG_X86_TRAMPOLINE)  += trampoli
 obj-$(CONFIG_X86_MPPARSE)  += mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)   += apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)  += io_apic.o
+obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o
 obj-$(CONFIG_X86_NUMAQ)+= numaq.o
 obj-$(CONFIG_X86_SUMMIT_NUMA)  += summit.o
 obj-$(CONFIG_KPROBES)  += kprobes.o
diff -uprN -X dontdiff linux-2.6.11.7-vanilla/arch/i386/kernel/reboot.c 
linux-2.6.11.7/arch/i386/kernel/reboot.c
--- linux-2.6.11.7-vanilla/arch/i386/kernel/reboot.c2005-04-08 
02:57:27.0 +0800
+++ linux-2.6.11.7/arch/i386/kernel/reboot.c2005-04-11 13:10:31.0 
+0800
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include "mach_reboot.h"
+#include 
 
 /*
  * Power off function, if any
@@ -348,6 +349,7 @@ void machine_restart(char * __unused)
/* rebooting needs to touch the page at absolute addr 0 */
*((unsigned short *)__va(0x472)) = reboot_mode;
for (;;) {
+   mach_reboot_fixups(); /* for board specific fixups */
mach_reboot();
/* That didn't work - force a triple fault.. */
__asm__ __volatile__("lidt %0": :"m" (no_idt));
diff -uprN -X dontdiff linux-2.6.11.7-vanilla/arch/i386/kernel/reboot_fixups.c 
linux-2.6.11.7/arch/i386/kernel/reboot_fixups.c
--- linux-2.6.11.7-vanilla/arch/i386/kernel/reboot_fixups.c 1970-01-01 
07:30:00.0 +0730
+++ linux-2.6.11.7/arch/i386/kernel/reboot_fixups.c 2005-04-11 
14:09:02.0 +0800
@@ -0,0 +1,56 @@
+/*
+ * linux/arch/i386/kernel/reboot_fixups.c
+ * 
+ * This is a good place to put board specific reboot fixups.
+ *
+ * List of supported fixups:
+ * geode-gx1/cs5530a - Jaya Kumar <[EMAIL PROTECTED]>
+ *
+ */
+
+#include 
+#include 
+
+static void cs5530a_warm_reset(struct pci_dev *dev)
+{
+   /* writing 1 to t

[RFC/PATCH 2.6.11.2 1/1] x86 reboot: Add reboot fixup for gx1/cs5530a

2005-03-28 Thread jayalk
Hi Riley, Dave, Peter, i386 boot/workaround maintainers,

This patch incorporates the suggestions from the previous thread.
ie: add header, use dummy macro, describe safety in help.

Please let me know if it's okay.

Thanks,
Jaya Kumar

--- 

I ran into a problem getting reboot working with 2.6.11 on an embedded
board. The board has a Geode GX1 with a CS5530A companion. What I observe on
reboot is the "Restarting system" printk, and then a cpu stall/hang. I think
the problem arises because the keyboard controller is disabled by the BIOS,
so the traditional mach_reboot()'s output to port 0x64 is ignored. Then the
386 triple fault issued after mach_reboot() results in a shutdown (because
the hardware doesn't have to detect the triple fault and issue a reset).
That then gives the end result of a stalled cpu/hang. 

I found that the CS5530A in question has a "issue system wide reset" bit.
The reboot works cleanly if I write that bit rather than do mach_reboot().
So the following patch is my attempt to incorporate that change into 2.6.11
by adding a X86_REBOOTFIXUPS option. In order to keep reboot.c free of hw
specific fixups, I put it in another file, reboot_fixups.c. I tried to make
it a bit generic so that if there are other reboot related fixups for other
chipsets/boards, there'd be a clean place to put it. Please let me know what
you think.

Thanks,
Jaya Kumar

---

Signed-off-by:  Jaya Kumar  <[EMAIL PROTECTED]>

diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/Kconfig 
linux-2.6.11.2/arch/i386/Kconfig
--- linux-2.6.11.2-vanilla/arch/i386/Kconfig2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/Kconfig2005-03-29 09:44:58.053898616 +0800
@@ -645,6 +645,24 @@ config I8K
  Say Y if you intend to run this kernel on a Dell Inspiron 8000.
  Say N otherwise.
 
+config X86_REBOOTFIXUPS
+   bool "Enable X86 Board Specific Fixups for Reboot"
+   depends on X86 
+   default n
+   ---help---
+ This enables chipset and/or board specific fixups to be done
+ in order to get reboot to work correctly. This is only needed on
+ some combinations of hardware and BIOS. The symptom, for which 
+ this config is intended, is when reboot ends with a stalled/hung 
+ system. 
+
+ Currently, the only fixup is for the Geode GX1/CS5530A/TROM2.1. 
+ combination.
+
+ Say Y if you want to enable the fixup. Currently, it's safe to
+ enable this option even if you don't need it.
+ Say N otherwise.
+
 config MICROCODE
tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
---help---
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/kernel/Makefile 
linux-2.6.11.2/arch/i386/kernel/Makefile
--- linux-2.6.11.2-vanilla/arch/i386/kernel/Makefile2005-03-10 
16:31:25.0 +0800
+++ linux-2.6.11.2/arch/i386/kernel/Makefile2005-03-28 15:56:31.0 
+0800
@@ -23,6 +23,7 @@ obj-$(CONFIG_X86_TRAMPOLINE)  += trampoli
 obj-$(CONFIG_X86_MPPARSE)  += mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)   += apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)  += io_apic.o
+obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o
 obj-$(CONFIG_X86_NUMAQ)+= numaq.o
 obj-$(CONFIG_X86_SUMMIT_NUMA)  += summit.o
 obj-$(CONFIG_KPROBES)  += kprobes.o
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/kernel/reboot.c 
linux-2.6.11.2/arch/i386/kernel/reboot.c
--- linux-2.6.11.2-vanilla/arch/i386/kernel/reboot.c2005-03-10 
16:31:25.0 +0800
+++ linux-2.6.11.2/arch/i386/kernel/reboot.c2005-03-29 09:35:19.858797632 
+0800
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include "mach_reboot.h"
+#include 
 
 /*
  * Power off function, if any
@@ -348,6 +349,7 @@ void machine_restart(char * __unused)
/* rebooting needs to touch the page at absolute addr 0 */
*((unsigned short *)__va(0x472)) = reboot_mode;
for (;;) {
+   mach_reboot_fixups(); /* for board specific fixups */
mach_reboot();
/* That didn't work - force a triple fault.. */
__asm__ __volatile__("lidt %0": :"m" (no_idt));
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/kernel/reboot_fixups.c 
linux-2.6.11.2/arch/i386/kernel/reboot_fixups.c
--- linux-2.6.11.2-vanilla/arch/i386/kernel/reboot_fixups.c 1970-01-01 
07:30:00.0 +0730
+++ linux-2.6.11.2/arch/i386/kernel/reboot_fixups.c 2005-03-29 
09:34:06.404964312 +0800
@@ -0,0 +1,53 @@
+/*
+ * linux/arch/i386/kernel/reboot_fixups.c
+ * 
+ * This is a good place to put board specific reboot fixups.
+ *
+ */
+
+#include 
+#include 
+
+void cs5530a_warm_reset(struct pci_dev *dev)
+{
+   /* writing 1 to the reset control register, 0x44 causes the 
+   cs5530a to perform a system warm reset */
+   pci_write_config_byte(dev, 0x44, 0x1);
+   udelay(50); /* shouldn't get here but be safe and 

[RESEND PATCH 2.6.11.2 1/1] PCI Allow OutOfRange PIRQ table address

2005-03-28 Thread jayalk
Hi Greg, PCI folk,

Resending this patch. Is it okay now?

---

I updated this to remove unnecessary variable initialization, make 
check_routing be inline only and not __init, switch to strtoul, and 
formatting fixes as per Randy Dunlap's recommendations.

I updated this to change pirq_table_addr to a long, and to add a warning
msg if the PIRQ table wasn't found at the specified address, as per thread
with Matthew Wilcox. 

In our hardware situation, the BIOS is unable to store or generate it's PIRQ
table in the Fh-10h standard range. This patch adds a pci kernel
parameter, pirqaddr to allow the bootloader (or BIOS based loader) to inform
the kernel where the PIRQ table got stored. A beneficial side-effect is that,
if one's BIOS uses a static address each time for it's PIRQ table, then
pirqaddr can be used to avoid the $pirq search through that address block each
time at boot for normal PIRQ BIOSes.

---

Signed-off-by:  Jaya Kumar  <[EMAIL PROTECTED]>

diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/common.c 
linux-2.6.11.2/arch/i386/pci/common.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/common.c   2005-03-10 
16:31:25.0 +0800
+++ linux-2.6.11.2/arch/i386/pci/common.c   2005-03-17 14:25:54.23816 
+0800
@@ -25,7 +25,8 @@ unsigned int pci_probe = PCI_PROBE_BIOS 
 
 int pci_routeirq;
 int pcibios_last_bus = -1;
-struct pci_bus *pci_root_bus = NULL;
+unsigned long pirq_table_addr;
+struct pci_bus *pci_root_bus;
 struct pci_raw_ops *raw_pci_ops;
 
 static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int 
size, u32 *value)
@@ -188,6 +189,9 @@ char * __devinit  pcibios_setup(char *st
} else if (!strcmp(str, "biosirq")) {
pci_probe |= PCI_BIOS_IRQ_SCAN;
return NULL;
+   } else if (!strncmp(str, "pirqaddr=", 9)) {
+   pirq_table_addr = simple_strtoul(str+9, NULL, 0);
+   return NULL;
}
 #endif
 #ifdef CONFIG_PCI_DIRECT
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/irq.c 
linux-2.6.11.2/arch/i386/pci/irq.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/irq.c  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/irq.c  2005-03-17 14:04:22.0 +0800
@@ -58,6 +58,35 @@ struct irq_router_handler {
 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
 
 /*
+ *  Check passed address for the PCI IRQ Routing Table signature 
+ *  and perform checksum verification.
+ */
+
+static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
+{
+   struct irq_routing_table *rt;
+   int i;
+   u8 sum;
+
+   rt = (struct irq_routing_table *) addr;
+   if (rt->signature != PIRQ_SIGNATURE ||
+   rt->version != PIRQ_VERSION ||
+   rt->size % 16 ||
+   rt->size < sizeof(struct irq_routing_table))
+   return NULL;
+   sum = 0;
+   for (i=0; i < rt->size; i++)
+   sum += addr[i];
+   if (!sum) {
+   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   return rt;
+   }
+   return NULL;
+}
+
+
+
+/*
  *  Search 0xf -- 0xf for the PCI IRQ Routing Table.
  */
 
@@ -65,23 +94,17 @@ static struct irq_routing_table * __init
 {
u8 *addr;
struct irq_routing_table *rt;
-   int i;
-   u8 sum;
 
+   if (pirq_table_addr) {
+   rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
+   if (rt)
+   return rt;
+   printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n"); 
+   }
for(addr = (u8 *) __va(0xf); addr < (u8 *) __va(0x10); addr += 
16) {
-   rt = (struct irq_routing_table *) addr;
-   if (rt->signature != PIRQ_SIGNATURE ||
-   rt->version != PIRQ_VERSION ||
-   rt->size % 16 ||
-   rt->size < sizeof(struct irq_routing_table))
-   continue;
-   sum = 0;
-   for(i=0; isize; i++)
-   sum += addr[i];
-   if (!sum) {
-   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   rt = pirq_check_routing_table(addr);
+   if (rt) 
return rt;
-   }
}
return NULL;
 }
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/pci.h 
linux-2.6.11.2/arch/i386/pci/pci.h
--- linux-2.6.11.2-vanilla/arch/i386/pci/pci.h  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/pci.h  2005-03-17 08:54:36.0 +0800
@@ -27,6 +27,7 @@
 #define PCI_ASSIGN_ALL_BUSSES  0x4000
 
 extern unsigned int pci_probe;
+extern unsigned long pirq_table_addr;
 
 /* pci-i386.c */
 
diff -uprN -X dontdiff 
linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt 
linux-2.6.11.2/Documentation/kernel-parameters.txt
--- linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt  2005-03-10 
16:31:44.0

[RFC 2.6.11.2 1/1] Add reboot fixup for gx1/cs5530a

2005-03-28 Thread jayalk
Hi Riley, Dave, Peter, i386 boot/workaround maintainers,

I ran into a problem getting reboot working with 2.6.11 on an embedded
board. The board has a Geode GX1 with a CS5530A companion. What I observe on
reboot is the "Restarting system" printk, and then a cpu stall/hang. I think
the problem arises because the keyboard controller is disabled by the BIOS,
so the traditional mach_reboot()'s output to port 0x64 is ignored. Then the
386 triple fault issued after mach_reboot() results in a shutdown (because
the hardware doesn't have to detect the triple fault and issue a reset).
That then gives the end result of a stalled cpu/hang. 

I found that the CS5530A in question has a "issue system wide reset" bit.
The reboot works cleanly if I write that bit rather than do mach_reboot().
So the following patch is my attempt to incorporate that change into 2.6.11
by adding a X86_REBOOTFIXUPS option. In order to keep reboot.c free of hw
specific fixups, I put it in another file, reboot_fixups.c. I tried to make
it a bit generic so that if there are other reboot related fixups for other
chipsets/boards, there'd be a clean place to put it. Please let me know what
you think.

Thanks,
Jaya Kumar

---

Signed-off-by:  Jaya Kumar  <[EMAIL PROTECTED]>

diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/Kconfig 
linux-2.6.11.2/arch/i386/Kconfig
--- linux-2.6.11.2-vanilla/arch/i386/Kconfig2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/Kconfig2005-03-28 21:30:15.0 +0800
@@ -645,6 +645,23 @@ config I8K
  Say Y if you intend to run this kernel on a Dell Inspiron 8000.
  Say N otherwise.
 
+config X86_REBOOTFIXUPS
+   bool "Enable X86 Board Specific Fixups for Reboot"
+   depends on X86 
+   default n
+   ---help---
+ This enables chipset and/or board specific fixups to be done
+ in order to get reboot to work correctly. This is only needed on
+ some combinations of hardware and BIOS. The symptom, for which 
+ this config is intended, is when reboot ends with a stalled/hung 
+ system. 
+
+ Currently, the only fixup is for the Geode GX1/CS5530A/TROM2.1. 
+ combination. 
+
+ Say Y if you want to enable the fixup.
+ Say N otherwise.
+
 config MICROCODE
tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
---help---
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/kernel/Makefile 
linux-2.6.11.2/arch/i386/kernel/Makefile
--- linux-2.6.11.2-vanilla/arch/i386/kernel/Makefile2005-03-10 
16:31:25.0 +0800
+++ linux-2.6.11.2/arch/i386/kernel/Makefile2005-03-28 15:56:31.0 
+0800
@@ -23,6 +23,7 @@ obj-$(CONFIG_X86_TRAMPOLINE)  += trampoli
 obj-$(CONFIG_X86_MPPARSE)  += mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)   += apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)  += io_apic.o
+obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o
 obj-$(CONFIG_X86_NUMAQ)+= numaq.o
 obj-$(CONFIG_X86_SUMMIT_NUMA)  += summit.o
 obj-$(CONFIG_KPROBES)  += kprobes.o
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/kernel/reboot.c 
linux-2.6.11.2/arch/i386/kernel/reboot.c
--- linux-2.6.11.2-vanilla/arch/i386/kernel/reboot.c2005-03-10 
16:31:25.0 +0800
+++ linux-2.6.11.2/arch/i386/kernel/reboot.c2005-03-28 21:36:39.562079136 
+0800
@@ -14,6 +14,10 @@
 #include 
 #include "mach_reboot.h"
 
+#ifdef CONFIG_X86_REBOOTFIXUPS
+extern void mach_reboot_fixups(void);
+#endif
+
 /*
  * Power off function, if any
  */
@@ -348,6 +352,9 @@ void machine_restart(char * __unused)
/* rebooting needs to touch the page at absolute addr 0 */
*((unsigned short *)__va(0x472)) = reboot_mode;
for (;;) {
+#ifdef CONFIG_X86_REBOOTFIXUPS
+   mach_reboot_fixups();
+#endif
mach_reboot();
/* That didn't work - force a triple fault.. */
__asm__ __volatile__("lidt %0": :"m" (no_idt));
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/kernel/reboot_fixups.c 
linux-2.6.11.2/arch/i386/kernel/reboot_fixups.c
--- linux-2.6.11.2-vanilla/arch/i386/kernel/reboot_fixups.c 1970-01-01 
07:30:00.0 +0730
+++ linux-2.6.11.2/arch/i386/kernel/reboot_fixups.c 2005-03-28 
21:38:30.893154240 +0800
@@ -0,0 +1,40 @@
+#include 
+#include 
+
+void cs5530a_warm_reset(struct pci_dev *dev)
+{
+   /* writing 1 to the reset control register, 0x44 causes the 
+   cs5530a to perform a system warm reset */
+   pci_write_config_byte(dev, 0x44, 0x1);
+   udelay(50); /* shouldn't get here but be safe and spin-a-while */
+   return; 
+}
+
+struct device_fixup {
+   unsigned int vendor;
+   unsigned int device;
+   void (*reboot_fixup)(struct pci_dev *);
+};
+
+struct device_fixup fixups_table[] = {
+   { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, 
cs5530a_warm_reset },
+};
+
+void mach

[PATCH 2.6.11.2 1/1] PCI Allow OutOfRange PIRQ table address

2005-03-21 Thread jayalk
Hi Greg, PCI folk,

I updated this to remove unnecessary variable initialization, make 
check_routing be inline only and not __init, switch to strtoul, and 
formatting fixes as per Randy Dunlap's recommendations.

I updated this to change pirq_table_addr to a long, and to add a warning
msg if the PIRQ table wasn't found at the specified address, as per thread
with Matthew Wilcox. 

In our hardware situation, the BIOS is unable to store or generate it's PIRQ
table in the Fh-10h standard range. This patch adds a pci kernel
parameter, pirqaddr to allow the bootloader (or BIOS based loader) to inform
the kernel where the PIRQ table got stored. A beneficial side-effect is that,
if one's BIOS uses a static address each time for it's PIRQ table, then
pirqaddr can be used to avoid the $pirq search through that address block each
time at boot for normal PIRQ BIOSes.

---

Signed-off-by:  Jaya Kumar  <[EMAIL PROTECTED]>

diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/common.c 
linux-2.6.11.2/arch/i386/pci/common.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/common.c   2005-03-10 
16:31:25.0 +0800
+++ linux-2.6.11.2/arch/i386/pci/common.c   2005-03-17 14:25:54.23816 
+0800
@@ -25,7 +25,8 @@ unsigned int pci_probe = PCI_PROBE_BIOS 
 
 int pci_routeirq;
 int pcibios_last_bus = -1;
-struct pci_bus *pci_root_bus = NULL;
+unsigned long pirq_table_addr;
+struct pci_bus *pci_root_bus;
 struct pci_raw_ops *raw_pci_ops;
 
 static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int 
size, u32 *value)
@@ -188,6 +189,9 @@ char * __devinit  pcibios_setup(char *st
} else if (!strcmp(str, "biosirq")) {
pci_probe |= PCI_BIOS_IRQ_SCAN;
return NULL;
+   } else if (!strncmp(str, "pirqaddr=", 9)) {
+   pirq_table_addr = simple_strtoul(str+9, NULL, 0);
+   return NULL;
}
 #endif
 #ifdef CONFIG_PCI_DIRECT
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/irq.c 
linux-2.6.11.2/arch/i386/pci/irq.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/irq.c  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/irq.c  2005-03-17 14:04:22.0 +0800
@@ -58,6 +58,35 @@ struct irq_router_handler {
 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
 
 /*
+ *  Check passed address for the PCI IRQ Routing Table signature 
+ *  and perform checksum verification.
+ */
+
+static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
+{
+   struct irq_routing_table *rt;
+   int i;
+   u8 sum;
+
+   rt = (struct irq_routing_table *) addr;
+   if (rt->signature != PIRQ_SIGNATURE ||
+   rt->version != PIRQ_VERSION ||
+   rt->size % 16 ||
+   rt->size < sizeof(struct irq_routing_table))
+   return NULL;
+   sum = 0;
+   for (i=0; i < rt->size; i++)
+   sum += addr[i];
+   if (!sum) {
+   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   return rt;
+   }
+   return NULL;
+}
+
+
+
+/*
  *  Search 0xf -- 0xf for the PCI IRQ Routing Table.
  */
 
@@ -65,23 +94,17 @@ static struct irq_routing_table * __init
 {
u8 *addr;
struct irq_routing_table *rt;
-   int i;
-   u8 sum;
 
+   if (pirq_table_addr) {
+   rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
+   if (rt)
+   return rt;
+   printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n"); 
+   }
for(addr = (u8 *) __va(0xf); addr < (u8 *) __va(0x10); addr += 
16) {
-   rt = (struct irq_routing_table *) addr;
-   if (rt->signature != PIRQ_SIGNATURE ||
-   rt->version != PIRQ_VERSION ||
-   rt->size % 16 ||
-   rt->size < sizeof(struct irq_routing_table))
-   continue;
-   sum = 0;
-   for(i=0; isize; i++)
-   sum += addr[i];
-   if (!sum) {
-   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   rt = pirq_check_routing_table(addr);
+   if (rt) 
return rt;
-   }
}
return NULL;
 }
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/pci.h 
linux-2.6.11.2/arch/i386/pci/pci.h
--- linux-2.6.11.2-vanilla/arch/i386/pci/pci.h  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/pci.h  2005-03-17 08:54:36.0 +0800
@@ -27,6 +27,7 @@
 #define PCI_ASSIGN_ALL_BUSSES  0x4000
 
 extern unsigned int pci_probe;
+extern unsigned long pirq_table_addr;
 
 /* pci-i386.c */
 
diff -uprN -X dontdiff 
linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt 
linux-2.6.11.2/Documentation/kernel-parameters.txt
--- linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt  2005-03-10 
16:31:44.0 +0800
+++ linux-2.6.11.2/Documentat

[PATCH 2.6.11.2 1/1] PCI Allow OutOfRange PIRQ table address

2005-03-16 Thread jayalk
Hi Greg, PCI folk,

Sorry, just also did the simple_strtol to strtoul. Let me know if it's okay. 
Thanks. 

---
I updated this to remove unnecessary variable initialization, make 
check_routing be inline only and not __init, and formatting fixes as per
Randy Dunlap's recommendations. 

I updated this to change pirq_table_addr to a long, and to add a warning
msg if the PIRQ table wasn't found at the specified address, as per thread
with Matthew Wilcox. 

In our hardware situation, the BIOS is unable to store or generate it's PIRQ
table in the Fh-10h standard range. This patch adds a pci kernel
parameter, pirqaddr to allow the bootloader (or BIOS based loader) to inform
the kernel where the PIRQ table got stored. A beneficial side-effect is that,
if one's BIOS uses a static address each time for it's PIRQ table, then
pirqaddr can be used to avoid the $pirq search through that address block each
time at boot for normal PIRQ BIOSes.

---

Signed-off-by:  Jaya Kumar  <[EMAIL PROTECTED]>

diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/common.c 
linux-2.6.11.2/arch/i386/pci/common.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/common.c   2005-03-10 
16:31:25.0 +0800
+++ linux-2.6.11.2/arch/i386/pci/common.c   2005-03-17 14:25:54.23816 
+0800
@@ -25,7 +25,8 @@ unsigned int pci_probe = PCI_PROBE_BIOS 
 
 int pci_routeirq;
 int pcibios_last_bus = -1;
-struct pci_bus *pci_root_bus = NULL;
+unsigned long pirq_table_addr;
+struct pci_bus *pci_root_bus;
 struct pci_raw_ops *raw_pci_ops;
 
 static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int 
size, u32 *value)
@@ -188,6 +189,9 @@ char * __devinit  pcibios_setup(char *st
} else if (!strcmp(str, "biosirq")) {
pci_probe |= PCI_BIOS_IRQ_SCAN;
return NULL;
+   } else if (!strncmp(str, "pirqaddr=", 9)) {
+   pirq_table_addr = simple_strtoul(str+9, NULL, 0);
+   return NULL;
}
 #endif
 #ifdef CONFIG_PCI_DIRECT
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/irq.c 
linux-2.6.11.2/arch/i386/pci/irq.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/irq.c  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/irq.c  2005-03-17 14:04:22.0 +0800
@@ -58,6 +58,35 @@ struct irq_router_handler {
 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
 
 /*
+ *  Check passed address for the PCI IRQ Routing Table signature 
+ *  and perform checksum verification.
+ */
+
+static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
+{
+   struct irq_routing_table *rt;
+   int i;
+   u8 sum;
+
+   rt = (struct irq_routing_table *) addr;
+   if (rt->signature != PIRQ_SIGNATURE ||
+   rt->version != PIRQ_VERSION ||
+   rt->size % 16 ||
+   rt->size < sizeof(struct irq_routing_table))
+   return NULL;
+   sum = 0;
+   for (i=0; i < rt->size; i++)
+   sum += addr[i];
+   if (!sum) {
+   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   return rt;
+   }
+   return NULL;
+}
+
+
+
+/*
  *  Search 0xf -- 0xf for the PCI IRQ Routing Table.
  */
 
@@ -65,23 +94,17 @@ static struct irq_routing_table * __init
 {
u8 *addr;
struct irq_routing_table *rt;
-   int i;
-   u8 sum;
 
+   if (pirq_table_addr) {
+   rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
+   if (rt)
+   return rt;
+   printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n"); 
+   }
for(addr = (u8 *) __va(0xf); addr < (u8 *) __va(0x10); addr += 
16) {
-   rt = (struct irq_routing_table *) addr;
-   if (rt->signature != PIRQ_SIGNATURE ||
-   rt->version != PIRQ_VERSION ||
-   rt->size % 16 ||
-   rt->size < sizeof(struct irq_routing_table))
-   continue;
-   sum = 0;
-   for(i=0; isize; i++)
-   sum += addr[i];
-   if (!sum) {
-   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   rt = pirq_check_routing_table(addr);
+   if (rt) 
return rt;
-   }
}
return NULL;
 }
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/pci.h 
linux-2.6.11.2/arch/i386/pci/pci.h
--- linux-2.6.11.2-vanilla/arch/i386/pci/pci.h  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/pci.h  2005-03-17 08:54:36.0 +0800
@@ -27,6 +27,7 @@
 #define PCI_ASSIGN_ALL_BUSSES  0x4000
 
 extern unsigned int pci_probe;
+extern unsigned long pirq_table_addr;
 
 /* pci-i386.c */
 
diff -uprN -X dontdiff 
linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt 
linux-2.6.11.2/Documentation/kernel-parameters.txt
--- linux-2.6.11.2-vanilla/Documentation/kernel-parameter

[PATCH 2.6.11.2 1/1] PCI Allow OutOfRange PIRQ table address

2005-03-16 Thread jayalk
Hi Greg, PCI folk,

I updated this to remove unnecessary variable initialization, make 
check_routing be inline only and not __init, and formatting fixes as per
Randy Dunlap's recommendations. Let me know if it's okay. Thanks. 

---

I updated this to change pirq_table_addr to a long, and to add a warning
msg if the PIRQ table wasn't found at the specified address, as per thread
with Matthew Wilcox. 

In our hardware situation, the BIOS is unable to store or generate it's PIRQ
table in the Fh-10h standard range. This patch adds a pci kernel
parameter, pirqaddr to allow the bootloader (or BIOS based loader) to inform
the kernel where the PIRQ table got stored. A beneficial side-effect is that,
if one's BIOS uses a static address each time for it's PIRQ table, then
pirqaddr can be used to avoid the $pirq search through that address block each
time at boot for normal PIRQ BIOSes.

---

Signed-off-by:  Jaya Kumar  <[EMAIL PROTECTED]>

diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/common.c 
linux-2.6.11.2/arch/i386/pci/common.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/common.c   2005-03-10 
16:31:25.0 +0800
+++ linux-2.6.11.2/arch/i386/pci/common.c   2005-03-17 12:58:45.246032136 
+0800
@@ -25,7 +25,8 @@ unsigned int pci_probe = PCI_PROBE_BIOS 
 
 int pci_routeirq;
 int pcibios_last_bus = -1;
-struct pci_bus *pci_root_bus = NULL;
+unsigned long pirq_table_addr;
+struct pci_bus *pci_root_bus;
 struct pci_raw_ops *raw_pci_ops;
 
 static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int 
size, u32 *value)
@@ -188,6 +189,9 @@ char * __devinit  pcibios_setup(char *st
} else if (!strcmp(str, "biosirq")) {
pci_probe |= PCI_BIOS_IRQ_SCAN;
return NULL;
+   } else if (!strncmp(str, "pirqaddr=", 9)) {
+   pirq_table_addr = simple_strtol(str+9, NULL, 0);
+   return NULL;
}
 #endif
 #ifdef CONFIG_PCI_DIRECT
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/irq.c 
linux-2.6.11.2/arch/i386/pci/irq.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/irq.c  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/irq.c  2005-03-17 14:04:22.924414032 +0800
@@ -58,6 +58,35 @@ struct irq_router_handler {
 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
 
 /*
+ *  Check passed address for the PCI IRQ Routing Table signature 
+ *  and perform checksum verification.
+ */
+
+static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
+{
+   struct irq_routing_table *rt;
+   int i;
+   u8 sum;
+
+   rt = (struct irq_routing_table *) addr;
+   if (rt->signature != PIRQ_SIGNATURE ||
+   rt->version != PIRQ_VERSION ||
+   rt->size % 16 ||
+   rt->size < sizeof(struct irq_routing_table))
+   return NULL;
+   sum = 0;
+   for (i=0; i < rt->size; i++)
+   sum += addr[i];
+   if (!sum) {
+   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   return rt;
+   }
+   return NULL;
+}
+
+
+
+/*
  *  Search 0xf -- 0xf for the PCI IRQ Routing Table.
  */
 
@@ -65,23 +94,17 @@ static struct irq_routing_table * __init
 {
u8 *addr;
struct irq_routing_table *rt;
-   int i;
-   u8 sum;
 
+   if (pirq_table_addr) {
+   rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
+   if (rt)
+   return rt;
+   printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n"); 
+   }
for(addr = (u8 *) __va(0xf); addr < (u8 *) __va(0x10); addr += 
16) {
-   rt = (struct irq_routing_table *) addr;
-   if (rt->signature != PIRQ_SIGNATURE ||
-   rt->version != PIRQ_VERSION ||
-   rt->size % 16 ||
-   rt->size < sizeof(struct irq_routing_table))
-   continue;
-   sum = 0;
-   for(i=0; isize; i++)
-   sum += addr[i];
-   if (!sum) {
-   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   rt = pirq_check_routing_table(addr);
+   if (rt) 
return rt;
-   }
}
return NULL;
 }
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/pci.h 
linux-2.6.11.2/arch/i386/pci/pci.h
--- linux-2.6.11.2-vanilla/arch/i386/pci/pci.h  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/pci.h  2005-03-17 08:54:36.0 +0800
@@ -27,6 +27,7 @@
 #define PCI_ASSIGN_ALL_BUSSES  0x4000
 
 extern unsigned int pci_probe;
+extern unsigned long pirq_table_addr;
 
 /* pci-i386.c */
 
diff -uprN -X dontdiff 
linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt 
linux-2.6.11.2/Documentation/kernel-parameters.txt
--- linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt  2005-03-10 
16:31:44.0 +0800
+++ linux-

[PATCH 2.6.11.2 1/1] PCI Allow OutOfRange PIRQ table address

2005-03-16 Thread jayalk
Hi Greg, PCI folk,

I updated this to change pirq_table_addr to a long, and to add a warning
msg if the PIRQ table wasn't found at the specified address, as per thread
with Matthew Wilcox. Let me know if it's okay. Thanks.

In our hardware situation, the BIOS is unable to store or generate it's PIRQ
table in the Fh-10h standard range. This patch adds a pci kernel
parameter, pirqaddr to allow the bootloader (or BIOS based loader) to inform
the kernel where the PIRQ table got stored. A beneficial side-effect is that,
if one's BIOS uses a static address each time for it's PIRQ table, then
pirqaddr can be used to avoid the $pirq search through that address block each
time at boot for normal PIRQ BIOSes.

Signed-off-by:  Jaya Kumar  <[EMAIL PROTECTED]>

diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/common.c 
linux-2.6.11.2/arch/i386/pci/common.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/common.c   2005-03-10 
16:31:25.0 +0800
+++ linux-2.6.11.2/arch/i386/pci/common.c   2005-03-11 20:35:41.0 
+0800
@@ -25,6 +25,7 @@ unsigned int pci_probe = PCI_PROBE_BIOS 
 
 int pci_routeirq;
 int pcibios_last_bus = -1;
+unsigned long pirq_table_addr = 0;
 struct pci_bus *pci_root_bus = NULL;
 struct pci_raw_ops *raw_pci_ops;
 
@@ -188,6 +189,9 @@ char * __devinit  pcibios_setup(char *st
} else if (!strcmp(str, "biosirq")) {
pci_probe |= PCI_BIOS_IRQ_SCAN;
return NULL;
+   } else if (!strncmp(str, "pirqaddr=", 9)) {
+   pirq_table_addr = simple_strtol(str+9, NULL, 0);
+   return NULL;
}
 #endif
 #ifdef CONFIG_PCI_DIRECT
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/irq.c 
linux-2.6.11.2/arch/i386/pci/irq.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/irq.c  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/irq.c  2005-03-11 20:40:28.0 +0800
@@ -58,6 +58,35 @@ struct irq_router_handler {
 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
 
 /*
+ *  Check passed address for the PCI IRQ Routing Table signature 
+ *  and perform checksum verification.
+ */
+
+static inline struct irq_routing_table * __init pirq_check_routing_table(u8 
*addr)
+{
+   struct irq_routing_table *rt;
+   int i;
+   u8 sum;
+
+   rt = (struct irq_routing_table *) addr;
+   if (rt->signature != PIRQ_SIGNATURE ||
+   rt->version != PIRQ_VERSION ||
+   rt->size % 16 ||
+   rt->size < sizeof(struct irq_routing_table))
+   return NULL;
+   sum = 0;
+   for(i=0; isize; i++)
+   sum += addr[i];
+   if (!sum) {
+   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   return rt;
+   }
+   return NULL;
+}
+
+
+
+/*
  *  Search 0xf -- 0xf for the PCI IRQ Routing Table.
  */
 
@@ -65,21 +94,17 @@ static struct irq_routing_table * __init
 {
u8 *addr;
struct irq_routing_table *rt;
-   int i;
-   u8 sum;
 
+   if (pirq_table_addr) {
+   rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
+   if (rt) {
+   return rt;
+   }
+   printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n"); 
+   }
for(addr = (u8 *) __va(0xf); addr < (u8 *) __va(0x10); addr += 
16) {
-   rt = (struct irq_routing_table *) addr;
-   if (rt->signature != PIRQ_SIGNATURE ||
-   rt->version != PIRQ_VERSION ||
-   rt->size % 16 ||
-   rt->size < sizeof(struct irq_routing_table))
-   continue;
-   sum = 0;
-   for(i=0; isize; i++)
-   sum += addr[i];
-   if (!sum) {
-   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   rt = pirq_check_routing_table(addr);
+   if (rt) {
return rt;
}
}
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/pci.h 
linux-2.6.11.2/arch/i386/pci/pci.h
--- linux-2.6.11.2-vanilla/arch/i386/pci/pci.h  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/pci.h  2005-03-11 20:35:55.0 +0800
@@ -27,6 +27,7 @@
 #define PCI_ASSIGN_ALL_BUSSES  0x4000
 
 extern unsigned int pci_probe;
+extern unsigned long pirq_table_addr;
 
 /* pci-i386.c */
 
diff -uprN -X dontdiff 
linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt 
linux-2.6.11.2/Documentation/kernel-parameters.txt
--- linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt  2005-03-10 
16:31:44.0 +0800
+++ linux-2.6.11.2/Documentation/kernel-parameters.txt  2005-03-10 
16:45:48.0 +0800
@@ -967,6 +967,10 @@ running once the system is up.
irqmask=0x  [IA-32] Set a bit mask of IRQs allowed 
to be assigned
automatically to PCI devices. You can 
mak

[PATCH 2.6.11.2 1/1] PCI Allow OutOfRange PIRQ table address

2005-03-16 Thread jayalk
Hi Greg, PCI folk,

In our hardware situation, the BIOS is unable to store or generate it's PIRQ
table in the Fh-10h standard range. This patch adds a pci kernel
parameter, pirqaddr to allow the bootloader (or BIOS based loader) to inform
the kernel where the PIRQ table got stored. A beneficial side-effect is that,
if one's BIOS uses a static address each time for it's PIRQ table, then
pirqaddr can be used to avoid the $pirq search through that address block each
time at boot for normal PIRQ BIOSes.

Signed-off-by:  Jaya Kumar  <[EMAIL PROTECTED]>

diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/common.c 
linux-2.6.11.2/arch/i386/pci/common.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/common.c   2005-03-10 
16:31:25.0 +0800
+++ linux-2.6.11.2/arch/i386/pci/common.c   2005-03-10 16:56:09.0 
+0800
@@ -25,6 +25,7 @@ unsigned int pci_probe = PCI_PROBE_BIOS 
 
 int pci_routeirq;
 int pcibios_last_bus = -1;
+unsigned int pirq_table_addr = 0;
 struct pci_bus *pci_root_bus = NULL;
 struct pci_raw_ops *raw_pci_ops;
 
@@ -188,6 +189,9 @@ char * __devinit  pcibios_setup(char *st
} else if (!strcmp(str, "biosirq")) {
pci_probe |= PCI_BIOS_IRQ_SCAN;
return NULL;
+   } else if (!strncmp(str, "pirqaddr=", 9)) {
+   pirq_table_addr = simple_strtol(str+9, NULL, 0);
+   return NULL;
}
 #endif
 #ifdef CONFIG_PCI_DIRECT
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/irq.c 
linux-2.6.11.2/arch/i386/pci/irq.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/irq.c  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/irq.c  2005-03-10 20:43:02.479487640 +0800
@@ -58,6 +58,35 @@ struct irq_router_handler {
 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
 
 /*
+ *  Check passed address for the PCI IRQ Routing Table signature 
+ *  and perform checksum verification.
+ */
+
+static inline struct irq_routing_table * __init pirq_check_routing_table(u8 
*addr)
+{
+   struct irq_routing_table *rt;
+   int i;
+   u8 sum;
+
+   rt = (struct irq_routing_table *) addr;
+   if (rt->signature != PIRQ_SIGNATURE ||
+   rt->version != PIRQ_VERSION ||
+   rt->size % 16 ||
+   rt->size < sizeof(struct irq_routing_table))
+   return NULL;
+   sum = 0;
+   for(i=0; isize; i++)
+   sum += addr[i];
+   if (!sum) {
+   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   return rt;
+   }
+   return NULL;
+}
+
+
+
+/*
  *  Search 0xf -- 0xf for the PCI IRQ Routing Table.
  */
 
@@ -65,21 +94,16 @@ static struct irq_routing_table * __init
 {
u8 *addr;
struct irq_routing_table *rt;
-   int i;
-   u8 sum;
 
+   if (pirq_table_addr) {
+   rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
+   if (rt) {
+   return rt;
+   }
+   }
for(addr = (u8 *) __va(0xf); addr < (u8 *) __va(0x10); addr += 
16) {
-   rt = (struct irq_routing_table *) addr;
-   if (rt->signature != PIRQ_SIGNATURE ||
-   rt->version != PIRQ_VERSION ||
-   rt->size % 16 ||
-   rt->size < sizeof(struct irq_routing_table))
-   continue;
-   sum = 0;
-   for(i=0; isize; i++)
-   sum += addr[i];
-   if (!sum) {
-   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   rt = pirq_check_routing_table(addr);
+   if (rt) {
return rt;
}
}
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/pci.h 
linux-2.6.11.2/arch/i386/pci/pci.h
--- linux-2.6.11.2-vanilla/arch/i386/pci/pci.h  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/pci.h  2005-03-10 16:52:09.0 +0800
@@ -27,6 +27,7 @@
 #define PCI_ASSIGN_ALL_BUSSES  0x4000
 
 extern unsigned int pci_probe;
+extern unsigned int pirq_table_addr;
 
 /* pci-i386.c */
 
diff -uprN -X dontdiff 
linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt 
linux-2.6.11.2/Documentation/kernel-parameters.txt
--- linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt  2005-03-10 
16:31:44.0 +0800
+++ linux-2.6.11.2/Documentation/kernel-parameters.txt  2005-03-10 
16:45:48.0 +0800
@@ -967,6 +967,10 @@ running once the system is up.
irqmask=0x  [IA-32] Set a bit mask of IRQs allowed 
to be assigned
automatically to PCI devices. You can 
make the kernel
exclude IRQs of your ISA cards this way.
+   pirqaddr=0xA[IA-32] Specify the physical address
+   of the PIRQ table (normally generated
+ 

Re: [PATCH 2.6.11.2 1/1] PCI Allow OutOfRange PIRQ table address

2005-03-11 Thread jayalk
On Thu, 10 Mar 2005, Matthew Wilcox wrote:
+extern unsigned int pirq_table_addr;
Completely nitpicking, but I think this should be an unsigned long rather
than an int -- physical addresses are normally expressed in terms of
unsigned long.
Yup, good point, I'll fix that.
Should we fall back to searching if someone's specified an address?  If not,
it becomes even simpler:
I think it'd be a failsafe in the case where someone mistakenly copied
an incorrect or mistaken boot loader config. I'll add a warning in that case
so that the user can see that there's been a problem.
 	for(addr = (u8 *) __va(0xf); addr < (u8 *) __va(0x10); addr += 16) {
This loop would become:
for (addr = 0xf; addr < 0x10; addr += 16) {
I prefered the former since the __va conversion only gets done for those
initial addresses rather than throughout the loop. I think the
check_routing... should use va addr not phys, for subjective reasons, feels
cleaner, I guess. I'll deferr to whatever the norm is. Let me know.
Thanks for the feedback.
jayakumar

On Thu, Mar 10, 2005 at 05:29:35AM -0800, [EMAIL PROTECTED] wrote:
Nice work, I like it.  You could make it even prettier:
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/irq.c 
linux-2.6.11.2/arch/i386/pci/irq.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/irq.c  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/irq.c  2005-03-10 20:43:02.479487640 +0800
@@ -58,6 +58,35 @@ struct irq_router_handler {
 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
 /*
+ *  Check passed address for the PCI IRQ Routing Table signature
+ *  and perform checksum verification.
+ */
+
+static inline struct irq_routing_table * __init pirq_check_routing_table(u8 
*addr)
+{
+   struct irq_routing_table *rt;
+   int i;
+   u8 sum;
+
+   rt = (struct irq_routing_table *) addr;
static inline struct irq_routing_table * __init 
pirq_check_routing_table(unsigned long phys)
{
struct irq_routing_table *rt = __va(phys);
[...]
@@ -65,21 +94,16 @@ static struct irq_routing_table * __init
 {
u8 *addr;
unsigned long addr;
struct irq_routing_table *rt;
-   int i;
-   u8 sum;
+   if (pirq_table_addr) {
+   rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
+   if (rt) {
+   return rt;
+   }
+   }
if (pirq_table_addr) {
rt = pirq_check_routing_table(pirq_table_addr);
if (rt)
return rt;
}
Should we fall back to searching if someone's specified an address?  If not,
it becomes even simpler:
if (pirq_table_addr) {
return pirq_check_routing_table(pirq_table_addr);
}
 	for(addr = (u8 *) __va(0xf); addr < (u8 *) __va(0x10); addr += 16) {
This loop would become:
for (addr = 0xf; addr < 0x10; addr += 16) {
@@ -27,6 +27,7 @@
 #define PCI_ASSIGN_ALL_BUSSES  0x4000
 extern unsigned int pci_probe;
+extern unsigned int pirq_table_addr;
Completely nitpicking, but I think this should be an unsigned long rather
than an int -- physical addresses are normally expressed in terms of
unsigned long.
+   pirqaddr=0xA[IA-32] Specify the physical address
+   of the PIRQ table (normally generated
+   by the BIOS) if it is outside the .
+   Fh-10h range.
And you even bothered to update the documentation!  This is definitely
a cut above most of the patches I review ;-)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2.6.11.2 1/1] PCI Allow OutOfRange PIRQ table address

2005-03-10 Thread jayalk
Hi Greg, PCI folk,

In our hardware situation, the BIOS is unable to store or generate it's PIRQ
table in the Fh-10h standard range. This patch adds a pci kernel
parameter, pirqaddr to allow the bootloader (or BIOS based loader) to inform
the kernel where the PIRQ table got stored. A beneficial side-effect is that,
if one's BIOS uses a static address each time for it's PIRQ table, then
pirqaddr can be used to avoid the $pirq search through that address block each
time at boot for normal PIRQ BIOSes.

Signed-off-by:  Jaya Kumar  <[EMAIL PROTECTED]>

diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/common.c 
linux-2.6.11.2/arch/i386/pci/common.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/common.c   2005-03-10 
16:31:25.0 +0800
+++ linux-2.6.11.2/arch/i386/pci/common.c   2005-03-10 16:56:09.0 
+0800
@@ -25,6 +25,7 @@ unsigned int pci_probe = PCI_PROBE_BIOS 
 
 int pci_routeirq;
 int pcibios_last_bus = -1;
+unsigned int pirq_table_addr = 0;
 struct pci_bus *pci_root_bus = NULL;
 struct pci_raw_ops *raw_pci_ops;
 
@@ -188,6 +189,9 @@ char * __devinit  pcibios_setup(char *st
} else if (!strcmp(str, "biosirq")) {
pci_probe |= PCI_BIOS_IRQ_SCAN;
return NULL;
+   } else if (!strncmp(str, "pirqaddr=", 9)) {
+   pirq_table_addr = simple_strtol(str+9, NULL, 0);
+   return NULL;
}
 #endif
 #ifdef CONFIG_PCI_DIRECT
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/irq.c 
linux-2.6.11.2/arch/i386/pci/irq.c
--- linux-2.6.11.2-vanilla/arch/i386/pci/irq.c  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/irq.c  2005-03-10 20:43:02.479487640 +0800
@@ -58,6 +58,35 @@ struct irq_router_handler {
 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
 
 /*
+ *  Check passed address for the PCI IRQ Routing Table signature 
+ *  and perform checksum verification.
+ */
+
+static inline struct irq_routing_table * __init pirq_check_routing_table(u8 
*addr)
+{
+   struct irq_routing_table *rt;
+   int i;
+   u8 sum;
+
+   rt = (struct irq_routing_table *) addr;
+   if (rt->signature != PIRQ_SIGNATURE ||
+   rt->version != PIRQ_VERSION ||
+   rt->size % 16 ||
+   rt->size < sizeof(struct irq_routing_table))
+   return NULL;
+   sum = 0;
+   for(i=0; isize; i++)
+   sum += addr[i];
+   if (!sum) {
+   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   return rt;
+   }
+   return NULL;
+}
+
+
+
+/*
  *  Search 0xf -- 0xf for the PCI IRQ Routing Table.
  */
 
@@ -65,21 +94,16 @@ static struct irq_routing_table * __init
 {
u8 *addr;
struct irq_routing_table *rt;
-   int i;
-   u8 sum;
 
+   if (pirq_table_addr) {
+   rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
+   if (rt) {
+   return rt;
+   }
+   }
for(addr = (u8 *) __va(0xf); addr < (u8 *) __va(0x10); addr += 
16) {
-   rt = (struct irq_routing_table *) addr;
-   if (rt->signature != PIRQ_SIGNATURE ||
-   rt->version != PIRQ_VERSION ||
-   rt->size % 16 ||
-   rt->size < sizeof(struct irq_routing_table))
-   continue;
-   sum = 0;
-   for(i=0; isize; i++)
-   sum += addr[i];
-   if (!sum) {
-   DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+   rt = pirq_check_routing_table(addr);
+   if (rt) {
return rt;
}
}
diff -uprN -X dontdiff linux-2.6.11.2-vanilla/arch/i386/pci/pci.h 
linux-2.6.11.2/arch/i386/pci/pci.h
--- linux-2.6.11.2-vanilla/arch/i386/pci/pci.h  2005-03-10 16:31:25.0 
+0800
+++ linux-2.6.11.2/arch/i386/pci/pci.h  2005-03-10 16:52:09.0 +0800
@@ -27,6 +27,7 @@
 #define PCI_ASSIGN_ALL_BUSSES  0x4000
 
 extern unsigned int pci_probe;
+extern unsigned int pirq_table_addr;
 
 /* pci-i386.c */
 
diff -uprN -X dontdiff 
linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt 
linux-2.6.11.2/Documentation/kernel-parameters.txt
--- linux-2.6.11.2-vanilla/Documentation/kernel-parameters.txt  2005-03-10 
16:31:44.0 +0800
+++ linux-2.6.11.2/Documentation/kernel-parameters.txt  2005-03-10 
16:45:48.0 +0800
@@ -967,6 +967,10 @@ running once the system is up.
irqmask=0x  [IA-32] Set a bit mask of IRQs allowed 
to be assigned
automatically to PCI devices. You can 
make the kernel
exclude IRQs of your ISA cards this way.
+   pirqaddr=0xA[IA-32] Specify the physical address
+   of the PIRQ table (normally generated
+