diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-04-10 21:37:07 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-06-07 19:08:17 -0400 |
commit | 98d9f30c820d509145757e6ecbc36013aa02f7bc (patch) | |
tree | dd5da915d991352ced56ed849612029339f64198 /arch/microblaze | |
parent | 1fa7b6a29c61358cc2ca6f64cef4aa0e1a7ca74c (diff) |
pci/of: Match PCI devices to OF nodes dynamically
powerpc has two different ways of matching PCI devices to their
corresponding OF node (if any) for historical reasons. The ppc64 one
does a scan looking for matching bus/dev/fn, while the ppc32 one does a
scan looking only for matching dev/fn on each level in order to be
agnostic to busses being renumbered (which Linux does on some
platforms).
This removes both and instead moves the matching code to the PCI core
itself. It's the most logical place to do it: when a pci_dev is created,
we know the parent and thus can do a single level scan for the matching
device_node (if any).
The benefit is that all archs now get the matching for free. There's one
hook the arch might want to provide to match a PHB bus to its device
node. A default weak implementation is provided that looks for the
parent device device node, but it's not entirely reliable on powerpc for
various reasons so powerpc provides its own.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Michal Simek <monstr@monstr.eu>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'arch/microblaze')
-rw-r--r-- | arch/microblaze/include/asm/pci-bridge.h | 14 | ||||
-rw-r--r-- | arch/microblaze/include/asm/prom.h | 15 | ||||
-rw-r--r-- | arch/microblaze/pci/pci_32.c | 40 |
3 files changed, 14 insertions, 55 deletions
diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h index 746df91e5796..728f8d6a59a4 100644 --- a/arch/microblaze/include/asm/pci-bridge.h +++ b/arch/microblaze/include/asm/pci-bridge.h | |||
@@ -105,19 +105,19 @@ struct pci_controller { | |||
105 | }; | 105 | }; |
106 | 106 | ||
107 | #ifdef CONFIG_PCI | 107 | #ifdef CONFIG_PCI |
108 | static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus) | 108 | static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev) |
109 | { | 109 | { |
110 | return bus->sysdata; | 110 | return dev->dev.of_node; |
111 | } | 111 | } |
112 | 112 | ||
113 | static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus) | 113 | static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus) |
114 | { | 114 | { |
115 | struct pci_controller *host; | 115 | return bus->dev.of_node; |
116 | } | ||
116 | 117 | ||
117 | if (bus->self) | 118 | static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus) |
118 | return pci_device_to_OF_node(bus->self); | 119 | { |
119 | host = pci_bus_to_host(bus); | 120 | return bus->sysdata; |
120 | return host ? host->dn : NULL; | ||
121 | } | 121 | } |
122 | 122 | ||
123 | static inline int isa_vaddr_is_ioport(void __iomem *address) | 123 | static inline int isa_vaddr_is_ioport(void __iomem *address) |
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h index d0890d36ef61..9bd01ecb00d6 100644 --- a/arch/microblaze/include/asm/prom.h +++ b/arch/microblaze/include/asm/prom.h | |||
@@ -29,21 +29,6 @@ | |||
29 | extern int early_uartlite_console(void); | 29 | extern int early_uartlite_console(void); |
30 | extern int early_uart16550_console(void); | 30 | extern int early_uart16550_console(void); |
31 | 31 | ||
32 | #ifdef CONFIG_PCI | ||
33 | /* | ||
34 | * PCI <-> OF matching functions | ||
35 | * (XXX should these be here?) | ||
36 | */ | ||
37 | struct pci_bus; | ||
38 | struct pci_dev; | ||
39 | extern int pci_device_from_OF_node(struct device_node *node, | ||
40 | u8 *bus, u8 *devfn); | ||
41 | extern struct device_node *pci_busdev_to_OF_node(struct pci_bus *bus, | ||
42 | int devfn); | ||
43 | extern struct device_node *pci_device_to_OF_node(struct pci_dev *dev); | ||
44 | extern void pci_create_OF_bus_map(void); | ||
45 | #endif | ||
46 | |||
47 | /* | 32 | /* |
48 | * OF address retreival & translation | 33 | * OF address retreival & translation |
49 | */ | 34 | */ |
diff --git a/arch/microblaze/pci/pci_32.c b/arch/microblaze/pci/pci_32.c index 92728a6cfd80..2fa95069e6ba 100644 --- a/arch/microblaze/pci/pci_32.c +++ b/arch/microblaze/pci/pci_32.c | |||
@@ -210,38 +210,6 @@ static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus) | |||
210 | return np; | 210 | return np; |
211 | } | 211 | } |
212 | 212 | ||
213 | /* | ||
214 | * Scans the OF tree for a device node matching a PCI device | ||
215 | */ | ||
216 | struct device_node * | ||
217 | pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) | ||
218 | { | ||
219 | struct device_node *parent, *np; | ||
220 | |||
221 | pr_debug("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn); | ||
222 | parent = scan_OF_for_pci_bus(bus); | ||
223 | if (parent == NULL) | ||
224 | return NULL; | ||
225 | pr_debug(" parent is %s\n", parent ? parent->full_name : "<NULL>"); | ||
226 | np = scan_OF_for_pci_dev(parent, devfn); | ||
227 | of_node_put(parent); | ||
228 | pr_debug(" result is %s\n", np ? np->full_name : "<NULL>"); | ||
229 | |||
230 | /* XXX most callers don't release the returned node | ||
231 | * mostly because ppc64 doesn't increase the refcount, | ||
232 | * we need to fix that. | ||
233 | */ | ||
234 | return np; | ||
235 | } | ||
236 | EXPORT_SYMBOL(pci_busdev_to_OF_node); | ||
237 | |||
238 | struct device_node* | ||
239 | pci_device_to_OF_node(struct pci_dev *dev) | ||
240 | { | ||
241 | return pci_busdev_to_OF_node(dev->bus, dev->devfn); | ||
242 | } | ||
243 | EXPORT_SYMBOL(pci_device_to_OF_node); | ||
244 | |||
245 | static int | 213 | static int |
246 | find_OF_pci_device_filter(struct device_node *node, void *data) | 214 | find_OF_pci_device_filter(struct device_node *node, void *data) |
247 | { | 215 | { |
@@ -315,6 +283,13 @@ pci_create_OF_bus_map(void) | |||
315 | } | 283 | } |
316 | } | 284 | } |
317 | 285 | ||
286 | struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus) | ||
287 | { | ||
288 | struct pci_controller *hose = bus->sysdata; | ||
289 | |||
290 | return of_node_get(hose->dn); | ||
291 | } | ||
292 | |||
318 | static void __devinit pcibios_scan_phb(struct pci_controller *hose) | 293 | static void __devinit pcibios_scan_phb(struct pci_controller *hose) |
319 | { | 294 | { |
320 | struct pci_bus *bus; | 295 | struct pci_bus *bus; |
@@ -332,7 +307,6 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose) | |||
332 | hose->global_number); | 307 | hose->global_number); |
333 | return; | 308 | return; |
334 | } | 309 | } |
335 | bus.dev->of_node = of_node_get(node); | ||
336 | bus->secondary = hose->first_busno; | 310 | bus->secondary = hose->first_busno; |
337 | hose->bus = bus; | 311 | hose->bus = bus; |
338 | 312 | ||