Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / arch / powerpc / kernel / pci_64.c
index 3cef1b8..247937d 100644 (file)
 #include <asm/byteorder.h>
 #include <asm/irq.h>
 #include <asm/machdep.h>
-#include <asm/udbg.h>
 #include <asm/ppc-pci.h>
 
 #ifdef DEBUG
-#define DBG(fmt...) udbg_printf(fmt)
+#include <asm/udbg.h>
+#define DBG(fmt...) printk(fmt)
 #else
 #define DBG(fmt...)
 #endif
 
 unsigned long pci_probe_only = 1;
-unsigned long pci_assign_all_buses = 0;
-
-/*
- * legal IO pages under MAX_ISA_PORT.  This is to ensure we don't touch
- * devices we don't have access to.
- */
-unsigned long io_page_mask;
-
-EXPORT_SYMBOL(io_page_mask);
+int pci_assign_all_buses = 0;
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
 static void fixup_resource(struct resource *res, struct pci_dev *dev);
 static void do_bus_setup(struct pci_bus *bus);
+static void phbs_remap_io(void);
 #endif
 
-unsigned int pcibios_assign_all_busses(void)
-{
-       return pci_assign_all_buses;
-}
-
 /* pci_io_base -- the base address from which io bars are offsets.
  * This is the lowest I/O base address (so bar values are always positive),
  * and it *must* be the start of ISA space if an ISA bus exists because
@@ -82,6 +70,7 @@ int global_phb_number;                /* Global phb counter */
 
 /* Cached ISA bridge dev. */
 struct pci_dev *ppc64_isabridge_dev = NULL;
+EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
 
 static void fixup_broken_pcnet32(struct pci_dev* dev)
 {
@@ -187,7 +176,7 @@ static DEFINE_SPINLOCK(hose_spinlock);
 /*
  * pci_controller(phb) initialized common variables.
  */
-void __devinit pci_setup_pci_controller(struct pci_controller *hose)
+static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
 {
        memset(hose, 0, sizeof(struct pci_controller));
 
@@ -197,7 +186,69 @@ void __devinit pci_setup_pci_controller(struct pci_controller *hose)
        spin_unlock(&hose_spinlock);
 }
 
-static void __init pcibios_claim_one_bus(struct pci_bus *b)
+static void add_linux_pci_domain(struct device_node *dev,
+                                struct pci_controller *phb)
+{
+       struct property *of_prop;
+       unsigned int size;
+
+       of_prop = (struct property *)
+               get_property(dev, "linux,pci-domain", &size);
+       if (of_prop != NULL)
+               return;
+       WARN_ON(of_prop && size < sizeof(int));
+       if (of_prop && size < sizeof(int))
+               of_prop = NULL;
+       size = sizeof(struct property) + sizeof(int);
+       if (of_prop == NULL) {
+               if (mem_init_done)
+                       of_prop = kmalloc(size, GFP_KERNEL);
+               else
+                       of_prop = alloc_bootmem(size);
+       }
+       memset(of_prop, 0, sizeof(struct property));
+       of_prop->name = "linux,pci-domain";
+       of_prop->length = sizeof(int);
+       of_prop->value = (unsigned char *)&of_prop[1];
+       *((int *)of_prop->value) = phb->global_number;
+       prom_add_property(dev, of_prop);
+}
+
+struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
+{
+       struct pci_controller *phb;
+
+       if (mem_init_done)
+               phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
+       else
+               phb = alloc_bootmem(sizeof (struct pci_controller));
+       if (phb == NULL)
+               return NULL;
+       pci_setup_pci_controller(phb);
+       phb->arch_data = dev;
+       phb->is_dynamic = mem_init_done;
+       if (dev) {
+               PHB_SET_NODE(phb, of_node_to_nid(dev));
+               add_linux_pci_domain(dev, phb);
+       }
+       return phb;
+}
+
+void pcibios_free_controller(struct pci_controller *phb)
+{
+       if (phb->arch_data) {
+               struct device_node *np = phb->arch_data;
+               int *domain = (int *)get_property(np,
+                                                 "linux,pci-domain", NULL);
+               if (domain)
+                       *domain = -1;
+       }
+       if (phb->is_dynamic)
+               kfree(phb);
+}
+
+#ifndef CONFIG_PPC_ISERIES
+void __devinit pcibios_claim_one_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
        struct pci_bus *child_bus;
@@ -217,8 +268,10 @@ static void __init pcibios_claim_one_bus(struct pci_bus *b)
        list_for_each_entry(child_bus, &b->children, node)
                pcibios_claim_one_bus(child_bus);
 }
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
+#endif
 
-#ifndef CONFIG_PPC_ISERIES
 static void __init pcibios_claim_of_setup(void)
 {
        struct pci_bus *b;
@@ -269,6 +322,7 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
        addrs = (u32 *) get_property(node, "assigned-addresses", &proplen);
        if (!addrs)
                return;
+       DBG("    parse addresses (%d bytes) @ %p\n", proplen, addrs);
        for (; proplen >= 20; proplen -= 20, addrs += 5) {
                flags = pci_parse_of_flags(addrs[0]);
                if (!flags)
@@ -278,6 +332,9 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
                if (!size)
                        continue;
                i = addrs[0] & 0xff;
+               DBG("  base: %llx, size: %llx, i: %x\n",
+                   (unsigned long long)base, (unsigned long long)size, i);
+
                if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
                        res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
                } else if (i == dev->rom_base_reg) {
@@ -308,6 +365,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
        if (type == NULL)
                type = "";
 
+       DBG("    create device, devfn: %x, type: %s\n", devfn, type);
+
        memset(dev, 0, sizeof(struct pci_dev));
        dev->bus = bus;
        dev->sysdata = node;
@@ -321,15 +380,17 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
        dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0);
        dev->subsystem_device = get_int_prop(node, "subsystem-id", 0);
 
-       dev->cfg_size = 256; /*pci_cfg_space_size(dev);*/
+       dev->cfg_size = pci_cfg_space_size(dev);
 
        sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
                dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
        dev->class = get_int_prop(node, "class-code", 0);
 
+       DBG("    class: 0x%x\n", dev->class);
+
        dev->current_state = 4;         /* unknown power state */
 
-       if (!strcmp(type, "pci")) {
+       if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
                /* a PCI-PCI bridge */
                dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
                dev->rom_base_reg = PCI_ROM_ADDRESS1;
@@ -348,6 +409,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
 
        pci_parse_of_addrs(node, dev);
 
+       DBG("    adding to system ...\n");
+
        pci_device_add(dev, bus);
 
        /* XXX pci_scan_msi_device(dev); */
@@ -364,15 +427,21 @@ void __devinit of_scan_bus(struct device_node *node,
        int reglen, devfn;
        struct pci_dev *dev;
 
+       DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number);
+
        while ((child = of_get_next_child(node, child)) != NULL) {
+               DBG("  * %s\n", child->full_name);
                reg = (u32 *) get_property(child, "reg", &reglen);
                if (reg == NULL || reglen < 20)
                        continue;
                devfn = (reg[0] >> 8) & 0xff;
+
                /* create a new pci_dev for this device */
                dev = of_create_pci_dev(child, bus, devfn);
                if (!dev)
                        continue;
+               DBG("dev header type: %x\n", dev->hdr_type);
+
                if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
                    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
                        of_scan_pci_bridge(child, dev);
@@ -392,16 +461,18 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
        unsigned int flags;
        u64 size;
 
+       DBG("of_scan_pci_bridge(%s)\n", node->full_name);
+
        /* parse bus-range property */
        busrange = (u32 *) get_property(node, "bus-range", &len);
        if (busrange == NULL || len != 8) {
-               printk(KERN_ERR "Can't get bus-range for PCI-PCI bridge %s\n",
+               printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n",
                       node->full_name);
                return;
        }
        ranges = (u32 *) get_property(node, "ranges", &len);
        if (ranges == NULL) {
-               printk(KERN_ERR "Can't get ranges for PCI-PCI bridge %s\n",
+               printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
                       node->full_name);
                return;
        }
@@ -455,10 +526,13 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
        }
        sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
                bus->number);
+       DBG("    bus name: %s\n", bus->name);
 
        mode = PCI_PROBE_NORMAL;
        if (ppc_md.pci_probe_mode)
                mode = ppc_md.pci_probe_mode(bus);
+       DBG("    probe mode: %d\n", mode);
+
        if (mode == PCI_PROBE_DEVTREE)
                of_scan_bus(node, bus);
        else if (mode == PCI_PROBE_NORMAL)
@@ -474,6 +548,8 @@ void __devinit scan_phb(struct pci_controller *hose)
        int i, mode;
        struct resource *res;
 
+       DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
+
        bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node);
        if (bus == NULL) {
                printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
@@ -498,8 +574,9 @@ void __devinit scan_phb(struct pci_controller *hose)
 
        mode = PCI_PROBE_NORMAL;
 #ifdef CONFIG_PPC_MULTIPLATFORM
-       if (ppc_md.pci_probe_mode)
+       if (node && ppc_md.pci_probe_mode)
                mode = ppc_md.pci_probe_mode(bus);
+       DBG("    probe mode: %d\n", mode);
        if (mode == PCI_PROBE_DEVTREE) {
                bus->subordinate = hose->last_busno;
                of_scan_bus(node, bus);
@@ -507,7 +584,6 @@ void __devinit scan_phb(struct pci_controller *hose)
 #endif /* CONFIG_PPC_MULTIPLATFORM */
        if (mode == PCI_PROBE_NORMAL)
                hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
-       pci_bus_add_devices(bus);
 }
 
 static int __init pcibios_init(void)
@@ -523,11 +599,13 @@ static int __init pcibios_init(void)
        iSeries_pcibios_init(); 
 #endif
 
-       printk("PCI: Probing PCI hardware\n");
+       printk(KERN_DEBUG "PCI: Probing PCI hardware\n");
 
        /* Scan all of the recorded PCI controllers.  */
-       list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
                scan_phb(hose);
+               pci_bus_add_devices(hose->bus);
+       }
 
 #ifndef CONFIG_PPC_ISERIES
        if (pci_probe_only)
@@ -546,14 +624,14 @@ static int __init pcibios_init(void)
        /* Cache the location of the ISA bridge (if we have one) */
        ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
        if (ppc64_isabridge_dev != NULL)
-               printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
+               printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
        /* map in PCI I/O space */
        phbs_remap_io();
 #endif
 
-       printk("PCI: Probing PCI hardware done\n");
+       printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
 
        return 0;
 }
@@ -720,7 +798,7 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
        else
                prot |= _PAGE_GUARDED;
 
-       printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
+       printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
               prot);
 
        return __pgprot(prot);
@@ -788,8 +866,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
  * Returns a negative error code on failure, zero on success.
  */
 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state,
-                       int write_combine)
+                       enum pci_mmap_state mmap_state, int write_combine)
 {
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
        struct resource *rp;
@@ -800,7 +877,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                return -EINVAL;
 
        vma->vm_pgoff = offset >> PAGE_SHIFT;
-       vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
        vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
                                                  vma->vm_page_prot,
                                                  mmap_state, write_combine);
@@ -811,8 +887,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
        return ret;
 }
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t pci_show_devspec(struct device *dev,
+               struct device_attribute *attr, char *buf)
 {
        struct pci_dev *pdev;
        struct device_node *np;
@@ -824,13 +900,10 @@ static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *att
        return sprintf(buf, "%s", np->full_name);
 }
 static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 void pcibios_add_platform_entries(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PPC_MULTIPLATFORM
        device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 }
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
@@ -842,6 +915,25 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
                                      unsigned long phb_io_base_phys,
                                      void __iomem * phb_io_base_virt)
 {
+       /* Remove these asap */
+
+       struct pci_address {
+               u32 a_hi;
+               u32 a_mid;
+               u32 a_lo;
+       };
+
+       struct isa_address {
+               u32 a_hi;
+               u32 a_lo;
+       };
+
+       struct isa_range {
+               struct isa_address isa_addr;
+               struct pci_address pci_addr;
+               unsigned int size;
+       };
+
        struct isa_range *range;
        unsigned long pci_addr;
        unsigned int isa_addr;
@@ -907,9 +999,10 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
         *                      (size depending on dev->n_addr_cells)
         *   cells 4+5 or 5+6:  the size of the range
         */
-       rlen = 0;
-       hose->io_base_phys = 0;
        ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+       if (ranges == NULL)
+               return;
+       hose->io_base_phys = 0;
        while ((rlen -= np * sizeof(unsigned int)) >= 0) {
                res = NULL;
                pci_space = ranges[0];
@@ -1001,8 +1094,6 @@ void __init pci_setup_phb_io(struct pci_controller *hose, int primary)
                        pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
                                                hose->io_base_virt);
                        of_node_put(isa_dn);
-                       /* Allow all IO */
-                       io_page_mask = -1;
                }
        }
 
@@ -1107,7 +1198,9 @@ int remap_bus_range(struct pci_bus *bus)
        
        if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
                return 1;
-       printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
+       if (start_phys == 0)
+               return 1;
+       printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
        if (__ioremap_explicit(start_phys, start_virt, size,
                               _PAGE_NO_CACHE | _PAGE_GUARDED))
                return 1;
@@ -1116,7 +1209,7 @@ int remap_bus_range(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(remap_bus_range);
 
-void phbs_remap_io(void)
+static void phbs_remap_io(void)
 {
        struct pci_controller *hose, *tmp;
 
@@ -1124,41 +1217,16 @@ void phbs_remap_io(void)
                remap_bus_range(hose->bus);
 }
 
-/*
- * ppc64 can have multifunction devices that do not respond to function 0.
- * In this case we must scan all functions.
- * XXX this can go now, we use the OF device tree in all the
- * cases that caused problems. -- paulus
- */
-int pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
-{
-       return 0;
-}
-
 static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
-       unsigned long start, end, mask, offset;
+       unsigned long offset;
 
        if (res->flags & IORESOURCE_IO) {
                offset = (unsigned long)hose->io_base_virt - pci_io_base;
 
-               start = res->start += offset;
-               end = res->end += offset;
-
-               /* Need to allow IO access to pages that are in the
-                  ISA range */
-               if (start < MAX_ISA_PORT) {
-                       if (end > MAX_ISA_PORT)
-                               end = MAX_ISA_PORT;
-
-                       start >>= PAGE_SHIFT;
-                       end >>= PAGE_SHIFT;
-
-                       /* get the range of pages for the map */
-                       mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1);
-                       io_page_mask |= mask;
-               }
+               res->start += offset;
+               res->end += offset;
        } else if (res->flags & IORESOURCE_MEM) {
                res->start += hose->pci_mem_offset;
                res->end += hose->pci_mem_offset;
@@ -1177,6 +1245,7 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
 }
 EXPORT_SYMBOL(pcibios_fixup_device_resources);
 
+
 static void __devinit do_bus_setup(struct pci_bus *bus)
 {
        struct pci_dev *dev;
@@ -1260,8 +1329,38 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
        *end = rsrc->end + offset;
 }
 
+struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
+{
+       if (!have_of)
+               return NULL;
+       while(node) {
+               struct pci_controller *hose, *tmp;
+               list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+                       if (hose->arch_data == node)
+                               return hose;
+               node = node->parent;
+       }
+       return NULL;
+}
+
 #endif /* CONFIG_PPC_MULTIPLATFORM */
 
+unsigned long pci_address_to_pio(phys_addr_t address)
+{
+       struct pci_controller *hose, *tmp;
+
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+               if (address >= hose->io_base_phys &&
+                   address < (hose->io_base_phys + hose->pci_io_size)) {
+                       unsigned long base =
+                               (unsigned long)hose->io_base_virt - pci_io_base;
+                       return base + (address - hose->io_base_phys);
+               }
+       }
+       return (unsigned int)-1;
+}
+EXPORT_SYMBOL_GPL(pci_address_to_pio);
+
 
 #define IOBASE_BRIDGE_NUMBER   0
 #define IOBASE_MEMORY          1
@@ -1317,3 +1416,12 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
 
        return -EOPNOTSUPP;
 }
+
+#ifdef CONFIG_NUMA
+int pcibus_to_node(struct pci_bus *bus)
+{
+       struct pci_controller *phb = pci_bus_to_host(bus);
+       return phb->node;
+}
+EXPORT_SYMBOL(pcibus_to_node);
+#endif