Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
bus.c
Go to the documentation of this file.
1 /*
2  * drivers/pci/bus.c
3  *
4  * From setup-res.c, by:
5  * Dave Rusling ([email protected])
6  * David Mosberger ([email protected])
7  * David Miller ([email protected])
8  * Ivan Kokshaysky ([email protected])
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 
23 {
25 
26  window = kzalloc(sizeof(struct pci_host_bridge_window), GFP_KERNEL);
27  if (!window) {
28  printk(KERN_ERR "PCI: can't add host bridge window %pR\n", res);
29  return;
30  }
31 
32  window->res = res;
33  window->offset = offset;
34  list_add_tail(&window->list, resources);
35 }
37 
39 {
40  pci_add_resource_offset(resources, res, 0);
41 }
43 
45 {
47 
48  list_for_each_entry_safe(window, tmp, resources, list) {
49  list_del(&window->list);
50  kfree(window);
51  }
52 }
54 
56  unsigned int flags)
57 {
58  struct pci_bus_resource *bus_res;
59 
60  bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL);
61  if (!bus_res) {
62  dev_err(&bus->dev, "can't add %pR resource\n", res);
63  return;
64  }
65 
66  bus_res->res = res;
67  bus_res->flags = flags;
68  list_add_tail(&bus_res->list, &bus->resources);
69 }
70 
71 struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n)
72 {
73  struct pci_bus_resource *bus_res;
74 
76  return bus->resource[n];
77 
79  list_for_each_entry(bus_res, &bus->resources, list) {
80  if (n-- == 0)
81  return bus_res->res;
82  }
83  return NULL;
84 }
86 
88 {
89  int i;
90  struct pci_bus_resource *bus_res, *tmp;
91 
92  for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
93  bus->resource[i] = NULL;
94 
95  list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
96  list_del(&bus_res->list);
97  kfree(bus_res);
98  }
99 }
100 
116 int
119  resource_size_t min, unsigned int type_mask,
120  resource_size_t (*alignf)(void *,
121  const struct resource *,
124  void *alignf_data)
125 {
126  int i, ret = -ENOMEM;
127  struct resource *r;
128  resource_size_t max = -1;
129 
130  type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
131 
132  /* don't allocate too high if the pref mem doesn't support 64bit*/
133  if (!(res->flags & IORESOURCE_MEM_64))
134  max = PCIBIOS_MAX_MEM_32;
135 
136  pci_bus_for_each_resource(bus, r, i) {
137  if (!r)
138  continue;
139 
140  /* type_mask must match */
141  if ((res->flags ^ r->flags) & type_mask)
142  continue;
143 
144  /* We cannot allocate a non-prefetching resource
145  from a pre-fetching area */
146  if ((r->flags & IORESOURCE_PREFETCH) &&
147  !(res->flags & IORESOURCE_PREFETCH))
148  continue;
149 
150  /* Ok, try it out.. */
151  ret = allocate_resource(r, res, size,
152  r->start ? : min,
153  max, align,
154  alignf, alignf_data);
155  if (ret == 0)
156  break;
157  }
158  return ret;
159 }
160 
169 {
170  int retval;
171 
173  retval = device_add(&dev->dev);
174  if (retval)
175  return retval;
176 
177  dev->is_added = 1;
180  return 0;
181 }
182 
189 int pci_bus_add_child(struct pci_bus *bus)
190 {
191  int retval;
192 
193  if (bus->bridge)
194  bus->dev.parent = bus->bridge;
195 
196  retval = device_register(&bus->dev);
197  if (retval)
198  return retval;
199 
200  bus->is_added = 1;
201 
202  /* Create legacy_io and legacy_mem files for this bus */
203  pci_create_legacy_files(bus);
204 
205  return retval;
206 }
207 
220 void pci_bus_add_devices(const struct pci_bus *bus)
221 {
222  struct pci_dev *dev;
223  struct pci_bus *child;
224  int retval;
225 
226  list_for_each_entry(dev, &bus->devices, bus_list) {
227  /* Skip already-added devices */
228  if (dev->is_added)
229  continue;
230  retval = pci_bus_add_device(dev);
231  if (retval)
232  dev_err(&dev->dev, "Error adding device, continuing\n");
233  }
234 
235  list_for_each_entry(dev, &bus->devices, bus_list) {
236  BUG_ON(!dev->is_added);
237 
238  child = dev->subordinate;
239  /*
240  * If there is an unattached subordinate bus, attach
241  * it and then scan for unattached PCI devices.
242  */
243  if (!child)
244  continue;
245  if (list_empty(&child->node)) {
247  list_add_tail(&child->node, &dev->bus->children);
249  }
250  pci_bus_add_devices(child);
251 
252  /*
253  * register the bus with sysfs as the parent is now
254  * properly registered.
255  */
256  if (child->is_added)
257  continue;
258  retval = pci_bus_add_child(child);
259  if (retval)
260  dev_err(&dev->dev, "Error adding bus, continuing\n");
261  }
262 }
263 
264 void pci_enable_bridges(struct pci_bus *bus)
265 {
266  struct pci_dev *dev;
267  int retval;
268 
269  list_for_each_entry(dev, &bus->devices, bus_list) {
270  if (dev->subordinate) {
271  if (!pci_is_enabled(dev)) {
272  retval = pci_enable_device(dev);
273  if (retval)
274  dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", retval);
275  pci_set_master(dev);
276  }
278  }
279  }
280 }
281 
295 void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
296  void *userdata)
297 {
298  struct pci_dev *dev;
299  struct pci_bus *bus;
300  struct list_head *next;
301  int retval;
302 
303  bus = top;
305  next = top->devices.next;
306  for (;;) {
307  if (next == &bus->devices) {
308  /* end of this bus, go up or finish */
309  if (bus == top)
310  break;
311  next = bus->self->bus_list.next;
312  bus = bus->self->bus;
313  continue;
314  }
315  dev = list_entry(next, struct pci_dev, bus_list);
316  if (dev->subordinate) {
317  /* this is a pci-pci bridge, do its devices next */
318  next = dev->subordinate->devices.next;
319  bus = dev->subordinate;
320  } else
321  next = dev->bus_list.next;
322 
323  retval = cb(dev, userdata);
324  if (retval)
325  break;
326  }
328 }
330