This patch simplifies the resource allocator by splitting it into distinct

phases.  One benefit of this is that it makes the call chain easier to follow.

device/device.c:
	Remove references to have_resources.
	Remove read_resources from compute allocate resources.
	Split compute_allocate_resources into two
	1. compute_resource_needs
		A. Traverse the tree depth first
		B. Sum resources
		C. Adjust limits and bases
		D. Update bridge resources sizes
	2. assign_resource_values
		A. Traverse the tree breadth first
		B. Assign resource values

device/device_util.c:
	Remove references to have_resources.

device/pci_device.c:
	Remove saved values stubs (they're not needed now.)
		1. Sizing function restores values
	Fix 64-bit flag masking.
	Add an error message for an invalid value.
	Update pci_record_bridge_resource:
		1. remove compute_allocate_resource call
		2. remove pci_set_resource call
	Update pci_bus_read_resources to read children's too.
	Update pci_set_resource:
		1. change logic for setting zero-size resources
			A. Set range to [limit->limit-2^gran]
				(Could have been any range with base > limit)
		2. remove compute_allocate_resource calls
		3. Change phase4_assign_resources ->phase4_set_resources

device/pci_ops.c:
	Change an error message to be more helpful.

device/root_device.c:
	Remove code for read_resources and set resources.
	Add a .id to the ops.

include/device/device.h:
	Remove have_resources.
	Comment out assign_resources.  I think we could comment out more here.
	Add debugging function prototypes.
	Change phase4_assign_resources to phase4_set_resources.

include/device/resource.h
	Add a IORESOURCE_BRIDGE flag.

device/cardbus_device.c
	Remove compute_allocate_resource call.
	Use probe_resource (doesn't die) instead of find_resource.

Signed-off-by: Myles Watson <mylesgw@gmail.com>
Acked-by: Ronald G. Minnich <rminnich@gmail.com>



git-svn-id: svn://coreboot.org/repository/coreboot-v3@1089 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
Myles Watson 2008-12-31 19:43:34 +00:00
commit 0fb2a8f081
8 changed files with 572 additions and 329 deletions

View file

@ -75,11 +75,10 @@ static void cardbus_size_bridge_resource(struct device *dev,
{
struct resource *resource;
resource_t min_size;
resource = find_resource(dev, index);
resource = probe_resource(dev, index);
if (resource) {
min_size = resource->size;
compute_allocate_resource(&dev->link[0], resource,
resource->flags, resource->flags);
/* Always allocate at least the minimum size to a
* cardbus bridge in case a new card is plugged in.
*/

View file

@ -13,6 +13,7 @@
* (Written by Yinghai Lu for Tyan)
* Copyright (C) 2005-2006 Stefan Reinauer <stepan@openbios.org>
* Copyright (C) 2007 coresystems GmbH
* Copyright (C) 2008 Myles Watson <mylesgw@gmail.com>
*/
/*
@ -47,18 +48,6 @@ struct device *all_devices = &dev_root;
*/
struct device **last_dev_p;
/**
* The upper limit of MEM resource of the devices.
* Reserve 20M for the system.
*/
#define DEVICE_MEM_HIGH 0xFEBFFFFFUL
/**
* The lower limit of I/O resource of the devices.
* Reserve 4K for ISA/Legacy devices.
*/
#define DEVICE_IO_START 0x1000
/**
* device memory. All the device tree wil live here
*/
@ -110,7 +99,7 @@ void default_device_constructor(struct device *dev,
/**
* Given a path, locate the device_operations for it from all_device_operations.
*
* @param id TODO
* @param id a device ID to match
* @return Pointer to the ops or 0, if none found.
* @see device_path
*/
@ -127,7 +116,8 @@ struct device_operations *find_device_operations(struct device_id *id)
printk(BIOS_SPEW, "%s: cons id %s\n",
__func__, dev_id_string(&c->id));
if (id_eq(&c->id, id)) {
printk(BIOS_SPEW, "%s: match\n", __func__);
printk(BIOS_SPEW, "%s: match %s\n",
__func__, dev_id_string(&c->id));
return c;
}
}
@ -138,10 +128,9 @@ struct device_operations *find_device_operations(struct device_id *id)
/**
* Initialization tasks for the device tree code.
*
* Sets up last_dev_p, which used to be done by
* Fucking Magic (FM) in the config tool. Also, for each of the
* devices, tries to find the constructor, and from there, the ops,
* for the device.
* Sets up last_dev_p, which used to be done by magic in the config tool. Also,
* for each of the devices, tries to find the constructor, and from there, the
* ops, for the device.
*/
void dev_init(void)
{
@ -206,7 +195,7 @@ spin_define(dev_lock);
*
* @param parent Parent bus the newly created device is attached to.
* @param path Path to the device to be created.
* @param devid TODO
* @param devid ID of the device we want allocated.
* @return Pointer to the newly created device structure.
* @see device_path
*/
@ -254,7 +243,7 @@ struct device *alloc_dev(struct bus *parent, struct device_path *path,
last_dev_p = &dev->next;
/* Give the device a name. */
if (dev->id.type == DEVICE_ID_PNP &&
if (dev->id.type == DEVICE_ID_PNP &&
parent->dev->id.type == DEVICE_ID_PNP)
sprintf(dev->dtsname, "%s_pnp_child_%d", parent->dev->dtsname,
dev->path.pnp.device);
@ -292,17 +281,12 @@ void read_resources(struct bus *bus)
/* Walk through all devices and find which resources they need. */
for (curdev = bus->children; curdev; curdev = curdev->sibling) {
unsigned int links;
int i;
printk(BIOS_SPEW,
"%s: %s(%s) dtsname %s have_resources %d enabled %d\n",
"%s: %s(%s) dtsname %s enabled %d\n",
__func__, bus->dev ? bus->dev->dtsname : "NOBUSDEV",
bus->dev ? dev_path(bus->dev) : "NOBUSDEV",
curdev->dtsname,
curdev->have_resources, curdev->enabled);
if (curdev->have_resources) {
continue;
}
curdev->dtsname, curdev->enabled);
if (!curdev->enabled) {
continue;
}
@ -313,28 +297,10 @@ void read_resources(struct bus *bus)
continue;
}
curdev->ops->phase4_read_resources(curdev);
curdev->have_resources = 1;
/* Read in subtractive resources behind the current device. */
links = 0;
for (i = 0; i < curdev->resources && (curdev->links > 0); i++) {
struct resource *resource;
unsigned int link;
resource = &curdev->resource[i];
if (!(resource->flags & IORESOURCE_SUBTRACTIVE))
continue;
link = IOINDEX_SUBTRACTIVE_LINK(resource->index);
if (link > MAX_LINKS) {
printk(BIOS_ERR,
"%s subtractive index on link: %d\n",
dev_path(curdev), link);
continue;
}
if (!(links & (1 << link))) {
links |= (1 << link);
read_resources(&curdev->link[link]);
}
}
/* Read in children's resources behind the current device. */
for (i = 0; i< curdev->links; i++)
read_resources(&curdev->link[i]);
}
printk(BIOS_SPEW, "%s: %s(%s) read_resources bus %d link: %d done\n",
__func__, bus->dev->dtsname, dev_path(bus->dev), bus->secondary,
@ -398,7 +364,7 @@ static struct device *largest_resource(struct bus *bus, struct resource
}
/**
* This function is the guts of the resource allocator.
* This function is the first part of the resource allocator.
*
* The problem.
* - Allocate resource locations for every device.
@ -424,85 +390,91 @@ static struct device *largest_resource(struct bus *bus, struct resource
* a device with a couple of resources, and not need to special case it in
* the allocator. Also this allows handling of other types of bridges.
*
* @param bus TODO
* @param bridge TODO
* @param type_mask TODO
* @param type TODO
* - This function calculates how large the resources are behind the bridges.
*
* @param bus The bus we are traversing.
* @param bridge The bridge resource which will contain the bus' resources.
* @param type_mask This value gets anded with the resource type.
* @param type This value must match the result of the and.
*/
void compute_allocate_resource(struct bus *bus, struct resource *bridge,
void compute_resource_needs(struct bus *bus, struct resource *bridge,
unsigned long type_mask, unsigned long type)
{
struct device *dev;
struct resource *resource;
resource_t base;
unsigned long align, min_align;
min_align = 0;
base = bridge->base;
base = align_up(bridge->base, bridge->align);
printk(BIOS_SPEW,
"%s compute_allocate_%s: base: %08llx size: %08llx align: %d gran: %d limit: %08llx\n",
dev_path(bus->dev),
(bridge->flags & IORESOURCE_IO) ? "io" : (bridge->flags &
IORESOURCE_PREFETCH) ?
"prefmem" : "mem", base, bridge->size, bridge->align,
"%s %s_%s: base: %llx size: %llx align: %d gran: %d limit: %llx\n",
dev_path(bus->dev), __func__,
(type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
"prefmem" : "mem",
base, bridge->size, bridge->align,
bridge->gran, bridge->limit);
/* We want different minimum alignments for different kinds of
* resources. These minimums are not device type specific but
* resource type specific.
*/
if (bridge->flags & IORESOURCE_IO) {
min_align = log2c(DEVICE_IO_ALIGN);
}
if (bridge->flags & IORESOURCE_MEM) {
min_align = log2c(DEVICE_MEM_ALIGN);
}
/* For each child which is a bridge, compute_resource_needs. */
for (dev = bus->children; dev; dev = dev->sibling) {
unsigned i;
struct resource *child_bridge;
/* Make certain we have read in all of the resources. */
read_resources(bus);
if (!dev->links)
continue;
/* Find the resources with matching type flags. */
for (i=0; i< dev->resources; i++){
child_bridge = &dev->resource[i];
if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
(child_bridge->flags & type_mask) != type)
continue;
/* Split prefetchable memory if combined. Many domains
* use the same address space for prefetchable memory
* and non-prefetchable memory. Bridges below them
* need it separated. Add the PREFETCH flag to the
* type_mask and type.
*/
compute_resource_needs(&dev->link[0], child_bridge,
type_mask | IORESOURCE_PREFETCH,
type | (child_bridge->flags &
IORESOURCE_PREFETCH));
}
}
/* Remember we haven't found anything yet. */
resource = NULL;
/* Walk through all the devices on the current bus and
* compute the addresses.
/* Walk through all the resources on the current bus and compute the
* amount of address space taken by them. Take granularity and
* alignment into account.
*/
while ((dev = largest_resource(bus, &resource, type_mask, type))) {
resource_t size;
/* Do NOT, I repeat do not, ignore resources which have zero
* size. If they need to be ignored dev->read_resources should
* not even return them. Some resources must be set even when
* they have no size. PCI bridge resources are a good example
* of this.
*/
/* Make certain we are dealing with a good minimum size. */
size = resource->size;
align = resource->align;
if (align < min_align) {
align = min_align;
}
/* Propagate the resource alignment to the bridge register */
if (align > bridge->align) {
bridge->align = align;
}
if (resource->flags & IORESOURCE_FIXED) {
/* Size 0 resources can be skipped. */
if (!resource->size) {
continue;
}
/* Propagate the resource alignment to the bridge resource. */
if (resource->align > bridge->align) {
bridge->align = resource->align;
}
/* Propagate the resource limit to the bridge register. */
if (bridge->limit > resource->limit) {
bridge->limit = resource->limit;
}
/* Artificially deny limits between DEVICE_MEM_HIGH and 0xffffffff. */
if ((bridge->limit > DEVICE_MEM_HIGH)
&& (bridge->limit <= 0xffffffff)) {
bridge->limit = DEVICE_MEM_HIGH;
}
/* I'm not sure what to do here. I'd really like this to go
* away into some PCI-specific file, but I don't see how to do
* it. I'm also not sure how to guarantee that larger
* allocations don't conflict with this address set.
* The example is 0x1000-0x13ff overlaps, but since the base
* doesn't, then this check doesn't trigger. It wouldn't do
* any good, though, since you can't move it to avoid the
* conflict.
*/
if (resource->flags & IORESOURCE_IO) {
/* Don't allow potential aliases over the legacy PCI
* expansion card addresses. The legacy PCI decodes
@ -520,40 +492,316 @@ void compute_allocate_resource(struct bus *bus, struct resource *bridge,
base = 0x3e0;
}
}
if (((align_up(base, align) + size) - 1) <= resource->limit) {
/* Base must be aligned to size. */
base = align_up(base, align);
/* Base must be aligned. */
base = align_up(base, resource->align);
resource->base = base;
base += resource->size;
printk(BIOS_SPEW, "%s %02lx * [0x%llx - 0x%llx] %s\n",
dev_path(dev), resource->index, resource->base,
resource->base + resource->size - 1,
(resource->flags & IORESOURCE_IO) ? "io" :
(resource-> flags & IORESOURCE_PREFETCH) ? "prefmem" :
"mem");
}
/* Bridge resources have a minimum granularity. Round the size up to
* that minimum granularity so we know not to place something else at
* an address positively decoded by the bridge.
*/
bridge->size = align_up(base, bridge->gran) -
align_up(bridge->base, bridge->align);
printk(BIOS_SPEW,
"%s %s_%s: base: %llx size: %llx align: %d gran: %d limit: %llx done\n",
dev_path(bus->dev), __func__,
(type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
"prefmem" : "mem",
base, bridge->size, bridge->align,
bridge->gran, bridge->limit);
}
/**
* This function is the second part of the resource allocator.
*
* The problem.
* - Allocate resource locations for every device.
* - Don't overlap, and follow the rules of bridges.
* - Don't overlap with resources in fixed locations.
* - Be efficient so we don't have ugly strategies.
*
* The strategy.
* - Devices that have fixed addresses are the minority so don't
* worry about them too much. Instead only use part of the address
* space for devices with programmable addresses. This easily handles
* everything except bridges.
*
* - PCI devices are required to have their sizes and their alignments
* equal. In this case an optimal solution to the packing problem
* exists. Allocate all devices from highest alignment to least
* alignment or vice versa. Use this.
*
* - So we can handle more than PCI run two allocation passes on bridges. The
* first to see how large the resources are behind the bridge, and what
* their alignment requirements are. The second to assign a safe address to
* the devices behind the bridge. This allows us to treat a bridge as just
* a device with a couple of resources, and not need to special case it in
* the allocator. Also this allows handling of other types of bridges.
*
* - This function assigns the resources a value.
*
* @param bus The bus we are traversing.
* @param bridge The bridge resource which must contain the bus' resources.
* @param type_mask This value gets anded with the resource type.
* @param type This value must match the result of the and.
*/
void assign_resource_values(struct bus *bus, struct resource *bridge,
unsigned long type_mask, unsigned long type)
{
struct device *dev;
struct resource *resource;
resource_t base;
base = bridge->base;
printk(BIOS_SPEW,
"%s %s_%s: base:%llx size:%llx align:%d gran:%d limit:%llx\n",
dev_path(bus->dev), __func__,
(type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
"prefmem" : "mem",
base, bridge->size, bridge->align,
bridge->gran, bridge->limit);
/* Remember we haven't found anything yet. */
resource = NULL;
/* Walk through all the resources on the current bus and allocate them
* address space.
*/
while ((dev = largest_resource(bus, &resource, type_mask, type))) {
/* Size 0 resources can be skipped. */
if (!resource->size) {
continue;
}
if (resource->flags & IORESOURCE_IO) {
/* Don't allow potential aliases over the legacy PCI
* expansion card addresses. The legacy PCI decodes
* only 10 bits, uses 0x100 - 0x3ff. Therefore, only
* 0x00 - 0xff can be used out of each 0x400 block of
* I/O space.
*/
if ((base & 0x300) != 0) {
base = (base & ~0x3ff) + 0x400;
}
/* Don't allow allocations in the VGA I/O range.
* PCI has special cases for that.
*/
else if ((base >= 0x3b0) && (base <= 0x3df)) {
base = 0x3e0;
}
}
if ((align_up(base, resource->align) + resource->size - 1) <=
resource->limit) {
/* Base must be aligned. */
base = align_up(base, resource->align);
resource->base = base;
resource->flags |= IORESOURCE_ASSIGNED;
resource->flags &= ~IORESOURCE_STORED;
base += size;
printk(BIOS_SPEW,
"%s %02lx * [0x%08llx - 0x%08llx] %s\n",
dev_path(dev),
resource->index,
resource->base,
resource->base + resource->size - 1,
(resource->flags & IORESOURCE_IO) ? "io" :
(resource->
flags & IORESOURCE_PREFETCH) ? "prefmem" :
"mem");
base += resource->size;
} else {
printk(BIOS_ERR, "!! Resource didn't fit !!\n");
printk(BIOS_ERR, " aligned base %llx size %llx limit %llx\n",
align_up(base, resource->align), resource->size, resource->limit);
printk(BIOS_ERR, " %llx needs to be <= %llx (limit)\n",
(align_up(base, resource->align)+resource->size)-1, resource->limit);
printk(BIOS_ERR, " %s%s %02lx * [0x%llx - 0x%llx] %s\n",
(resource->flags & IORESOURCE_ASSIGNED) ? "Assigned: "
: "",
dev_path(dev), resource->index, resource->base,
resource->base + resource->size - 1,
(resource->flags & IORESOURCE_IO) ? "io" :
(resource-> flags & IORESOURCE_PREFETCH) ? "prefmem" :
"mem");
}
printk(BIOS_SPEW, "%s%s %02lx * [0x%llx - 0x%llx] %s\n",
(resource->flags & IORESOURCE_ASSIGNED) ? "Assigned: "
: "",
dev_path(dev), resource->index, resource->base,
resource->size? resource->base + resource->size - 1 :
resource->base,
(resource->flags & IORESOURCE_IO) ? "io" :
(resource-> flags & IORESOURCE_PREFETCH) ? "prefmem" :
"mem");
}
/* A PCI bridge resource does not need to be a power of two size, but
* it does have a minimum granularity. Round the size up to that
* minimum granularity so we know not to place something else at an
* address positively decoded by the bridge.
*/
bridge->size = align_up(base, bridge->gran) - bridge->base;
bridge->flags |= IORESOURCE_ASSIGNED;
printk(BIOS_SPEW,
"%s compute_allocate_%s: base: %08llx size: %08llx align: %d gran: %d done\n",
dev_path(bus->dev),
(bridge->flags & IORESOURCE_IO) ? "io" : (bridge->flags &
IORESOURCE_PREFETCH) ?
"prefmem" : "mem", base, bridge->size, bridge->align,
"%s %s_%s: next_base: %llx size: %llx align: %d gran: %d done\n",
dev_path(bus->dev), __func__,
(type & IORESOURCE_IO) ? "io" : (type & IORESOURCE_PREFETCH) ?
"prefmem" : "mem",
base, bridge->size, bridge->align,
bridge->gran);
/* For each child which is a bridge, assign_resource_values. */
for (dev = bus->children; dev; dev = dev->sibling) {
unsigned i;
struct resource *child_bridge;
if (!dev->links)
continue;
/* Find the resources with matching type flags. */
for (i=0; i< dev->resources; i++){
child_bridge = &dev->resource[i];
if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
(child_bridge->flags & type_mask) != type)
continue;
/* Split prefetchable memory if combined. Many domains
* use the same address space for prefetchable memory
* and non-prefetchable memory. Bridges below them
* need it separated. Add the PREFETCH flag to the
* type_mask and type.
*/
assign_resource_values(&dev->link[0], child_bridge,
type_mask | IORESOURCE_PREFETCH,
type | (child_bridge->flags &
IORESOURCE_PREFETCH));
}
}
}
struct constraints {
struct resource pref, io, mem;
};
static void constrain_resources(struct device *dev, struct constraints* limits)
{
struct device *child;
struct resource *res;
struct resource *lim;
int i;
#ifdef CONFIG_PCI_64BIT_PREF_MEM
#define MEM_MASK (IORESOURCE_PREFETCH | IORESOURCE_MEM)
#else
#define MEM_MASK (IORESOURCE_MEM)
#endif
#define IO_MASK (IORESOURCE_IO)
#define PREF_TYPE (IORESOURCE_PREFETCH | IORESOURCE_MEM)
#define MEM_TYPE (IORESOURCE_MEM)
#define IO_TYPE (IORESOURCE_IO)
/* Descend into every child and look for fixed resources. */
for (child=dev->link[0].children; child; child = child->sibling) {
constrain_resources(child, limits);
for (i = 0; i<child->resources; i++) {
res = &child->resource[i];
if (!(res->flags & IORESOURCE_FIXED))
continue;
/* PREFETCH, MEM, or I/O - skip any others. */
if ((res->flags & MEM_MASK) == PREF_TYPE)
lim = &limits->pref;
else if ((res->flags & MEM_MASK) == MEM_TYPE)
lim = &limits->mem;
else if ((res->flags & IO_MASK) == IO_TYPE)
lim = &limits->io;
else
continue;
/* Is it already outside the limits? */
if (res->size &&
(((res->base + res->size -1) < lim->base) ||
(res->base > lim->limit)))
continue;
/* Choose to be above or below fixed resources. This
* check is signed so that "negative" amounts of space
* are handled correctly.
*/
if ((s64)(lim->limit - (res->base + res->size -1)) >
(s64)(res->base - lim->base))
lim->base = res->base + res->size;
else
lim->limit = res->base -1;
}
}
}
static void avoid_fixed_resources(struct device *dev)
{
struct constraints limits;
struct resource *res;
int i;
/* Initialize constraints to maximum size. */
limits.pref.base = 0;
limits.pref.limit = 0xffffffffffffffffULL;
limits.io.base = 0;
limits.io.limit = 0xffffffffffffffffULL;
limits.mem.base = 0;
limits.mem.limit = 0xffffffffffffffffULL;
/* Constrain the limits to dev's initial resources. */
for (i = 0; i<dev->resources; i++) {
res = &dev->resource[i];
if ((res->flags & IORESOURCE_FIXED) ||
!(res->flags & IORESOURCE_BRIDGE))
continue;
if ((res->flags & MEM_MASK) == PREF_TYPE &&
(res->limit < limits.pref.limit))
limits.pref.limit = res->limit;
if ((res->flags & MEM_MASK) == MEM_TYPE &&
(res->limit < limits.mem.limit))
limits.mem.limit = res->limit;
if ((res->flags & IO_MASK) == IO_TYPE &&
(res->limit < limits.io.limit))
limits.io.limit = res->limit;
}
/* Look through the tree for fixed resources and update the limits. */
constrain_resources(dev, &limits);
/* Update dev's resources with new limits. */
for (i = 0; i<dev->resources; i++) {
struct resource *lim;
res = &dev->resource[i];
if ((res->flags & IORESOURCE_FIXED) ||
!(res->flags & IORESOURCE_BRIDGE))
continue;
/* PREFETCH, MEM, or I/O - skip any others. */
if ((res->flags & MEM_MASK) == PREF_TYPE)
lim = &limits.pref;
else if ((res->flags & MEM_MASK) == MEM_TYPE)
lim = &limits.mem;
else if ((res->flags & IO_MASK) == IO_TYPE)
lim = &limits.io;
else
continue;
/* Is the resource outside the limits? */
if ( lim->base > res->base )
res->base = lim->base;
if ( res->limit > lim->limit )
res->limit = lim->limit;
}
}
#ifdef CONFIG_PCI_OPTION_ROM_RUN
@ -639,16 +887,16 @@ static void allocate_vga_resource(void)
* has to recurse into every down stream buses.
*
* Mutual recursion:
* assign_resources() -> device_operation::set_resources()
* device_operation::set_resources() -> assign_resources()
* phase4_set_resources() -> device_operation::set_resources()
* device_operation::set_resources() -> phase4_set_resources()
*
* @param bus Pointer to the structure for this bus.
*/
void phase4_assign_resources(struct bus *bus)
void phase4_set_resources(struct bus *bus)
{
struct device *curdev;
printk(BIOS_SPEW, "%s(%s) assign_resources, bus %d link: %d\n",
printk(BIOS_SPEW, "%s(%s) %s, bus %d link: %d\n", __func__,
bus->dev->dtsname, dev_path(bus->dev), bus->secondary,
bus->link);
@ -669,7 +917,7 @@ void phase4_assign_resources(struct bus *bus)
}
curdev->ops->phase4_set_resources(curdev);
}
printk(BIOS_SPEW, "%s(%s) assign_resources done, bus %d link: %d\n",
printk(BIOS_SPEW, "%s(%s) %s done, bus %d link: %d\n", __func__,
bus->dev->dtsname, dev_path(bus->dev), bus->secondary,
bus->link);
}
@ -895,7 +1143,7 @@ void resource_tree(const struct device *const root, int debug_level, int depth)
dtsname : "NULL");
for (i = 0; i < root->resources; i++) {
printk(BIOS_DEBUG,
"%s%s resource base %llx size %llx align %x gran %x limit %llx flags %lx index %lx\n",
"%s%s resource base %llx size %llx align %d gran %d limit %llx flags %lx index %lx\n",
indent, dev_path(root), root->resource[i].base,
root->resource[i].size, root->resource[i].align,
root->resource[i].gran, root->resource[i].limit,
@ -919,129 +1167,140 @@ void print_resource_tree(const struct device *const root, int debug_level,
}
/* Bail if not printing to screen. */
if (!printk(debug_level, "Show all resources in tree form...%s\n", msg))
if (!printk(debug_level, "Show resources in subtree (%s)...%s\n",
root->dtsname, msg))
return;
resource_tree(root, debug_level, 0);
}
/**
* Configure devices on the device tree.
* Allocate resources.
*
* Starting at the root of the device tree, travel it recursively in two
* passes. In the first pass, we compute and allocate resources (ranges)
* required by each device. In the second pass, the resources ranges are
* relocated to their final position and stored to the hardware.
* Starting at the root of the device tree, travel it recursively in four
* passes. In the first pass, we read all the resources. In the second pass we
* compute the resource needs. In the third pass we assign final values to the
* resources. In the fourth pass we set them.
*
* I/O resources start at DEVICE_IO_START and grow upward. MEM resources start
* at DEVICE_MEM_START and grow downward.
* I/O resources start at the bottom of the domain's resource and grow upward.
* MEM resources start at the top of the domain's resource and grow downward.
*
* Since the assignment is hierarchical we set the values into the dev_root
* struct.
*/
void dev_phase4(void)
{
struct resource *io, *mem;
struct resource *res;
struct device *root;
struct device * child;
int i;
printk(BIOS_INFO, "Phase 4: Allocating resources...\n");
root = &dev_root;
if (!root->ops) {
printk(BIOS_ERR,
"Phase 4: dev_root missing ops initialization\nPhase 4: Failed.\n");
return;
}
if (!root->ops->phase4_read_resources) {
printk(BIOS_ERR,
"dev_root ops missing read_resources\nPhase 4: Failed.\n");
return;
}
if (!root->ops->phase4_set_resources) {
printk(BIOS_ERR,
"dev_root ops missing set_resources\nPhase 4: Failed.\n");
return;
}
/* Each domain should create resources which contain the entire address
* space for IO, MEM, and PREFMEM resources in the domain. The
* allocation of device resources will be done from this address space.
*/
printk(BIOS_INFO, "Phase 4: Reading resources...\n");
root->ops->phase4_read_resources(root);
/* Read the resources for the entire tree. */
read_resources(&root->link[0]);
printk(BIOS_INFO, "Phase 4: Done reading resources.\n");
/* We have read the resources. We now compute the global allocation of
* resources. We have to create a root resource for the base of the
* tree. The root resource should contain the entire address space for
* IO and MEM resources. The allocation of device resources will be done
* from this resource address space.
*/
printk(BIOS_INFO, "Phase 4: Constrain resources.\n");
/* Allocate a resource from the root device resource pool and initialize
* the system-wide I/O space constraints.
*/
io = new_resource(root, 0);
io->base = 0x400;
io->size = 0;
io->align = 0;
io->gran = 0;
io->limit = 0xffffUL;
io->flags = IORESOURCE_IO;
/* For all domains. */
for (child = root->link[0].children; child;
child=child->sibling)
if (child->path.type == DEVICE_PATH_PCI_DOMAIN)
avoid_fixed_resources(child);
/* Allocate a resource from the root device resource pool and initialize
* the system-wide memory resources constraints.
*/
mem = new_resource(root, 1);
mem->base = 0;
mem->size = 0;
mem->align = 0;
mem->gran = 0;
mem->limit = 0xffffffffUL;
mem->flags = IORESOURCE_MEM;
print_resource_tree(root, BIOS_DEBUG, "Original.");
compute_allocate_resource(&root->link[0], io,
IORESOURCE_IO, IORESOURCE_IO);
/* Compute resources for all domains. */
for (child = root->link[0].children; child; child=child->sibling) {
if (!(child->path.type == DEVICE_PATH_PCI_DOMAIN))
continue;
for (i=0; i< child->resources; i++) {
res = &child->resource[i];
if ( res->flags & IORESOURCE_FIXED )
continue;
if ( res->flags & IORESOURCE_PREFETCH ) {
compute_resource_needs(&child->link[0],
res, MEM_MASK, PREF_TYPE);
continue;
}
if ( res->flags & IORESOURCE_MEM ) {
compute_resource_needs(&child->link[0],
res, MEM_MASK, MEM_TYPE);
continue;
}
if ( res->flags & IORESOURCE_IO ) {
compute_resource_needs(&child->link[0],
res, IO_MASK, IO_TYPE);
continue;
}
}
}
compute_allocate_resource(&root->link[0], mem,
IORESOURCE_MEM, IORESOURCE_MEM);
print_resource_tree(root, BIOS_DEBUG, "After first compute_allocate.");
print_resource_tree(root, BIOS_DEBUG, "After summations.");
/* Now we need to adjust the resources. The issue is that mem grows
* downward.
* downward. Reallocate the MEM resources with the highest addresses
* I can manage.
*/
/* Make certain the I/O devices are allocated somewhere safe. */
io->base = DEVICE_IO_START;
io->flags |= IORESOURCE_ASSIGNED;
io->flags &= ~IORESOURCE_STORED;
/* Now reallocate the PCI resources memory with the
* highest addresses I can manage.
*/
mem->base = resource_max(&root->resource[1]);
mem->flags |= IORESOURCE_ASSIGNED;
mem->flags &= ~IORESOURCE_STORED;
for (child = root->link[0].children; child; child=child->sibling) {
if (child->path.type != DEVICE_PATH_PCI_DOMAIN)
continue;
for (i=0; i< child->resources; i++) {
res = &child->resource[i];
if (!(res->flags & IORESOURCE_MEM) ||
res->flags & IORESOURCE_FIXED )
continue;
res->base = resource_max(res);
}
}
#ifdef CONFIG_PCI_OPTION_ROM_RUN
/* Allocate the VGA I/O resource. */
allocate_vga_resource();
print_resource_tree(root, BIOS_DEBUG, "After VGA.");
#endif
/* now rerun the compute allocate with the adjusted resources */
compute_allocate_resource(&root->link[0], io,
IORESOURCE_IO, IORESOURCE_IO);
/* Assign values to the resources for all domains. */
/* If the domain has a prefetchable memory resource, use it. */
for (child = root->link[0].children; child; child=child->sibling) {
if (!(child->path.type == DEVICE_PATH_PCI_DOMAIN))
continue;
for (i=0; i< child->resources; i++) {
res = &child->resource[i];
if ( res->flags & IORESOURCE_FIXED )
continue;
if ( res->flags & IORESOURCE_PREFETCH ) {
assign_resource_values(&child->link[0],
res, MEM_MASK, PREF_TYPE);
continue;
}
if ( res->flags & IORESOURCE_MEM ) {
assign_resource_values(&child->link[0],
res, MEM_MASK, MEM_TYPE);
continue;
}
if ( res->flags & IORESOURCE_IO ) {
assign_resource_values(&child->link[0],
res, IO_MASK, IO_TYPE);
continue;
}
}
}
compute_allocate_resource(&root->link[0], mem,
IORESOURCE_MEM, IORESOURCE_MEM);
print_resource_tree(root, BIOS_DEBUG, "After second compute_allocate.");
print_resource_tree(root, BIOS_DEBUG, "After assigning values.");
/* Store the computed resource allocations into device registers. */
printk(BIOS_INFO, "Phase 4: Setting resources...\n");
root->ops->phase4_set_resources(root);
phase4_set_resources(&root->link[0]);
print_resource_tree(root, BIOS_DEBUG, "After setting resources.");
printk(BIOS_INFO, "Phase 4: Done setting resources.\n");
#if 0
mem->flags |= IORESOURCE_STORED;
report_resource_stored(root, mem, "");
#endif
printk(BIOS_INFO, "Phase 4: Done allocating resources.\n");
}
@ -1132,21 +1391,21 @@ void show_all_devs(int debug_level, const char *msg)
return;
for (dev = all_devices; dev; dev = dev->next) {
printk(debug_level,
"%s(%s): enabled %d have_resources %d\n",
"%s(%s): enabled %d, %d resources\n",
dev->dtsname, dev_path(dev), dev->enabled,
dev->have_resources);
dev->resources);
}
}
void show_one_resource(struct device *dev, struct resource *resource,
const char *comment)
void show_one_resource(int debug_level, struct device *dev,
struct resource *resource, const char *comment)
{
char buf[10];
unsigned long long base, end;
base = resource->base;
end = resource_end(resource);
buf[0] = '\0';
if (resource->flags & IORESOURCE_PCI_BRIDGE) {
if (resource->flags & IORESOURCE_BRIDGE) {
#if PCI_BUS_SEGN_BITS
sprintf(buf, "bus %04x:%02x ", dev->bus->secondary >> 8,
dev->link[0].secondary & 0xff);
@ -1154,7 +1413,7 @@ void show_one_resource(struct device *dev, struct resource *resource,
sprintf(buf, "bus %02x ", dev->link[0].secondary);
#endif
}
printk(BIOS_DEBUG, "%s %02lx <- [0x%010llx - 0x%010llx] "
printk(debug_level, "%s %02lx <- [0x%010llx - 0x%010llx] "
"size 0x%08Lx gran 0x%02x %s%s%s\n",
dev_path(dev), resource->index, base, end,
resource->size, resource->gran, buf,
@ -1162,18 +1421,20 @@ void show_one_resource(struct device *dev, struct resource *resource,
}
void show_all_devs_resources(void)
void show_all_devs_resources(int debug_level, const char* msg)
{
struct device *dev;
printk(BIOS_INFO, "Show all devs...\n");
if(!printk(debug_level, "Show all devs with resources...%s\n", msg))
return;
for (dev = all_devices; dev; dev = dev->next) {
int i;
printk(BIOS_SPEW,
"%s(%s): enabled %d have_resources %d\n",
printk(debug_level,
"%s(%s): enabled %d, %d resources\n",
dev->dtsname, dev_path(dev), dev->enabled,
dev->have_resources);
dev->resources);
for (i = 0; i < dev->resources; i++)
show_one_resource(dev, &dev->resource[i], "");
show_one_resource(debug_level, dev, &dev->resource[i], "");
}
}

View file

@ -241,7 +241,7 @@ const char *dev_path(const struct device *dev)
dev->path.ioport.iobase);
break;
default:
printk(BIOS_ERR, "%s: Unknown device path type: %d\n",
printk(BIOS_ERR, "%s: Unknown device path type: %x\n",
dev->dtsname, dev->path.type);
break;
}
@ -293,7 +293,7 @@ const char *dev_id_string(const struct device_id *id)
id->cpu_bus.vendor, id->cpu_bus.device);
break;
default:
printk(BIOS_ERR, "%s: Unknown device ID type: %d\n",
printk(BIOS_ERR, "%s: Unknown device ID type: %x\n",
__func__, id->type);
memcpy(buffer, "Unknown", 8);
break;
@ -349,8 +349,8 @@ int path_eq(const struct device_path *path1, const struct device_path *path2)
equal = (path1->cpu_bus.id == path2->cpu_bus.id);
break;
default:
printk(BIOS_ERR, "Unknown device type: %d\n",
path1->type);
printk(BIOS_ERR, "%s: Unknown device type: %x\n",
__func__, path1->type);
break;
}
}
@ -403,8 +403,8 @@ int id_eq(struct device_id *path1, struct device_id *path2)
&& (path1->cpu_bus.device == path2->cpu_bus.device);
break;
default:
printk(BIOS_ERR, "Unknown device type: %d\n",
path1->type);
printk(BIOS_ERR, "%s: Unknown device type: %x\n",
__func__, path1->type);
break;
}
}
@ -615,26 +615,29 @@ const char *resource_type(struct resource *resource)
void report_resource_stored(struct device *dev, struct resource *resource,
const char *comment)
{
if (resource->flags & IORESOURCE_STORED) {
char buf[10];
unsigned long long base, end;
base = resource->base;
end = resource_end(resource);
buf[0] = '\0';
if (resource->flags & IORESOURCE_PCI_BRIDGE) {
char buf[10];
unsigned long long base, end;
base = resource->base;
end = resource_end(resource);
buf[0] = '\0';
if (!(resource->flags & IORESOURCE_STORED))
printk(BIOS_DEBUG, "%s lying: %s(%s) %02lx\n",
__func__, dev_path(dev), dev->dtsname, resource->index);
if (resource->flags & IORESOURCE_BRIDGE) {
#if PCI_BUS_SEGN_BITS
sprintf(buf, "bus %04x:%02x ", dev->bus->secondary >> 8,
dev->link[0].secondary & 0xff);
sprintf(buf, "bus %04x:%02x ", dev->bus->secondary >> 8,
dev->link[0].secondary & 0xff);
#else
sprintf(buf, "bus %02x ", dev->link[0].secondary);
sprintf(buf, "bus %02x ", dev->link[0].secondary);
#endif
}
printk(BIOS_DEBUG, "%s %02lx <- [0x%010llx - 0x%010llx] "
"size 0x%08Lx gran 0x%02x %s%s%s\n",
dev_path(dev), resource->index, base, end,
resource->size, resource->gran, buf,
resource_type(resource), comment);
}
printk(BIOS_DEBUG, "%s %02lx <- [0x%010llx - 0x%010llx] "
"size 0x%08Lx gran 0x%02x %s%s %s\n",
dev_path(dev), resource->index, base, end,
resource->size, resource->gran, buf,
resource_type(resource), comment);
}
void search_bus_resources(struct bus *bus,
@ -644,9 +647,6 @@ void search_bus_resources(struct bus *bus,
struct device *curdev;
for (curdev = bus->children; curdev; curdev = curdev->sibling) {
int i;
/* Ignore disabled devices. */
if (!curdev->have_resources)
continue;
for (i = 0; i < curdev->resources; i++) {
struct resource *resource = &curdev->resource[i];
/* If it isn't the right kind of resource ignore it. */
@ -676,12 +676,8 @@ void search_global_resources(unsigned long type_mask, unsigned long type,
for (curdev = all_devices; curdev; curdev = curdev->next) {
int i;
printk(BIOS_SPEW,
"%s: dev %s, have_resources %d #resources %d\n",
__func__, curdev->dtsname, curdev->have_resources,
curdev->resources);
/* Ignore disabled devices. */
if (!curdev->have_resources)
continue;
"%s: dev %s, #resources %d\n",
__func__, curdev->dtsname, curdev->resources);
for (i = 0; i < curdev->resources; i++) {
struct resource *resource = &curdev->resource[i];
printk(BIOS_SPEW,

View file

@ -11,6 +11,7 @@
* Copyright (C) 2005-2006 Tyan
* (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
* Copyright (C) 2005-2007 Stefan Reinauer <stepan@openbios.org>
* Copyright (C) 2008 Myles Watson <mylesgw@gmail.com>
*/
/*
@ -153,7 +154,7 @@ unsigned int pci_find_capability(struct device *dev, unsigned int cap_type)
struct resource *pci_get_resource(struct device *dev, unsigned long index)
{
struct resource *resource;
unsigned long value, attr, base;
unsigned long value, attr;
resource_t moving, limit;
/* Initialize the resources to nothing. */
@ -162,15 +163,9 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index)
/* Get the initial value. */
value = pci_read_config32(dev, index);
/* save the base address */
if (value & PCI_BASE_ADDRESS_SPACE_IO)
base = value & ~PCI_BASE_ADDRESS_IO_ATTR_MASK;
else
base = value & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
/* See which bits move. */
moving = pci_moving_config32(dev, index);
/* Next step: save the base in the dev struct. For later next week */
/* Initialize attr to the bits that do not move. */
attr = value & ~moving;
@ -222,7 +217,7 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index)
* Shouldn't zero because we'll get off with 64-bit BARs.
* Are there any others to save?
*/
resource->flags &= ~IORESOURCE_PCI64;
resource->flags &= IORESOURCE_PCI64;
} else if (attr & PCI_BASE_ADDRESS_SPACE_IO) {
/* An I/O mapped base address. */
attr &= PCI_BASE_ADDRESS_IO_ATTR_MASK;
@ -248,6 +243,8 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index)
resource->limit = 0xffffffffffffffffULL;
} else {
/* Invalid value. */
printk(BIOS_ERR,"Broken BAR with value %lx\n",attr);
printk(BIOS_ERR," on dev %s at index %02lx\n",dev->dtsname,index);
resource->flags = 0;
}
}
@ -347,15 +344,12 @@ static void pci_read_bases(struct device *dev, unsigned int howmany)
compact_resources(dev);
}
static void pci_set_resource(struct device *dev, struct resource *resource);
static void pci_record_bridge_resource(struct device *dev, resource_t moving,
unsigned int index, unsigned long mask,
unsigned long type)
unsigned int index, unsigned long type)
{
/* Initialize the constraints on the current bus. */
struct resource *resource;
resource = 0;
resource = NULL;
if (moving) {
unsigned long gran;
resource_t step;
@ -370,18 +364,7 @@ static void pci_record_bridge_resource(struct device *dev, resource_t moving,
resource->gran = gran;
resource->align = gran;
resource->limit = moving | (step - 1);
resource->flags = type | IORESOURCE_PCI_BRIDGE;
compute_allocate_resource(&dev->link[0], resource, mask, type);
/* If there is nothing behind the resource,
* clear it and forget it.
*/
if (resource->size == 0) {
resource->base = moving;
resource->flags |= IORESOURCE_ASSIGNED;
resource->flags &= ~IORESOURCE_STORED;
pci_set_resource(dev, resource);
resource->flags = 0;
}
resource->flags = type | IORESOURCE_PCI_BRIDGE | IORESOURCE_BRIDGE;
}
return;
}
@ -402,8 +385,7 @@ static void pci_bridge_read_bases(struct device *dev)
moving = moving_base & moving_limit;
/* Initialize the I/O space constraints on the current bus. */
pci_record_bridge_resource(dev, moving, PCI_IO_BASE,
IORESOURCE_IO, IORESOURCE_IO);
pci_record_bridge_resource(dev, moving, PCI_IO_BASE, IORESOURCE_IO);
/* See if the bridge prefmem resources are implemented. */
moving_base =
@ -416,7 +398,6 @@ static void pci_bridge_read_bases(struct device *dev)
moving = moving_base & moving_limit;
/* Initialize the prefetchable memory constraints on the current bus. */
pci_record_bridge_resource(dev, moving, PCI_PREF_MEMORY_BASE,
IORESOURCE_MEM | IORESOURCE_PREFETCH,
IORESOURCE_MEM | IORESOURCE_PREFETCH);
/* See if the bridge mem resources are implemented. */
@ -427,7 +408,6 @@ static void pci_bridge_read_bases(struct device *dev)
/* Initialize the memory resources on the current bus. */
pci_record_bridge_resource(dev, moving, PCI_MEMORY_BASE,
IORESOURCE_MEM | IORESOURCE_PREFETCH,
IORESOURCE_MEM);
compact_resources(dev);
@ -441,9 +421,24 @@ void pci_dev_read_resources(struct device *dev)
void pci_bus_read_resources(struct device *dev)
{
struct device *child;
printk(BIOS_DEBUG, "%s: %s bus %s\n",
__func__, dev_path(dev), dev->bus? dev_path(dev->bus->dev):"NULL");
pci_bridge_read_bases(dev);
pci_read_bases(dev, 2);
pci_get_rom_resource(dev, PCI_ROM_ADDRESS1);
if (!dev->bus){
printk(BIOS_ERR, "%s: %s bus %s\n",
__func__, dev_path(dev), dev->bus? dev_path(dev->bus->dev):"NULL");
}
for (child = dev->link[0].children; child; child = child->sibling)
if (child->ops && child->ops->phase4_read_resources)
child->ops->phase4_read_resources(child);
else
printk(BIOS_ERR, "%s: %s missing Phase4\n",
__func__, dev_path(child));
}
/**
@ -462,22 +457,22 @@ void pci_domain_read_resources(struct device *dev)
/* Initialize the system-wide I/O space constraints. */
res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
res->limit = 0xffffUL;
res->flags =
IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
IORESOURCE_ASSIGNED | IORESOURCE_BRIDGE;
/* Initialize the system-wide memory resources constraints. */
res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
res->limit = 0xffffffffULL;
res->flags =
IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
IORESOURCE_ASSIGNED | IORESOURCE_BRIDGE;
}
static void pci_set_resource(struct device *dev, struct resource *resource)
{
resource_t base, end;
/* Make certain the resource has actually been set. */
if (!(resource->flags & IORESOURCE_ASSIGNED)) {
/* Make certain the resource has actually been assigned a value. */
if (!(resource->flags & IORESOURCE_ASSIGNED) && resource->size!=0) {
printk(BIOS_ERR,
"ERROR: %s %02lx %s size: 0x%010llx not assigned\n",
dev_path(dev), resource->index, resource_type(resource),
@ -519,6 +514,16 @@ static void pci_set_resource(struct device *dev, struct resource *resource)
/* Now store the resource. */
resource->flags |= IORESOURCE_STORED;
/* PCI Bridges have no enable bit. They are disabled if the base of
* the range is greater than the limit. If the size is zero, disable
* by setting the base = limit and end = limit - 2^gran.
*/
if (resource->size == 0 && (resource->flags & IORESOURCE_PCI_BRIDGE)) {
base = resource->limit;
end = resource->limit - (1<<resource->gran);
resource->base = base;
}
if (!(resource->flags & IORESOURCE_PCI_BRIDGE)) {
unsigned long base_lo, base_hi;
/* Some chipsets allow us to set/clear the I/O bit
@ -535,24 +540,16 @@ static void pci_set_resource(struct device *dev, struct resource *resource)
}
} else if (resource->index == PCI_IO_BASE) {
/* Set the I/O ranges. */
compute_allocate_resource(&dev->link[0], resource,
IORESOURCE_IO, IORESOURCE_IO);
pci_write_config8(dev, PCI_IO_BASE, base >> 8);
pci_write_config16(dev, PCI_IO_BASE_UPPER16, base >> 16);
pci_write_config8(dev, PCI_IO_LIMIT, end >> 8);
pci_write_config16(dev, PCI_IO_LIMIT_UPPER16, end >> 16);
} else if (resource->index == PCI_MEMORY_BASE) {
/* Set the memory range. */
compute_allocate_resource(&dev->link[0], resource,
IORESOURCE_MEM | IORESOURCE_PREFETCH,
IORESOURCE_MEM);
pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16);
pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16);
} else if (resource->index == PCI_PREF_MEMORY_BASE) {
/* Set the prefetchable memory range. */
compute_allocate_resource(&dev->link[0], resource,
IORESOURCE_MEM | IORESOURCE_PREFETCH,
IORESOURCE_MEM | IORESOURCE_PREFETCH);
pci_write_config16(dev, PCI_PREF_MEMORY_BASE, base >> 16);
pci_write_config32(dev, PCI_PREF_BASE_UPPER32, base >> 32);
pci_write_config16(dev, PCI_PREF_MEMORY_LIMIT, end >> 16);
@ -563,7 +560,7 @@ static void pci_set_resource(struct device *dev, struct resource *resource)
printk(BIOS_ERR, "ERROR: invalid resource->index %lx\n",
resource->index);
}
report_resource_stored(dev, resource, "");
report_resource_stored(dev, resource, __func__);
return;
}
@ -582,7 +579,7 @@ void pci_set_resources(struct device *dev)
struct bus *bus;
bus = &dev->link[link];
if (bus->children) {
phase4_assign_resources(bus);
phase4_set_resources(bus);
}
}

View file

@ -36,7 +36,7 @@ static struct bus *get_pbus(struct device *dev)
struct bus *pbus = dev->bus;
while (pbus && pbus->dev && !ops_pci_bus(pbus)) {
if (pbus->dev == dev) {
printk(BIOS_EMERG, "Loop: dev->dtsname dev->bus->dev\n");
printk(BIOS_EMERG, "Loop: %s->bus->dev\n", dev->dtsname);
printk(BIOS_EMERG, "To fix this, set ops_pci_bus in dts\n");
die("loop due to insufficient dts");
}

View file

@ -35,13 +35,7 @@
*/
void root_dev_read_resources(struct device *root)
{
void read_resources(struct bus *bus);
void show_all_devs_resources(void);
read_resources(&root->link[0]);
printk(BIOS_DEBUG, "%s: Done allocating\n", __FUNCTION__);
show_all_devs_resources();
printk(BIOS_DEBUG, "This shouldn't be called!\n");
}
/**
@ -52,7 +46,7 @@ void root_dev_read_resources(struct device *root)
*/
void root_dev_set_resources(struct device *root)
{
phase4_assign_resources(&root->link[0]);
printk(BIOS_DEBUG, "This shouldn't be called!\n");
}
/**
@ -193,6 +187,7 @@ void root_dev_reset(struct bus *bus)
* mainboard directory.
*/
struct device_operations default_dev_ops_root = {
.id = {.type = DEVICE_ID_ROOT},
.phase3_scan = root_dev_scan_bus,
.phase4_read_resources = root_dev_read_resources,
.phase4_set_resources = root_dev_set_resources,

View file

@ -199,12 +199,11 @@ struct device {
u16 subsystem_vendor;
u16 subsystem_device;
unsigned int class; /* 3 bytes: (base,sub,prog-if) */
unsigned int hdr_type; /* PCI header type */
unsigned int enabled:1; /* set if we should enable the device */
unsigned int have_resources:1; /* Set if we have read the devices resources */
unsigned int on_mainboard:1;
unsigned long rom_address;
unsigned int class; /* 3 bytes: (base,sub,prog-if) */
unsigned int hdr_type; /* PCI header type */
unsigned int enabled : 1; /* set if we should enable the device */
unsigned int on_mainboard : 1;
unsigned long rom_address;
u8 command;
@ -239,9 +238,7 @@ void dev_optimize(void);
/* Generic device helper functions */
int reset_bus(struct bus *bus);
unsigned int scan_bus(struct device *bus, unsigned int max);
void compute_allocate_resource(struct bus *bus, struct resource *bridge,
unsigned long type_mask, unsigned long type);
void assign_resources(struct bus *bus);
//void assign_resources(struct bus *bus);
void enable_resources(struct device *dev);
void enumerate_static_device(void);
void enumerate_static_devices(void);
@ -267,12 +264,9 @@ void default_device_constructor(struct device *dev,
const struct device_operations *constructor);
void show_all_devs(int debug_level, const char *msg);
void show_all_devs_tree(int debug_level, const char *msg);
/* Rounding for boundaries.
* Due to some chip bugs, go ahead and round IO to 16
*/
#define DEVICE_IO_ALIGN 16
#define DEVICE_MEM_ALIGN 4096
void show_all_devs(int debug_level, const char *msg);
void show_all_devs_tree(int debug_level, const char *msg);
void print_resource_tree(const struct device * const dev, int debug_level, const char* msg);
resource_t align_up(resource_t val, unsigned long gran);
resource_t align_down(resource_t val, unsigned long gran);
@ -296,7 +290,7 @@ void dev_phase4(void);
void dev_root_phase5(void);
void dev_phase6(void);
void phase4_assign_resources(struct bus *bus);
void phase4_set_resources(struct bus *bus);
unsigned int dev_phase3(struct device *bus, unsigned int max);
void dev_phase5(struct device *dev);

View file

@ -36,6 +36,7 @@
#define IORESOURCE_SUBTRACTIVE 0x00040000 /* This resource filters all of the unclaimed transactions
* to the bus below.
*/
#define IORESOURCE_BRIDGE 0x00080000 /* The IO resource has a bus below it. */
#define IORESOURCE_STORED 0x20000000 /* The IO resource assignment has been stored in the device */
#define IORESOURCE_ASSIGNED 0x40000000 /* An IO resource that has been assigned a value */
#define IORESOURCE_FIXED 0x80000000 /* An IO resource the allocator must not change */