Same conversion as with resources from static arrays to lists, except
there is no free list.

Converting resource arrays to lists reduced the size of each device
struct from 1092 to 228 bytes.

Converting link arrays to lists reduced the size of each device struct
from 228 to 68 bytes.

Signed-off-by: Myles Watson <mylesgw@gmail.com>
Acked-by: Stefan Reinauer <stepan@coresystems.de>


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5626 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
diff --git a/src/arch/i386/boot/mpspec.c b/src/arch/i386/boot/mpspec.c
index 93e6ae1..57a10ac 100644
--- a/src/arch/i386/boot/mpspec.c
+++ b/src/arch/i386/boot/mpspec.c
@@ -190,7 +190,6 @@
 {
 	struct device *child;
 
-	int linkn;
 	int i;
 	int srcbus;
 	int slot;
@@ -198,9 +197,8 @@
 	struct bus *link;
 	unsigned char dstirq_x[4];
 
-	for (linkn = 0; linkn < dev->links; linkn++) {
+	for (link = dev->link_list; link; link = link->next) {
 
-		link = &dev->link[linkn];
 		child = link->children;
 		srcbus = link->secondary;
 
diff --git a/src/cpu/amd/sc520/sc520.c b/src/cpu/amd/sc520/sc520.c
index 4c93ebd..400ba6e 100644
--- a/src/cpu/amd/sc520/sc520.c
+++ b/src/cpu/amd/sc520/sc520.c
@@ -130,8 +130,8 @@
 	device_t mc_dev;
         uint32_t pci_tolm;
   printk(BIOS_SPEW, "%s\n", __func__);
-        pci_tolm = find_pci_tolm(&dev->link[0]);
-	mc_dev = dev->link[0].children;
+        pci_tolm = find_pci_tolm(dev->link_list);
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		unsigned long tomk, tolmk;
 		//		unsigned char rambits;
@@ -168,7 +168,7 @@
 		idx = 10;
 		ram_resource(dev, idx++, 0, tolmk);
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 #if 0
diff --git a/src/devices/cardbus_device.c b/src/devices/cardbus_device.c
index d48939f..fab0a3a 100644
--- a/src/devices/cardbus_device.c
+++ b/src/devices/cardbus_device.c
@@ -158,7 +158,7 @@
 {
 	uint16_t ctrl;
 	ctrl = pci_read_config16(dev, PCI_CB_BRIDGE_CONTROL);
-	ctrl |= (dev->link[0].bridge_ctrl & (
+	ctrl |= (dev->link_list->bridge_ctrl & (
 			PCI_BRIDGE_CTL_PARITY |
 			PCI_BRIDGE_CTL_SERR |
 			PCI_BRIDGE_CTL_NO_ISA |
@@ -178,8 +178,8 @@
 	.read_resources   = cardbus_read_resources,
 	.set_resources    = pci_dev_set_resources,
 	.enable_resources = cardbus_enable_resources,
-	.init		  = 0,
-	.scan_bus	  = pci_scan_bridge,
+	.init			  = 0,
+	.scan_bus		  = pci_scan_bridge,
 	.enable           = 0,
 	.reset_bus        = pci_bus_reset,
 };
diff --git a/src/devices/device.c b/src/devices/device.c
index f6c7af4..2a05a30 100644
--- a/src/devices/device.c
+++ b/src/devices/device.c
@@ -66,7 +66,6 @@
 device_t alloc_dev(struct bus *parent, struct device_path *path)
 {
 	device_t dev, child;
-	int link;
 
 	spin_lock(&dev_lock);
 
@@ -82,12 +81,6 @@
 	memset(dev, 0, sizeof(*dev));
 	memcpy(&dev->path, path, sizeof(*path));
 
-	/* Initialize the back pointers in the link fields. */
-	for (link = 0; link < MAX_LINKS; link++) {
-		dev->link[link].dev = dev;
-		dev->link[link].link = link;
-	}
-
 	/* By default devices are enabled. */
 	dev->enabled = 1;
 
@@ -132,11 +125,11 @@
 	struct device *curdev;
 
 	printk(BIOS_SPEW, "%s %s bus %x link: %d\n", dev_path(bus->dev), __func__,
-		    bus->secondary, bus->link);
+		    bus->secondary, bus->link_num);
 
 	/* Walk through all devices and find which resources they need. */
 	for (curdev = bus->children; curdev; curdev = curdev->sibling) {
-		int i;
+		struct bus *link;
 		if (!curdev->enabled) {
 			continue;
 		}
@@ -148,11 +141,11 @@
 		curdev->ops->read_resources(curdev);
 
 		/* Read in the resources behind the current device's links. */
-		for (i = 0; i < curdev->links; i++)
-			read_resources(&curdev->link[i]);
+		for (link = curdev->link_list; link; link = link->next)
+			read_resources(link);
 	}
 	printk(BIOS_SPEW, "%s read_resources bus %d link: %d done\n",
-		    dev_path(bus->dev), bus->secondary, bus->link);
+		    dev_path(bus->dev), bus->secondary, bus->link_num);
 }
 
 struct pick_largest_state {
@@ -257,13 +250,13 @@
 	for (dev = bus->children; dev; dev = dev->sibling) {
 		struct resource *child_bridge;
 
-		if (!dev->links)
+		if (!dev->link_list)
 			continue;
 
 		/* Find the resources with matching type flags. */
 		for (child_bridge = dev->resource_list; child_bridge;
 		     child_bridge = child_bridge->next) {
-			unsigned link;
+			struct bus* link;
 
 			if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
 			    (child_bridge->flags & type_mask) != type)
@@ -275,8 +268,15 @@
 			 * need it separated.  Add the PREFETCH flag to the
 			 * type_mask and type.
 			 */
-			link = IOINDEX_LINK(child_bridge->index);
-			compute_resources(&dev->link[link], child_bridge,
+			link = dev->link_list;
+			while (link && link->link_num !=
+					IOINDEX_LINK(child_bridge->index))
+				link = link->next;
+			if (link == NULL)
+				printk(BIOS_ERR, "link %ld not found on %s\n",
+				       IOINDEX_LINK(child_bridge->index),
+				       dev_path(dev));
+			compute_resources(link, child_bridge,
 					  type_mask | IORESOURCE_PREFETCH,
 					  type | (child_bridge->flags &
 						  IORESOURCE_PREFETCH));
@@ -505,13 +505,13 @@
 	for (dev = bus->children; dev; dev = dev->sibling) {
 		struct resource *child_bridge;
 
-		if (!dev->links)
+		if (!dev->link_list)
 			continue;
 
 		/* Find the resources with matching type flags. */
 		for (child_bridge = dev->resource_list; child_bridge;
 		     child_bridge = child_bridge->next) {
-			unsigned link;
+			struct bus* link;
 
 			if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
 			    (child_bridge->flags & type_mask) != type)
@@ -523,8 +523,15 @@
 			 * need it separated.  Add the PREFETCH flag to the
 			 * type_mask and type.
 			 */
-			link = IOINDEX_LINK(child_bridge->index);
-			allocate_resources(&dev->link[link], child_bridge,
+			link = dev->link_list;
+			while (link && link->link_num !=
+			               IOINDEX_LINK(child_bridge->index))
+				link = link->next;
+			if (link == NULL)
+				printk(BIOS_ERR, "link %ld not found on %s\n",
+				       IOINDEX_LINK(child_bridge->index),
+				       dev_path(dev));
+			allocate_resources(link, child_bridge,
 					   type_mask | IORESOURCE_PREFETCH,
 					   type | (child_bridge->flags &
 						   IORESOURCE_PREFETCH));
@@ -551,7 +558,7 @@
 	struct device *child;
 	struct resource *res;
 	struct resource *lim;
-	int i;
+	struct bus *link;
 
 	printk(BIOS_SPEW, "%s: %s\n", __func__, dev_path(dev));
 
@@ -592,8 +599,8 @@
 	}
 
 	/* Descend into every enabled child and look for fixed resources. */
-	for (i = 0; i < dev->links; i++)
-		for (child = dev->link[i].children; child;
+	for (link = dev->link_list; link; link = link->next)
+		for (child = link->children; child;
 		     child = child->sibling)
 			if (child->enabled)
 				constrain_resources(child, limits);
@@ -757,7 +764,7 @@
 	struct device *curdev;
 
 	printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n",
-		    dev_path(bus->dev), bus->secondary, bus->link);
+		    dev_path(bus->dev), bus->secondary, bus->link_num);
 
 	for (curdev = bus->children; curdev; curdev = curdev->sibling) {
 		if (!curdev->enabled || !curdev->resource_list) {
@@ -771,7 +778,7 @@
 		curdev->ops->set_resources(curdev);
 	}
 	printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n",
-		    dev_path(bus->dev), bus->secondary, bus->link);
+		    dev_path(bus->dev), bus->secondary, bus->link_num);
 }
 
 /**
@@ -846,12 +853,12 @@
 
 	do_scan_bus = 1;
 	while (do_scan_bus) {
-		int link;
+		struct bus *link;
 		new_max = busdev->ops->scan_bus(busdev, max);
 		do_scan_bus = 0;
-		for (link = 0; link < busdev->links; link++) {
-			if (busdev->link[link].reset_needed) {
-				if (reset_bus(&busdev->link[link])) {
+		for (link = busdev->link_list; link; link = link->next) {
+			if (link->reset_needed) {
+				if (reset_bus(link)) {
 					do_scan_bus = 1;
 				} else {
 					busdev->bus->reset_needed = 1;
@@ -940,30 +947,30 @@
 	/* Read the resources for the entire tree. */
 
 	printk(BIOS_INFO, "Reading resources...\n");
-	read_resources(&root->link[0]);
+	read_resources(root->link_list);
 	printk(BIOS_INFO, "Done reading resources.\n");
 
 	print_resource_tree(root, BIOS_SPEW, "After reading.");
 
 	/* Compute resources for all domains. */
-	for (child = root->link[0].children; child; child = child->sibling) {
+	for (child = root->link_list->children; child; child = child->sibling) {
 		if (!(child->path.type == DEVICE_PATH_PCI_DOMAIN))
 			continue;
 		for (res = child->resource_list; res; res = res->next) {
 			if (res->flags & IORESOURCE_FIXED)
 				continue;
 			if (res->flags & IORESOURCE_PREFETCH) {
-				compute_resources(&child->link[0],
+				compute_resources(child->link_list,
 					       res, MEM_MASK, PREF_TYPE);
 				continue;
 			}
 			if (res->flags & IORESOURCE_MEM) {
-				compute_resources(&child->link[0],
+				compute_resources(child->link_list,
 					       res, MEM_MASK, MEM_TYPE);
 				continue;
 			}
 			if (res->flags & IORESOURCE_IO) {
-				compute_resources(&child->link[0],
+				compute_resources(child->link_list,
 					       res, IO_MASK, IO_TYPE);
 				continue;
 			}
@@ -971,14 +978,14 @@
 	}
 
 	/* For all domains. */
-	for (child = root->link[0].children; child; child=child->sibling)
+	for (child = root->link_list->children; child; child=child->sibling)
 		if (child->path.type == DEVICE_PATH_PCI_DOMAIN)
 			avoid_fixed_resources(child);
 
 	/* Now we need to adjust the resources. MEM resources need to start at
 	 * the highest address managable.
 	 */
-	for (child = root->link[0].children; child; child = child->sibling) {
+	for (child = root->link_list->children; child; child = child->sibling) {
 		if (child->path.type != DEVICE_PATH_PCI_DOMAIN)
 			continue;
 		for (res = child->resource_list; res; res = res->next) {
@@ -991,30 +998,30 @@
 
 	/* Store the computed resource allocations into device registers ... */
 	printk(BIOS_INFO, "Setting resources...\n");
-	for (child = root->link[0].children; child; child = child->sibling) {
+	for (child = root->link_list->children; child; child = child->sibling) {
 		if (!(child->path.type == DEVICE_PATH_PCI_DOMAIN))
 			continue;
 		for (res = child->resource_list; res; res = res->next) {
 			if (res->flags & IORESOURCE_FIXED)
 				continue;
 			if (res->flags & IORESOURCE_PREFETCH) {
-				allocate_resources(&child->link[0],
+				allocate_resources(child->link_list,
 					       res, MEM_MASK, PREF_TYPE);
 				continue;
 			}
 			if (res->flags & IORESOURCE_MEM) {
-				allocate_resources(&child->link[0],
+				allocate_resources(child->link_list,
 					       res, MEM_MASK, MEM_TYPE);
 				continue;
 			}
 			if (res->flags & IORESOURCE_IO) {
-				allocate_resources(&child->link[0],
+				allocate_resources(child->link_list,
 					       res, IO_MASK, IO_TYPE);
 				continue;
 			}
 		}
 	}
-	assign_resources(&root->link[0]);
+	assign_resources(root->link_list);
 	printk(BIOS_INFO, "Done setting resources.\n");
 	print_resource_tree(root, BIOS_SPEW, "After assigning values.");
 
@@ -1055,7 +1062,7 @@
 			if (dev->path.type == DEVICE_PATH_I2C) {
 				printk(BIOS_DEBUG, "smbus: %s[%d]->",
 					     dev_path(dev->bus->dev),
-					     dev->bus->link);
+					     dev->bus->link_num);
 			}
 			printk(BIOS_DEBUG, "%s init\n", dev_path(dev));
 			dev->initialized = 1;
diff --git a/src/devices/device_util.c b/src/devices/device_util.c
index 91a41af..c845ecd 100644
--- a/src/devices/device_util.c
+++ b/src/devices/device_util.c
@@ -40,7 +40,7 @@
 device_t find_dev_path(struct bus *parent, struct device_path *path)
 {
 	device_t child;
-	for(child = parent->children; child; child = child->sibling) {
+	for (child = parent->children; child; child = child->sibling) {
 		if (path_eq(path, &child->path)) {
 			break;
 		}
@@ -213,7 +213,7 @@
 const char *bus_path(struct bus *bus)
 {
 	static char buffer[BUS_PATH_MAX];
-	sprintf(buffer, "%s,%d", dev_path(bus->dev), bus->link);
+	sprintf(buffer, "%s,%d", dev_path(bus->dev), bus->link_num);
 	return buffer;
 }
 
@@ -303,7 +303,7 @@
 {
 	struct resource *res, *next, *prev = NULL;
 	/* Move all of the free resources to the end */
-	for(res = dev->resource_list; res; res = next) {
+	for (res = dev->resource_list; res; res = next) {
 		next = res->next;
 		if (!res->flags)
 			free_resource(dev, res, prev);
@@ -323,7 +323,7 @@
 {
 	struct resource *res;
 	/* See if there is a resource with the appropriate index */
-	for(res = dev->resource_list; res; res = res->next) {
+	for (res = dev->resource_list; res; res = res->next) {
 		if (res->index == index)
 			break;
 	}
@@ -496,9 +496,9 @@
 		buf[0] = '\0';
 		if (resource->flags & IORESOURCE_PCI_BRIDGE) {
 #if CONFIG_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_list->secondary & 0xff);
 #else
-			sprintf(buf, "bus %02x ", dev->link[0].secondary);
+			sprintf(buf, "bus %02x ", dev->link_list->secondary);
 #endif
 		}
 		printk(BIOS_DEBUG,
@@ -518,11 +518,11 @@
 	resource_search_t search, void *gp)
 {
 	struct device *curdev;
-	for(curdev = bus->children; curdev; curdev = curdev->sibling) {
+	for (curdev = bus->children; curdev; curdev = curdev->sibling) {
 		struct resource *res;
 		/* Ignore disabled devices */
 		if (!curdev->enabled) continue;
-		for(res = curdev->resource_list; res; res = res->next) {
+		for (res = curdev->resource_list; res; res = res->next) {
 			/* If it isn't the right kind of resource ignore it */
 			if ((res->flags & type_mask) != type) {
 				continue;
@@ -530,7 +530,9 @@
 			/* If it is a subtractive resource recurse */
 			if (res->flags & IORESOURCE_SUBTRACTIVE) {
 				struct bus * subbus;
-				subbus = &curdev->link[IOINDEX_SUBTRACTIVE_LINK(res->index)];
+				for (subbus = curdev->link_list; subbus; subbus = subbus->next)
+					if (subbus->link_num == IOINDEX_SUBTRACTIVE_LINK(res->index))
+						break;
 				search_bus_resources(subbus, type_mask, type, search, gp);
 				continue;
 			}
@@ -544,11 +546,11 @@
 	resource_search_t search, void *gp)
 {
 	struct device *curdev;
-	for(curdev = all_devices; curdev; curdev = curdev->next) {
+	for (curdev = all_devices; curdev; curdev = curdev->next) {
 		struct resource *res;
 		/* Ignore disabled devices */
 		if (!curdev->enabled) continue;
-		for(res = curdev->resource_list; res; res = res->next) {
+		for (res = curdev->resource_list; res; res = res->next) {
 			/* If it isn't the right kind of resource ignore it */
 			if ((res->flags & type_mask) != type) {
 				continue;
@@ -579,10 +581,10 @@
 void disable_children(struct bus *bus)
 {
 	device_t child;
-	for(child = bus->children; child; child = child->sibling) {
-		int link;
-		for(link = 0; link < child->links; link++) {
-			disable_children(&child->link[link]);
+	for (child = bus->children; child; child = child->sibling) {
+		struct bus *link;
+		for (link = child->link_list; link; link = link->next) {
+			disable_children(link);
 		}
 		dev_set_enabled(child, 0);
 	}
@@ -590,8 +592,9 @@
 
 static void resource_tree(struct device *root, int debug_level, int depth)
 {
-	int i = 0, link = 0;
+	int i = 0;
 	struct device *child;
+	struct bus *link;
 	struct resource *res;
 	char indent[30];	/* If your tree has more levels, it's wrong. */
 
@@ -599,10 +602,12 @@
 		indent[i] = ' ';
 	indent[i] = '\0';
 
-	do_printk(debug_level, "%s%s links %x child on link 0", indent,
-		  dev_path(root), root->links);
-	do_printk(debug_level, " %s\n", root->link[0].children ?
-		  dev_path(root->link[0].children) : "NULL");
+ 	do_printk(BIOS_DEBUG, "%s%s", indent, dev_path(root));
+ 	if (root->link_list && root->link_list->children)
+ 		do_printk(BIOS_DEBUG, " child on link 0 %s",
+ 			  dev_path(root->link_list->children));
+ 	do_printk(BIOS_DEBUG, "\n");
+
 	for (res = root->resource_list; res; res = res->next) {
 		do_printk(debug_level,
 			  "%s%s resource base %llx size %llx align %d gran %d limit %llx flags %lx index %lx\n",
@@ -612,9 +617,8 @@
 			  res->flags, res->index);
 	}
 
-	for (link = 0; link < root->links; link++) {
-		for (child = root->link[link].children; child;
-		     child = child->sibling)
+	for (link = root->link_list; link; link = link->next) {
+		for (child = link->children; child; child = child->sibling)
 			resource_tree(child, debug_level, depth + 1);
 	}
 }
@@ -640,13 +644,15 @@
 	char depth_str[20] = "";
 	int i;
 	struct device *sibling;
+	struct bus *link;
+
 	for (i = 0; i < depth; i++)
 		depth_str[i] = ' ';
 	depth_str[i] = '\0';
 	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;
+	for (link = dev->link_list; link; link = link->next) {
+		for (sibling = link->children; sibling;
 		     sibling = sibling->sibling)
 			show_devs_tree(sibling, debug_level, depth + 1, i);
 	}
diff --git a/src/devices/oprom/yabel/device.c b/src/devices/oprom/yabel/device.c
index 8bfb1fd..7fdc438 100644
--- a/src/devices/oprom/yabel/device.c
+++ b/src/devices/oprom/yabel/device.c
@@ -45,7 +45,7 @@
 {
 	int taa_index = 0;
 	struct resource *r;
-	u8 bus = bios_device.dev->bus->link;
+	u8 bus = bios_device.dev->bus->link_num;
 	u16 devfn = bios_device.dev->path.pci.devfn;
 
 	bios_device.bus =  bus;
diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c
index 4aed35d..e6cebca 100644
--- a/src/devices/pci_device.c
+++ b/src/devices/pci_device.c
@@ -551,15 +551,13 @@
 void pci_dev_set_resources(struct device *dev)
 {
 	struct resource *res;
-	unsigned link;
+	struct bus *bus;
 	u8 line;
 
 	for (res = dev->resource_list; res; res = res->next) {
 		pci_set_resource(dev, res);
 	}
-	for (link = 0; link < dev->links; link++) {
-		struct bus *bus;
-		bus = &dev->link[link];
+	for (bus = dev->link_list; bus; bus = bus->next) {
 		if (bus->children) {
 			assign_resources(bus);
 		}
@@ -614,10 +612,10 @@
 	/* Enable I/O in command register if there is VGA card
 	 * connected with (even it does not claim I/O resource).
 	 */
-	if (dev->link[0].bridge_ctrl & PCI_BRIDGE_CTL_VGA)
+	if (dev->link_list->bridge_ctrl & PCI_BRIDGE_CTL_VGA)
 		dev->command |= PCI_COMMAND_IO;
 	ctrl = pci_read_config16(dev, PCI_BRIDGE_CONTROL);
-	ctrl |= dev->link[0].bridge_ctrl;
+	ctrl |= dev->link_list->bridge_ctrl;
 	ctrl |= (PCI_BRIDGE_CTL_PARITY + PCI_BRIDGE_CTL_SERR);	/* Error check. */
 	printk(BIOS_DEBUG, "%s bridge ctrl <- %04x\n", dev_path(dev), ctrl);
 	pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl);
@@ -1102,9 +1100,17 @@
 
 	printk(BIOS_SPEW, "%s for %s\n", __func__, dev_path(dev));
 
-	bus = &dev->link[0];
-	bus->dev = dev;
-	dev->links = 1;
+	if (dev->link_list == NULL) {
+		struct bus *link;
+		link = malloc(sizeof(*link));
+		if (link == NULL)
+			die("Couldn't allocate a link!\n");
+		memset(link, 0, sizeof(*link));
+		link->dev = dev;
+		dev->link_list = link;
+	}
+
+	bus = dev->link_list;
 
 	/* Set up the primary, secondary and subordinate bus numbers. We have
 	 * no idea how many buses are behind this bridge yet, so we set the
@@ -1179,7 +1185,7 @@
  */
 unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
 {
-	max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
+	max = pci_scan_bus(dev->link_list, PCI_DEVFN(0, 0), 0xff, max);
 	return max;
 }
 
diff --git a/src/devices/pcix_device.c b/src/devices/pcix_device.c
index d3af53e..0fcedd5 100644
--- a/src/devices/pcix_device.c
+++ b/src/devices/pcix_device.c
@@ -61,20 +61,11 @@
 	}
 }
 
-unsigned int pcix_scan_bus(struct bus *bus,
-	unsigned min_devfn, unsigned max_devfn, unsigned int max)
+static void pcix_tune_bus(struct bus *bus)
 {
 	device_t child;
-	max = pci_scan_bus(bus, min_devfn, max_devfn, max);
-	for(child = bus->children; child; child = child->sibling) {
-		if (	(child->path.pci.devfn < min_devfn) ||
-			(child->path.pci.devfn > max_devfn))
-		{
-			continue;
-		}
+	for(child = bus->children; child; child = child->sibling)
 		pcix_tune_dev(child);
-	}
-	return max;
 }
 
 const char *pcix_speed(unsigned sstatus)
@@ -124,18 +115,17 @@
 	unsigned pos;
 	unsigned sstatus;
 
+	max = do_pci_scan_bridge(dev, max, pci_scan_bus);
 	/* Find the PCI-X capability */
 	pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
 	sstatus = pci_read_config16(dev, pos + PCI_X_SEC_STATUS);
 
-	if (PCI_X_SSTATUS_MFREQ(sstatus) == PCI_X_SSTATUS_CONVENTIONAL_PCI) {
-		max = do_pci_scan_bridge(dev, max, pci_scan_bus);
-	} else {
-		max = do_pci_scan_bridge(dev, max, pcix_scan_bus);
+	if (PCI_X_SSTATUS_MFREQ(sstatus) != PCI_X_SSTATUS_CONVENTIONAL_PCI) {
+		pcix_tune_bus(dev->link_list);
 	}
 
 	/* Print the PCI-X bus speed */
-	printk(BIOS_DEBUG, "PCI: %02x: %s\n", dev->link[0].secondary, pcix_speed(sstatus));
+	printk(BIOS_DEBUG, "PCI: %02x: %s\n", dev->link_list->secondary, pcix_speed(sstatus));
 
 	return max;
 }
diff --git a/src/devices/root_device.c b/src/devices/root_device.c
index b9369bc..a77b5c8 100644
--- a/src/devices/root_device.c
+++ b/src/devices/root_device.c
@@ -75,17 +75,17 @@
 unsigned int scan_static_bus(device_t bus, unsigned int max)
 {
 	device_t child;
-	unsigned link;
+	struct bus* link;
 
 	printk(BIOS_SPEW, "%s for %s\n", __func__, dev_path(bus));
 
-	for(link = 0; link < bus->links; link++) {
+	for(link = bus->link_list; link; link = link->next) {
 		/* for smbus bus enumerate */
-		child = bus->link[link].children;
+		child = link->children;
 		if(child && child->path.type == DEVICE_PATH_I2C) {
-			bus->link[link].secondary = ++smbus_max;
+			link->secondary = ++smbus_max;
 		}
-		for(child = bus->link[link].children; child; child = child->sibling) {
+		for(child =link->children; child; child = child->sibling) {
 			if (child->chip_ops && child->chip_ops->enable_dev) {
 				child->chip_ops->enable_dev(child);
 			}
@@ -94,15 +94,15 @@
 			}
  			if (child->path.type == DEVICE_PATH_I2C) {
  				printk(BIOS_DEBUG, "smbus: %s[%d]->",
-					dev_path(child->bus->dev), child->bus->link );
+					dev_path(child->bus->dev), child->bus->link_num );
 			}
 			printk(BIOS_DEBUG, "%s %s\n",
 				dev_path(child),
 				child->enabled?"enabled": "disabled");
 		}
 	}
-	for(link = 0; link < bus->links; link++) {
-		for(child = bus->link[link].children; child; child = child->sibling) {
+	for(link = bus->link_list; link; link = link->next) {
+		for(child = link->children; child; child = child->sibling) {
 			if (!child->ops || !child->ops->scan_bus)
 				continue;
 			printk(BIOS_SPEW, "%s scanning...\n", dev_path(child));
@@ -130,10 +130,10 @@
  */
 void enable_childrens_resources(device_t dev)
 {
-	unsigned link;
-	for(link = 0; link < dev->links; link++) {
+	struct bus *link;
+	for(link = dev->link_list; link; link = link->next) {
 		device_t child;
-		for(child = dev->link[link].children; child; child = child->sibling) {
+		for(child = link->children; child; child = child->sibling) {
 			enable_resources(child);
 		}
 	}
diff --git a/src/devices/smbus_ops.c b/src/devices/smbus_ops.c
index b224281..4a61e87 100644
--- a/src/devices/smbus_ops.c
+++ b/src/devices/smbus_ops.c
@@ -58,7 +58,7 @@
 //		printk(BIOS_INFO, " %s[%d] -> ", dev_path(pbus_a[i]->dev), pbus_a[i]->link);
         	if (ops_smbus_bus(get_pbus_smbus(pbus_a[i]->dev))) {
                 	if (pbus_a[i]->dev->ops && pbus_a[i]->dev->ops->set_link)
-                        	pbus_a[i]->dev->ops->set_link(pbus_a[i]->dev, pbus_a[i]->link);
+                        	pbus_a[i]->dev->ops->set_link(pbus_a[i]->dev, pbus_a[i]->link_num);
 		}
 	}
 //	printk(BIOS_INFO, " %s\n", dev_path(dev));
diff --git a/src/drivers/generic/debug/debug_dev.c b/src/drivers/generic/debug/debug_dev.c
index 5c5dc8b..60d610f 100644
--- a/src/drivers/generic/debug/debug_dev.c
+++ b/src/drivers/generic/debug/debug_dev.c
@@ -85,7 +85,7 @@
 static void print_smbus_regs(struct device *dev)
 {
 	int j;
-	printk(BIOS_DEBUG, "smbus: %s[%d]->", dev_path(dev->bus->dev), dev->bus->link);
+	printk(BIOS_DEBUG, "smbus: %s[%d]->", dev_path(dev->bus->dev), dev->bus->link_num);
 	printk(BIOS_DEBUG, "%s", dev_path(dev));
 	for(j = 0; j < 256; j++) {
 		int status;
@@ -107,22 +107,22 @@
 static void print_smbus_regs_all(struct device *dev)
 {
 	struct device *child;
-	int i;
+	struct bus *link;
 	if (dev->enabled && dev->path.type == DEVICE_PATH_I2C)
 	{
 		// Here don't need to call smbus_set_link, because we scan it from top to down
 		if( dev->bus->dev->path.type == DEVICE_PATH_I2C) { // it's under i2c MUX so set mux at first
 			if(ops_smbus_bus(get_pbus_smbus(dev->bus->dev))) {
 				if(dev->bus->dev->ops && dev->bus->dev->ops->set_link)
-					dev->bus->dev->ops->set_link(dev->bus->dev, dev->bus->link);
+					dev->bus->dev->ops->set_link(dev->bus->dev, dev->bus->link_num);
 			}
 		}
 
 		if(ops_smbus_bus(get_pbus_smbus(dev))) print_smbus_regs(dev);
 	}
 
-	for(i=0; i< dev->links; i++) {
-		for (child = dev->link[i].children; child; child = child->sibling) {
+	for(link = dev->link_list; link; link = link->next) {
+		for (child = link->children; child; child = child->sibling) {
 			print_smbus_regs_all(child);
         	}
 	}
diff --git a/src/drivers/i2c/i2cmux/i2cmux.c b/src/drivers/i2c/i2cmux/i2cmux.c
index cd68a01..14c52cc 100644
--- a/src/drivers/i2c/i2cmux/i2cmux.c
+++ b/src/drivers/i2c/i2cmux/i2cmux.c
@@ -34,7 +34,7 @@
 
 static void enable_dev(struct device *dev)
 {
-	if(dev->links>0)
+	if(dev->link_list != NULL)
 		dev->ops = &i2cmux_operations;
 }
 
diff --git a/src/drivers/i2c/i2cmux2/i2cmux2.c b/src/drivers/i2c/i2cmux2/i2cmux2.c
index 4d2eeb99..c0f8e70 100644
--- a/src/drivers/i2c/i2cmux2/i2cmux2.c
+++ b/src/drivers/i2c/i2cmux2/i2cmux2.c
@@ -33,7 +33,7 @@
 
 static void enable_dev(struct device *dev)
 {
-	if(dev->links>0)
+	if(dev->link_list != NULL)
 		dev->ops = &i2cmux2_operations;
 }
 
diff --git a/src/include/device/device.h b/src/include/device/device.h
index 6ac2d10..b6e7a7b 100644
--- a/src/include/device/device.h
+++ b/src/include/device/device.h
@@ -40,8 +40,9 @@
 struct bus {
 	device_t 	dev;		/* This bridge device */
 	device_t 	children;	/* devices behind this bridge */
+	struct bus	*next;		/* The next bridge on this device */
 	unsigned	bridge_ctrl;	/* Bridge control register */
-	unsigned char	link;		/* The index of this link */
+	unsigned char	link_num;	/* The index of this link */
 	uint16_t	secondary; 	/* secondary bus number */
 	uint16_t	subordinate;	/* max subordinate bus number */
 	unsigned char   cap;		/* PCi capability offset */
@@ -49,8 +50,6 @@
 	unsigned	disable_relaxed_ordering : 1;
 };
 
-#define MAX_RESOURCES 24
-#define MAX_LINKS    8
 /*
  * There is one device structure for each slot-number/function-number
  * combination:
@@ -79,9 +78,7 @@
 	/* links are (downstream) buses attached to the device, usually a leaf
 	 * device with no children has 0 buses attached and a bridge has 1 bus
 	 */
-	struct bus link[MAX_LINKS];
-	/* number of buses attached to the device */
-	unsigned int links;
+	struct bus *link_list;
 
 	struct device_operations *ops;
 	const struct chip_operations *chip_ops;
@@ -96,6 +93,7 @@
 extern struct device	*all_devices;	/* list of all devices */
 
 extern struct resource	*free_resources;
+extern struct bus	*free_links;
 
 /* Generic device interface functions */
 device_t alloc_dev(struct bus *parent, struct device_path *path);
diff --git a/src/mainboard/emulation/qemu-x86/northbridge.c b/src/mainboard/emulation/qemu-x86/northbridge.c
index 7b84928..f4a0cc2 100644
--- a/src/mainboard/emulation/qemu-x86/northbridge.c
+++ b/src/mainboard/emulation/qemu-x86/northbridge.c
@@ -60,7 +60,7 @@
 
 static void cpu_pci_domain_set_resources(device_t dev)
 {
-	u32 pci_tolm = find_pci_tolm(&dev->link[0]);
+	u32 pci_tolm = find_pci_tolm(dev->link_list);
 	unsigned long tomk = 0, tolmk;
 	int idx;
 
@@ -91,7 +91,7 @@
 	high_tables_size = HIGH_TABLES_SIZE * 1024;
 #endif
 
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static void cpu_pci_domain_read_resources(struct device *dev)
diff --git a/src/mainboard/ibase/mb899/mptable.c b/src/mainboard/ibase/mb899/mptable.c
index c1854ec..d582ec6 100644
--- a/src/mainboard/ibase/mb899/mptable.c
+++ b/src/mainboard/ibase/mb899/mptable.c
@@ -70,7 +70,7 @@
 	if (!riser)
 		riser = dev_find_device(0x3388, 0x0022, 0);
 	if (riser) {
-		riser_bus = riser->link[0].secondary;
+		riser_bus = riser->link_list->secondary;
 		printk(BIOS_SPEW, "Riser bus is %x\n", riser_bus);
 		max_pci_bus = riser_bus;
 	}
diff --git a/src/mainboard/kontron/986lcd-m/mptable.c b/src/mainboard/kontron/986lcd-m/mptable.c
index bdba295..cfa7cb7 100644
--- a/src/mainboard/kontron/986lcd-m/mptable.c
+++ b/src/mainboard/kontron/986lcd-m/mptable.c
@@ -70,7 +70,7 @@
 	if (!riser)
 		riser = dev_find_device(0x3388, 0x0022, 0);
 	if (riser) {
-		riser_bus = riser->link[0].secondary;
+		riser_bus = riser->link_list->secondary;
 		printk(BIOS_SPEW, "Riser bus is %x\n", riser_bus);
 		max_pci_bus = riser_bus;
 	}
diff --git a/src/mainboard/tyan/s2881/mainboard.c b/src/mainboard/tyan/s2881/mainboard.c
index 773f254..6c41839 100644
--- a/src/mainboard/tyan/s2881/mainboard.c
+++ b/src/mainboard/tyan/s2881/mainboard.c
@@ -46,7 +46,7 @@
 	/* Find the ADT7463 device. */
 	path.type = DEVICE_PATH_I2C;
 	path.i2c.device = 0x2d;
-	adt7463 = find_dev_path(smbus_dev->link, &path);
+	adt7463 = find_dev_path(smbus_dev->link_list, &path);
 	if (!adt7463)
 		die("ADT7463 not found\n");
 	printk(BIOS_DEBUG, "ADT7463 found\n");
@@ -113,7 +113,6 @@
 {
 	struct device_path path;
 	device_t dummy;
-	unsigned link_i;
 
 	max = root_dev_scan_bus(root, max);
 
@@ -126,20 +125,10 @@
 	 * as the last device to be initialized.
 	 */
 
-	link_i = root->links;
-	if (link_i >= MAX_LINKS) {
-		printk(BIOS_DEBUG, "Reached MAX_LINKS, not configuring ADT7463");
-		return max;
-	}
-	root->link[link_i].link = link_i;
-	root->link[link_i].dev = root;
-	root->link[link_i].children = 0;
-	root->links++;
-
 	path.type = DEVICE_PATH_PNP;
 	path.pnp.port = 0;
 	path.pnp.device = 0;
-	dummy = alloc_dev(&root->link[link_i], &path);
+	dummy = alloc_dev(root->link_list, &path);
 	dummy->ops = &dummy_operations;
 
 	return max;
diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c
index a25a8df..253a209 100644
--- a/src/northbridge/amd/amdfam10/northbridge.c
+++ b/src/northbridge/amd/amdfam10/northbridge.c
@@ -137,7 +137,7 @@
 
 }
 
-static u32 amdfam10_scan_chain(device_t dev, u32 nodeid, u32 link, u32 sblink,
+static u32 amdfam10_scan_chain(device_t dev, u32 nodeid, struct bus *link, u32 link_num, u32 sblink,
 				u32 max, u32 offset_unitid)
 {
 //	I want to put sb chain in bus 0 can I?
@@ -149,7 +149,7 @@
 		u32 ht_unitid_base[4]; // here assume only 4 HT device on chain
 		u32 max_bus;
 		u32 min_bus;
-		u32 is_sublink1 = (link>3);
+		u32 is_sublink1 = (link_num>3);
 		device_t devx;
 		u32 busses;
 		u32 segn = max>>8;
@@ -162,7 +162,7 @@
 		if(is_sublink1) {
 			u32 regpos;
 			u32 reg;
-			regpos = 0x170 + 4 * (link&3); // it is only on sublink0
+			regpos = 0x170 + 4 * (link_num&3); // it is only on sublink0
 			reg = pci_read_config32(dev, regpos);
 			if(reg & 1) return max; // already ganged no sblink1
 			devx = get_node_pci(nodeid, 4);
@@ -171,15 +171,15 @@
 			devx = dev;
 
 
-		dev->link[link].cap = 0x80 + ((link&3) *0x20);
+		link->cap = 0x80 + ((link_num&3) *0x20);
 		do {
-			link_type = pci_read_config32(devx, dev->link[link].cap + 0x18);
+			link_type = pci_read_config32(devx, link->cap + 0x18);
 		} while(link_type & ConnectionPending);
 		if (!(link_type & LinkConnected)) {
 			return max;
 		}
 		do {
-			link_type = pci_read_config32(devx, dev->link[link].cap + 0x18);
+			link_type = pci_read_config32(devx, link->cap + 0x18);
 		} while(!(link_type & InitComplete));
 		if (!(link_type & NonCoherent)) {
 			return max;
@@ -187,7 +187,7 @@
 		/* See if there is an available configuration space mapping
 		 * register in function 1.
 		 */
-		ht_c_index = get_ht_c_index(nodeid, link, &sysconf);
+		ht_c_index = get_ht_c_index(nodeid, link_num, &sysconf);
 
 #if CONFIG_EXT_CONF_SUPPORT == 0
 		if(ht_c_index>=4) return max;
@@ -199,7 +199,7 @@
 		 */
 #if CONFIG_SB_HT_CHAIN_ON_BUS0 > 0
 		// first chain will on bus 0
-		if((nodeid == 0) && (sblink==link)) { // actually max is 0 here
+		if((nodeid == 0) && (sblink==link_num)) { // actually max is 0 here
 			min_bus = max;
 		}
 	#if CONFIG_SB_HT_CHAIN_ON_BUS0 > 1
@@ -221,26 +221,26 @@
 #endif
 		max_bus = 0xfc | (segn<<8);
 
-		dev->link[link].secondary = min_bus;
-		dev->link[link].subordinate = max_bus;
+		link->secondary = min_bus;
+		link->subordinate = max_bus;
 
 		/* Read the existing primary/secondary/subordinate bus
 		 * number configuration.
 		 */
-		busses = pci_read_config32(devx, dev->link[link].cap + 0x14);
+		busses = pci_read_config32(devx, link->cap + 0x14);
 
 		/* Configure the bus numbers for this bridge: the configuration
 		 * transactions will not be propagates by the bridge if it is
 		 * not correctly configured
 		 */
 		busses &= 0xffff00ff;
-		busses |= ((u32)(dev->link[link].secondary) << 8);
-		pci_write_config32(devx, dev->link[link].cap + 0x14, busses);
+		busses |= ((u32)(link->secondary) << 8);
+		pci_write_config32(devx, link->cap + 0x14, busses);
 
 
 		/* set the config map space */
 
-		set_config_map_reg(nodeid, link, ht_c_index, dev->link[link].secondary, dev->link[link].subordinate, sysconf.segbit, sysconf.nodes);
+		set_config_map_reg(nodeid, link_num, ht_c_index, link->secondary, link->subordinate, sysconf.segbit, sysconf.nodes);
 
 		/* Now we can scan all of the subordinate busses i.e. the
 		 * chain on the hypertranport link
@@ -255,17 +255,17 @@
 		else
 			max_devfn = (0x1f<<3) | 7;
 
-		max = hypertransport_scan_chain(&dev->link[link], 0, max_devfn, max, ht_unitid_base, offset_unitid);
+		max = hypertransport_scan_chain(link, 0, max_devfn, max, ht_unitid_base, offset_unitid);
 
 		/* We know the number of busses behind this bridge.  Set the
 		 * subordinate bus number to it's real value
 		 */
 		if(ht_c_index>3) { // clear the extend reg
-			clear_config_map_reg(nodeid, link, ht_c_index, (max+1)>>sysconf.segbit, (dev->link[link].subordinate)>>sysconf.segbit, sysconf.nodes);
+			clear_config_map_reg(nodeid, link_num, ht_c_index, (max+1)>>sysconf.segbit, (link->subordinate)>>sysconf.segbit, sysconf.nodes);
 		}
 
-		dev->link[link].subordinate = max;
-		set_config_map_reg(nodeid, link, ht_c_index, dev->link[link].secondary, dev->link[link].subordinate, sysconf.segbit, sysconf.nodes);
+		link->subordinate = max;
+		set_config_map_reg(nodeid, link_num, ht_c_index, link->secondary, link->subordinate, sysconf.segbit, sysconf.nodes);
 		sysconf.ht_c_num++;
 
 		{
@@ -278,14 +278,14 @@
 			sysconf.hcdn_reg[ht_c_index] = temp;
 
 		}
-	store_ht_c_conf_bus(nodeid, link, ht_c_index, dev->link[link].secondary, dev->link[link].subordinate, &sysconf);
+	store_ht_c_conf_bus(nodeid, link_num, ht_c_index, link->secondary, link->subordinate, &sysconf);
 	return max;
 }
 
-static u32 amdfam10_scan_chains(device_t dev, u32 max)
+static unsigned amdfam10_scan_chains(device_t dev, unsigned max)
 {
 	unsigned nodeid;
-	u32 link;
+	struct bus *link;
 	unsigned sblink = sysconf.sblk;
 	unsigned offset_unitid = 0;
 
@@ -297,7 +297,9 @@
 	#if ((CONFIG_HT_CHAIN_UNITID_BASE != 1) || (CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20))
 		offset_unitid = 1;
 	#endif
-		max = amdfam10_scan_chain(dev, nodeid, sblink, sblink, max, offset_unitid ); // do sb ht chain at first, in case s2885 put sb chain (8131/8111) on link2, but put 8151 on link0
+		for (link = dev->link_list; link; link = link->next)
+			if (link->link_num == sblink)
+				max = amdfam10_scan_chain(dev, nodeid, link, sblink, sblink, max, offset_unitid ); // do sb ht chain at first, in case s2885 put sb chain (8131/8111) on link2, but put 8151 on link0
 	}
 #endif
 
@@ -305,19 +307,19 @@
 	max = check_segn(dev, max, sysconf.nodes, &sysconf);
 #endif
 
-	for(link = 0; link < dev->links; link++) {
+	for(link = dev->link_list; link; link = link->next) {
 #if CONFIG_SB_HT_CHAIN_ON_BUS0 > 0
-		if( (nodeid == 0) && (sblink == link) ) continue; //already done
+		if( (nodeid == 0) && (sblink == link->link_num) ) continue; //already done
 #endif
 		offset_unitid = 0;
 		#if ((CONFIG_HT_CHAIN_UNITID_BASE != 1) || (CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20))
 			#if CONFIG_SB_HT_CHAIN_UNITID_OFFSET_ONLY == 1
-			if((nodeid == 0) && (sblink == link))
+			if((nodeid == 0) && (sblink == link->link_num))
 			#endif
 				offset_unitid = 1;
 		#endif
 
-		max = amdfam10_scan_chain(dev, nodeid, link, sblink, max, offset_unitid);
+		max = amdfam10_scan_chain(dev, nodeid, link, link->link_num, sblink, max, offset_unitid);
 	}
 	return max;
 }
@@ -482,12 +484,12 @@
 
 static void amdfam10_read_resources(device_t dev)
 {
-	u32 nodeid, link;
-
+	u32 nodeid;
+	struct bus *link;
 	nodeid = amdfam10_nodeid(dev);
-	for(link = 0; link < dev->links; link++) {
-		if (dev->link[link].children) {
-			amdfam10_link_read_bases(dev, nodeid, link);
+	for(link = dev->link_list; link; link = link->next) {
+		if (link->children) {
+			amdfam10_link_read_bases(dev, nodeid, link->link_num);
 		}
 	}
 }
@@ -496,7 +498,7 @@
 				u32 nodeid)
 {
 	resource_t rbase, rend;
-	unsigned reg, link;
+	unsigned reg, link_num;
 	char buf[50];
 
 	/* Make certain the resource has actually been set */
@@ -525,20 +527,20 @@
 
 	/* Get the register and link */
 	reg  = resource->index & 0xfff; // 4k
-	link = IOINDEX_LINK(resource->index);
+	link_num = IOINDEX_LINK(resource->index);
 
 	if (resource->flags & IORESOURCE_IO) {
 
-		set_io_addr_reg(dev, nodeid, link, reg, rbase>>8, rend>>8);
-		store_conf_io_addr(nodeid, link, reg, (resource->index >> 24), rbase>>8, rend>>8);
+		set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
+		store_conf_io_addr(nodeid, link_num, reg, (resource->index >> 24), rbase>>8, rend>>8);
 	}
 	else if (resource->flags & IORESOURCE_MEM) {
-		set_mmio_addr_reg(nodeid, link, reg, (resource->index >>24), rbase>>8, rend>>8, sysconf.nodes) ;// [39:8]
-		store_conf_mmio_addr(nodeid, link, reg, (resource->index >>24), rbase>>8, rend>>8);
+		set_mmio_addr_reg(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8, sysconf.nodes) ;// [39:8]
+		store_conf_mmio_addr(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8);
 	}
 	resource->flags |= IORESOURCE_STORED;
-	sprintf(buf, " <node %02x link %02x>",
-		nodeid, link);
+	sprintf(buf, " <node %x link %x>",
+		nodeid, link_num);
 	report_resource_stored(dev, resource, buf);
 }
 
@@ -553,18 +555,18 @@
 
 static void amdfam10_create_vga_resource(device_t dev, unsigned nodeid)
 {
-	unsigned link;
+	struct bus *link;
 
 	/* find out which link the VGA card is connected,
 	 * we only deal with the 'first' vga card */
-	for (link = 0; link < dev->links; link++) {
-		if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
+	for (link = dev->link_list; link; link = link->next) {
+		if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
 #if CONFIG_CONSOLE_VGA_MULTI == 1
-			printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d dev->link[link] bus range [%d,%d]\n", vga_pri->bus->secondary,
-				dev->link[link].secondary,dev->link[link].subordinate);
+			printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d bus range [%d,%d]\n", vga_pri->bus->secondary,
+				link->secondary,link->subordinate);
 			/* We need to make sure the vga_pri is under the link */
-			if((vga_pri->bus->secondary >= dev->link[link].secondary ) &&
-				(vga_pri->bus->secondary <= dev->link[link].subordinate )
+			if((vga_pri->bus->secondary >= link->secondary ) &&
+				(vga_pri->bus->secondary <= link->subordinate )
 			)
 #endif
 			break;
@@ -572,16 +574,17 @@
 	}
 
 	/* no VGA card installed */
-	if (link == dev->links)
+	if (link == NULL)
 		return;
 
-	printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, link);
-	set_vga_enable_reg(nodeid, link);
+	printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, link->link_num);
+	set_vga_enable_reg(nodeid, link->link_num);
 }
 
 static void amdfam10_set_resources(device_t dev)
 {
-	u32 nodeid, link;
+	unsigned nodeid;
+	struct bus *bus;
 	struct resource *res;
 
 	/* Find the nodeid */
@@ -594,9 +597,7 @@
 		amdfam10_set_resource(dev, res, nodeid);
 	}
 
-	for(link = 0; link < dev->links; link++) {
-		struct bus *bus;
-		bus = &dev->link[link];
+	for(bus = dev->link_list; bus; bus = bus->next) {
 		if (bus->children) {
 			assign_resources(bus);
 		}
@@ -672,22 +673,22 @@
 #if CONFIG_PCI_64BIT_PREF_MEM == 0
 	pci_domain_read_resources(dev);
 #else
-	unsigned link;
+	struct bus *link;
 	struct resource *resource;
-	for(link=0; link<dev->links; link++) {
+	for(link=dev->link_list; link; link = link->next) {
 		/* Initialize the system wide io space constraints */
-		resource = new_resource(dev, 0|(link<<2));
+		resource = new_resource(dev, 0|(link->link_num<<2));
 		resource->base	= 0x400;
 		resource->limit = 0xffffUL;
 		resource->flags = IORESOURCE_IO;
 
 		/* Initialize the system wide prefetchable memory resources constraints */
-		resource = new_resource(dev, 1|(link<<2));
+		resource = new_resource(dev, 1|(link->link_num<<2));
 		resource->limit = 0xfcffffffffULL;
 		resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
 
 		/* Initialize the system wide memory resources constraints */
-		resource = new_resource(dev, 2|(link<<2));
+		resource = new_resource(dev, 2|(link->link_num<<2));
 		resource->limit = 0xfcffffffffULL;
 		resource->flags = IORESOURCE_MEM;
 	}
@@ -881,7 +882,7 @@
 	unsigned long mmio_basek;
 	u32 pci_tolm;
 	int i, idx;
-	u32 link;
+	struct bus *link;
 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
 	struct hw_mem_hole_info mem_hole;
 	u32 reset_memhole = 1;
@@ -889,12 +890,12 @@
 
 #if CONFIG_PCI_64BIT_PREF_MEM == 1
 
-	for(link = 0; link < dev->links; link++) {
+	for(link = dev->link_list; link; link = link->next) {
 		/* Now reallocate the pci resources memory with the
 		 * highest addresses I can manage.
 		 */
-		mem1 = find_resource(dev, 1|(link<<2));
-		mem2 = find_resource(dev, 2|(link<<2));
+		mem1 = find_resource(dev, 1|(link->link_num<<2));
+		mem2 = find_resource(dev, 2|(link->link_num<<2));
 
 		printk(BIOS_DEBUG, "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
 			mem1->base, mem1->limit, mem1->size, mem1->align);
@@ -939,8 +940,8 @@
 #endif
 
 	pci_tolm = 0xffffffffUL;
-	for(link = 0; link<dev->links; link++) {
-		pci_tolm = find_pci_tolm(&dev->link[link], pci_tolm);
+	for(link = dev->link_list; link; link = link->next) {
+		pci_tolm = find_pci_tolm(link, pci_tolm);
 	}
 
 	// FIXME handle interleaved nodes. If you fix this here, please fix
@@ -1084,11 +1085,9 @@
 #endif
 	}
 
-	for(link = 0; link < dev->links; link++) {
-		struct bus *bus;
-		bus = &dev->link[link];
-		if (bus->children) {
-			assign_resources(bus);
+	for(link = dev->link_list; link; link = link->next) {
+		if (link->children) {
+			assign_resources(link);
 		}
 	}
 }
@@ -1097,6 +1096,7 @@
 {
 	u32 reg;
 	int i;
+	struct bus *link;
 	/* Unmap all of the HT chains */
 	for(reg = 0xe0; reg <= 0xec; reg += 4) {
 		f1_write_config32(reg, 0);
@@ -1114,8 +1114,8 @@
 #endif
 
 
-	for(i = 0; i < dev->links; i++) {
-		max = pci_scan_bus(&dev->link[i], PCI_DEVFN(CONFIG_CDB, 0), 0xff, max);
+	for(link = dev->link_list; link; link = link->next) {
+		max = pci_scan_bus(link, PCI_DEVFN(CONFIG_CDB, 0), 0xff, max);
 	}
 
 	/* Tune the hypertransport transaction for best performance.
@@ -1129,12 +1129,12 @@
 			u32 httc;
 			httc = pci_read_config32(f0_dev, HT_TRANSACTION_CONTROL);
 			httc &= ~HTTC_RSP_PASS_PW;
-			if (!dev->link[0].disable_relaxed_ordering) {
+			if (!dev->link_list->disable_relaxed_ordering) {
 				httc |= HTTC_RSP_PASS_PW;
 			}
 			printk(BIOS_SPEW, "%s passpw: %s\n",
 				dev_path(dev),
-				(!dev->link[0].disable_relaxed_ordering)?
+				(!dev->link_list->disable_relaxed_ordering)?
 				"enabled":"disabled");
 			pci_write_config32(f0_dev, HT_TRANSACTION_CONTROL, httc);
 		}
@@ -1197,6 +1197,42 @@
 #endif
 }
 
+static void add_more_links(device_t dev, unsigned total_links)
+{
+	struct bus *link, *last = NULL;
+	int link_num;
+
+	for (link = dev->link_list; link; link = link->next)
+		last = link;
+
+	if (last) {
+		int links = total_links - last->link_num;
+		link_num = last->link_num;
+		if (links > 0) {
+			link = malloc(links*sizeof(*link));
+			if (!link)
+				die("Couldn't allocate more links!\n");
+			memset(link, 0, links*sizeof(*link));
+			last->next = link;
+		}
+	}
+	else {
+		link_num = -1;
+		link = malloc(total_links*sizeof(*link));
+		memset(link, 0, total_links*sizeof(*link));
+		dev->link_list = link;
+	}
+
+	for (link_num = link_num + 1; link_num < total_links; link_num++) {
+		link->link_num = link_num;
+		link->dev = dev;
+		link->next = link + 1;
+		last = link;
+		link = link->next;
+	}
+	last->next = NULL;
+}
+
 static u32 cpu_bus_scan(device_t dev, u32 max)
 {
 	struct bus *cpu_bus;
@@ -1250,7 +1286,7 @@
 			printk(BIOS_DEBUG, "%s found\n", dev_path(dev_mc));
 			pci_domain = dev_mc->bus->dev;
 			if(pci_domain && (pci_domain->path.type == DEVICE_PATH_PCI_DOMAIN)) {
-				if((pci_domain->links==1) && (pci_domain->link[0].children == dev_mc)) {
+				if((pci_domain->link_list) && (pci_domain->link_list->children == dev_mc)) {
 					printk(BIOS_DEBUG, "%s move to ",dev_path(dev_mc));
 					dev_mc->bus->secondary = CONFIG_CBB; // move to 0xff
 					printk(BIOS_DEBUG, "%s\n",dev_path(dev_mc));
@@ -1279,18 +1315,19 @@
 
 #if CONFIG_CBB && (NODE_NUMS > 32)
 	if(nodes>32) { // need to put node 32 to node 63 to bus 0xfe
-		if(pci_domain->links==1) {
-			pci_domain->links++; // from 1 to 2
-			pci_domain->link[1].link = 1;
-			pci_domain->link[1].dev = pci_domain;
-			pci_domain->link[1].children = 0;
-			printk(BIOS_DEBUG, "%s links increase to %d\n", dev_path(pci_domain), pci_domain->links);
+		if(pci_domain->link_list && !pci_domain->link_list->next) {
+			struct bus *new_link = new_link(pci_domain);
+			pci_domain->link_list->next = new_link;
+			new_link->link_num = 1;
+			new_link->dev = pci_domain;
+			new_link->children = 0;
+			printk(BIOS_DEBUG, "%s links now 2\n", dev_path(pci_domain));
 		}
-		pci_domain->link[1].secondary = CONFIG_CBB - 1;
+		pci_domain->link_list->next->secondary = CONFIG_CBB - 1;
 	}
 #endif
 	/* Find which cpus are present */
-	cpu_bus = &dev->link[0];
+	cpu_bus = dev->link_list;
 	for(i = 0; i < nodes; i++) {
 		device_t cdb_dev, cpu;
 		struct device_path cpu_path;
@@ -1304,7 +1341,7 @@
 		if(i>=32) {
 			busn--;
 			devn-=32;
-			pbus = &(pci_domain->link[1]);
+			pbus = pci_domain->link_list->next);
 		}
 #endif
 
@@ -1325,21 +1362,13 @@
 			/* Ok, We need to set the links for that device.
 			 * otherwise the device under it will not be scanned
 			 */
-			int link;
 			int linknum;
 #if CONFIG_HT3_SUPPORT==1
 			linknum = 8;
 #else
 			linknum = 4;
 #endif
-			if (cdb_dev->links < linknum) {
-				for(link=cdb_dev->links; link<linknum; link++) {
-					 cdb_dev->link[link].link = link;
-					 cdb_dev->link[link].dev = cdb_dev;
-				}
-				cdb_dev->links = linknum;
-				printk(BIOS_DEBUG, "%s links increase to %d\n", dev_path(cdb_dev), cdb_dev->links);
-			}
+			add_more_links(cdb_dev, linknum);
 		}
 
 		cores_found = 0; // one core
@@ -1410,7 +1439,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/amd/amdk8/northbridge.c b/src/northbridge/amd/amdk8/northbridge.c
index b798b0b..227a02e 100644
--- a/src/northbridge/amd/amdk8/northbridge.c
+++ b/src/northbridge/amd/amdk8/northbridge.c
@@ -81,7 +81,7 @@
 	return (dev->path.pci.devfn >> 3) - 0x18;
 }
 
-static u32 amdk8_scan_chain(device_t dev, u32 nodeid, u32 link, u32 sblink,
+static u32 amdk8_scan_chain(device_t dev, u32 nodeid, struct bus *link, u32 link_num, u32 sblink,
 				u32 max, u32 offset_unitid)
 {
 
@@ -94,15 +94,15 @@
 		u32 min_bus;
 		u32 max_devfn;
 
-		dev->link[link].cap = 0x80 + (link *0x20);
+		link->cap = 0x80 + (link_num *0x20);
 		do {
-			link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
+			link_type = pci_read_config32(dev, link->cap + 0x18);
 		} while(link_type & ConnectionPending);
 		if (!(link_type & LinkConnected)) {
 			return max;
 		}
 		do {
-			link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
+			link_type = pci_read_config32(dev, link->cap + 0x18);
 		} while(!(link_type & InitComplete));
 		if (!(link_type & NonCoherent)) {
 			return max;
@@ -120,7 +120,7 @@
 			}
 			if (((config & 3) == 3) &&
 				(((config >> 4) & 7) == nodeid) &&
-				(((config >> 8) & 3) == link)) {
+				(((config >> 8) & 3) == link_num)) {
 				break;
 			}
 		}
@@ -140,7 +140,7 @@
 		 */
 #if CONFIG_SB_HT_CHAIN_ON_BUS0 > 0
 		// first chain will on bus 0
-		if((nodeid == 0) && (sblink==link)) { // actually max is 0 here
+		if((nodeid == 0) && (sblink==link_num)) { // actually max is 0 here
 			min_bus = max;
 		}
 	#if CONFIG_SB_HT_CHAIN_ON_BUS0 > 1
@@ -160,13 +160,13 @@
 #endif
 		max_bus = 0xff;
 
-		dev->link[link].secondary = min_bus;
-		dev->link[link].subordinate = max_bus;
+		link->secondary = min_bus;
+		link->subordinate = max_bus;
 
 		/* Read the existing primary/secondary/subordinate bus
 		 * number configuration.
 		 */
-		busses = pci_read_config32(dev, dev->link[link].cap + 0x14);
+		busses = pci_read_config32(dev, link->cap + 0x14);
 		config_busses = f1_read_config32(config_reg);
 
 		/* Configure the bus numbers for this bridge: the configuration
@@ -175,17 +175,17 @@
 		 */
 		busses &= 0xff000000;
 		busses |= (((unsigned int)(dev->bus->secondary) << 0) |
-			((unsigned int)(dev->link[link].secondary) << 8) |
-			((unsigned int)(dev->link[link].subordinate) << 16));
-		pci_write_config32(dev, dev->link[link].cap + 0x14, busses);
+			((unsigned int)(link->secondary) << 8) |
+			((unsigned int)(link->subordinate) << 16));
+		pci_write_config32(dev, link->cap + 0x14, busses);
 
 		config_busses &= 0x000fc88;
 		config_busses |=
 			(3 << 0) |  /* rw enable, no device compare */
 			(( nodeid & 7) << 4) |
-			(( link & 3 ) << 8) |
-			((dev->link[link].secondary) << 16) |
-			((dev->link[link].subordinate) << 24);
+			(( link_num & 3 ) << 8) |
+			((link->secondary) << 16) |
+			((link->subordinate) << 24);
 		f1_write_config32(config_reg, config_busses);
 
 		/* Now we can scan all of the subordinate busses i.e. the
@@ -200,18 +200,18 @@
 		else
 			max_devfn = (0x1f<<3) | 7;
 
-		max = hypertransport_scan_chain(&dev->link[link], 0, max_devfn, max, ht_unitid_base, offset_unitid);
+		max = hypertransport_scan_chain(link, 0, max_devfn, max, ht_unitid_base, offset_unitid);
 
 		/* We know the number of busses behind this bridge.  Set the
 		 * subordinate bus number to it's real value
 		 */
-		dev->link[link].subordinate = max;
+		link->subordinate = max;
 		busses = (busses & 0xff00ffff) |
-			((unsigned int) (dev->link[link].subordinate) << 16);
-		pci_write_config32(dev, dev->link[link].cap + 0x14, busses);
+			((unsigned int) (link->subordinate) << 16);
+		pci_write_config32(dev, link->cap + 0x14, busses);
 
 		config_busses = (config_busses & 0x00ffffff) |
-			(dev->link[link].subordinate << 24);
+			(link->subordinate << 24);
 		f1_write_config32(config_reg, config_busses);
 
 		{
@@ -232,7 +232,7 @@
 static unsigned amdk8_scan_chains(device_t dev, unsigned max)
 {
 	unsigned nodeid;
-	unsigned link;
+	struct bus *link;
 	unsigned sblink = 0;
 	unsigned offset_unitid = 0;
 
@@ -244,23 +244,25 @@
 	#if ((CONFIG_HT_CHAIN_UNITID_BASE != 1) || (CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20))
 		offset_unitid = 1;
 	#endif
-		max = amdk8_scan_chain(dev, nodeid, sblink, sblink, max, offset_unitid ); // do sb ht chain at first, in case s2885 put sb chain (8131/8111) on link2, but put 8151 on link0
+		for (link = dev->link_list; link; link = link->next)
+			if (link->link_num == sblink)
+				max = amdk8_scan_chain(dev, nodeid, link, sblink, sblink, max, offset_unitid ); // do sb ht chain at first, in case s2885 put sb chain (8131/8111) on link2, but put 8151 on link0
 #endif
 	}
 
-	for (link = 0; link < dev->links; link++) {
+	for (link = dev->link_list; link; link = link->next) {
 #if CONFIG_SB_HT_CHAIN_ON_BUS0 > 0
-		if( (nodeid == 0) && (sblink == link) ) continue; //already done
+		if( (nodeid == 0) && (sblink == link->link_num) ) continue; //already done
 #endif
 		offset_unitid = 0;
 		#if ((CONFIG_HT_CHAIN_UNITID_BASE != 1) || (CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20))
 			#if CONFIG_SB_HT_CHAIN_UNITID_OFFSET_ONLY == 1
-			if((nodeid == 0) && (sblink == link))
+			if((nodeid == 0) && (sblink == link->link_num))
 			#endif
 				offset_unitid = 1;
 		#endif
 
-		max = amdk8_scan_chain(dev, nodeid, link, sblink, max, offset_unitid);
+		max = amdk8_scan_chain(dev, nodeid, link, link->link_num, sblink, max, offset_unitid);
 	}
 	return max;
 }
@@ -375,21 +377,22 @@
 
 static void amdk8_read_resources(device_t dev)
 {
-	unsigned nodeid, link;
+	unsigned nodeid;
+	struct bus *link;
 	nodeid = amdk8_nodeid(dev);
-	for(link = 0; link < dev->links; link++) {
-		if (dev->link[link].children) {
-			amdk8_link_read_bases(dev, nodeid, link);
+	for(link = dev->link_list; link; link = link->next) {
+		if (link->children) {
+			amdk8_link_read_bases(dev, nodeid, link->link_num);
 		}
 	}
-
 	amdk8_create_vga_resource(dev, nodeid);
 }
 
 static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned nodeid)
 {
+	struct bus *link;
 	resource_t rbase, rend;
-	unsigned reg, link;
+	unsigned reg, link_num;
 	char buf[50];
 
 	/* Make certain the resource has actually been set */
@@ -426,7 +429,17 @@
 
 	/* Get the register and link */
 	reg  = resource->index & 0xfc;
-	link = IOINDEX_LINK(resource->index);
+	link_num = IOINDEX_LINK(resource->index);
+
+	for (link = dev->link_list; link; link = link->next)
+		if (link->link_num == link_num)
+			break;
+
+	if (link == NULL) {
+		printk(BIOS_ERR, "%s: can't find link %x for %lx\n", __func__,
+			   link_num, resource->index);
+		return;
+	}
 
 	if (resource->flags & IORESOURCE_IO) {
 		u32 base, limit;
@@ -437,15 +450,15 @@
 		base  |= 3;
 		limit &= 0xfe000fc8;
 		limit |= rend & 0x01fff000;
-		limit |= (link & 3) << 4;
+		limit |= (link_num & 3) << 4;
 		limit |= (nodeid & 7);
 
-		if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
+		if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
 			printk(BIOS_SPEW, "%s, enabling legacy VGA IO forwarding for %s link 0x%x\n",
-				    __func__, dev_path(dev), link);
+				    __func__, dev_path(dev), link_num);
 			base |= PCI_IO_BASE_VGA_EN;
 		}
-		if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) {
+		if (link->bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) {
 			base |= PCI_IO_BASE_NO_ISA;
 		}
 
@@ -461,14 +474,14 @@
 		base  |= 3;
 		limit &= 0x00000048;
 		limit |= (rend >> 8) & 0xffffff00;
-		limit |= (link & 3) << 4;
+		limit |= (link_num & 3) << 4;
 		limit |= (nodeid & 7);
 		f1_write_config32(reg + 0x4, limit);
 		f1_write_config32(reg, base);
 	}
 	resource->flags |= IORESOURCE_STORED;
 	sprintf(buf, " <node %x link %x>",
-		nodeid, link);
+		nodeid, link_num);
 	report_resource_stored(dev, resource, buf);
 }
 
@@ -479,18 +492,18 @@
 static void amdk8_create_vga_resource(device_t dev, unsigned nodeid)
 {
 	struct resource *resource;
-	unsigned link;
+	struct bus *link;
 
 	/* find out which link the VGA card is connected,
 	 * we only deal with the 'first' vga card */
-	for (link = 0; link < dev->links; link++) {
-		if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
+	for (link = dev->link_list; link; link = link->next) {
+		if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
 #if CONFIG_CONSOLE_VGA_MULTI == 1
-			printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d dev->link[link] bus range [%d,%d]\n", vga_pri->bus->secondary,
-				dev->link[link].secondary,dev->link[link].subordinate);
+			printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d link bus range [%d,%d]\n", vga_pri->bus->secondary,
+				link->secondary,link->subordinate);
 			/* We need to make sure the vga_pri is under the link */
-			if((vga_pri->bus->secondary >= dev->link[link].secondary ) &&
-				(vga_pri->bus->secondary <= dev->link[link].subordinate )
+			if((vga_pri->bus->secondary >= link->secondary ) &&
+				(vga_pri->bus->secondary <= link->subordinate )
 			)
 #endif
 			break;
@@ -498,13 +511,13 @@
 	}
 
 	/* no VGA card installed */
-	if (link == dev->links)
+	if (link == NULL)
 		return;
 
-	printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, link);
+	printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, link->link_num);
 
 	/* allocate a temp resource for the legacy VGA buffer */
-	resource = new_resource(dev, IOINDEX(4, link));
+	resource = new_resource(dev, IOINDEX(4, link->link_num));
 	if(!resource){
 		printk(BIOS_DEBUG, "VGA: %s out of resources.\n", dev_path(dev));
 		return;
@@ -518,7 +531,8 @@
 
 static void amdk8_set_resources(device_t dev)
 {
-	unsigned nodeid, link;
+	unsigned nodeid;
+	struct bus *bus;
 	struct resource *res;
 
 	/* Find the nodeid */
@@ -553,9 +567,7 @@
 
 	compact_resources(dev);
 
-	for(link = 0; link < dev->links; link++) {
-		struct bus *bus;
-		bus = &dev->link[link];
+	for(bus = dev->link_list; bus; bus = bus->next) {
 		if (bus->children) {
 			assign_resources(bus);
 		}
@@ -909,7 +921,7 @@
 	}
 #endif
 
-	pci_tolm = find_pci_tolm(&dev->link[0]);
+	pci_tolm = find_pci_tolm(dev->link_list);
 
 	// FIXME handle interleaved nodes. If you fix this here, please fix
 	// amdfam10, too.
@@ -1066,7 +1078,7 @@
 		}
 #endif
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 
 }
 
@@ -1078,7 +1090,7 @@
 	for(reg = 0xe0; reg <= 0xec; reg += 4) {
 		f1_write_config32(reg, 0);
 	}
-	max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0x18, 0), 0xff, max);
+	max = pci_scan_bus(dev->link_list, PCI_DEVFN(0x18, 0), 0xff, max);
 
 	/* Tune the hypertransport transaction for best performance.
 	 * Including enabling relaxed ordering if it is safe.
@@ -1091,12 +1103,12 @@
 			u32 httc;
 			httc = pci_read_config32(f0_dev, HT_TRANSACTION_CONTROL);
 			httc &= ~HTTC_RSP_PASS_PW;
-			if (!dev->link[0].disable_relaxed_ordering) {
+			if (!dev->link_list->disable_relaxed_ordering) {
 				httc |= HTTC_RSP_PASS_PW;
 			}
 			printk(BIOS_SPEW, "%s passpw: %s\n",
 				dev_path(dev),
-				(!dev->link[0].disable_relaxed_ordering)?
+				(!dev->link_list->disable_relaxed_ordering)?
 				"enabled":"disabled");
 			pci_write_config32(f0_dev, HT_TRANSACTION_CONTROL, httc);
 		}
@@ -1113,6 +1125,42 @@
 	.ops_pci_bus	  = &pci_cf8_conf1,
 };
 
+static void add_more_links(device_t dev, unsigned total_links)
+{
+	struct bus *link, *last = NULL;
+	int link_num;
+
+	for (link = dev->link_list; link; link = link->next)
+		last = link;
+
+	if (last) {
+		int links = total_links - last->link_num;
+		link_num = last->link_num;
+		if (links > 0) {
+			link = malloc(links*sizeof(*link));
+			if (!link)
+				die("Couldn't allocate more links!\n");
+			memset(link, 0, links*sizeof(*link));
+			last->next = link;
+		}
+	}
+	else {
+		link_num = -1;
+		link = malloc(total_links*sizeof(*link));
+		memset(link, 0, total_links*sizeof(*link));
+		dev->link_list = link;
+	}
+
+	for (link_num = link_num + 1; link_num < total_links; link_num++) {
+		link->link_num = link_num;
+		link->dev = dev;
+		link->next = link + 1;
+		last = link;
+		link = link->next;
+	}
+	last->next = NULL;
+}
+
 static u32 cpu_bus_scan(device_t dev, u32 max)
 {
 	struct bus *cpu_bus;
@@ -1165,7 +1213,7 @@
 	}
 
 	/* Find which cpus are present */
-	cpu_bus = &dev->link[0];
+	cpu_bus = dev->link_list;
 	for(i = 0; i < sysconf.nodes; i++) {
 		device_t cpu_dev, cpu;
 		struct device_path cpu_path;
@@ -1187,11 +1235,7 @@
 			 */
 			dev_f0 = dev_find_slot(0, PCI_DEVFN(0x18+i,0));
 			if(dev_f0) {
-				dev_f0->links = 3;
-				for(local_j=0;local_j<3;local_j++) {
-					dev_f0->link[local_j].link = local_j;
-					dev_f0->link[local_j].dev = dev_f0;
-				}
+				add_more_links(dev_f0, 3);
 			}
 		}
 
@@ -1290,7 +1334,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/amd/gx1/northbridge.c b/src/northbridge/amd/gx1/northbridge.c
index 1176744..8b60345 100644
--- a/src/northbridge/amd/gx1/northbridge.c
+++ b/src/northbridge/amd/gx1/northbridge.c
@@ -115,8 +115,8 @@
 	device_t mc_dev;
         uint32_t pci_tolm;
 
-        pci_tolm = find_pci_tolm(&dev->link[0]);
-	mc_dev = dev->link[0].children;
+        pci_tolm = find_pci_tolm(dev->link_list);
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		unsigned int tomk, tolmk;
 		unsigned int ramreg = 0;
@@ -163,7 +163,7 @@
 		idx = 10;
 		ram_resource(dev, idx++, 0, tolmk);
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -177,7 +177,7 @@
 static void cpu_bus_init(device_t dev)
 {
 	printk(BIOS_SPEW, "%s:%s()\n", NORTHBRIDGE_FILE, __func__);
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/amd/gx2/northbridge.c b/src/northbridge/amd/gx2/northbridge.c
index bb41fd0..4846ac3 100644
--- a/src/northbridge/amd/gx2/northbridge.c
+++ b/src/northbridge/amd/gx2/northbridge.c
@@ -303,11 +303,9 @@
                 pci_set_resource(dev, resource);
         }
 #endif
-        unsigned link;
+	struct bus *bus;
 
-        for(link = 0; link < dev->links; link++) {
-                struct bus *bus;
-                bus = &dev->link[link];
+	for(bus = dev->link_list; bus; bus = bus->next) {
                 if (bus->children) {
                         assign_resources(bus);
                 }
@@ -402,8 +400,8 @@
 	device_t mc_dev;
         u32 pci_tolm;
 
-        pci_tolm = find_pci_tolm(&dev->link[0]);
-	mc_dev = dev->link[0].children;
+        pci_tolm = find_pci_tolm(dev->link_list);
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		unsigned int tomk, tolmk;
 		unsigned int ramreg = 0;
@@ -444,7 +442,7 @@
 		ram_resource(dev, idx++, 0, tolmk);
 	}
 #endif
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -457,7 +455,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-        initialize_cpus(&dev->link[0]);
+        initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/amd/lx/northbridge.c b/src/northbridge/amd/lx/northbridge.c
index 8fd8d9e..5202de2 100644
--- a/src/northbridge/amd/lx/northbridge.c
+++ b/src/northbridge/amd/lx/northbridge.c
@@ -318,7 +318,6 @@
 
 static void northbridge_set_resources(struct device *dev)
 {
-	unsigned link;
 	uint8_t line;
 
 #if 0
@@ -331,9 +330,8 @@
 	}
 #endif
 
-	for (link = 0; link < dev->links; link++) {
-		struct bus *bus;
-		bus = &dev->link[link];
+	struct bus *bus;
+	for (bus = dev->link_list; bus; bus = bus->next) {
 		if (bus->children) {
 			printk(BIOS_DEBUG, "my_dev_set_resources: assign_resources %d\n",
 			     bus->secondary);
@@ -402,7 +400,7 @@
 
 	printk(BIOS_SPEW, ">> Entering northbridge.c: %s\n", __func__);
 
-	mc_dev = dev->link[0].children;
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		tomk = get_systop() / 1024;
 		/* Report the memory regions
@@ -418,7 +416,7 @@
 #endif
 	}
 
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static void pci_domain_enable(device_t dev)
@@ -452,7 +450,7 @@
 {
 	printk(BIOS_SPEW, ">> Entering northbridge.c: %s\n", __func__);
 
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/intel/e7501/northbridge.c b/src/northbridge/intel/e7501/northbridge.c
index a2e4b245..5db56dc 100644
--- a/src/northbridge/intel/e7501/northbridge.c
+++ b/src/northbridge/intel/e7501/northbridge.c
@@ -58,8 +58,8 @@
 	device_t mc_dev;
         uint32_t pci_tolm;
 
-        pci_tolm = find_pci_tolm(&dev->link[0]);
-	mc_dev = dev->link[0].children;
+        pci_tolm = find_pci_tolm(dev->link_list);
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		/* Figure out which areas are/should be occupied by RAM.
 		 * This is all computed in kilobytes and converted to/from
@@ -135,7 +135,7 @@
 		high_tables_size = HIGH_TABLES_SIZE * 1024;
 #endif
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -149,7 +149,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-        initialize_cpus(&dev->link[0]);
+        initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/intel/e7520/northbridge.c b/src/northbridge/intel/e7520/northbridge.c
index 02f7c45..c0580bb 100644
--- a/src/northbridge/intel/e7520/northbridge.c
+++ b/src/northbridge/intel/e7520/northbridge.c
@@ -62,7 +62,7 @@
 	device_t mc_dev;
 	uint32_t pci_tolm;
 
-        pci_tolm = find_pci_tolm(&dev->link[0]);
+        pci_tolm = find_pci_tolm(dev->link_list);
 
 #if 1
 	printk(BIOS_DEBUG, "PCI mem marker = %x\n", pci_tolm);
@@ -72,7 +72,7 @@
 		pci_tolm = 0xe0000000;
 	/* Ensure pci_tolm is 128M aligned */
 	pci_tolm &= 0xf8000000;
-	mc_dev = dev->link[0].children;
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		/* Figure out which areas are/should be occupied by RAM.
 		 * This is all computed in kilobytes and converted to/from
@@ -151,7 +151,7 @@
 		high_tables_size = HIGH_TABLES_SIZE * 1024;
 #endif
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static u32 e7520_domain_scan_bus(device_t dev, u32 max)
@@ -219,7 +219,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-        initialize_cpus(&dev->link[0]);
+        initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/intel/e7525/northbridge.c b/src/northbridge/intel/e7525/northbridge.c
index a227f22..2af6c25 100644
--- a/src/northbridge/intel/e7525/northbridge.c
+++ b/src/northbridge/intel/e7525/northbridge.c
@@ -62,7 +62,7 @@
 	device_t mc_dev;
 	uint32_t pci_tolm;
 
-        pci_tolm = find_pci_tolm(&dev->link[0]);
+        pci_tolm = find_pci_tolm(dev->link_list);
 
 #if 1
 	printk(BIOS_DEBUG, "PCI mem marker = %x\n", pci_tolm);
@@ -72,7 +72,7 @@
 		pci_tolm = 0xe0000000;
 	/* Ensure pci_tolm is 128M aligned */
 	pci_tolm &= 0xf8000000;
-	mc_dev = dev->link[0].children;
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		/* Figure out which areas are/should be occupied by RAM.
 		 * This is all computed in kilobytes and converted to/from
@@ -151,7 +151,7 @@
 		high_tables_size = HIGH_TABLES_SIZE * 1024;
 #endif
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static u32 e7525_domain_scan_bus(device_t dev, u32 max)
@@ -219,7 +219,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-        initialize_cpus(&dev->link[0]);
+        initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/intel/i3100/northbridge.c b/src/northbridge/intel/i3100/northbridge.c
index 0675aea..482e600 100644
--- a/src/northbridge/intel/i3100/northbridge.c
+++ b/src/northbridge/intel/i3100/northbridge.c
@@ -83,7 +83,7 @@
 	device_t mc_dev;
 	u32 pci_tolm;
 
-        pci_tolm = find_pci_tolm(&dev->link[0]);
+        pci_tolm = find_pci_tolm(dev->link_list);
 
 #if 1
 	printk(BIOS_DEBUG, "PCI mem marker = %x\n", pci_tolm);
@@ -93,7 +93,7 @@
 		pci_tolm = 0xe0000000;
 	/* Ensure pci_tolm is 128M aligned */
 	pci_tolm &= 0xf8000000;
-	mc_dev = dev->link[0].children;
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		/* Figure out which areas are/should be occupied by RAM.
 		 * This is all computed in kilobytes and converted to/from
@@ -172,7 +172,7 @@
 		high_tables_size = HIGH_TABLES_SIZE * 1024;
 #endif
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static u32 i3100_domain_scan_bus(device_t dev, u32 max)
@@ -240,7 +240,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-        initialize_cpus(&dev->link[0]);
+        initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/intel/i3100/pciexp_porta_ep80579.c b/src/northbridge/intel/i3100/pciexp_porta_ep80579.c
index 42f624a..a17cb0b 100644
--- a/src/northbridge/intel/i3100/pciexp_porta_ep80579.c
+++ b/src/northbridge/intel/i3100/pciexp_porta_ep80579.c
@@ -56,7 +56,7 @@
 
 static void pcie_bus_enable_resources(struct device *dev)
 {
-	if (dev->link[0].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
+	if (dev->link_list->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
 		printk(BIOS_SPEW, "Enable VGA IO/MEM forwarding on PCIe port\n");
 		pci_write_config8(dev, PCI_BRIDGE_CONTROL, 8);
 
diff --git a/src/northbridge/intel/i440bx/northbridge.c b/src/northbridge/intel/i440bx/northbridge.c
index 772ab1c..c5f0934 100644
--- a/src/northbridge/intel/i440bx/northbridge.c
+++ b/src/northbridge/intel/i440bx/northbridge.c
@@ -82,8 +82,8 @@
 	device_t mc_dev;
 	uint32_t pci_tolm;
 
-	pci_tolm = find_pci_tolm(&dev->link[0]);
-	mc_dev = dev->link[0].children;
+	pci_tolm = find_pci_tolm(dev->link_list);
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		unsigned long tomk, tolmk;
 		int idx;
@@ -118,7 +118,7 @@
 		high_tables_size = HIGH_TABLES_SIZE * 1024;
 #endif
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -131,7 +131,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/intel/i440lx/northbridge.c b/src/northbridge/intel/i440lx/northbridge.c
index 7ebc002..7c41e59 100644
--- a/src/northbridge/intel/i440lx/northbridge.c
+++ b/src/northbridge/intel/i440lx/northbridge.c
@@ -110,8 +110,8 @@
 	device_t mc_dev;
 	uint32_t pci_tolm;
 
-	pci_tolm = find_pci_tolm(&dev->link[0]);
-	mc_dev = dev->link[0].children;
+	pci_tolm = find_pci_tolm(dev->link_list);
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		unsigned long tomk, tolmk;
 		int idx;
@@ -146,7 +146,7 @@
 		high_tables_size = HIGH_TABLES_SIZE * 1024;
 #endif
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -159,7 +159,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/intel/i82810/northbridge.c b/src/northbridge/intel/i82810/northbridge.c
index 5b68046..612d6c0 100644
--- a/src/northbridge/intel/i82810/northbridge.c
+++ b/src/northbridge/intel/i82810/northbridge.c
@@ -119,8 +119,8 @@
 	device_t mc_dev;
 	uint32_t pci_tolm;
 
-	pci_tolm = find_pci_tolm(&dev->link[0]);
-	mc_dev = dev->link[0].children;
+	pci_tolm = find_pci_tolm(dev->link_list);
+	mc_dev = dev->link_list->children;
 
 	if (mc_dev) {
 		/* Figure out which areas are/should be occupied by RAM.
@@ -178,7 +178,7 @@
 		high_tables_size = HIGH_TABLES_SIZE * 1024;
 #endif
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -191,7 +191,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/intel/i82830/northbridge.c b/src/northbridge/intel/i82830/northbridge.c
index eb21b7cb..a1a3893 100644
--- a/src/northbridge/intel/i82830/northbridge.c
+++ b/src/northbridge/intel/i82830/northbridge.c
@@ -111,8 +111,8 @@
 	uint32_t pci_tolm;
 	int igd_memory = 0;
 
-	pci_tolm = find_pci_tolm(&dev->link[0]);
-	mc_dev = dev->link[0].children;
+	pci_tolm = find_pci_tolm(dev->link_list);
+	mc_dev = dev->link_list->children;
 	if (!mc_dev)
 		return;
 
@@ -152,7 +152,7 @@
 	ram_resource(dev, idx++, 768, 256);
 	ram_resource(dev, idx++, 1024, tolmk - 1024);
 
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 
 #if CONFIG_WRITE_HIGH_TABLES==1
 	/* Leave some space for ACPI, PIRQ and MP tables */
@@ -171,7 +171,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/intel/i855/northbridge.c b/src/northbridge/intel/i855/northbridge.c
index 3495fb6..0438d09 100644
--- a/src/northbridge/intel/i855/northbridge.c
+++ b/src/northbridge/intel/i855/northbridge.c
@@ -83,8 +83,8 @@
         printk(BIOS_DEBUG, "Entered with dev vid = %x\n", dev->vendor);
 	printk(BIOS_DEBUG, "Entered with dev did = %x\n", dev->device);
 
-        pci_tolm = find_pci_tolm(&dev->link[0]);
-	mc_dev = dev->link[0].children->sibling;
+        pci_tolm = find_pci_tolm(dev->link_list);
+	mc_dev = dev->link_list->children->sibling;
 	printk(BIOS_DEBUG, "MC dev vendor = %x\n", mc_dev->vendor);
 	printk(BIOS_DEBUG, "MC dev device = %x\n", mc_dev->device);
 
@@ -134,7 +134,7 @@
 		high_tables_size = HIGH_TABLES_SIZE * 1024;
 #endif
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -147,7 +147,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-        initialize_cpus(&dev->link[0]);
+        initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/intel/i945/northbridge.c b/src/northbridge/intel/i945/northbridge.c
index 0812460..81b61bd 100644
--- a/src/northbridge/intel/i945/northbridge.c
+++ b/src/northbridge/intel/i945/northbridge.c
@@ -138,7 +138,7 @@
 	/* Can we find out how much memory we can use at most
 	 * this way?
 	 */
-	pci_tolm = find_pci_tolm(&dev->link[0]);
+	pci_tolm = find_pci_tolm(dev->link_list);
 	printk(BIOS_DEBUG, "pci_tolm: 0x%x\n", pci_tolm);
 
 	printk(BIOS_SPEW, "Base of stolen memory: 0x%08x\n",
@@ -208,7 +208,7 @@
 		ram_resource(dev, 5, 4096 * 1024, tomk - 4 * 1024 * 1024);
 	}
 
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 
 #if CONFIG_WRITE_HIGH_TABLES==1
 	/* Leave some space for ACPI, PIRQ and MP tables */
@@ -326,7 +326,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/via/cn400/northbridge.c b/src/northbridge/via/cn400/northbridge.c
index 3fbc358..2974d23 100644
--- a/src/northbridge/via/cn400/northbridge.c
+++ b/src/northbridge/via/cn400/northbridge.c
@@ -233,7 +233,7 @@
 
 	printk(BIOS_SPEW, "Entering %s.\n", __func__);
 
-	pci_tolm = find_pci_tolm(&dev->link[0]);
+	pci_tolm = find_pci_tolm(dev->link_list);
 	mc_dev = dev_find_device(PCI_VENDOR_ID_VIA,
 				 PCI_DEVICE_ID_VIA_CN400_MEMCTRL, 0);
 
@@ -267,7 +267,7 @@
 		ram_resource(dev, idx++, 768,
 			     (tolmk - 768 - CONFIG_VIDEO_MB * 1024));
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 
 	printk(BIOS_SPEW, "Leaving %s.\n", __func__);
 }
@@ -276,7 +276,7 @@
 {
 	printk(BIOS_DEBUG, "Entering %s.\n", __func__);
 
-	max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
+	max = pci_scan_bus(dev->link_list, PCI_DEVFN(0, 0), 0xff, max);
 	return max;
 }
 
@@ -290,7 +290,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/via/cn700/northbridge.c b/src/northbridge/via/cn700/northbridge.c
index 445ecf2..b122a5e 100644
--- a/src/northbridge/via/cn700/northbridge.c
+++ b/src/northbridge/via/cn700/northbridge.c
@@ -157,7 +157,7 @@
 
 	printk(BIOS_SPEW, "Entering cn700 pci_domain_set_resources.\n");
 
-	pci_tolm = find_pci_tolm(&dev->link[0]);
+	pci_tolm = find_pci_tolm(dev->link_list);
 	mc_dev = dev_find_device(PCI_VENDOR_ID_VIA,
 				 PCI_DEVICE_ID_VIA_CN700_MEMCTRL, 0);
 
@@ -199,7 +199,7 @@
 		ram_resource(dev, idx++, 768,
 			     (tolmk - 768 - CONFIG_VIDEO_MB * 1024));
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -212,7 +212,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/via/cx700/northbridge.c b/src/northbridge/via/cx700/northbridge.c
index 6a69d43..3f5ed28 100644
--- a/src/northbridge/via/cx700/northbridge.c
+++ b/src/northbridge/via/cx700/northbridge.c
@@ -87,7 +87,7 @@
 	unsigned char rambits;
 	int idx;
 
-	pci_tolm = find_pci_tolm(&dev->link[0]);
+	pci_tolm = find_pci_tolm(dev->link_list);
 	mc_dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x3324, 0);
 
 	rambits = pci_read_config8(mc_dev, 0x88);
@@ -128,7 +128,7 @@
 	/* TODO: Hole needed? Should this go elsewhere? */
 	ram_resource(dev, idx++, 0, 640);	/* first 640k */
 	ram_resource(dev, idx++, 768, (tolmk - 768));	/* leave a hole for vga */
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -141,7 +141,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/via/vt8601/northbridge.c b/src/northbridge/via/vt8601/northbridge.c
index 8fca0ea..1f15b70 100644
--- a/src/northbridge/via/vt8601/northbridge.c
+++ b/src/northbridge/via/vt8601/northbridge.c
@@ -98,8 +98,8 @@
 	device_t mc_dev;
         uint32_t pci_tolm;
 
-        pci_tolm = find_pci_tolm(&dev->link[0]);
-	mc_dev = dev->link[0].children;
+        pci_tolm = find_pci_tolm(dev->link_list);
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		unsigned long tomk, tolmk;
 		unsigned char rambits;
@@ -140,7 +140,7 @@
 		idx = 10;
 		ram_resource(dev, idx++, 0, tolmk);
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -153,7 +153,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-        initialize_cpus(&dev->link[0]);
+        initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/via/vt8623/northbridge.c b/src/northbridge/via/vt8623/northbridge.c
index 7ba9cd6..d7fff33 100644
--- a/src/northbridge/via/vt8623/northbridge.c
+++ b/src/northbridge/via/vt8623/northbridge.c
@@ -158,8 +158,8 @@
 
 	printk(BIOS_SPEW, "Entering vt8623 pci_domain_set_resources.\n");
 
-        pci_tolm = find_pci_tolm(&dev->link[0]);
-	mc_dev = dev->link[0].children;
+        pci_tolm = find_pci_tolm(dev->link_list);
+	mc_dev = dev->link_list->children;
 	if (mc_dev) {
 		unsigned long tomk, tolmk;
 		unsigned char rambits;
@@ -201,7 +201,7 @@
 		ram_resource(dev, idx++, 0, 640);		/* first 640k */
 		ram_resource(dev, idx++, 768, tolmk - 768);	/* leave a hole for vga */
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -214,7 +214,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-        initialize_cpus(&dev->link[0]);
+        initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/northbridge/via/vx800/northbridge.c b/src/northbridge/via/vx800/northbridge.c
index 37e559c..ec978e8 100644
--- a/src/northbridge/via/vx800/northbridge.c
+++ b/src/northbridge/via/vx800/northbridge.c
@@ -128,7 +128,7 @@
 
 	printk(BIOS_SPEW, "Entering vx800 pci_domain_set_resources.\n");
 
-	pci_tolm = find_pci_tolm(&dev->link[0]);
+	pci_tolm = find_pci_tolm(dev->link_list);
 	mc_dev = dev_find_device(PCI_VENDOR_ID_VIA,
 				 PCI_DEVICE_ID_VIA_VX855_MEMCTRL, 0);
 
@@ -175,7 +175,7 @@
 		/* Leave a hole for vga, 0xa0000 - 0xc0000 */
 		ram_resource(dev, idx++, 768, (tolmk - 768));
 	}
-	assign_resources(&dev->link[0]);
+	assign_resources(dev->link_list);
 }
 
 static struct device_operations pci_domain_ops = {
@@ -188,7 +188,7 @@
 
 static void cpu_bus_init(device_t dev)
 {
-	initialize_cpus(&dev->link[0]);
+	initialize_cpus(dev->link_list);
 }
 
 static void cpu_bus_noop(device_t dev)
diff --git a/src/southbridge/amd/amd8131/amd8131_bridge.c b/src/southbridge/amd/amd8131/amd8131_bridge.c
index ae2c4cf..d258450 100644
--- a/src/southbridge/amd/amd8131/amd8131_bridge.c
+++ b/src/southbridge/amd/amd8131/amd8131_bridge.c
@@ -25,7 +25,7 @@
 			continue;
 		}
 		if (child->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-			amd8131_walk_children(&child->link[0], visit, ptr);
+			amd8131_walk_children(child->link_list, visit, ptr);
 		}
 		visit(child, ptr);
 	}
diff --git a/src/southbridge/amd/amd8132/amd8132_bridge.c b/src/southbridge/amd/amd8132/amd8132_bridge.c
index 5bbc3dc5..2ce46cd 100644
--- a/src/southbridge/amd/amd8132/amd8132_bridge.c
+++ b/src/southbridge/amd/amd8132/amd8132_bridge.c
@@ -47,7 +47,7 @@
 			continue;
 		}
 		if (child->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-			amd8132_walk_children(&child->link[0], visit, ptr);
+			amd8132_walk_children(child->link_list, visit, ptr);
 		}
 		visit(child, ptr);
 	}
diff --git a/src/southbridge/amd/sb600/sb600_lpc.c b/src/southbridge/amd/sb600/sb600_lpc.c
index 0653772..fd06f44 100644
--- a/src/southbridge/amd/sb600/sb600_lpc.c
+++ b/src/southbridge/amd/sb600/sb600_lpc.c
@@ -106,7 +106,7 @@
  */
 static void sb600_lpc_enable_childrens_resources(device_t dev)
 {
-	u32 link;
+	struct bus *link;
 	u32 reg, reg_x;
 	int var_num = 0;
 	u16 reg_var[3];
@@ -114,9 +114,9 @@
 	reg = pci_read_config32(dev, 0x44);
 	reg_x = pci_read_config32(dev, 0x48);
 
-	for (link = 0; link < dev->links; link++) {
+	for (link = dev->link_list; link; link = link->next) {
 		device_t child;
-		for (child = dev->link[link].children; child;
+		for (child = link->children; child;
 		     child = child->sibling) {
 			enable_resources(child);
 			if (child->enabled
diff --git a/src/southbridge/amd/sb700/sb700_lpc.c b/src/southbridge/amd/sb700/sb700_lpc.c
index ab0a5ba..e8bfbfa 100644
--- a/src/southbridge/amd/sb700/sb700_lpc.c
+++ b/src/southbridge/amd/sb700/sb700_lpc.c
@@ -118,7 +118,7 @@
  */
 static void sb700_lpc_enable_childrens_resources(device_t dev)
 {
-	u32 link;
+	struct bus *link;
 	u32 reg, reg_x;
 	int var_num = 0;
 	u16 reg_var[3];
@@ -126,9 +126,9 @@
 	reg = pci_read_config32(dev, 0x44);
 	reg_x = pci_read_config32(dev, 0x48);
 
-	for (link = 0; link < dev->links; link++) {
+	for (link = dev->link_list; link; link = link->next) {
 		device_t child;
-		for (child = dev->link[link].children; child;
+		for (child = link->children; child;
 		     child = child->sibling) {
 			enable_resources(child);
 			if (child->enabled
diff --git a/src/southbridge/broadcom/bcm5785/bcm5785_lpc.c b/src/southbridge/broadcom/bcm5785/bcm5785_lpc.c
index a80f5d7..3a876de 100644
--- a/src/southbridge/broadcom/bcm5785/bcm5785_lpc.c
+++ b/src/southbridge/broadcom/bcm5785/bcm5785_lpc.c
@@ -67,14 +67,14 @@
  */
 static void bcm5785_lpc_enable_childrens_resources(device_t dev)
 {
-        unsigned link;
+	struct bus *link;
 	uint32_t reg;
 
 	reg = pci_read_config8(dev, 0x44);
 
-        for (link = 0; link < dev->links; link++) {
+	for (link = dev->link_list; link; link = link->next) {
                 device_t child;
-                for (child = dev->link[link].children; child; child = child->sibling) {
+                for (child = link->children; child; child = child->sibling) {
                         enable_resources(child);
 			if(child->enabled && (child->path.type == DEVICE_PATH_PNP)) {
 				struct resource *res;
diff --git a/src/southbridge/intel/i82801gx/i82801gx_pci.c b/src/southbridge/intel/i82801gx/i82801gx_pci.c
index c4c22f0..1bdc67a 100644
--- a/src/southbridge/intel/i82801gx/i82801gx_pci.c
+++ b/src/southbridge/intel/i82801gx/i82801gx_pci.c
@@ -100,10 +100,10 @@
 	/* enable IO in command register if there is VGA card
 	 * connected with (even it does not claim IO resource)
 	 */
-	if (dev->link[0].bridge_ctrl & PCI_BRIDGE_CTL_VGA)
+	if (dev->link_list->bridge_ctrl & PCI_BRIDGE_CTL_VGA)
 		dev->command |= PCI_COMMAND_IO;
 	ctrl = pci_read_config16(dev, PCI_BRIDGE_CONTROL);
-	ctrl |= dev->link[0].bridge_ctrl;
+	ctrl |= dev->link_list->bridge_ctrl;
 	ctrl |= (PCI_BRIDGE_CTL_PARITY + PCI_BRIDGE_CTL_SERR); /* error check */
 	printk(BIOS_DEBUG, "%s bridge ctrl <- %04x\n", dev_path(dev), ctrl);
 	pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl);
diff --git a/src/southbridge/intel/pxhd/pxhd_bridge.c b/src/southbridge/intel/pxhd/pxhd_bridge.c
index bfce8b6..1134f8f 100644
--- a/src/southbridge/intel/pxhd/pxhd_bridge.c
+++ b/src/southbridge/intel/pxhd/pxhd_bridge.c
@@ -41,8 +41,7 @@
 {
 	int bus_100Mhz = 0;
 
-	dev->link[0].dev = dev;
-	dev->links = 1;
+	dev->link_list->dev = dev;
 
 	get_option(&bus_100Mhz, "pxhd_bus_speed_100");
 	if(bus_100Mhz) {
@@ -58,7 +57,7 @@
 		pci_write_config16(dev, 0x40, word);
 
 		/* reset the bus to make the new frequencies effective */
-		pci_bus_reset(&dev->link[0]);
+		pci_bus_reset(dev->link_list);
 	}
 	return pcix_scan_bridge(dev, max);
 }
diff --git a/src/southbridge/nvidia/ck804/ck804_lpc.c b/src/southbridge/nvidia/ck804/ck804_lpc.c
index a6637ca..e626400 100644
--- a/src/southbridge/nvidia/ck804/ck804_lpc.c
+++ b/src/southbridge/nvidia/ck804/ck804_lpc.c
@@ -231,15 +231,15 @@
  */
 static void ck804_lpc_enable_childrens_resources(device_t dev)
 {
-	unsigned link;
+	struct bus *link;
 	uint32_t reg, reg_var[4];
 	int i, var_num = 0;
 
 	reg = pci_read_config32(dev, 0xa0);
 
-	for (link = 0; link < dev->links; link++) {
+	for (link = dev->link_list; link; link = link->next) {
 		device_t child;
-		for (child = dev->link[link].children; child; child = child->sibling) {
+		for (child = link->children; child; child = child->sibling) {
 			enable_resources(child);
 			if (child->enabled && (child->path.type == DEVICE_PATH_PNP)) {
 				struct resource *res;
diff --git a/src/southbridge/nvidia/ck804/ck804_smbus.c b/src/southbridge/nvidia/ck804/ck804_smbus.c
index 3d8c9ce..cc75a10 100644
--- a/src/southbridge/nvidia/ck804/ck804_smbus.c
+++ b/src/southbridge/nvidia/ck804/ck804_smbus.c
@@ -23,7 +23,7 @@
 	device = dev->path.i2c.device;
 	pbus = get_pbus_smbus(dev);
 
-	res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+	res = find_resource(pbus->dev, 0x20 + (pbus->link_num * 4));
 
 	return do_smbus_recv_byte(res->base, device);
 }
@@ -37,7 +37,7 @@
 	device = dev->path.i2c.device;
 	pbus = get_pbus_smbus(dev);
 
-	res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+	res = find_resource(pbus->dev, 0x20 + (pbus->link_num * 4));
 
 	return do_smbus_send_byte(res->base, device, val);
 }
@@ -51,7 +51,7 @@
 	device = dev->path.i2c.device;
 	pbus = get_pbus_smbus(dev);
 
-	res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+	res = find_resource(pbus->dev, 0x20 + (pbus->link_num * 4));
 
 	return do_smbus_read_byte(res->base, device, address);
 }
@@ -65,7 +65,7 @@
 	device = dev->path.i2c.device;
 	pbus = get_pbus_smbus(dev);
 
-	res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+	res = find_resource(pbus->dev, 0x20 + (pbus->link_num * 4));
 
 	return do_smbus_write_byte(res->base, device, address, val);
 }
diff --git a/src/southbridge/nvidia/mcp55/mcp55_lpc.c b/src/southbridge/nvidia/mcp55/mcp55_lpc.c
index 0f9a50c..0d32cb8 100644
--- a/src/southbridge/nvidia/mcp55/mcp55_lpc.c
+++ b/src/southbridge/nvidia/mcp55/mcp55_lpc.c
@@ -205,16 +205,16 @@
  */
 static void mcp55_lpc_enable_childrens_resources(device_t dev)
 {
-	unsigned link;
 	uint32_t reg, reg_var[4];
 	int i;
 	int var_num = 0;
+	struct bus *link;
 
 	reg = pci_read_config32(dev, 0xa0);
 
-	for (link = 0; link < dev->links; link++) {
+	for (link = dev->link_list; link; link = link->next) {
 		device_t child;
-		for (child = dev->link[link].children; child; child = child->sibling) {
+		for (child = link->children; child; child = child->sibling) {
 			enable_resources(child);
 			if(child->enabled && (child->path.type == DEVICE_PATH_PNP)) {
 				struct resource *res;
diff --git a/src/southbridge/nvidia/mcp55/mcp55_smbus.c b/src/southbridge/nvidia/mcp55/mcp55_smbus.c
index fd28710..8e049a7 100644
--- a/src/southbridge/nvidia/mcp55/mcp55_smbus.c
+++ b/src/southbridge/nvidia/mcp55/mcp55_smbus.c
@@ -41,7 +41,7 @@
 	device = dev->path.i2c.device;
 	pbus = get_pbus_smbus(dev);
 
-	res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+	res = find_resource(pbus->dev, 0x20 + (pbus->link_num * 4));
 
 	return do_smbus_recv_byte(res->base, device);
 }
@@ -55,7 +55,7 @@
 	device = dev->path.i2c.device;
 	pbus = get_pbus_smbus(dev);
 
-	res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+	res = find_resource(pbus->dev, 0x20 + (pbus->link_num * 4));
 
 	return do_smbus_send_byte(res->base, device, val);
 }
@@ -69,7 +69,7 @@
 	device = dev->path.i2c.device;
 	pbus = get_pbus_smbus(dev);
 
-	res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+	res = find_resource(pbus->dev, 0x20 + (pbus->link_num * 4));
 
 	return do_smbus_read_byte(res->base, device, address);
 }
@@ -83,7 +83,7 @@
 	device = dev->path.i2c.device;
 	pbus = get_pbus_smbus(dev);
 
-	res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+	res = find_resource(pbus->dev, 0x20 + (pbus->link_num * 4));
 
 	return do_smbus_write_byte(res->base, device, address, val);
 }
diff --git a/src/southbridge/sis/sis966/sis966_lpc.c b/src/southbridge/sis/sis966/sis966_lpc.c
index a3b79f0..3b620ca 100644
--- a/src/southbridge/sis/sis966/sis966_lpc.c
+++ b/src/southbridge/sis/sis966/sis966_lpc.c
@@ -198,16 +198,16 @@
  */
 static void sis966_lpc_enable_childrens_resources(device_t dev)
 {
-	unsigned link;
+	struct bus *link;
 	uint32_t reg, reg_var[4];
 	int i;
 	int var_num = 0;
 
 	reg = pci_read_config32(dev, 0xa0);
 
-	for (link = 0; link < dev->links; link++) {
+	for (link = dev->link_list; link; link = link->next) {
 		device_t child;
-		for (child = dev->link[link].children; child; child = child->sibling) {
+		for (child = link->children; child; child = child->sibling) {
 			enable_resources(child);
 			if(child->enabled && (child->path.type == DEVICE_PATH_PNP)) {
 				struct resource *res;