[POWERPC] Check cache coherency of kernel vs firmware
[safe/jmp/linux-2.6] / arch / powerpc / kernel / pci_32.c
index ab5887b..e66064b 100644 (file)
@@ -637,7 +637,7 @@ make_one_node_map(struct device_node* node, u8 pci_bus)
 
        if (pci_bus >= pci_bus_count)
                return;
-       bus_range = get_property(node, "bus-range", &len);
+       bus_range = of_get_property(node, "bus-range", &len);
        if (bus_range == NULL || len < 2 * sizeof(int)) {
                printk(KERN_WARNING "Can't get bus-range for %s, "
                       "assuming it starts at 0\n", node->full_name);
@@ -649,17 +649,20 @@ make_one_node_map(struct device_node* node, u8 pci_bus)
                struct pci_dev* dev;
                const unsigned int *class_code, *reg;
        
-               class_code = get_property(node, "class-code", NULL);
+               class_code = of_get_property(node, "class-code", NULL);
                if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
                        (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
                        continue;
-               reg = get_property(node, "reg", NULL);
+               reg = of_get_property(node, "reg", NULL);
                if (!reg)
                        continue;
-               dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));
-               if (!dev || !dev->subordinate)
+               dev = pci_get_bus_and_slot(pci_bus, ((reg[0] >> 8) & 0xff));
+               if (!dev || !dev->subordinate) {
+                       pci_dev_put(dev);
                        continue;
+               }
                make_one_node_map(node, dev->subordinate->number);
+               pci_dev_put(dev);
        }
 }
        
@@ -669,8 +672,9 @@ pcibios_make_OF_bus_map(void)
        int i;
        struct pci_controller* hose;
        struct property *map_prop;
+       struct device_node *dn;
 
-       pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
+       pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL);
        if (!pci_to_OF_bus_map) {
                printk(KERN_ERR "Can't allocate OF bus map !\n");
                return;
@@ -690,12 +694,13 @@ pcibios_make_OF_bus_map(void)
                        continue;
                make_one_node_map(node, hose->first_busno);
        }
-       map_prop = of_find_property(find_path_device("/"),
-                       "pci-OF-bus-map", NULL);
+       dn = of_find_node_by_path("/");
+       map_prop = of_find_property(dn, "pci-OF-bus-map", NULL);
        if (map_prop) {
                BUG_ON(pci_bus_count > map_prop->length);
                memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count);
        }
+       of_node_put(dn);
 #ifdef DEBUG
        printk("PCI->OF bus map:\n");
        for (i=0; i<pci_bus_count; i++) {
@@ -724,7 +729,7 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void*
                 * a fake root for all functions of a multi-function device,
                 * we go down them as well.
                 */
-               class_code = get_property(node, "class-code", NULL);
+               class_code = of_get_property(node, "class-code", NULL);
                if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
                        (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
                        strcmp(node->name, "multifunc-device"))
@@ -736,25 +741,46 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void*
        return NULL;
 }
 
-static int
-scan_OF_pci_childs_iterator(struct device_node* node, void* data)
+static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
+                                              unsigned int devfn)
 {
-       const unsigned int *reg;
-       u8* fdata = (u8*)data;
-       
-       reg = get_property(node, "reg", NULL);
-       if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
-               && ((reg[0] >> 16) & 0xff) == fdata[0])
-               return 1;
-       return 0;
+       struct device_node *np = NULL;
+       const u32 *reg;
+       unsigned int psize;
+
+       while ((np = of_get_next_child(parent, np)) != NULL) {
+               reg = of_get_property(np, "reg", &psize);
+               if (reg == NULL || psize < 4)
+                       continue;
+               if (((reg[0] >> 8) & 0xff) == devfn)
+                       return np;
+       }
+       return NULL;
 }
 
-static struct device_node*
-scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
+
+static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
 {
-       u8 filter_data[2] = {bus, dev_fn};
+       struct device_node *parent, *np;
+
+       /* Are we a root bus ? */
+       if (bus->self == NULL || bus->parent == NULL) {
+               struct pci_controller *hose = pci_bus_to_hose(bus->number);
+               if (hose == NULL)
+                       return NULL;
+               return of_node_get(hose->arch_data);
+       }
+
+       /* not a root bus, we need to get our parent */
+       parent = scan_OF_for_pci_bus(bus->parent);
+       if (parent == NULL)
+               return NULL;
 
-       return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);
+       /* now iterate for children for a match */
+       np = scan_OF_for_pci_dev(parent, bus->self->devfn);
+       of_node_put(parent);
+
+       return np;
 }
 
 /*
@@ -763,43 +789,25 @@ scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
 struct device_node *
 pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
 {
-       struct pci_controller *hose;
-       struct device_node *node;
-       int busnr;
+       struct device_node *parent, *np;
 
        if (!have_of)
                return NULL;
-       
-       /* Lookup the hose */
-       busnr = bus->number;
-       hose = pci_bus_to_hose(busnr);
-       if (!hose)
-               return NULL;
 
-       /* Check it has an OF node associated */
-       node = (struct device_node *) hose->arch_data;
-       if (!node)
+       DBG("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
+       parent = scan_OF_for_pci_bus(bus);
+       if (parent == NULL)
                return NULL;
-
-       /* Fixup bus number according to what OF think it is. */
-#ifdef CONFIG_PPC_PMAC
-       /* The G5 need a special case here. Basically, we don't remap all
-        * busses on it so we don't create the pci-OF-map. However, we do
-        * remap the AGP bus and so have to deal with it. A future better
-        * fix has to be done by making the remapping per-host and always
-        * filling the pci_to_OF map. --BenH
+       DBG(" parent is %s\n", parent ? parent->full_name : "<NULL>");
+       np = scan_OF_for_pci_dev(parent, devfn);
+       of_node_put(parent);
+       DBG(" result is %s\n", np ? np->full_name : "<NULL>");
+
+       /* XXX most callers don't release the returned node
+        * mostly because ppc64 doesn't increase the refcount,
+        * we need to fix that.
         */
-       if (machine_is(powermac) && busnr >= 0xf0)
-               busnr -= 0xf0;
-       else
-#endif
-       if (pci_to_OF_bus_map)
-               busnr = pci_to_OF_bus_map[busnr];
-       if (busnr == 0xff)
-               return NULL;
-       
-       /* Now, lookup childs of the hose */
-       return scan_OF_childs_for_device(node->child, busnr, devfn);
+       return np;
 }
 EXPORT_SYMBOL(pci_busdev_to_OF_node);
 
@@ -856,7 +864,7 @@ pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
        if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
                        find_OF_pci_device_filter, (void *)node))
                return -ENODEV;
-       reg = get_property(node, "reg", NULL);
+       reg = of_get_property(node, "reg", NULL);
        if (!reg)
                return -ENODEV;
        *bus = (reg[0] >> 16) & 0xff;
@@ -892,14 +900,14 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
        int rlen = 0, orig_rlen;
        int memno = 0;
        struct resource *res;
-       int np, na = prom_n_addr_cells(dev);
+       int np, na = of_n_addr_cells(dev);
        np = na + 5;
 
        /* First we try to merge ranges to fix a problem with some pmacs
         * that can have more than 3 ranges, fortunately using contiguous
         * addresses -- BenH
         */
-       dt_ranges = get_property(dev, "ranges", &rlen);
+       dt_ranges = of_get_property(dev, "ranges", &rlen);
        if (!dt_ranges)
                return;
        /* Sanity check, though hopefully that never happens */
@@ -1003,14 +1011,19 @@ void __init
 pci_create_OF_bus_map(void)
 {
        struct property* of_prop;
-       
+       struct device_node *dn;
+
        of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);
-       if (of_prop && find_path_device("/")) {
+       if (!of_prop)
+               return;
+       dn = of_find_node_by_path("/");
+       if (dn) {
                memset(of_prop, -1, sizeof(struct property) + 256);
                of_prop->name = "pci-OF-bus-map";
                of_prop->length = 256;
-               of_prop->value = (unsigned char *)&of_prop[1];
-               prom_add_property(find_path_device("/"), of_prop);
+               of_prop->value = &of_prop[1];
+               prom_add_property(dn, of_prop);
+               of_node_put(dn);
        }
 }
 
@@ -1447,7 +1460,6 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
                return -1;
        }
        pci_dev->irq = virq;
-       pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, virq);
 
        return 0;
 }
@@ -1646,7 +1658,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
        int i;
 
        if (page_is_ram(pfn))
-               return prot;
+               return __pgprot(prot);
 
        prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;