patch-2.3.37 linux/drivers/pci/pci.c

Next file: linux/drivers/pci/pci.ids
Previous file: linux/drivers/pci/helper.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.36/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
@@ -6,7 +6,7 @@
  *	Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter,
  *	David Mosberger-Tang
  *
- *	Copyright 1997 -- 1999 Martin Mares <mj@suse.cz>
+ *	Copyright 1997 -- 2000 Martin Mares <mj@suse.cz>
  */
 
 #include <linux/types.h>
@@ -27,19 +27,19 @@
 #define DBG(x...)
 #endif
 
-struct pci_bus *pci_root;
-struct pci_dev *pci_devices = NULL;
-static struct pci_dev **pci_last_dev_p = &pci_devices;
+LIST_HEAD(pci_root_buses);
+LIST_HEAD(pci_devices);
 
 struct pci_dev *
 pci_find_slot(unsigned int bus, unsigned int devfn)
 {
 	struct pci_dev *dev;
 
-	for(dev=pci_devices; dev; dev=dev->next)
+	pci_for_each_dev(dev) {
 		if (dev->bus->number == bus && dev->devfn == devfn)
-			break;
-	return dev;
+			return dev;
+	}
+	return NULL;
 }
 
 
@@ -48,20 +48,16 @@
 		unsigned int ss_vendor, unsigned int ss_device,
 		struct pci_dev *from)
 {
-	struct pci_dev *dev;
+	struct list_head *n = from ? from->global_list.next : pci_devices.next;
 
-	if (from)
-		dev = from->next;
-	else
-		dev = pci_devices;
-
-	while (dev) {
+	while (n != &pci_devices) {
+		struct pci_dev *dev = pci_dev_g(n);
 		if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
 		    (device == PCI_ANY_ID || dev->device == device) &&
 		    (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
 		    (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
 			return dev;
-		dev = dev->next;
+		n = n->next;
 	}
 	return NULL;
 }
@@ -77,13 +73,15 @@
 struct pci_dev *
 pci_find_class(unsigned int class, struct pci_dev *from)
 {
-	if (!from)
-		from = pci_devices;
-	else
-		from = from->next;
-	while (from && from->class != class)
-		from = from->next;
-	return from;
+	struct list_head *n = from ? from->global_list.next : pci_devices.next;
+
+	while (n != &pci_devices) {
+		struct pci_dev *dev = pci_dev_g(n);
+		if (dev->class == class)
+			return dev;
+		n = n->next;
+	}
+	return NULL;
 }
 
 
@@ -412,6 +410,19 @@
 	}
 }
 
+static struct pci_bus * __init pci_alloc_bus(void)
+{
+	struct pci_bus *b;
+
+	b = kmalloc(sizeof(*b), GFP_KERNEL);
+	if (b) {
+		memset(b, 0, sizeof(*b));
+		INIT_LIST_HEAD(&b->children);
+		INIT_LIST_HEAD(&b->devices);
+	}
+	return b;
+}
+
 static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
 {
 	struct pci_bus *child;
@@ -419,11 +430,9 @@
 	/*
 	 * Allocate a new bus, and inherit stuff from the parent..
 	 */
-	child = kmalloc(sizeof(*child), GFP_KERNEL);
-	memset(child, 0, sizeof(*child));
+	child = pci_alloc_bus();
 
-	child->next = parent->children;
-	parent->children = child;
+	list_add_tail(&child->node, &parent->children);
 	child->self = dev;
 	dev->subordinate = child;
 	child->parent = parent;
@@ -455,6 +464,7 @@
 	/*
 	 * Insert it into the tree of buses.
 	 */
+	DBG("Scanning CardBus bridge %s\n", dev->slot_name);
 	child = pci_add_new_bus(bus, dev, ++busnr);
 
 	for (i = 0; i < 4; i++)
@@ -517,6 +527,7 @@
 	/*
 	 * Insert it into the tree of buses.
 	 */
+	DBG("Scanning behind PCI bridge %s\n", dev->slot_name);
 	child = pci_add_new_bus(bus, dev, ++max);
 	sprintf(child->name, "PCI Bus #%02x", child->number);
 
@@ -599,6 +610,8 @@
 	dev->class = class;
 	class >>= 8;
 
+	DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn, dev->vendor, dev->device, class, dev->hdr_type);
+
 	switch (dev->hdr_type) {		    /* header type */
 	case PCI_HEADER_TYPE_NORMAL:		    /* standard header */
 		if (class == PCI_CLASS_BRIDGE_PCI)
@@ -694,21 +707,12 @@
 			first_dev = dev;
 		}
 
-		DBG("PCI: %02x:%02x [%04x/%04x] %06x %02x\n", bus->number, dev->devfn, dev->vendor, dev->device, dev->class, hdr_type);
-
-		/*
-		 * Put it into the global PCI device chain. It's used to
-		 * find devices once everything is set up.
-		 */
-		*pci_last_dev_p = dev;
-		pci_last_dev_p = &dev->next;
-
 		/*
-		 * Now insert it into the list of devices held
-		 * by the parent bus.
+		 * Link the device to both the global PCI device chain and
+		 * the per-bus list of devices.
 		 */
-		*bus->last_dev_p = dev;
-		bus->last_dev_p = &dev->sibling;
+		list_add_tail(&dev->global_list, &pci_devices);
+		list_add_tail(&dev->bus_list, &bus->devices);
 
 		/* Fix up broken headers */
 		pci_fixup_device(PCI_FIXUP_HEADER, dev);
@@ -719,10 +723,10 @@
 static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
 {
 	unsigned int devfn, max;
+	struct list_head *ln;
 	struct pci_dev *dev, dev0;
 
-	DBG("pci_do_scan_bus for bus %d\n", bus->number);
-	bus->last_dev_p = &bus->devices;
+	DBG("Scanning bus %02x\n", bus->number);
 	max = bus->secondary;
 
 	/* Create a device template */
@@ -740,8 +744,10 @@
 	 * After performing arch-dependent fixup of the bus, look behind
 	 * all PCI-to-PCI bridges on this bus.
 	 */
+	DBG("Fixups for bus %02x\n", bus->number);
 	pcibios_fixup_bus(bus);
-	for (dev = bus->devices; dev; dev = dev->sibling) {
+	for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
+		dev = pci_dev_b(ln);
 		switch (dev->class >> 8) {
 		case PCI_CLASS_BRIDGE_PCI:
 			max = pci_scan_bridge(bus, dev, max);
@@ -759,40 +765,34 @@
 	 *
 	 * Return how far we've got finding sub-buses.
 	 */
-	DBG("PCI: pci_do_scan_bus returning with max=%02x\n", max);
+	DBG("Bus scan for %02x returning with max=%02x\n", bus->number, max);
 	return max;
 }
 
-static int __init pci_bus_exists(struct pci_bus *b, int nr)
+static int __init pci_bus_exists(struct list_head *list, int nr)
 {
-	while (b) {
-		if (b->number == nr)
-			return 1;
-		if (b->children && pci_bus_exists(b->children, nr))
+	struct list_head *l;
+
+	for(l=list->next; l != list; l = l->next) {
+		struct pci_bus *b = pci_bus_b(l);
+		if (b->number == nr || pci_bus_exists(&b->children, nr))
 			return 1;
-		b = b->next;
 	}
 	return 0;
 }
 
 struct pci_bus * __init pci_alloc_primary_bus(int bus)
 {
-	struct pci_bus *b, **r;
+	struct pci_bus *b;
 
-	if (pci_bus_exists(pci_root, bus)) {
+	if (pci_bus_exists(&pci_root_buses, bus)) {
 		/* If we already got to this bus through a different bridge, ignore it */
 		DBG("PCI: Bus %02x already known\n", bus);
 		return NULL;
 	}
 
-	b = kmalloc(sizeof(*b), GFP_KERNEL);
-	memset(b, 0, sizeof(*b));
-
-	/* Put the new bus at the end of the chain of busses.  */
-	r = &pci_root;
-	while (*r)
-		r = &(*r)->next;
-	*r = b;
+	b = pci_alloc_bus();
+	list_add_tail(&b->node, &pci_root_buses);
 
 	b->number = b->secondary = bus;
 	b->resource[0] = &ioport_resource;
@@ -817,8 +817,9 @@
 
 	pcibios_init();
 
-	for(dev=pci_devices; dev; dev=dev->next)
+	pci_for_each_dev(dev) {
 		pci_fixup_device(PCI_FIXUP_FINAL, dev);
+	}
 }
 
 static int __init pci_setup(char *str)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)