aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/pci_32.c
diff options
context:
space:
mode:
authorTom Arbuckle <tom.d.arbuckle@gmail.com>2009-02-11 05:41:48 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-02-22 18:48:57 -0500
commitf81786913aa0ca27a3230f30d099e9613d0d7973 (patch)
tree2431bff1643e0105985fd00bc68ddea428782cd7 /arch/powerpc/kernel/pci_32.c
parent16c57b3620d77e0bc981da5ef32beae730512684 (diff)
powerpc/pci: Fix PCI<->OF matching of old style multifunc devices
Old OF variants used to create a 'dummy' parent node "multifunc-device" for devices with more than one PCI function. Our code that matches OF nodes to PCI devices dealt with that in one place but not in another, this fixes it. This has the practical effect of fixing interrupt routing of multifunction PCI cards on some older PowerMac machines. Signed-off-by: Tom Arbuckle <tom.d.arbuckle@gmail.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/pci_32.c')
-rw-r--r--arch/powerpc/kernel/pci_32.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index c6368506455f..d473634e39e3 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -218,16 +218,23 @@ scan_OF_pci_childs(struct device_node *parent, pci_OF_scan_iterator filter, void
218static struct device_node *scan_OF_for_pci_dev(struct device_node *parent, 218static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
219 unsigned int devfn) 219 unsigned int devfn)
220{ 220{
221 struct device_node *np; 221 struct device_node *np, *cnp;
222 const u32 *reg; 222 const u32 *reg;
223 unsigned int psize; 223 unsigned int psize;
224 224
225 for_each_child_of_node(parent, np) { 225 for_each_child_of_node(parent, np) {
226 reg = of_get_property(np, "reg", &psize); 226 reg = of_get_property(np, "reg", &psize);
227 if (reg == NULL || psize < 4) 227 if (reg && psize >= 4 && ((reg[0] >> 8) & 0xff) == devfn)
228 continue;
229 if (((reg[0] >> 8) & 0xff) == devfn)
230 return np; 228 return np;
229
230 /* Note: some OFs create a parent node "multifunc-device" as
231 * a fake root for all functions of a multi-function device,
232 * we go down them as well. */
233 if (!strcmp(np->name, "multifunc-device")) {
234 cnp = scan_OF_for_pci_dev(np, devfn);
235 if (cnp)
236 return cnp;
237 }
231 } 238 }
232 return NULL; 239 return NULL;
233} 240}