Exemple #1
0
/*
 *  Handle resources of PCI devices.  If the world were perfect, we could
 *  just allocate all the resource regions and do nothing more.  It isn't.
 *  On the other hand, we cannot just re-allocate all devices, as it would
 *  require us to know lots of host bridge internals.  So we attempt to
 *  keep as much of the original configuration as possible, but tweak it
 *  when it's found to be wrong.
 *
 *  Known BIOS problems we have to work around:
 *	- I/O or memory regions not configured
 *	- regions configured, but not enabled in the command register
 *	- bogus I/O addresses above 64K used
 *	- expansion ROMs left enabled (this may sound harmless, but given
 *	  the fact the PCI specs explicitly allow address decoders to be
 *	  shared between expansion ROMs and other resource regions, it's
 *	  at least dangerous)
 *
 *  Our solution:
 *	(1) Allocate resources for all buses behind PCI-to-PCI bridges.
 *	    This gives us fixed barriers on where we can allocate.
 *	(2) Allocate resources for all enabled devices.  If there is
 *	    a collision, just mark the resource as unallocated. Also
 *	    disable expansion ROMs during this step.
 *	(3) Try to allocate resources for disabled devices.  If the
 *	    resources were assigned correctly, everything goes well,
 *	    if they weren't, they won't disturb allocation of other
 *	    resources.
 *	(4) Assign new addresses to resources which were either
 *	    not configured at all or misconfigured.  If explicitly
 *	    requested by the user, configure expansion ROM address
 *	    as well.
 */
static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
{
	struct pci_bus *bus;
	struct pci_dev *dev;
	int idx;
	struct resource *r, *pr;

	/* Depth-First Search on bus tree */
	list_for_each_entry(bus, bus_list, node) {
		dev = bus->self;
		if (dev) {
			for (idx = PCI_BRIDGE_RESOURCES;
			     idx < PCI_NUM_RESOURCES;
			     idx++) {
				r = &dev->resource[idx];
				if (!r->flags)
					continue;
				pr = pci_find_parent_resource(dev, r);
				if (!r->start ||
				    !pr ||
				    request_resource(pr, r) < 0) {
					printk(KERN_ERR "PCI:"
					       " Cannot allocate resource"
					       " region %d of bridge %s\n",
					       idx, pci_name(dev));
					/* Something is wrong with the region.
					 * Invalidate the resource to prevent
					 * child resource allocations in this
					 * range. */
					r->flags = 0;
				}
			}
		}
		pcibios_allocate_bus_resources(&bus->children);
	}
void __init
pcibios_allocate_bus_resources(struct list_head *bus_list)
{
	struct list_head *ln;
	struct pci_bus *bus;
	int i;
	struct resource *res, *pr;

	if(!bus_list) return; 

	/* Depth-First Search on bus tree */
	for (ln = bus_list->next; ln != bus_list; ln=ln->next) {
		bus = pci_bus_b(ln);
		pci_read_bridge_bases(bus);
		for (i = 0; i < 4; ++i) {
			if ((res = bus->resource[i]) == NULL || !res->flags)
				continue;
			if (bus->parent == NULL)
				pr = (res->flags & IORESOURCE_IO)?
					&ioport_resource: &iomem_resource;
			else
				pr = pci_find_parent_resource(bus->self, res);

			if (pr && request_resource(pr, res) == 0)
				continue;
			printk(KERN_ERR "PCI: Can not allocate resource region "
			       "%d of PCI bridge %d\n", i, bus->number);
			DBG("PCI: resource is %lx..%lx (%lx)\n",
					res->start, res->end, res->flags);
		}
		pcibios_allocate_bus_resources(&bus->children);
	}
}
static inline void __init alloc_resource(struct pci_dev *dev, int idx)
{
	struct resource *pr, *r = &dev->resource[idx];

	pr = pci_find_parent_resource(dev, r);
	if(!pr || request_resource(pr, r) < 0)
	{
		printk(KERN_ERR "PCI: Can not allocate resource region %d" \
				" of device %s\n", idx, dev->slot_name);
		r->end -= r->start;
		r->start = 0;
	}
}
static struct resource *resource_parent(unsigned long b, unsigned long n,
					int flags, struct pci_dev *dev)
{
#ifdef CONFIG_PCI
	struct resource res, *pr;

	if (dev != NULL) {
		res.start = b;
		res.end = b + n - 1;
		res.flags = flags;
		pr = pci_find_parent_resource(dev, &res);
		if (pr)
			return pr;
	}
#endif /* CONFIG_PCI */
	if (flags & IORESOURCE_MEM)
		return &iomem_resource;
	return &ioport_resource;
}
Exemple #5
0
static struct resource *
claim_region(struct pcmcia_socket *s, unsigned long base, unsigned long size,
	     int type, char *name)
{
	struct resource *res, *parent;

	parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
	res = make_resource(base, size, type | IORESOURCE_BUSY, name);

	if (res) {
#ifdef CONFIG_PCI
		if (s && s->cb_dev)
			parent = pci_find_parent_resource(s->cb_dev, res);
#endif
		if (!parent || request_resource(parent, res)) {
			kfree(res);
			res = NULL;
		}
	}
	return res;
}