1 /* 2 * drivers/pci/bus.c 3 * 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) 9 */ 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> 17 #include <linux/slab.h> 18 19 #include "pci.h" 20 21 void pci_add_resource(struct list_head *resources, struct resource *res) 22 { 23 struct pci_bus_resource *bus_res; 24 25 bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL); 26 if (!bus_res) { 27 printk(KERN_ERR "PCI: can't add bus resource %pR\n", res); 28 return; 29 } 30 31 bus_res->res = res; 32 list_add_tail(&bus_res->list, resources); 33 } 34 EXPORT_SYMBOL(pci_add_resource); 35 36 void pci_free_resource_list(struct list_head *resources) 37 { 38 struct pci_bus_resource *bus_res, *tmp; 39 40 list_for_each_entry_safe(bus_res, tmp, resources, list) { 41 list_del(&bus_res->list); 42 kfree(bus_res); 43 } 44 } 45 EXPORT_SYMBOL(pci_free_resource_list); 46 47 void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, 48 unsigned int flags) 49 { 50 struct pci_bus_resource *bus_res; 51 52 bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL); 53 if (!bus_res) { 54 dev_err(&bus->dev, "can't add %pR resource\n", res); 55 return; 56 } 57 58 bus_res->res = res; 59 bus_res->flags = flags; 60 list_add_tail(&bus_res->list, &bus->resources); 61 } 62 63 struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n) 64 { 65 struct pci_bus_resource *bus_res; 66 67 if (n < PCI_BRIDGE_RESOURCE_NUM) 68 return bus->resource[n]; 69 70 n -= PCI_BRIDGE_RESOURCE_NUM; 71 list_for_each_entry(bus_res, &bus->resources, list) { 72 if (n-- == 0) 73 return bus_res->res; 74 } 75 return NULL; 76 } 77 EXPORT_SYMBOL_GPL(pci_bus_resource_n); 78 79 void pci_bus_remove_resources(struct pci_bus *bus) 80 { 81 int i; 82 83 for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) 84 bus->resource[i] = NULL; 85 86 pci_free_resource_list(&bus->resources); 87 } 88 89 /** 90 * pci_bus_alloc_resource - allocate a resource from a parent bus 91 * @bus: PCI bus 92 * @res: resource to allocate 93 * @size: size of resource to allocate 94 * @align: alignment of resource to allocate 95 * @min: minimum /proc/iomem address to allocate 96 * @type_mask: IORESOURCE_* type flags 97 * @alignf: resource alignment function 98 * @alignf_data: data argument for resource alignment function 99 * 100 * Given the PCI bus a device resides on, the size, minimum address, 101 * alignment and type, try to find an acceptable resource allocation 102 * for a specific device resource. 103 */ 104 int 105 pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, 106 resource_size_t size, resource_size_t align, 107 resource_size_t min, unsigned int type_mask, 108 resource_size_t (*alignf)(void *, 109 const struct resource *, 110 resource_size_t, 111 resource_size_t), 112 void *alignf_data) 113 { 114 int i, ret = -ENOMEM; 115 struct resource *r; 116 resource_size_t max = -1; 117 118 type_mask |= IORESOURCE_IO | IORESOURCE_MEM; 119 120 /* don't allocate too high if the pref mem doesn't support 64bit*/ 121 if (!(res->flags & IORESOURCE_MEM_64)) 122 max = PCIBIOS_MAX_MEM_32; 123 124 pci_bus_for_each_resource(bus, r, i) { 125 if (!r) 126 continue; 127 128 /* type_mask must match */ 129 if ((res->flags ^ r->flags) & type_mask) 130 continue; 131 132 /* We cannot allocate a non-prefetching resource 133 from a pre-fetching area */ 134 if ((r->flags & IORESOURCE_PREFETCH) && 135 !(res->flags & IORESOURCE_PREFETCH)) 136 continue; 137 138 /* Ok, try it out.. */ 139 ret = allocate_resource(r, res, size, 140 r->start ? : min, 141 max, align, 142 alignf, alignf_data); 143 if (ret == 0) 144 break; 145 } 146 return ret; 147 } 148 149 /** 150 * pci_bus_add_device - add a single device 151 * @dev: device to add 152 * 153 * This adds a single pci device to the global 154 * device list and adds sysfs and procfs entries 155 */ 156 int pci_bus_add_device(struct pci_dev *dev) 157 { 158 int retval; 159 retval = device_add(&dev->dev); 160 if (retval) 161 return retval; 162 163 dev->is_added = 1; 164 pci_proc_attach_device(dev); 165 pci_create_sysfs_dev_files(dev); 166 return 0; 167 } 168 169 /** 170 * pci_bus_add_child - add a child bus 171 * @bus: bus to add 172 * 173 * This adds sysfs entries for a single bus 174 */ 175 int pci_bus_add_child(struct pci_bus *bus) 176 { 177 int retval; 178 179 if (bus->bridge) 180 bus->dev.parent = bus->bridge; 181 182 retval = device_register(&bus->dev); 183 if (retval) 184 return retval; 185 186 bus->is_added = 1; 187 188 /* Create legacy_io and legacy_mem files for this bus */ 189 pci_create_legacy_files(bus); 190 191 return retval; 192 } 193 194 /** 195 * pci_bus_add_devices - insert newly discovered PCI devices 196 * @bus: bus to check for new devices 197 * 198 * Add newly discovered PCI devices (which are on the bus->devices 199 * list) to the global PCI device list, add the sysfs and procfs 200 * entries. Where a bridge is found, add the discovered bus to 201 * the parents list of child buses, and recurse (breadth-first 202 * to be compatible with 2.4) 203 * 204 * Call hotplug for each new devices. 205 */ 206 void pci_bus_add_devices(const struct pci_bus *bus) 207 { 208 struct pci_dev *dev; 209 struct pci_bus *child; 210 int retval; 211 212 list_for_each_entry(dev, &bus->devices, bus_list) { 213 /* Skip already-added devices */ 214 if (dev->is_added) 215 continue; 216 retval = pci_bus_add_device(dev); 217 if (retval) 218 dev_err(&dev->dev, "Error adding device, continuing\n"); 219 } 220 221 list_for_each_entry(dev, &bus->devices, bus_list) { 222 BUG_ON(!dev->is_added); 223 224 child = dev->subordinate; 225 /* 226 * If there is an unattached subordinate bus, attach 227 * it and then scan for unattached PCI devices. 228 */ 229 if (!child) 230 continue; 231 if (list_empty(&child->node)) { 232 down_write(&pci_bus_sem); 233 list_add_tail(&child->node, &dev->bus->children); 234 up_write(&pci_bus_sem); 235 } 236 pci_bus_add_devices(child); 237 238 /* 239 * register the bus with sysfs as the parent is now 240 * properly registered. 241 */ 242 if (child->is_added) 243 continue; 244 retval = pci_bus_add_child(child); 245 if (retval) 246 dev_err(&dev->dev, "Error adding bus, continuing\n"); 247 } 248 } 249 250 void pci_enable_bridges(struct pci_bus *bus) 251 { 252 struct pci_dev *dev; 253 int retval; 254 255 list_for_each_entry(dev, &bus->devices, bus_list) { 256 if (dev->subordinate) { 257 if (!pci_is_enabled(dev)) { 258 retval = pci_enable_device(dev); 259 if (retval) 260 dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", retval); 261 pci_set_master(dev); 262 } 263 pci_enable_bridges(dev->subordinate); 264 } 265 } 266 } 267 268 /** pci_walk_bus - walk devices on/under bus, calling callback. 269 * @top bus whose devices should be walked 270 * @cb callback to be called for each device found 271 * @userdata arbitrary pointer to be passed to callback. 272 * 273 * Walk the given bus, including any bridged devices 274 * on buses under this bus. Call the provided callback 275 * on each device found. 276 * 277 * We check the return of @cb each time. If it returns anything 278 * other than 0, we break out. 279 * 280 */ 281 void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), 282 void *userdata) 283 { 284 struct pci_dev *dev; 285 struct pci_bus *bus; 286 struct list_head *next; 287 int retval; 288 289 bus = top; 290 down_read(&pci_bus_sem); 291 next = top->devices.next; 292 for (;;) { 293 if (next == &bus->devices) { 294 /* end of this bus, go up or finish */ 295 if (bus == top) 296 break; 297 next = bus->self->bus_list.next; 298 bus = bus->self->bus; 299 continue; 300 } 301 dev = list_entry(next, struct pci_dev, bus_list); 302 if (dev->subordinate) { 303 /* this is a pci-pci bridge, do its devices next */ 304 next = dev->subordinate->devices.next; 305 bus = dev->subordinate; 306 } else 307 next = dev->bus_list.next; 308 309 /* Run device routines with the device locked */ 310 device_lock(&dev->dev); 311 retval = cb(dev, userdata); 312 device_unlock(&dev->dev); 313 if (retval) 314 break; 315 } 316 up_read(&pci_bus_sem); 317 } 318 EXPORT_SYMBOL_GPL(pci_walk_bus); 319 320 EXPORT_SYMBOL(pci_bus_alloc_resource); 321 EXPORT_SYMBOL_GPL(pci_bus_add_device); 322 EXPORT_SYMBOL(pci_bus_add_devices); 323 EXPORT_SYMBOL(pci_enable_bridges); 324