Commit 120bb424 authored by jayalk@intworks.biz's avatar jayalk@intworks.biz Committed by Greg Kroah-Hartman

[PATCH] PCI Allow OutOfRange PIRQ table address

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 F0000h-100000h 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: default avatarJaya Kumar <jayalk@intworks.biz>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 020f46a3
...@@ -1030,6 +1030,10 @@ running once the system is up. ...@@ -1030,6 +1030,10 @@ running once the system is up.
irqmask=0xMMMM [IA-32] Set a bit mask of IRQs allowed to be assigned irqmask=0xMMMM [IA-32] Set a bit mask of IRQs allowed to be assigned
automatically to PCI devices. You can make the kernel automatically to PCI devices. You can make the kernel
exclude IRQs of your ISA cards this way. exclude IRQs of your ISA cards this way.
pirqaddr=0xAAAAA [IA-32] Specify the physical address
of the PIRQ table (normally generated
by the BIOS) if it is outside the
F0000h-100000h range.
lastbus=N [IA-32] Scan all buses till bus #N. Can be useful lastbus=N [IA-32] Scan all buses till bus #N. Can be useful
if the kernel is unable to find your secondary buses if the kernel is unable to find your secondary buses
and you want to tell it explicitly which ones they are. and you want to tell it explicitly which ones they are.
......
...@@ -25,7 +25,8 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | ...@@ -25,7 +25,8 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
int pci_routeirq; int pci_routeirq;
int pcibios_last_bus = -1; 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; struct pci_raw_ops *raw_pci_ops;
static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) 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 *str) ...@@ -188,6 +189,9 @@ char * __devinit pcibios_setup(char *str)
} else if (!strcmp(str, "biosirq")) { } else if (!strcmp(str, "biosirq")) {
pci_probe |= PCI_BIOS_IRQ_SCAN; pci_probe |= PCI_BIOS_IRQ_SCAN;
return NULL; return NULL;
} else if (!strncmp(str, "pirqaddr=", 9)) {
pirq_table_addr = simple_strtoul(str+9, NULL, 0);
return NULL;
} }
#endif #endif
#ifdef CONFIG_PCI_DIRECT #ifdef CONFIG_PCI_DIRECT
......
...@@ -58,30 +58,53 @@ struct irq_router_handler { ...@@ -58,30 +58,53 @@ struct irq_router_handler {
int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
/* /*
* Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. * Check passed address for the PCI IRQ Routing Table signature
* and perform checksum verification.
*/ */
static struct irq_routing_table * __init pirq_find_routing_table(void) static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
{ {
u8 *addr;
struct irq_routing_table *rt; struct irq_routing_table *rt;
int i; int i;
u8 sum; u8 sum;
for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
rt = (struct irq_routing_table *) addr; rt = (struct irq_routing_table *) addr;
if (rt->signature != PIRQ_SIGNATURE || if (rt->signature != PIRQ_SIGNATURE ||
rt->version != PIRQ_VERSION || rt->version != PIRQ_VERSION ||
rt->size % 16 || rt->size % 16 ||
rt->size < sizeof(struct irq_routing_table)) rt->size < sizeof(struct irq_routing_table))
continue; return NULL;
sum = 0; sum = 0;
for(i=0; i<rt->size; i++) for (i=0; i < rt->size; i++)
sum += addr[i]; sum += addr[i];
if (!sum) { if (!sum) {
DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt); DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
return rt; return rt;
} }
return NULL;
}
/*
* Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
*/
static struct irq_routing_table * __init pirq_find_routing_table(void)
{
u8 *addr;
struct irq_routing_table *rt;
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(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
rt = pirq_check_routing_table(addr);
if (rt)
return rt;
} }
return NULL; return NULL;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define PCI_ASSIGN_ALL_BUSSES 0x4000 #define PCI_ASSIGN_ALL_BUSSES 0x4000
extern unsigned int pci_probe; extern unsigned int pci_probe;
extern unsigned long pirq_table_addr;
/* pci-i386.c */ /* pci-i386.c */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment