Use lists instead of arrays for resources in devices to reduce memory usage.

Signed-off-by: Myles Watson <mylesgw@gmail.com>
Acked-by: Patrick Georgi <patrick.georgi@coresystems.de>


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5576 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Myles Watson
2010-05-21 14:33:48 +00:00
parent c5b87c8f89
commit c25cc11ae3
25 changed files with 200 additions and 190 deletions

View File

@@ -43,6 +43,8 @@
struct device *all_devices = &dev_root;
/** Pointer to the last device */
extern struct device **last_dev_p;
/** Linked list of free resources */
struct resource *free_resources = NULL;
/**
@@ -253,16 +255,15 @@ static void compute_resources(struct bus *bus, struct resource *bridge,
/* For each child which is a bridge, compute_resource_needs. */
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++) {
for (child_bridge = dev->resource_list; child_bridge;
child_bridge = child_bridge->next) {
unsigned link;
child_bridge = &dev->resource[i];
if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
(child_bridge->flags & type_mask) != type)
@@ -502,16 +503,15 @@ static void allocate_resources(struct bus *bus, struct resource *bridge,
/* For each child which is a bridge, allocate_resources. */
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++) {
for (child_bridge = dev->resource_list; child_bridge;
child_bridge = child_bridge->next) {
unsigned link;
child_bridge = &dev->resource[i];
if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
(child_bridge->flags & type_mask) != type)
@@ -556,8 +556,7 @@ static void constrain_resources(struct device *dev, struct constraints* limits)
printk(BIOS_SPEW, "%s: %s\n", __func__, dev_path(dev));
/* Constrain limits based on the fixed resources of this device. */
for (i = 0; i < dev->resources; i++) {
res = &dev->resource[i];
for (res = dev->resource_list; res; res = res->next) {
if (!(res->flags & IORESOURCE_FIXED))
continue;
if (!res->size) {
@@ -604,7 +603,6 @@ static void avoid_fixed_resources(struct device *dev)
{
struct constraints limits;
struct resource *res;
int i;
printk(BIOS_SPEW, "%s: %s\n", __func__, dev_path(dev));
/* Initialize constraints to maximum size. */
@@ -617,8 +615,7 @@ static void avoid_fixed_resources(struct device *dev)
limits.mem.limit = 0xffffffffffffffffULL;
/* Constrain the limits to dev's initial resources. */
for (i = 0; i < dev->resources; i++) {
res = &dev->resource[i];
for (res = dev->resource_list; res; res = res->next) {
if ((res->flags & IORESOURCE_FIXED))
continue;
printk(BIOS_SPEW, "%s:@%s %02lx limit %08Lx\n", __func__,
@@ -638,9 +635,8 @@ static void avoid_fixed_resources(struct device *dev)
constrain_resources(dev, &limits);
/* Update dev's resources with new limits. */
for (i = 0; i < dev->resources; i++) {
for (res = dev->resource_list; res; res = res->next) {
struct resource *lim;
res = &dev->resource[i];
if ((res->flags & IORESOURCE_FIXED))
continue;
@@ -764,7 +760,7 @@ void assign_resources(struct bus *bus)
dev_path(bus->dev), bus->secondary, bus->link);
for (curdev = bus->children; curdev; curdev = curdev->sibling) {
if (!curdev->enabled || !curdev->resources) {
if (!curdev->enabled || !curdev->resource_list) {
continue;
}
if (!curdev->ops || !curdev->ops->set_resources) {
@@ -927,7 +923,6 @@ void dev_configure(void)
struct resource *res;
struct device *root;
struct device *child;
int i;
#if CONFIG_VGA_BRIDGE_SETUP == 1
set_vga_bridge_bits();
@@ -954,8 +949,7 @@ void dev_configure(void)
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];
for (res = child->resource_list; res; res = res->next) {
if (res->flags & IORESOURCE_FIXED)
continue;
if (res->flags & IORESOURCE_PREFETCH) {
@@ -987,8 +981,7 @@ void dev_configure(void)
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];
for (res = child->resource_list; res; res = res->next) {
if (!(res->flags & IORESOURCE_MEM) ||
res->flags & IORESOURCE_FIXED)
continue;
@@ -1001,8 +994,7 @@ void dev_configure(void)
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];
for (res = child->resource_list; res; res = res->next) {
if (res->flags & IORESOURCE_FIXED)
continue;
if (res->flags & IORESOURCE_PREFETCH) {

View File

@@ -260,6 +260,40 @@ int path_eq(struct device_path *path1, struct device_path *path2)
return equal;
}
/**
* Allocate 64 more resources to the free list.
*/
static int allocate_more_resources(void)
{
int i;
struct resource *new_res_list;
new_res_list = malloc(64 * sizeof(*new_res_list));
if (new_res_list == NULL)
return 0;
memset(new_res_list, 0, 64 * sizeof(*new_res_list));
for (i = 0; i < 64-1; i++)
new_res_list[i].next = &new_res_list[i+1];
free_resources = new_res_list;
return 1;
}
/**
* Remove resource res from the device's list and add it to the free list.
*/
static void free_resource(device_t dev, struct resource *res, struct resource *prev)
{
if (prev)
prev->next = res->next;
else
dev->resource_list = res->next;
res->next = free_resources;
free_resources = res;
}
/**
* See if we have unused but allocated resource structures.
* If so remove the allocation.
@@ -267,19 +301,14 @@ int path_eq(struct device_path *path1, struct device_path *path2)
*/
void compact_resources(device_t dev)
{
struct resource *resource;
int i;
struct resource *res, *next, *prev = NULL;
/* Move all of the free resources to the end */
for(i = 0; i < dev->resources;) {
resource = &dev->resource[i];
if (!resource->flags) {
memmove(resource, resource + 1, (dev->resources - i) *
sizeof(*resource));
dev->resources -= 1;
memset(&dev->resource[dev->resources], 0, sizeof(*resource));
} else {
i++;
}
for(res = dev->resource_list; res; res = next) {
next = res->next;
if (!res->flags)
free_resource(dev, res, prev);
else
prev = res;
}
}
@@ -292,17 +321,13 @@ void compact_resources(device_t dev)
*/
struct resource *probe_resource(device_t dev, unsigned index)
{
struct resource *resource;
int i;
struct resource *res;
/* See if there is a resource with the appropriate index */
resource = 0;
for(i = 0; i < dev->resources; i++) {
if (dev->resource[i].index == index) {
resource = &dev->resource[i];
for(res = dev->resource_list; res; res = res->next) {
if (res->index == index)
break;
}
}
return resource;
return res;
}
/**
@@ -314,7 +339,7 @@ struct resource *probe_resource(device_t dev, unsigned index)
*/
struct resource *new_resource(device_t dev, unsigned index)
{
struct resource *resource;
struct resource *resource, *tail;
/* First move all of the free resources to the end */
compact_resources(dev);
@@ -322,12 +347,20 @@ struct resource *new_resource(device_t dev, unsigned index)
/* See if there is a resource with the appropriate index */
resource = probe_resource(dev, index);
if (!resource) {
if (dev->resources == MAX_RESOURCES) {
die("MAX_RESOURCES exceeded.");
}
resource = &dev->resource[dev->resources];
if (free_resources == NULL && !allocate_more_resources())
die("Couldn't allocate more resources.");
resource = free_resources;
free_resources = free_resources->next;
memset(resource, 0, sizeof(*resource));
dev->resources++;
resource->next = NULL;
tail = dev->resource_list;
if (tail) {
while (tail->next) tail = tail->next;
tail->next = resource;
}
else
dev->resource_list = resource;
}
/* Initialize the resource values */
if (!(resource->flags & IORESOURCE_FIXED)) {
@@ -486,23 +519,22 @@ void search_bus_resources(struct bus *bus,
{
struct device *curdev;
for(curdev = bus->children; curdev; curdev = curdev->sibling) {
int i;
struct resource *res;
/* Ignore disabled devices */
if (!curdev->enabled) continue;
for(i = 0; i < curdev->resources; i++) {
struct resource *resource = &curdev->resource[i];
for(res = curdev->resource_list; res; res = res->next) {
/* If it isn't the right kind of resource ignore it */
if ((resource->flags & type_mask) != type) {
if ((res->flags & type_mask) != type) {
continue;
}
/* If it is a subtractive resource recurse */
if (resource->flags & IORESOURCE_SUBTRACTIVE) {
if (res->flags & IORESOURCE_SUBTRACTIVE) {
struct bus * subbus;
subbus = &curdev->link[IOINDEX_SUBTRACTIVE_LINK(resource->index)];
subbus = &curdev->link[IOINDEX_SUBTRACTIVE_LINK(res->index)];
search_bus_resources(subbus, type_mask, type, search, gp);
continue;
}
search(gp, curdev, resource);
search(gp, curdev, res);
}
}
}
@@ -513,20 +545,19 @@ void search_global_resources(
{
struct device *curdev;
for(curdev = all_devices; curdev; curdev = curdev->next) {
int i;
struct resource *res;
/* Ignore disabled devices */
if (!curdev->enabled) continue;
for(i = 0; i < curdev->resources; i++) {
struct resource *resource = &curdev->resource[i];
for(res = curdev->resource_list; res; res = res->next) {
/* If it isn't the right kind of resource ignore it */
if ((resource->flags & type_mask) != type) {
if ((res->flags & type_mask) != type) {
continue;
}
/* If it is a subtractive resource ignore it */
if (resource->flags & IORESOURCE_SUBTRACTIVE) {
if (res->flags & IORESOURCE_SUBTRACTIVE) {
continue;
}
search(gp, curdev, resource);
search(gp, curdev, res);
}
}
}
@@ -561,6 +592,7 @@ static void resource_tree(struct device *root, int debug_level, int depth)
{
int i = 0, link = 0;
struct device *child;
struct resource *res;
char indent[30]; /* If your tree has more levels, it's wrong. */
for (i = 0; i < depth + 1 && i < 29; i++)
@@ -571,13 +603,13 @@ static void resource_tree(struct device *root, int debug_level, int depth)
dev_path(root), root->links);
do_printk(BIOS_DEBUG, " %s\n", root->link[0].children ?
dev_path(root->link[0].children) : "NULL");
for (i = 0; i < root->resources; i++) {
for (res = root->resource_list; res; res = res->next) {
do_printk(BIOS_DEBUG,
"%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,
root->resource[i].flags, root->resource[i].index);
indent, dev_path(root), res->base,
res->size, res->align,
res->gran, res->limit,
res->flags, res->index);
}
for (link = 0; link < root->links; link++) {
@@ -611,8 +643,8 @@ void show_devs_tree(struct device *dev, int debug_level, int depth, int linknum)
for (i = 0; i < depth; i++)
depth_str[i] = ' ';
depth_str[i] = '\0';
do_printk(debug_level, "%s%s: enabled %d, %d resources\n",
depth_str, dev_path(dev), dev->enabled, dev->resources);
do_printk(debug_level, "%s%s: enabled %d\n",
depth_str, dev_path(dev), dev->enabled);
for (i = 0; i < dev->links; i++) {
for (sibling = dev->link[i].children; sibling;
sibling = sibling->sibling)
@@ -646,10 +678,8 @@ void show_all_devs(int debug_level, const char *msg)
if (!do_printk(debug_level, "Show all devs...%s\n", msg))
return;
for (dev = all_devices; dev; dev = dev->next) {
do_printk(debug_level,
"%s: enabled %d, %d resources\n",
dev_path(dev), dev->enabled,
dev->resources);
do_printk(debug_level, "%s: enabled %d\n",
dev_path(dev), dev->enabled);
}
}
@@ -687,12 +717,10 @@ void show_all_devs_resources(int debug_level, const char* msg)
return;
for (dev = all_devices; dev; dev = dev->next) {
int i;
do_printk(debug_level,
"%s: enabled %d, %d resources\n",
dev_path(dev), dev->enabled,
dev->resources);
for (i = 0; i < dev->resources; i++)
show_one_resource(debug_level, dev, &dev->resource[i], "");
struct resource *res;
do_printk(debug_level, "%s: enabled %d\n",
dev_path(dev), dev->enabled);
for (res = dev->resource_list; res; res = res->next)
show_one_resource(debug_level, dev, res, "");
}
}

View File

@@ -53,8 +53,7 @@ biosemu_dev_get_addr_info(void)
bios_device.devfn = devfn;
DEBUG_PRINTF("bus: %x, devfn: %x\n", bus, devfn);
for (i = 0; i < bios_device.dev->resources; i++) {
r = &bios_device.dev->resource[i];
for (r = bios_device.dev->resource_list; r; r = r->next) {
translate_address_array[taa_index].info = r->flags;
translate_address_array[taa_index].bus = bus;
translate_address_array[taa_index].devfn = devfn;

View File

@@ -550,14 +550,12 @@ static void pci_set_resource(struct device *dev, struct resource *resource)
void pci_dev_set_resources(struct device *dev)
{
struct resource *resource, *last;
struct resource *res;
unsigned link;
u8 line;
last = &dev->resource[dev->resources];
for (resource = &dev->resource[0]; resource < last; resource++) {
pci_set_resource(dev, resource);
for (res = dev->resource_list; res; res = res->next) {
pci_set_resource(dev, res);
}
for (link = 0; link < dev->links; link++) {
struct bus *bus;

View File

@@ -132,14 +132,14 @@ static void pnp_set_resource(device_t dev, struct resource *resource)
void pnp_set_resources(device_t dev)
{
int i;
struct resource *res;
/* Select the device */
pnp_set_logical_device(dev);
/* Paranoia says I should disable the device here... */
for(i = 0; i < dev->resources; i++) {
pnp_set_resource(dev, &dev->resource[i]);
for(res = dev->resource_list; res; res = res->next) {
pnp_set_resource(dev, res);
}
}