Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / sparc64 / kernel / pci.c
index 4e69806..f97ddeb 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/sched.h>
@@ -17,6 +18,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/pbm.h>
+#include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/ebus.h>
 #include <asm/isa.h>
@@ -40,7 +42,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
 #else
 
 /* List of all PCI controllers found in the system. */
-spinlock_t pci_controller_lock = SPIN_LOCK_UNLOCKED;
 struct pci_controller_info *pci_controller_root = NULL;
 
 /* Each PCI controller found gets a unique index. */
@@ -56,7 +57,7 @@ volatile int pci_poke_in_progress;
 volatile int pci_poke_cpu = -1;
 volatile int pci_poke_faulted;
 
-static spinlock_t pci_poke_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pci_poke_lock);
 
 void pci_config_read8(u8 *addr, u8 *ret)
 {
@@ -187,6 +188,7 @@ extern void psycho_init(int, char *);
 extern void schizo_init(int, char *);
 extern void schizo_plus_init(int, char *);
 extern void tomatillo_init(int, char *);
+extern void sun4v_pci_init(int, char *);
 
 static struct {
        char *model_name;
@@ -203,6 +205,7 @@ static struct {
        { "pci108e,8002", schizo_plus_init },
        { "SUNW,tomatillo", tomatillo_init },
        { "pci108e,a801", tomatillo_init },
+       { "SUNW,sun4v-pci", sun4v_pci_init },
 };
 #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
                                  sizeof(pci_controller_table[0]))
@@ -282,6 +285,12 @@ int __init pcic_present(void)
        return pci_controller_scan(pci_is_controller);
 }
 
+struct pci_iommu_ops *pci_iommu_ops;
+EXPORT_SYMBOL(pci_iommu_ops);
+
+extern struct pci_iommu_ops pci_sun4u_iommu_ops,
+       pci_sun4v_iommu_ops;
+
 /* Find each controller in the system, attach and initialize
  * software state structure for each and link into the
  * pci_controller_root.  Setup the controller enough such
@@ -289,6 +298,11 @@ int __init pcic_present(void)
  */
 static void __init pci_controller_probe(void)
 {
+       if (tlb_type == hypervisor)
+               pci_iommu_ops = &pci_sun4v_iommu_ops;
+       else
+               pci_iommu_ops = &pci_sun4u_iommu_ops;
+
        printk("PCI: Probing for controllers.\n");
 
        pci_controller_scan(pci_controller_init);
@@ -297,12 +311,9 @@ static void __init pci_controller_probe(void)
 static void __init pci_scan_each_controller_bus(void)
 {
        struct pci_controller_info *p;
-       unsigned long flags;
 
-       spin_lock_irqsave(&pci_controller_lock, flags);
        for (p = pci_controller_root; p; p = p->next)
                p->scan_bus(p);
-       spin_unlock_irqrestore(&pci_controller_lock, flags);
 }
 
 /* Reorder the pci_dev chain, so that onboard devices come first
@@ -350,10 +361,6 @@ static int __init pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-struct pci_fixup pcibios_fixups[] = {
-       { 0 }
-};
-
 void pcibios_fixup_bus(struct pci_bus *pbus)
 {
        struct pci_pbm_info *pbm = pbus->sysdata;
@@ -365,134 +372,17 @@ void pcibios_fixup_bus(struct pci_bus *pbus)
        pbus->resource[1] = &pbm->mem_space;
 }
 
-int pci_claim_resource(struct pci_dev *pdev, int resource)
+struct resource *pcibios_select_root(struct pci_dev *pdev, struct resource *r)
 {
        struct pci_pbm_info *pbm = pdev->bus->sysdata;
-       struct resource *res = &pdev->resource[resource];
-       struct resource *root;
+       struct resource *root = NULL;
 
-       if (!pbm)
-               return -EINVAL;
-
-       if (res->flags & IORESOURCE_IO)
+       if (r->flags & IORESOURCE_IO)
                root = &pbm->io_space;
-       else
+       if (r->flags & IORESOURCE_MEM)
                root = &pbm->mem_space;
 
-       pbm->parent->resource_adjust(pdev, res, root);
-
-       return request_resource(root, res);
-}
-
-/*
- * Given the PCI bus a device resides on, try to
- * find an acceptable resource allocation for a
- * specific device resource..
- */
-static int pci_assign_bus_resource(const struct pci_bus *bus,
-       struct pci_dev *dev,
-       struct resource *res,
-       unsigned long size,
-       unsigned long min,
-       int resno)
-{
-       unsigned int type_mask;
-       int i;
-
-       type_mask = IORESOURCE_IO | IORESOURCE_MEM;
-       for (i = 0 ; i < 4; i++) {
-               struct resource *r = bus->resource[i];
-               if (!r)
-                       continue;
-
-               /* type_mask must match */
-               if ((res->flags ^ r->flags) & type_mask)
-                       continue;
-
-               /* Ok, try it out.. */
-               if (allocate_resource(r, res, size, min, -1, size, NULL, NULL) < 0)
-                       continue;
-
-               /* PCI config space updated by caller.  */
-               return 0;
-       }
-       return -EBUSY;
-}
-
-int pci_assign_resource(struct pci_dev *pdev, int resource)
-{
-       struct pcidev_cookie *pcp = pdev->sysdata;
-       struct pci_pbm_info *pbm = pcp->pbm;
-       struct resource *res = &pdev->resource[resource];
-       unsigned long min, size;
-       int err;
-
-       if (res->flags & IORESOURCE_IO)
-               min = pbm->io_space.start + 0x400UL;
-       else
-               min = pbm->mem_space.start;
-
-       size = res->end - res->start + 1;
-
-       err = pci_assign_bus_resource(pdev->bus, pdev, res, size, min, resource);
-
-       if (err < 0) {
-               printk("PCI: Failed to allocate resource %d for %s\n",
-                      resource, pci_name(pdev));
-       } else {
-               /* Update PCI config space. */
-               pbm->parent->base_address_update(pdev, resource);
-       }
-
-       return err;
-}
-
-/* Sort resources by alignment */
-void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
-{
-       int i;
-
-       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-               struct resource *r;
-               struct resource_list *list, *tmp;
-               unsigned long r_align;
-
-               r = &dev->resource[i];
-               r_align = r->end - r->start;
-               
-               if (!(r->flags) || r->parent)
-                       continue;
-               if (!r_align) {
-                       printk(KERN_WARNING "PCI: Ignore bogus resource %d "
-                                           "[%lx:%lx] of %s\n",
-                                           i, r->start, r->end, pci_name(dev));
-                       continue;
-               }
-               r_align = (i < PCI_BRIDGE_RESOURCES) ? r_align + 1 : r->start;
-               for (list = head; ; list = list->next) {
-                       unsigned long align = 0;
-                       struct resource_list *ln = list->next;
-                       int idx;
-
-                       if (ln) {
-                               idx = ln->res - &ln->dev->resource[0];
-                               align = (idx < PCI_BRIDGE_RESOURCES) ?
-                                       ln->res->end - ln->res->start + 1 :
-                                       ln->res->start;
-                       }
-                       if (r_align > align) {
-                               tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
-                               if (!tmp)
-                                       panic("pdev_sort_resources(): "
-                                             "kmalloc() failed!\n");
-                               tmp->next = ln;
-                               tmp->res = r;
-                               tmp->dev = dev;
-                               list->next = tmp;
-                               break;
-                       }
-               }
-       }
+       return root;
 }
 
 void pcibios_update_irq(struct pci_dev *pdev, int irq)
@@ -529,6 +419,7 @@ void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region
        region->start = res->start - zero_res.start;
        region->end = res->end - zero_res.start;
 }
+EXPORT_SYMBOL(pcibios_resource_to_bus);
 
 void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
                             struct pci_bus_region *region)
@@ -546,6 +437,7 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
 
        pbm->parent->resource_adjust(pdev, res, root);
 }
+EXPORT_SYMBOL(pcibios_bus_to_resource);
 
 char * __init pcibios_setup(char *str)
 {
@@ -732,7 +624,7 @@ static int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vm
 static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
                                            enum pci_mmap_state mmap_state)
 {
-       vma->vm_flags |= (VM_SHM | VM_LOCKED);
+       vma->vm_flags |= (VM_IO | VM_RESERVED);
 }
 
 /* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
@@ -741,12 +633,9 @@ static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma
 static void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
                                             enum pci_mmap_state mmap_state)
 {
-       /* Our io_remap_page_range takes care of this, do nothing. */
+       /* Our io_remap_pfn_range takes care of this, do nothing.  */
 }
 
-extern int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long offset,
-                              unsigned long size, pgprot_t prot, int space);
-
 /* Perform the actual remap of the pages for a PCI device mapping, as appropriate
  * for this architecture.  The region in the process to map is described by vm_start
  * and vm_end members of VMA, the base physical address is found in vm_pgoff.
@@ -768,14 +657,14 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
        __pci_mmap_set_flags(dev, vma, mmap_state);
        __pci_mmap_set_pgprot(dev, vma, mmap_state);
 
-       ret = io_remap_page_range(vma, vma->vm_start,
-                                 (vma->vm_pgoff << PAGE_SHIFT |
-                                  (write_combine ? 0x1UL : 0x0UL)),
-                                 vma->vm_end - vma->vm_start, vma->vm_page_prot, 0);
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       ret = io_remap_pfn_range(vma, vma->vm_start,
+                                vma->vm_pgoff,
+                                vma->vm_end - vma->vm_start,
+                                vma->vm_page_prot);
        if (ret)
                return ret;
 
-       vma->vm_flags |= VM_IO;
        return 0;
 }
 
@@ -799,12 +688,7 @@ int pci_domain_nr(struct pci_bus *pbus)
 
        return ret;
 }
-
-int pci_name_bus(char *name, struct pci_bus *bus)
-{
-       sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
-       return 0;
-}
+EXPORT_SYMBOL(pci_domain_nr);
 
 int pcibios_prep_mwi(struct pci_dev *dev)
 {