patch-2.4.0-test6 linux/drivers/pci/setup-res.c
Next file: linux/drivers/pcmcia/Makefile
Previous file: linux/drivers/pci/quirks.c
Back to the patch index
Back to the overall index
- Lines: 102
- Date:
Mon Aug 7 14:33:10 2000
- Orig file:
v2.4.0-test5/linux/drivers/pci/setup-res.c
- Orig date:
Fri Jun 23 21:55:09 2000
diff -u --recursive --new-file v2.4.0-test5/linux/drivers/pci/setup-res.c linux/drivers/pci/setup-res.c
@@ -50,45 +50,70 @@
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 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;
+
+ /* 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.. */
+ if (allocate_resource(r, res, size, min, -1, size, pcibios_align_resource, dev) < 0)
+ continue;
+
+ /* Update PCI config space. */
+ pcibios_update_resource(dev, r, res, i);
+ return 0;
+ }
+ return -EBUSY;
+}
+
int
pci_assign_resource(struct pci_dev *dev, int i)
{
- struct resource *root, *res;
+ const struct pci_bus *bus = dev->bus;
+ struct resource *res = dev->resource + i;
unsigned long size, min;
- res = &dev->resource[i];
+ size = res->end - res->start + 1;
+ min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
- /* Determine the root we allocate from. */
- res->end -= res->start;
- res->start = 0;
- root = pci_find_parent_resource(dev, res);
- if (root == NULL) {
- printk(KERN_ERR "PCI: Cannot find parent resource for "
- "device %s\n", dev->slot_name);
- return -EINVAL;
+ /* First, try exact prefetching match.. */
+ if (pci_assign_bus_resource(bus, dev, res, size, min, IORESOURCE_PREFETCH) < 0) {
+ /*
+ * 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) < 0) {
+ printk(KERN_ERR "PCI: Failed to allocate resource %d for %s\n", i, dev->name);
+ return -EBUSY;
+ }
}
- min = (res->flags & IORESOURCE_IO ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM);
- size = res->end + 1;
- DBGC((" for root[%lx:%lx] min[%lx] size[%lx]\n",
- root->start, root->end, min, size));
-
- if (allocate_resource(root, res, size, min, -1, size,
- pcibios_align_resource, dev) < 0) {
- printk(KERN_ERR "PCI: Failed to allocate resource %d for %s\n",
- i, dev->name);
- printk(KERN_ERR " failed root[%lx:%lx] min[%lx] size[%lx]\n",
- root->start, root->end, min, size);
- printk(KERN_ERR " failed res[%lx:%lx]\n",
- res->start, res->end);
- return -EBUSY;
- }
-
- DBGC((" got res[%lx:%lx] for resource %d\n",
- res->start, res->end, i));
-
- /* Update PCI config space. */
- pcibios_update_resource(dev, root, res, i);
+ DBGC((" got res[%lx:%lx] for resource %d\n", res->start, res->end, i));
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)