aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/pci_32.c98
1 files changed, 53 insertions, 45 deletions
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index ab5887bff02a..8336deafc624 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -736,25 +736,51 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void*
736 return NULL; 736 return NULL;
737} 737}
738 738
739static int 739static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
740scan_OF_pci_childs_iterator(struct device_node* node, void* data) 740 unsigned int devfn)
741{ 741{
742 const unsigned int *reg; 742 struct device_node *np = NULL;
743 u8* fdata = (u8*)data; 743 const u32 *reg;
744 744 unsigned int psize;
745 reg = get_property(node, "reg", NULL); 745
746 if (reg && ((reg[0] >> 8) & 0xff) == fdata[1] 746 while ((np = of_get_next_child(parent, np)) != NULL) {
747 && ((reg[0] >> 16) & 0xff) == fdata[0]) 747 reg = get_property(np, "reg", &psize);
748 return 1; 748 if (reg == NULL || psize < 4)
749 return 0; 749 continue;
750 if (((reg[0] >> 8) & 0xff) == devfn)
751 return np;
752 }
753 return NULL;
750} 754}
751 755
752static struct device_node* 756
753scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn) 757static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
754{ 758{
755 u8 filter_data[2] = {bus, dev_fn}; 759 struct device_node *parent, *np;
760
761 /* Are we a root bus ? */
762 if (bus->self == NULL || bus->parent == NULL) {
763 struct pci_controller *hose = pci_bus_to_hose(bus->number);
764 if (hose == NULL)
765 return NULL;
766 return of_node_get(hose->arch_data);
767 }
768
769 /* not a root bus, we need to get our parent */
770 parent = scan_OF_for_pci_bus(bus->parent);
771 if (parent == NULL)
772 return NULL;
773
774 /* now iterate for children for a match */
775 np = scan_OF_for_pci_dev(parent, bus->self->devfn);
776 of_node_put(parent);
756 777
757 return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data); 778 /* sanity check */
779 if (strcmp(np->type, "pci") != 0)
780 printk(KERN_WARNING "pci: wrong type \"%s\" for bridge %s\n",
781 np->type, np->full_name);
782
783 return np;
758} 784}
759 785
760/* 786/*
@@ -763,43 +789,25 @@ scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
763struct device_node * 789struct device_node *
764pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) 790pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
765{ 791{
766 struct pci_controller *hose; 792 struct device_node *parent, *np;
767 struct device_node *node;
768 int busnr;
769 793
770 if (!have_of) 794 if (!have_of)
771 return NULL; 795 return NULL;
772
773 /* Lookup the hose */
774 busnr = bus->number;
775 hose = pci_bus_to_hose(busnr);
776 if (!hose)
777 return NULL;
778 796
779 /* Check it has an OF node associated */ 797 DBG("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
780 node = (struct device_node *) hose->arch_data; 798 parent = scan_OF_for_pci_bus(bus);
781 if (!node) 799 if (parent == NULL)
782 return NULL; 800 return NULL;
783 801 DBG(" parent is %s\n", parent ? parent->full_name : "<NULL>");
784 /* Fixup bus number according to what OF think it is. */ 802 np = scan_OF_for_pci_dev(parent, devfn);
785#ifdef CONFIG_PPC_PMAC 803 of_node_put(parent);
786 /* The G5 need a special case here. Basically, we don't remap all 804 DBG(" result is %s\n", np ? np->full_name : "<NULL>");
787 * busses on it so we don't create the pci-OF-map. However, we do 805
788 * remap the AGP bus and so have to deal with it. A future better 806 /* XXX most callers don't release the returned node
789 * fix has to be done by making the remapping per-host and always 807 * mostly because ppc64 doesn't increase the refcount,
790 * filling the pci_to_OF map. --BenH 808 * we need to fix that.
791 */ 809 */
792 if (machine_is(powermac) && busnr >= 0xf0) 810 return np;
793 busnr -= 0xf0;
794 else
795#endif
796 if (pci_to_OF_bus_map)
797 busnr = pci_to_OF_bus_map[busnr];
798 if (busnr == 0xff)
799 return NULL;
800
801 /* Now, lookup childs of the hose */
802 return scan_OF_childs_for_device(node->child, busnr, devfn);
803} 811}
804EXPORT_SYMBOL(pci_busdev_to_OF_node); 812EXPORT_SYMBOL(pci_busdev_to_OF_node);
805 813