]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/ppc64/kernel/pci.c
ppc64: move stack switching up in interrupt processing
[karo-tx-linux.git] / arch / ppc64 / kernel / pci.c
index ff4be1da69d5b11e19a93add1b33154c5a3c212a..30247ff74972d3ef3a4048b3baca0d24141e5420 100644 (file)
@@ -31,8 +31,7 @@
 #include <asm/irq.h>
 #include <asm/machdep.h>
 #include <asm/udbg.h>
-
-#include "pci.h"
+#include <asm/ppc-pci.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -296,8 +295,8 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
        }
 }
 
-static struct pci_dev *of_create_pci_dev(struct device_node *node,
-                                        struct pci_bus *bus, int devfn)
+struct pci_dev *of_create_pci_dev(struct device_node *node,
+                                struct pci_bus *bus, int devfn)
 {
        struct pci_dev *dev;
        const char *type;
@@ -355,10 +354,9 @@ static struct pci_dev *of_create_pci_dev(struct device_node *node,
 
        return dev;
 }
+EXPORT_SYMBOL(of_create_pci_dev);
 
-static void of_scan_pci_bridge(struct device_node *node, struct pci_dev *dev);
-
-static void __devinit of_scan_bus(struct device_node *node,
+void __devinit of_scan_bus(struct device_node *node,
                                  struct pci_bus *bus)
 {
        struct device_node *child = NULL;
@@ -382,9 +380,10 @@ static void __devinit of_scan_bus(struct device_node *node,
 
        do_bus_setup(bus);
 }
+EXPORT_SYMBOL(of_scan_bus);
 
-static void __devinit of_scan_pci_bridge(struct device_node *node,
-                                        struct pci_dev *dev)
+void __devinit of_scan_pci_bridge(struct device_node *node,
+                               struct pci_dev *dev)
 {
        struct pci_bus *bus;
        u32 *busrange, *ranges;
@@ -465,9 +464,10 @@ static void __devinit of_scan_pci_bridge(struct device_node *node,
        else if (mode == PCI_PROBE_NORMAL)
                pci_scan_child_bus(bus);
 }
+EXPORT_SYMBOL(of_scan_pci_bridge);
 #endif /* CONFIG_PPC_MULTIPLATFORM */
 
-static void __devinit scan_phb(struct pci_controller *hose)
+void __devinit scan_phb(struct pci_controller *hose)
 {
        struct pci_bus *bus;
        struct device_node *node = hose->arch_data;
@@ -727,16 +727,17 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
  * above routine
  */
 pgprot_t pci_phys_mem_access_prot(struct file *file,
-                                 unsigned long offset,
+                                 unsigned long pfn,
                                  unsigned long size,
                                  pgprot_t protection)
 {
        struct pci_dev *pdev = NULL;
        struct resource *found = NULL;
        unsigned long prot = pgprot_val(protection);
+       unsigned long offset = pfn << PAGE_SHIFT;
        int i;
 
-       if (page_is_ram(offset >> PAGE_SHIFT))
+       if (page_is_ram(pfn))
                return __pgprot(prot);
 
        prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
@@ -881,9 +882,9 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
 }
 
 void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
-                                           struct device_node *dev)
+                                           struct device_node *dev, int prim)
 {
-       unsigned int *ranges;
+       unsigned int *ranges, pci_space;
        unsigned long size;
        int rlen = 0;
        int memno = 0;
@@ -906,16 +907,39 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
        ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
        while ((rlen -= np * sizeof(unsigned int)) >= 0) {
                res = NULL;
-               pci_addr = (unsigned long)ranges[1] << 32 | ranges[2];
+               pci_space = ranges[0];
+               pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2];
 
                cpu_phys_addr = ranges[3];
-               if (na == 2)
-                       cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
+               if (na >= 2)
+                       cpu_phys_addr = (cpu_phys_addr << 32) | ranges[4];
 
-               size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
+               size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4];
+               ranges += np;
                if (size == 0)
                        continue;
-               switch ((ranges[0] >> 24) & 0x3) {
+
+               /* Now consume following elements while they are contiguous */
+               while (rlen >= np * sizeof(unsigned int)) {
+                       unsigned long addr, phys;
+
+                       if (ranges[0] != pci_space)
+                               break;
+                       addr = ((unsigned long)ranges[1] << 32) | ranges[2];
+                       phys = ranges[3];
+                       if (na >= 2)
+                               phys = (phys << 32) | ranges[4];
+                       if (addr != pci_addr + size ||
+                           phys != cpu_phys_addr + size)
+                               break;
+
+                       size += ((unsigned long)ranges[na+3] << 32)
+                               | ranges[na+4];
+                       ranges += np;
+                       rlen -= np * sizeof(unsigned int);
+               }
+
+               switch ((pci_space >> 24) & 0x3) {
                case 1:         /* I/O space */
                        hose->io_base_phys = cpu_phys_addr;
                        hose->pci_io_size = size;
@@ -949,7 +973,6 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
                        res->sibling = NULL;
                        res->child = NULL;
                }
-               ranges += np;
        }
 }