]> Pileus Git - ~andy/linux/blobdiff - drivers/pci/setup-res.c
Merge tag 'parisc-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6
[~andy/linux] / drivers / pci / setup-res.c
index b66bfdbd21f7aafa55f3ea9e6b4782bf29dc2f01..eea85dafc7632ce149d432355301ed3157eee195 100644 (file)
@@ -114,7 +114,6 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
 }
 EXPORT_SYMBOL(pci_claim_resource);
 
-#ifdef CONFIG_PCI_QUIRKS
 void pci_disable_bridge_window(struct pci_dev *dev)
 {
        dev_info(&dev->dev, "disabling bridge mem windows\n");
@@ -127,9 +126,6 @@ void pci_disable_bridge_window(struct pci_dev *dev)
        pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0);
        pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);
 }
-#endif /* CONFIG_PCI_QUIRKS */
-
-
 
 static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
                int resno, resource_size_t size, resource_size_t align)
@@ -158,22 +154,44 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
        return ret;
 }
 
+/*
+ * Generic function that returns a value indicating that the device's
+ * original BIOS BAR address was not saved and so is not available for
+ * reinstatement.
+ *
+ * Can be over-ridden by architecture specific code that implements
+ * reinstatement functionality rather than leaving it disabled when
+ * normal allocation attempts fail.
+ */
+resource_size_t __weak pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
+{
+       return 0;
+}
+
 static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, 
                int resno, resource_size_t size)
 {
        struct resource *root, *conflict;
-       resource_size_t start, end;
+       resource_size_t fw_addr, start, end;
        int ret = 0;
 
-       if (res->flags & IORESOURCE_IO)
-               root = &ioport_resource;
-       else
-               root = &iomem_resource;
+       fw_addr = pcibios_retrieve_fw_addr(dev, resno);
+       if (!fw_addr)
+               return 1;
 
        start = res->start;
        end = res->end;
-       res->start = dev->fw_addr[resno];
+       res->start = fw_addr;
        res->end = res->start + size - 1;
+
+       root = pci_find_parent_resource(dev, res);
+       if (!root) {
+               if (res->flags & IORESOURCE_IO)
+                       root = &ioport_resource;
+               else
+                       root = &iomem_resource;
+       }
+
        dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n",
                 resno, res);
        conflict = request_resource_conflict(root, res);
@@ -228,16 +246,17 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
        int ret;
 
        if (!res->parent) {
-               dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resouce %pR "
+               dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR "
                         "\n", resno, res);
                return -EINVAL;
        }
 
-       new_size = resource_size(res) + addsize + min_align;
+       /* already aligned with min_align */
+       new_size = resource_size(res) + addsize;
        ret = _pci_assign_resource(dev, resno, new_size, min_align);
        if (!ret) {
                res->flags &= ~IORESOURCE_STARTALIGN;
-               dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
+               dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
                if (resno < PCI_BRIDGE_RESOURCES)
                        pci_update_resource(dev, resno);
        }
@@ -267,7 +286,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
         * where firmware left it.  That at least has a chance of
         * working, which is better than just leaving it disabled.
         */
-       if (ret < 0 && dev->fw_addr[resno])
+       if (ret < 0)
                ret = pci_revert_fw_address(res, dev, resno, size);
 
        if (!ret) {
@@ -279,53 +298,6 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
        return ret;
 }
 
-
-/* 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;
-               resource_size_t r_align;
-
-               r = &dev->resource[i];
-
-               if (r->flags & IORESOURCE_PCI_FIXED)
-                       continue;
-
-               if (!(r->flags) || r->parent)
-                       continue;
-
-               r_align = pci_resource_alignment(dev, r);
-               if (!r_align) {
-                       dev_warn(&dev->dev, "BAR %d: %pR has bogus alignment\n",
-                                i, r);
-                       continue;
-               }
-               for (list = head; ; list = list->next) {
-                       resource_size_t align = 0;
-                       struct resource_list *ln = list->next;
-
-                       if (ln)
-                               align = pci_resource_alignment(ln->dev, ln->res);
-
-                       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;
-                       }
-               }
-       }
-}
-
 int pci_enable_resources(struct pci_dev *dev, int mask)
 {
        u16 cmd, old_cmd;