diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-12-15 07:13:26 +1100 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-12-20 16:37:47 +1100 |
commit | 6f67f9d26fe5ced50f716e9620b42c0721d8b8d9 (patch) | |
tree | e03f4476dba4782c86dd5749ae3d3a36f35a7845 /arch | |
parent | 3cd7613e25ffc0a76080045e179f984a32208829 (diff) | |
download | op-kernel-dev-6f67f9d26fe5ced50f716e9620b42c0721d8b8d9.zip op-kernel-dev-6f67f9d26fe5ced50f716e9620b42c0721d8b8d9.tar.gz |
[POWERPC] Workaround oldworld OF bug with IRQs & P2P bridges
On some oldworld PowerMacs, OF doesn't assign interrupts properly
beyond P2P bridges. Fortunately, the fix is easy as all those machines
just wire all IRQ lines together to one IRQ which is assigned to the
bridge itself. We already have a special function for parsing Apple
OldWorld interrupts which are special, so let's add to it the ability
to walk up the PCI tree to find interrupts.
This fixes irqs on the lower slots of s900 clones among others.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/prom_parse.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 0dfbe1c..12c51e4 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -920,9 +920,20 @@ static int of_irq_map_oldworld(struct device_node *device, int index, /* * Old machines just have a list of interrupt numbers - * and no interrupt-controller nodes. + * and no interrupt-controller nodes. We also have dodgy + * cases where the APPL,interrupts property is completely + * missing behind pci-pci bridges and we have to get it + * from the parent (the bridge itself, as apple just wired + * everything together on these) */ - ints = get_property(device, "AAPL,interrupts", &intlen); + while (device) { + ints = get_property(device, "AAPL,interrupts", &intlen); + if (ints != NULL) + break; + device = device->parent; + if (device && strcmp(device->type, "pci") != 0) + break; + } if (ints == NULL) return -EINVAL; intlen /= sizeof(u32); |