4  * From setup-res.c, by:
 
   5  *      Dave Rusling (david.rusling@reo.mts.dec.com)
 
   6  *      David Mosberger (davidm@cs.arizona.edu)
 
   7  *      David Miller (davem@redhat.com)
 
   8  *      Ivan Kokshaysky (ink@jurassic.park.msu.ru)
 
  10 #include <linux/module.h>
 
  11 #include <linux/kernel.h>
 
  12 #include <linux/pci.h>
 
  13 #include <linux/errno.h>
 
  14 #include <linux/ioport.h>
 
  15 #include <linux/proc_fs.h>
 
  16 #include <linux/init.h>
 
  21  * pci_bus_alloc_resource - allocate a resource from a parent bus
 
  23  * @res: resource to allocate
 
  24  * @size: size of resource to allocate
 
  25  * @align: alignment of resource to allocate
 
  26  * @min: minimum /proc/iomem address to allocate
 
  27  * @type_mask: IORESOURCE_* type flags
 
  28  * @alignf: resource alignment function
 
  29  * @alignf_data: data argument for resource alignment function
 
  31  * Given the PCI bus a device resides on, the size, minimum address,
 
  32  * alignment and type, try to find an acceptable resource allocation
 
  33  * for a specific device resource.
 
  36 pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
 
  37                 resource_size_t size, resource_size_t align,
 
  38                 resource_size_t min, unsigned int type_mask,
 
  39                 void (*alignf)(void *, struct resource *, resource_size_t,
 
  45         type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
 
  47         for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
 
  48                 struct resource *r = bus->resource[i];
 
  52                 /* type_mask must match */
 
  53                 if ((res->flags ^ r->flags) & type_mask)
 
  56                 /* We cannot allocate a non-prefetching resource
 
  57                    from a pre-fetching area */
 
  58                 if ((r->flags & IORESOURCE_PREFETCH) &&
 
  59                     !(res->flags & IORESOURCE_PREFETCH))
 
  62                 /* Ok, try it out.. */
 
  63                 ret = allocate_resource(r, res, size,
 
  77  * This adds a single pci device to the global
 
  78  * device list and adds sysfs and procfs entries
 
  80 int pci_bus_add_device(struct pci_dev *dev)
 
  83         retval = device_add(&dev->dev);
 
  87         down_write(&pci_bus_sem);
 
  88         list_add_tail(&dev->global_list, &pci_devices);
 
  89         up_write(&pci_bus_sem);
 
  91         pci_proc_attach_device(dev);
 
  92         pci_create_sysfs_dev_files(dev);
 
  97  * pci_bus_add_devices - insert newly discovered PCI devices
 
  98  * @bus: bus to check for new devices
 
 100  * Add newly discovered PCI devices (which are on the bus->devices
 
 101  * list) to the global PCI device list, add the sysfs and procfs
 
 102  * entries.  Where a bridge is found, add the discovered bus to
 
 103  * the parents list of child buses, and recurse (breadth-first
 
 104  * to be compatible with 2.4)
 
 106  * Call hotplug for each new devices.
 
 108 void pci_bus_add_devices(struct pci_bus *bus)
 
 113         list_for_each_entry(dev, &bus->devices, bus_list) {
 
 115                  * Skip already-present devices (which are on the
 
 116                  * global device list.)
 
 118                 if (!list_empty(&dev->global_list))
 
 120                 retval = pci_bus_add_device(dev);
 
 122                         dev_err(&dev->dev, "Error adding device, continuing\n");
 
 125         list_for_each_entry(dev, &bus->devices, bus_list) {
 
 127                 BUG_ON(list_empty(&dev->global_list));
 
 130                  * If there is an unattached subordinate bus, attach
 
 131                  * it and then scan for unattached PCI devices.
 
 133                 if (dev->subordinate) {
 
 134                        if (list_empty(&dev->subordinate->node)) {
 
 135                                down_write(&pci_bus_sem);
 
 136                                list_add_tail(&dev->subordinate->node,
 
 137                                                &dev->bus->children);
 
 138                                up_write(&pci_bus_sem);
 
 140                         pci_bus_add_devices(dev->subordinate);
 
 141                         retval = sysfs_create_link(&dev->subordinate->class_dev.kobj,
 
 142                                                    &dev->dev.kobj, "bridge");
 
 144                                 dev_err(&dev->dev, "Error creating sysfs "
 
 145                                         "bridge symlink, continuing...\n");
 
 150 void pci_enable_bridges(struct pci_bus *bus)
 
 155         list_for_each_entry(dev, &bus->devices, bus_list) {
 
 156                 if (dev->subordinate) {
 
 157                         retval = pci_enable_device(dev);
 
 159                         pci_enable_bridges(dev->subordinate);
 
 164 /** pci_walk_bus - walk devices on/under bus, calling callback.
 
 165  *  @top      bus whose devices should be walked
 
 166  *  @cb       callback to be called for each device found
 
 167  *  @userdata arbitrary pointer to be passed to callback.
 
 169  *  Walk the given bus, including any bridged devices
 
 170  *  on buses under this bus.  Call the provided callback
 
 171  *  on each device found.
 
 173 void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
 
 178         struct list_head *next;
 
 181         down_read(&pci_bus_sem);
 
 182         next = top->devices.next;
 
 184                 if (next == &bus->devices) {
 
 185                         /* end of this bus, go up or finish */
 
 188                         next = bus->self->bus_list.next;
 
 189                         bus = bus->self->bus;
 
 192                 dev = list_entry(next, struct pci_dev, bus_list);
 
 193                 if (dev->subordinate) {
 
 194                         /* this is a pci-pci bridge, do its devices next */
 
 195                         next = dev->subordinate->devices.next;
 
 196                         bus = dev->subordinate;
 
 198                         next = dev->bus_list.next;
 
 200                 /* Run device routines with the device locked */
 
 205         up_read(&pci_bus_sem);
 
 207 EXPORT_SYMBOL_GPL(pci_walk_bus);
 
 209 EXPORT_SYMBOL(pci_bus_alloc_resource);
 
 210 EXPORT_SYMBOL_GPL(pci_bus_add_device);
 
 211 EXPORT_SYMBOL(pci_bus_add_devices);
 
 212 EXPORT_SYMBOL(pci_enable_bridges);