]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/pci/bus.c
Remove obsolete #include <linux/config.h>
[karo-tx-linux.git] / drivers / pci / bus.c
index fb9a11243d2a1fbff876749a997617cfb4013670..5f7db9d2436e76141e15d50a44e9f1fc38e54378 100644 (file)
  */
 int
 pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
-       unsigned long size, unsigned long align, unsigned long min,
-       unsigned int type_mask,
-       void (*alignf)(void *, struct resource *,
-                       unsigned long, unsigned long),
-       void *alignf_data)
+               resource_size_t size, resource_size_t align,
+               resource_size_t min, unsigned int type_mask,
+               void (*alignf)(void *, struct resource *, resource_size_t,
+                               resource_size_t),
+               void *alignf_data)
 {
        int i, ret = -ENOMEM;
 
@@ -81,9 +81,9 @@ void __devinit pci_bus_add_device(struct pci_dev *dev)
 {
        device_add(&dev->dev);
 
-       spin_lock(&pci_bus_lock);
+       down_write(&pci_bus_sem);
        list_add_tail(&dev->global_list, &pci_devices);
-       spin_unlock(&pci_bus_lock);
+       up_write(&pci_bus_sem);
 
        pci_proc_attach_device(dev);
        pci_create_sysfs_dev_files(dev);
@@ -125,10 +125,10 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
                 */
                if (dev->subordinate) {
                       if (list_empty(&dev->subordinate->node)) {
-                              spin_lock(&pci_bus_lock);
+                              down_write(&pci_bus_sem);
                               list_add_tail(&dev->subordinate->node,
                                               &dev->bus->children);
-                              spin_unlock(&pci_bus_lock);
+                              up_write(&pci_bus_sem);
                       }
                        pci_bus_add_devices(dev->subordinate);
 
@@ -140,16 +140,62 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
 void pci_enable_bridges(struct pci_bus *bus)
 {
        struct pci_dev *dev;
+       int retval;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                if (dev->subordinate) {
-                       pci_enable_device(dev);
+                       retval = pci_enable_device(dev);
                        pci_set_master(dev);
                        pci_enable_bridges(dev->subordinate);
                }
        }
 }
 
+/** pci_walk_bus - walk devices on/under bus, calling callback.
+ *  @top      bus whose devices should be walked
+ *  @cb       callback to be called for each device found
+ *  @userdata arbitrary pointer to be passed to callback.
+ *
+ *  Walk the given bus, including any bridged devices
+ *  on buses under this bus.  Call the provided callback
+ *  on each device found.
+ */
+void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
+                 void *userdata)
+{
+       struct pci_dev *dev;
+       struct pci_bus *bus;
+       struct list_head *next;
+
+       bus = top;
+       down_read(&pci_bus_sem);
+       next = top->devices.next;
+       for (;;) {
+               if (next == &bus->devices) {
+                       /* end of this bus, go up or finish */
+                       if (bus == top)
+                               break;
+                       next = bus->self->bus_list.next;
+                       bus = bus->self->bus;
+                       continue;
+               }
+               dev = list_entry(next, struct pci_dev, bus_list);
+               if (dev->subordinate) {
+                       /* this is a pci-pci bridge, do its devices next */
+                       next = dev->subordinate->devices.next;
+                       bus = dev->subordinate;
+               } else
+                       next = dev->bus_list.next;
+
+               /* Run device routines with the device locked */
+               down(&dev->dev.sem);
+               cb(dev, userdata);
+               up(&dev->dev.sem);
+       }
+       up_read(&pci_bus_sem);
+}
+EXPORT_SYMBOL_GPL(pci_walk_bus);
+
 EXPORT_SYMBOL(pci_bus_alloc_resource);
 EXPORT_SYMBOL_GPL(pci_bus_add_device);
 EXPORT_SYMBOL(pci_bus_add_devices);