]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Separate out pci bus resource allocator
authorRussell King <rmk@arm.linux.org.uk>
Thu, 6 Mar 2003 09:49:06 +0000 (01:49 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Thu, 6 Mar 2003 09:49:06 +0000 (01:49 -0800)
- Separate out bus resource allocator (pci_bus_alloc_resource)
- Provide pci_enable_bridges to setup command register for all
  pci bridges.

drivers/pci/Makefile
drivers/pci/bus.c [new file with mode: 0644]
drivers/pci/setup-res.c
include/linux/pci.h

index f0585cf2489dd18dcd915651a692e83aefa7f3c3..78ca0a2b3843bb9aa16c82e808b16e02d909b204 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the PCI bus specific drivers.
 #
 
-obj-y          += access.o probe.o pci.o pool.o quirks.o \
+obj-y          += access.o bus.o probe.o pci.o pool.o quirks.o \
                        names.o pci-driver.o search.o hotplug.o \
                        pci-sysfs.o
 obj-$(CONFIG_PM)  += power.o
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
new file mode 100644 (file)
index 0000000..b9e7d93
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *     drivers/pci/bus.c
+ *
+ * From setup-res.c, by:
+ *     Dave Rusling (david.rusling@reo.mts.dec.com)
+ *     David Mosberger (davidm@cs.arizona.edu)
+ *     David Miller (davem@redhat.com)
+ *     Ivan Kokshaysky (ink@jurassic.park.msu.ru)
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+
+/**
+ * pci_bus_alloc_resource - allocate a resource from a parent bus
+ * @bus: PCI bus
+ * @res: resource to allocate
+ * @size: size of resource to allocate
+ * @align: alignment of resource to allocate
+ * @min: minimum /proc/iomem address to allocate
+ * @type_mask: IORESOURCE_* type flags
+ * @alignf: resource alignment function
+ * @alignf_data: data argument for resource alignment function
+ *
+ * Given the PCI bus a device resides on, the size, minimum address,
+ * alignment and type, try to find an acceptable resource allocation
+ * for a specific device resource.
+ */
+int
+pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
+       unsigned long size, unsigned long align, unsigned long min,
+       unsigned int type_mask,
+       void (*alignf)(void *, struct resource *,
+                       unsigned long, unsigned long),
+       void *alignf_data)
+{
+       int i, ret = -ENOMEM;
+
+       type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
+
+       for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
+               struct resource *r = bus->resource[i];
+               if (!r)
+                       continue;
+
+               /* type_mask must match */
+               if ((res->flags ^ r->flags) & type_mask)
+                       continue;
+
+               /* We cannot allocate a non-prefetching resource
+                  from a pre-fetching area */
+               if ((r->flags & IORESOURCE_PREFETCH) &&
+                   !(res->flags & IORESOURCE_PREFETCH))
+                       continue;
+
+               /* Ok, try it out.. */
+               ret = allocate_resource(r, res, size, min, -1, align,
+                                       alignf, alignf_data);
+               if (ret == 0)
+                       break;
+       }
+       return ret;
+}
+
+void pci_enable_bridges(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               if (dev->subordinate) {
+                       pci_enable_device(dev);
+                       pci_set_master(dev);
+                       pci_enable_bridges(dev->subordinate);
+               }
+       }
+}
+
+EXPORT_SYMBOL(pci_bus_alloc_resource);
+EXPORT_SYMBOL(pci_enable_bridges);
index f7024cd0969424a16e92afbed1dea5385e42447b..3331a411db7b2798ac4781a74d4809be2cd37102 100644 (file)
@@ -55,84 +55,47 @@ pci_claim_resource(struct pci_dev *dev, int resource)
        return err;
 }
 
-/*
- * 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,
-       unsigned int type_mask,
-       int resno)
-{
-       unsigned long align;
-       int i;
-
-       type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
-       for (i = 0 ; i < PCI_BUS_NUM_RESOURCES; i++) {
-               struct resource *r = bus->resource[i];
-               if (!r)
-                       continue;
-
-               /* type_mask must match */
-               if ((res->flags ^ r->flags) & type_mask)
-                       continue;
-
-               /* We cannot allocate a non-prefetching resource
-                  from a pre-fetching area */
-               if ((r->flags & IORESOURCE_PREFETCH) &&
-                   !(res->flags & IORESOURCE_PREFETCH))
-                       continue;
-
-               /* The bridge resources are special, as their
-                  size != alignment. Sizing routines return
-                  required alignment in the "start" field. */
-               align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start;
-
-               /* Ok, try it out.. */
-               if (allocate_resource(r, res, size, min, -1, align,
-                                     pcibios_align_resource, dev) < 0)
-                       continue;
-
-               /* Update PCI config space.  */
-               pcibios_update_resource(dev, r, res, resno);
-               return 0;
-       }
-       return -EBUSY;
-}
-
-int 
-pci_assign_resource(struct pci_dev *dev, int i)
+int pci_assign_resource(struct pci_dev *dev, int resno)
 {
-       const struct pci_bus *bus = dev->bus;
-       struct resource *res = dev->resource + i;
-       unsigned long size, min;
+       struct pci_bus *bus = dev->bus;
+       struct resource *res = dev->resource + resno;
+       unsigned long size, min, align;
+       int ret;
 
        size = res->end - res->start + 1;
        min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
+       /* The bridge resources are special, as their
+          size != alignment. Sizing routines return
+          required alignment in the "start" field. */
+       align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start;
 
        /* First, try exact prefetching match.. */
-       if (pci_assign_bus_resource(bus, dev, res, size, min, IORESOURCE_PREFETCH, i) < 0) {
+       ret = pci_bus_alloc_resource(bus, res, size, align, min,
+                                    IORESOURCE_PREFETCH,
+                                    pcibios_align_resource, dev);
+
+       if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) {
                /*
                 * That failed.
                 *
                 * But a prefetching area can handle a non-prefetching
                 * window (it will just not perform as well).
                 */
-               if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0, i) < 0) {
-                       printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
-                              i, res->start, res->end, dev->slot_name);
-                       return -EBUSY;
-               }
+               ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
+                                            pcibios_align_resource, dev);
        }
 
-       DBGC((KERN_ERR "  got res[%lx:%lx] for resource %d of %s\n", res->start,
-                                               res->end, i, dev->dev.name));
+       if (ret) {
+               printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
+                      resno, res->start, res->end, dev->slot_name);
+       } else {
+               DBGC((KERN_ERR "  got res[%lx:%lx] for resource %d of %s\n",
+                     res->start, res->end, i, dev->dev.name));
+               /* Update PCI config space.  */
+               pcibios_update_resource(dev, res->parent, res, resno);
+       }
 
-       return 0;
+       return ret;
 }
 
 /* Sort resources by alignment */
index 29983aeb029cd09d0a75851ff99fd5947e1f534d..d10ec7697449d0a77bf04b94528b389444cba5e6 100644 (file)
@@ -641,6 +641,16 @@ void pci_release_regions(struct pci_dev *);
 int pci_request_region(struct pci_dev *, int, char *);
 void pci_release_region(struct pci_dev *, int);
 
+/* drivers/pci/bus.c */
+
+int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
+                          unsigned long size, unsigned long align,
+                          unsigned long min, unsigned int type_mask,
+                          void (*alignf)(void *, struct resource *,
+                                         unsigned long, unsigned long),
+                          void *alignf_data);
+void pci_enable_bridges(struct pci_bus *bus);
+
 /* New-style probing supporting hot-pluggable devices */
 int pci_register_driver(struct pci_driver *);
 void pci_unregister_driver(struct pci_driver *);