blob: b067a4cdce43ec3909c0039a4d06570e7e000112 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * drivers/pci/setup-bus.c
3 *
4 * Extruded from code written by
5 * Dave Rusling (david.rusling@reo.mts.dec.com)
6 * David Mosberger (davidm@cs.arizona.edu)
7 * David Miller (davem@redhat.com)
8 *
9 * Support routines for initializing a PCI subsystem.
10 */
11
12/*
13 * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
14 * PCI-PCI bridges cleanup, sorted resource allocation.
15 * Feb 2002, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
16 * Converted to allocation in 3 passes, which gives
17 * tighter packing. Prefetchable range support.
18 */
19
20#include <linux/init.h>
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/pci.h>
24#include <linux/errno.h>
25#include <linux/ioport.h>
26#include <linux/cache.h>
27#include <linux/slab.h>
Chris Wright6faf17f2009-08-28 13:00:06 -070028#include "pci.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
Yinghai Lu2934a0d2012-01-21 02:08:26 -080030struct resource_list {
31 struct resource_list *next;
32 struct resource *res;
33 struct pci_dev *dev;
34};
35
Yinghai Lu568ddef2010-01-22 01:02:21 -080036struct resource_list_x {
37 struct resource_list_x *next;
38 struct resource *res;
39 struct pci_dev *dev;
40 resource_size_t start;
41 resource_size_t end;
Ram Paic8adf9a2011-02-14 17:43:20 -080042 resource_size_t add_size;
Ram Pai2bbc6942011-07-25 13:08:39 -070043 resource_size_t min_align;
Yinghai Lu568ddef2010-01-22 01:02:21 -080044 unsigned long flags;
45};
46
Ram Pai094732a2011-02-14 17:43:18 -080047#define free_list(type, head) do { \
48 struct type *list, *tmp; \
49 for (list = (head)->next; list;) { \
50 tmp = list; \
51 list = list->next; \
52 kfree(tmp); \
53 } \
54 (head)->next = NULL; \
55} while (0)
56
Ram Paif483d392011-07-07 11:19:10 -070057int pci_realloc_enable = 0;
58#define pci_realloc_enabled() pci_realloc_enable
59void pci_realloc(void)
60{
61 pci_realloc_enable = 1;
62}
63
Ram Paic8adf9a2011-02-14 17:43:20 -080064/**
65 * add_to_list() - add a new resource tracker to the list
66 * @head: Head of the list
67 * @dev: device corresponding to which the resource
68 * belongs
69 * @res: The resource to be tracked
70 * @add_size: additional size to be optionally added
71 * to the resource
72 */
Yinghai Luef62dfe2012-01-21 02:08:18 -080073static int add_to_list(struct resource_list_x *head,
Ram Paic8adf9a2011-02-14 17:43:20 -080074 struct pci_dev *dev, struct resource *res,
Ram Pai2bbc6942011-07-25 13:08:39 -070075 resource_size_t add_size, resource_size_t min_align)
Yinghai Lu568ddef2010-01-22 01:02:21 -080076{
77 struct resource_list_x *list = head;
78 struct resource_list_x *ln = list->next;
79 struct resource_list_x *tmp;
80
81 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
82 if (!tmp) {
Ram Paic8adf9a2011-02-14 17:43:20 -080083 pr_warning("add_to_list: kmalloc() failed!\n");
Yinghai Luef62dfe2012-01-21 02:08:18 -080084 return -ENOMEM;
Yinghai Lu568ddef2010-01-22 01:02:21 -080085 }
86
87 tmp->next = ln;
88 tmp->res = res;
89 tmp->dev = dev;
90 tmp->start = res->start;
91 tmp->end = res->end;
92 tmp->flags = res->flags;
Ram Paic8adf9a2011-02-14 17:43:20 -080093 tmp->add_size = add_size;
Ram Pai2bbc6942011-07-25 13:08:39 -070094 tmp->min_align = min_align;
Yinghai Lu568ddef2010-01-22 01:02:21 -080095 list->next = tmp;
Yinghai Luef62dfe2012-01-21 02:08:18 -080096
97 return 0;
Yinghai Lu568ddef2010-01-22 01:02:21 -080098}
99
Ram Paic8adf9a2011-02-14 17:43:20 -0800100static void add_to_failed_list(struct resource_list_x *head,
101 struct pci_dev *dev, struct resource *res)
102{
Ram Pai2bbc6942011-07-25 13:08:39 -0700103 add_to_list(head, dev, res,
104 0 /* dont care */,
105 0 /* dont care */);
Ram Paic8adf9a2011-02-14 17:43:20 -0800106}
107
Yinghai Lu3e6e0d82012-01-21 02:08:20 -0800108static void remove_from_list(struct resource_list_x *realloc_head,
109 struct resource *res)
110{
111 struct resource_list_x *prev, *tmp, *list;
112
113 prev = realloc_head;
114 for (list = realloc_head->next; list;) {
115 if (list->res != res) {
116 prev = list;
117 list = list->next;
118 continue;
119 }
120 tmp = list;
121 prev->next = list = list->next;
122 kfree(tmp);
123 }
124}
125
Yinghai Lu1c372352012-01-21 02:08:19 -0800126static resource_size_t get_res_add_size(struct resource_list_x *realloc_head,
127 struct resource *res)
128{
129 struct resource_list_x *list;
130
131 /* check if it is in realloc_head list */
132 for (list = realloc_head->next; list && list->res != res;
133 list = list->next)
134 ;
Yinghai Lu3e6e0d82012-01-21 02:08:20 -0800135
136 if (list) {
137 dev_printk(KERN_DEBUG, &list->dev->dev,
138 "%pR get_res_add_size add_size %llx\n",
139 list->res, (unsigned long long)list->add_size);
Yinghai Lu1c372352012-01-21 02:08:19 -0800140 return list->add_size;
Yinghai Lu3e6e0d82012-01-21 02:08:20 -0800141 }
Yinghai Lu1c372352012-01-21 02:08:19 -0800142
143 return 0;
144}
145
Yinghai Lu78c3b322012-01-21 02:08:25 -0800146/* Sort resources by alignment */
147static void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
148{
149 int i;
150
151 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
152 struct resource *r;
153 struct resource_list *list, *tmp;
154 resource_size_t r_align;
155
156 r = &dev->resource[i];
157
158 if (r->flags & IORESOURCE_PCI_FIXED)
159 continue;
160
161 if (!(r->flags) || r->parent)
162 continue;
163
164 r_align = pci_resource_alignment(dev, r);
165 if (!r_align) {
166 dev_warn(&dev->dev, "BAR %d: %pR has bogus alignment\n",
167 i, r);
168 continue;
169 }
170 for (list = head; ; list = list->next) {
171 resource_size_t align = 0;
172 struct resource_list *ln = list->next;
173
174 if (ln)
175 align = pci_resource_alignment(ln->dev, ln->res);
176
177 if (r_align > align) {
178 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
179 if (!tmp)
180 panic("pdev_sort_resources(): "
181 "kmalloc() failed!\n");
182 tmp->next = ln;
183 tmp->res = r;
184 tmp->dev = dev;
185 list->next = tmp;
186 break;
187 }
188 }
189 }
190}
191
Yinghai Lu6841ec62010-01-22 01:02:25 -0800192static void __dev_sort_resources(struct pci_dev *dev,
193 struct resource_list *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194{
Yinghai Lu6841ec62010-01-22 01:02:25 -0800195 u16 class = dev->class >> 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
Yinghai Lu6841ec62010-01-22 01:02:25 -0800197 /* Don't touch classless devices or host bridges or ioapics. */
198 if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
199 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
Yinghai Lu6841ec62010-01-22 01:02:25 -0800201 /* Don't touch ioapic devices already enabled by firmware */
202 if (class == PCI_CLASS_SYSTEM_PIC) {
203 u16 command;
204 pci_read_config_word(dev, PCI_COMMAND, &command);
205 if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY))
206 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 }
208
Yinghai Lu6841ec62010-01-22 01:02:25 -0800209 pdev_sort_resources(dev, head);
210}
211
Ram Paifc075e12011-02-14 17:43:19 -0800212static inline void reset_resource(struct resource *res)
213{
214 res->start = 0;
215 res->end = 0;
216 res->flags = 0;
217}
218
Ram Paic8adf9a2011-02-14 17:43:20 -0800219/**
Ram Pai9e8bf932011-07-25 13:08:42 -0700220 * reassign_resources_sorted() - satisfy any additional resource requests
Ram Paic8adf9a2011-02-14 17:43:20 -0800221 *
Ram Pai9e8bf932011-07-25 13:08:42 -0700222 * @realloc_head : head of the list tracking requests requiring additional
Ram Paic8adf9a2011-02-14 17:43:20 -0800223 * resources
224 * @head : head of the list tracking requests with allocated
225 * resources
226 *
Ram Pai9e8bf932011-07-25 13:08:42 -0700227 * Walk through each element of the realloc_head and try to procure
Ram Paic8adf9a2011-02-14 17:43:20 -0800228 * additional resources for the element, provided the element
229 * is in the head list.
230 */
Ram Pai9e8bf932011-07-25 13:08:42 -0700231static void reassign_resources_sorted(struct resource_list_x *realloc_head,
Ram Paic8adf9a2011-02-14 17:43:20 -0800232 struct resource_list *head)
233{
234 struct resource *res;
235 struct resource_list_x *list, *tmp, *prev;
236 struct resource_list *hlist;
237 resource_size_t add_size;
238 int idx;
239
Ram Pai9e8bf932011-07-25 13:08:42 -0700240 prev = realloc_head;
241 for (list = realloc_head->next; list;) {
Ram Paic8adf9a2011-02-14 17:43:20 -0800242 res = list->res;
243 /* skip resource that has been reset */
244 if (!res->flags)
245 goto out;
246
247 /* skip this resource if not found in head list */
248 for (hlist = head->next; hlist && hlist->res != res;
249 hlist = hlist->next);
250 if (!hlist) { /* just skip */
251 prev = list;
252 list = list->next;
253 continue;
254 }
255
256 idx = res - &list->dev->resource[0];
257 add_size=list->add_size;
Ram Pai2bbc6942011-07-25 13:08:39 -0700258 if (!resource_size(res)) {
Ram Pai0a2daa12011-07-25 13:08:41 -0700259 res->start = list->start;
Ram Pai2bbc6942011-07-25 13:08:39 -0700260 res->end = res->start + add_size - 1;
261 if(pci_assign_resource(list->dev, idx))
Ram Paic8adf9a2011-02-14 17:43:20 -0800262 reset_resource(res);
Ram Pai2bbc6942011-07-25 13:08:39 -0700263 } else {
264 resource_size_t align = list->min_align;
265 res->flags |= list->flags & (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN);
266 if (pci_reassign_resource(list->dev, idx, add_size, align))
267 dev_printk(KERN_DEBUG, &list->dev->dev, "failed to add optional resources res=%pR\n",
268 res);
Ram Paic8adf9a2011-02-14 17:43:20 -0800269 }
270out:
271 tmp = list;
272 prev->next = list = list->next;
273 kfree(tmp);
274 }
275}
276
277/**
278 * assign_requested_resources_sorted() - satisfy resource requests
279 *
280 * @head : head of the list tracking requests for resources
281 * @failed_list : head of the list tracking requests that could
282 * not be allocated
283 *
284 * Satisfy resource requests of each element in the list. Add
285 * requests that could not satisfied to the failed_list.
286 */
287static void assign_requested_resources_sorted(struct resource_list *head,
Yinghai Lu6841ec62010-01-22 01:02:25 -0800288 struct resource_list_x *fail_head)
289{
290 struct resource *res;
Ram Paic8adf9a2011-02-14 17:43:20 -0800291 struct resource_list *list;
Yinghai Lu6841ec62010-01-22 01:02:25 -0800292 int idx;
293
Ram Paic8adf9a2011-02-14 17:43:20 -0800294 for (list = head->next; list; list = list->next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 res = list->res;
296 idx = res - &list->dev->resource[0];
Ram Paic8adf9a2011-02-14 17:43:20 -0800297 if (resource_size(res) && pci_assign_resource(list->dev, idx)) {
Yinghai Lu9a928662010-02-28 15:49:39 -0800298 if (fail_head && !pci_is_root_bus(list->dev->bus)) {
299 /*
300 * if the failed res is for ROM BAR, and it will
301 * be enabled later, don't add it to the list
302 */
303 if (!((idx == PCI_ROM_RESOURCE) &&
304 (!(res->flags & IORESOURCE_ROM_ENABLE))))
305 add_to_failed_list(fail_head, list->dev, res);
306 }
Ram Paifc075e12011-02-14 17:43:19 -0800307 reset_resource(res);
Rajesh Shah542df5d2005-04-28 00:25:50 -0700308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 }
310}
311
Ram Paic8adf9a2011-02-14 17:43:20 -0800312static void __assign_resources_sorted(struct resource_list *head,
Ram Pai9e8bf932011-07-25 13:08:42 -0700313 struct resource_list_x *realloc_head,
Ram Paic8adf9a2011-02-14 17:43:20 -0800314 struct resource_list_x *fail_head)
315{
Yinghai Lu3e6e0d82012-01-21 02:08:20 -0800316 /*
317 * Should not assign requested resources at first.
318 * they could be adjacent, so later reassign can not reallocate
319 * them one by one in parent resource window.
320 * Try to assign requested + add_size at begining
321 * if could do that, could get out early.
322 * if could not do that, we still try to assign requested at first,
323 * then try to reassign add_size for some resources.
324 */
325 struct resource_list_x save_head, local_fail_head, *list;
326 struct resource_list *l;
327
328 /* Check if optional add_size is there */
329 if (!realloc_head || !realloc_head->next)
330 goto requested_and_reassign;
331
332 /* Save original start, end, flags etc at first */
333 save_head.next = NULL;
334 for (l = head->next; l; l = l->next)
335 if (add_to_list(&save_head, l->dev, l->res, 0, 0)) {
336 free_list(resource_list_x, &save_head);
337 goto requested_and_reassign;
338 }
339
340 /* Update res in head list with add_size in realloc_head list */
341 for (l = head->next; l; l = l->next)
342 l->res->end += get_res_add_size(realloc_head, l->res);
343
344 /* Try updated head list with add_size added */
345 local_fail_head.next = NULL;
346 assign_requested_resources_sorted(head, &local_fail_head);
347
348 /* all assigned with add_size ? */
349 if (!local_fail_head.next) {
350 /* Remove head list from realloc_head list */
351 for (l = head->next; l; l = l->next)
352 remove_from_list(realloc_head, l->res);
353 free_list(resource_list_x, &save_head);
354 free_list(resource_list, head);
355 return;
356 }
357
358 free_list(resource_list_x, &local_fail_head);
359 /* Release assigned resource */
360 for (l = head->next; l; l = l->next)
361 if (l->res->parent)
362 release_resource(l->res);
363 /* Restore start/end/flags from saved list */
364 for (list = save_head.next; list; list = list->next) {
365 struct resource *res = list->res;
366
367 res->start = list->start;
368 res->end = list->end;
369 res->flags = list->flags;
370 }
371 free_list(resource_list_x, &save_head);
372
373requested_and_reassign:
Ram Paic8adf9a2011-02-14 17:43:20 -0800374 /* Satisfy the must-have resource requests */
375 assign_requested_resources_sorted(head, fail_head);
376
Ram Pai0a2daa12011-07-25 13:08:41 -0700377 /* Try to satisfy any additional optional resource
Ram Paic8adf9a2011-02-14 17:43:20 -0800378 requests */
Ram Pai9e8bf932011-07-25 13:08:42 -0700379 if (realloc_head)
380 reassign_resources_sorted(realloc_head, head);
Ram Paic8adf9a2011-02-14 17:43:20 -0800381 free_list(resource_list, head);
382}
383
Yinghai Lu6841ec62010-01-22 01:02:25 -0800384static void pdev_assign_resources_sorted(struct pci_dev *dev,
Yinghai Lu8424d752012-01-21 02:08:21 -0800385 struct resource_list_x *add_head,
Yinghai Lu6841ec62010-01-22 01:02:25 -0800386 struct resource_list_x *fail_head)
387{
388 struct resource_list head;
389
390 head.next = NULL;
391 __dev_sort_resources(dev, &head);
Yinghai Lu8424d752012-01-21 02:08:21 -0800392 __assign_resources_sorted(&head, add_head, fail_head);
Yinghai Lu6841ec62010-01-22 01:02:25 -0800393
394}
395
396static void pbus_assign_resources_sorted(const struct pci_bus *bus,
Ram Pai9e8bf932011-07-25 13:08:42 -0700397 struct resource_list_x *realloc_head,
Yinghai Lu6841ec62010-01-22 01:02:25 -0800398 struct resource_list_x *fail_head)
399{
400 struct pci_dev *dev;
401 struct resource_list head;
402
403 head.next = NULL;
404 list_for_each_entry(dev, &bus->devices, bus_list)
405 __dev_sort_resources(dev, &head);
406
Ram Pai9e8bf932011-07-25 13:08:42 -0700407 __assign_resources_sorted(&head, realloc_head, fail_head);
Yinghai Lu6841ec62010-01-22 01:02:25 -0800408}
409
Dominik Brodowskib3743fa2005-09-09 13:03:23 -0700410void pci_setup_cardbus(struct pci_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411{
412 struct pci_dev *bridge = bus->self;
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600413 struct resource *res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 struct pci_bus_region region;
415
Bjorn Helgaas865df572009-11-04 10:32:57 -0700416 dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n",
417 bus->secondary, bus->subordinate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600419 res = bus->resource[0];
420 pcibios_resource_to_bus(bridge, &region, res);
421 if (res->flags & IORESOURCE_IO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 /*
423 * The IO resource is allocated a range twice as large as it
424 * would normally need. This allows us to set both IO regs.
425 */
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600426 dev_info(&bridge->dev, " bridge window %pR\n", res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
428 region.start);
429 pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
430 region.end);
431 }
432
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600433 res = bus->resource[1];
434 pcibios_resource_to_bus(bridge, &region, res);
435 if (res->flags & IORESOURCE_IO) {
436 dev_info(&bridge->dev, " bridge window %pR\n", res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
438 region.start);
439 pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
440 region.end);
441 }
442
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600443 res = bus->resource[2];
444 pcibios_resource_to_bus(bridge, &region, res);
445 if (res->flags & IORESOURCE_MEM) {
446 dev_info(&bridge->dev, " bridge window %pR\n", res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
448 region.start);
449 pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
450 region.end);
451 }
452
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600453 res = bus->resource[3];
454 pcibios_resource_to_bus(bridge, &region, res);
455 if (res->flags & IORESOURCE_MEM) {
456 dev_info(&bridge->dev, " bridge window %pR\n", res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
458 region.start);
459 pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
460 region.end);
461 }
462}
Dominik Brodowskib3743fa2005-09-09 13:03:23 -0700463EXPORT_SYMBOL(pci_setup_cardbus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
465/* Initialize bridges with base/limit values we have collected.
466 PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
467 requires that if there is no I/O ports or memory behind the
468 bridge, corresponding range must be turned off by writing base
469 value greater than limit to the bridge's base/limit registers.
470
471 Note: care must be taken when updating I/O base/limit registers
472 of bridges which support 32-bit I/O. This update requires two
473 config space writes, so it's quite possible that an I/O window of
474 the bridge will have some undesirable address (e.g. 0) after the
475 first write. Ditto 64-bit prefetchable MMIO. */
Yinghai Lu7cc59972009-12-22 15:02:21 -0800476static void pci_setup_bridge_io(struct pci_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477{
478 struct pci_dev *bridge = bus->self;
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600479 struct resource *res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 struct pci_bus_region region;
Yinghai Lu7cc59972009-12-22 15:02:21 -0800481 u32 l, io_upper16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
483 /* Set up the top and bottom of the PCI I/O segment for this bus. */
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600484 res = bus->resource[0];
485 pcibios_resource_to_bus(bridge, &region, res);
486 if (res->flags & IORESOURCE_IO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 pci_read_config_dword(bridge, PCI_IO_BASE, &l);
488 l &= 0xffff0000;
489 l |= (region.start >> 8) & 0x00f0;
490 l |= region.end & 0xf000;
491 /* Set up upper 16 bits of I/O base/limit. */
492 io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600493 dev_info(&bridge->dev, " bridge window %pR\n", res);
Yinghai Lu7cc59972009-12-22 15:02:21 -0800494 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 /* Clear upper 16 bits of I/O base/limit. */
496 io_upper16 = 0;
497 l = 0x00f0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 }
499 /* Temporarily disable the I/O range before updating PCI_IO_BASE. */
500 pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
501 /* Update lower 16 bits of I/O base/limit. */
502 pci_write_config_dword(bridge, PCI_IO_BASE, l);
503 /* Update upper 16 bits of I/O base/limit. */
504 pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16);
Yinghai Lu7cc59972009-12-22 15:02:21 -0800505}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Yinghai Lu7cc59972009-12-22 15:02:21 -0800507static void pci_setup_bridge_mmio(struct pci_bus *bus)
508{
509 struct pci_dev *bridge = bus->self;
510 struct resource *res;
511 struct pci_bus_region region;
512 u32 l;
513
514 /* Set up the top and bottom of the PCI Memory segment for this bus. */
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600515 res = bus->resource[1];
516 pcibios_resource_to_bus(bridge, &region, res);
517 if (res->flags & IORESOURCE_MEM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 l = (region.start >> 16) & 0xfff0;
519 l |= region.end & 0xfff00000;
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600520 dev_info(&bridge->dev, " bridge window %pR\n", res);
Yinghai Lu7cc59972009-12-22 15:02:21 -0800521 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 l = 0x0000fff0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 }
524 pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
Yinghai Lu7cc59972009-12-22 15:02:21 -0800525}
526
527static void pci_setup_bridge_mmio_pref(struct pci_bus *bus)
528{
529 struct pci_dev *bridge = bus->self;
530 struct resource *res;
531 struct pci_bus_region region;
532 u32 l, bu, lu;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
534 /* Clear out the upper 32 bits of PREF limit.
535 If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily
536 disables PREF range, which is ok. */
537 pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
538
539 /* Set up PREF base/limit. */
Benjamin Herrenschmidtc40a22e2007-12-10 17:32:15 +1100540 bu = lu = 0;
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600541 res = bus->resource[2];
542 pcibios_resource_to_bus(bridge, &region, res);
543 if (res->flags & IORESOURCE_PREFETCH) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 l = (region.start >> 16) & 0xfff0;
545 l |= region.end & 0xfff00000;
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600546 if (res->flags & IORESOURCE_MEM_64) {
Yinghai Lu1f82de12009-04-23 20:48:32 -0700547 bu = upper_32_bits(region.start);
548 lu = upper_32_bits(region.end);
Yinghai Lu1f82de12009-04-23 20:48:32 -0700549 }
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -0600550 dev_info(&bridge->dev, " bridge window %pR\n", res);
Yinghai Lu7cc59972009-12-22 15:02:21 -0800551 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 l = 0x0000fff0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 }
554 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
555
Alex Williamson59353ea2009-11-30 14:51:44 -0700556 /* Set the upper 32 bits of PREF base & limit. */
557 pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
558 pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
Yinghai Lu7cc59972009-12-22 15:02:21 -0800559}
560
561static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
562{
563 struct pci_dev *bridge = bus->self;
564
Yinghai Lu7cc59972009-12-22 15:02:21 -0800565 dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n",
566 bus->secondary, bus->subordinate);
567
568 if (type & IORESOURCE_IO)
569 pci_setup_bridge_io(bus);
570
571 if (type & IORESOURCE_MEM)
572 pci_setup_bridge_mmio(bus);
573
574 if (type & IORESOURCE_PREFETCH)
575 pci_setup_bridge_mmio_pref(bus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576
577 pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
578}
579
Benjamin Herrenschmidte2444272011-09-11 14:08:38 -0300580void pci_setup_bridge(struct pci_bus *bus)
Yinghai Lu7cc59972009-12-22 15:02:21 -0800581{
582 unsigned long type = IORESOURCE_IO | IORESOURCE_MEM |
583 IORESOURCE_PREFETCH;
584
585 __pci_setup_bridge(bus, type);
586}
587
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588/* Check whether the bridge supports optional I/O and
589 prefetchable memory ranges. If not, the respective
590 base/limit registers must be read-only and read as 0. */
Sam Ravnborg96bde062007-03-26 21:53:30 -0800591static void pci_bridge_check_ranges(struct pci_bus *bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592{
593 u16 io;
594 u32 pmem;
595 struct pci_dev *bridge = bus->self;
596 struct resource *b_res;
597
598 b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
599 b_res[1].flags |= IORESOURCE_MEM;
600
601 pci_read_config_word(bridge, PCI_IO_BASE, &io);
602 if (!io) {
603 pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0);
604 pci_read_config_word(bridge, PCI_IO_BASE, &io);
605 pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
606 }
607 if (io)
608 b_res[0].flags |= IORESOURCE_IO;
609 /* DECchip 21050 pass 2 errata: the bridge may miss an address
610 disconnect boundary by one PCI data phase.
611 Workaround: do not use prefetching on this device. */
612 if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001)
613 return;
614 pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
615 if (!pmem) {
616 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE,
617 0xfff0fff0);
618 pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
619 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);
620 }
Yinghai Lu1f82de12009-04-23 20:48:32 -0700621 if (pmem) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
Yinghai Lu99586102010-01-22 01:02:28 -0800623 if ((pmem & PCI_PREF_RANGE_TYPE_MASK) ==
624 PCI_PREF_RANGE_TYPE_64) {
Yinghai Lu1f82de12009-04-23 20:48:32 -0700625 b_res[2].flags |= IORESOURCE_MEM_64;
Yinghai Lu99586102010-01-22 01:02:28 -0800626 b_res[2].flags |= PCI_PREF_RANGE_TYPE_64;
627 }
Yinghai Lu1f82de12009-04-23 20:48:32 -0700628 }
629
630 /* double check if bridge does support 64 bit pref */
631 if (b_res[2].flags & IORESOURCE_MEM_64) {
632 u32 mem_base_hi, tmp;
633 pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32,
634 &mem_base_hi);
635 pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
636 0xffffffff);
637 pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp);
638 if (!tmp)
639 b_res[2].flags &= ~IORESOURCE_MEM_64;
640 pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
641 mem_base_hi);
642 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643}
644
645/* Helper function for sizing routines: find first available
646 bus resource of a given type. Note: we intentionally skip
647 the bus resources which have already been assigned (that is,
648 have non-NULL parent resource). */
Sam Ravnborg96bde062007-03-26 21:53:30 -0800649static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned long type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650{
651 int i;
652 struct resource *r;
653 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
654 IORESOURCE_PREFETCH;
655
Bjorn Helgaas89a74ec2010-02-23 10:24:31 -0700656 pci_bus_for_each_resource(bus, r, i) {
Ivan Kokshaysky299de032005-06-15 18:59:27 +0400657 if (r == &ioport_resource || r == &iomem_resource)
658 continue;
Jesse Barnes55a10982009-10-27 09:39:18 -0700659 if (r && (r->flags & type_mask) == type && !r->parent)
660 return r;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 }
662 return NULL;
663}
664
Ram Pai13583b12011-02-14 17:43:17 -0800665static resource_size_t calculate_iosize(resource_size_t size,
666 resource_size_t min_size,
667 resource_size_t size1,
668 resource_size_t old_size,
669 resource_size_t align)
670{
671 if (size < min_size)
672 size = min_size;
673 if (old_size == 1 )
674 old_size = 0;
675 /* To be fixed in 2.5: we should have sort of HAVE_ISA
676 flag in the struct pci_bus. */
677#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
678 size = (size & 0xff) + ((size & ~0xffUL) << 2);
679#endif
680 size = ALIGN(size + size1, align);
681 if (size < old_size)
682 size = old_size;
683 return size;
684}
685
686static resource_size_t calculate_memsize(resource_size_t size,
687 resource_size_t min_size,
688 resource_size_t size1,
689 resource_size_t old_size,
690 resource_size_t align)
691{
692 if (size < min_size)
693 size = min_size;
694 if (old_size == 1 )
695 old_size = 0;
696 if (size < old_size)
697 size = old_size;
698 size = ALIGN(size + size1, align);
699 return size;
700}
701
Ram Paic8adf9a2011-02-14 17:43:20 -0800702/**
703 * pbus_size_io() - size the io window of a given bus
704 *
705 * @bus : the bus
706 * @min_size : the minimum io window that must to be allocated
707 * @add_size : additional optional io window
Ram Pai9e8bf932011-07-25 13:08:42 -0700708 * @realloc_head : track the additional io window on this list
Ram Paic8adf9a2011-02-14 17:43:20 -0800709 *
710 * Sizing the IO windows of the PCI-PCI bridge is trivial,
711 * since these windows have 4K granularity and the IO ranges
712 * of non-bridge PCI devices are limited to 256 bytes.
713 * We must be careful with the ISA aliasing though.
714 */
715static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
Ram Pai9e8bf932011-07-25 13:08:42 -0700716 resource_size_t add_size, struct resource_list_x *realloc_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717{
718 struct pci_dev *dev;
719 struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
Ram Paic8adf9a2011-02-14 17:43:20 -0800720 unsigned long size = 0, size0 = 0, size1 = 0;
Yinghai Lube768912011-07-25 13:08:38 -0700721 resource_size_t children_add_size = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
723 if (!b_res)
724 return;
725
726 list_for_each_entry(dev, &bus->devices, bus_list) {
727 int i;
728
729 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
730 struct resource *r = &dev->resource[i];
731 unsigned long r_size;
732
733 if (r->parent || !(r->flags & IORESOURCE_IO))
734 continue;
Zhao, Yu022edd82008-10-13 19:24:28 +0800735 r_size = resource_size(r);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
737 if (r_size < 0x400)
738 /* Might be re-aligned for ISA */
739 size += r_size;
740 else
741 size1 += r_size;
Yinghai Lube768912011-07-25 13:08:38 -0700742
Ram Pai9e8bf932011-07-25 13:08:42 -0700743 if (realloc_head)
744 children_add_size += get_res_add_size(realloc_head, r);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 }
746 }
Ram Paic8adf9a2011-02-14 17:43:20 -0800747 size0 = calculate_iosize(size, min_size, size1,
Ram Pai13583b12011-02-14 17:43:17 -0800748 resource_size(b_res), 4096);
Yinghai Lube768912011-07-25 13:08:38 -0700749 if (children_add_size > add_size)
750 add_size = children_add_size;
Ram Pai9e8bf932011-07-25 13:08:42 -0700751 size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
Yinghai Lua4ac9fe2012-01-21 02:08:17 -0800752 calculate_iosize(size, min_size, add_size + size1,
Ram Paic8adf9a2011-02-14 17:43:20 -0800753 resource_size(b_res), 4096);
754 if (!size0 && !size1) {
Bjorn Helgaas865df572009-11-04 10:32:57 -0700755 if (b_res->start || b_res->end)
756 dev_info(&bus->self->dev, "disabling bridge window "
757 "%pR to [bus %02x-%02x] (unused)\n", b_res,
758 bus->secondary, bus->subordinate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 b_res->flags = 0;
760 return;
761 }
762 /* Alignment of the IO window is always 4K */
763 b_res->start = 4096;
Ram Paic8adf9a2011-02-14 17:43:20 -0800764 b_res->end = b_res->start + size0 - 1;
Ivan Kokshaysky88452562008-03-30 19:50:14 +0400765 b_res->flags |= IORESOURCE_STARTALIGN;
Ram Pai9e8bf932011-07-25 13:08:42 -0700766 if (size1 > size0 && realloc_head)
767 add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768}
769
Ram Paic8adf9a2011-02-14 17:43:20 -0800770/**
771 * pbus_size_mem() - size the memory window of a given bus
772 *
773 * @bus : the bus
774 * @min_size : the minimum memory window that must to be allocated
775 * @add_size : additional optional memory window
Ram Pai9e8bf932011-07-25 13:08:42 -0700776 * @realloc_head : track the additional memory window on this list
Ram Paic8adf9a2011-02-14 17:43:20 -0800777 *
778 * Calculate the size of the bus and minimal alignment which
779 * guarantees that all child resources fit in this size.
780 */
Eric W. Biederman28760482009-09-09 14:09:24 -0700781static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
Ram Paic8adf9a2011-02-14 17:43:20 -0800782 unsigned long type, resource_size_t min_size,
783 resource_size_t add_size,
Ram Pai9e8bf932011-07-25 13:08:42 -0700784 struct resource_list_x *realloc_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
786 struct pci_dev *dev;
Ram Paic8adf9a2011-02-14 17:43:20 -0800787 resource_size_t min_align, align, size, size0, size1;
Benjamin Herrenschmidtc40a22e2007-12-10 17:32:15 +1100788 resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 int order, max_order;
790 struct resource *b_res = find_free_bus_resource(bus, type);
Yinghai Lu1f82de12009-04-23 20:48:32 -0700791 unsigned int mem64_mask = 0;
Yinghai Lube768912011-07-25 13:08:38 -0700792 resource_size_t children_add_size = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793
794 if (!b_res)
795 return 0;
796
797 memset(aligns, 0, sizeof(aligns));
798 max_order = 0;
799 size = 0;
800
Yinghai Lu1f82de12009-04-23 20:48:32 -0700801 mem64_mask = b_res->flags & IORESOURCE_MEM_64;
802 b_res->flags &= ~IORESOURCE_MEM_64;
803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 list_for_each_entry(dev, &bus->devices, bus_list) {
805 int i;
Yinghai Lu1f82de12009-04-23 20:48:32 -0700806
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
808 struct resource *r = &dev->resource[i];
Benjamin Herrenschmidtc40a22e2007-12-10 17:32:15 +1100809 resource_size_t r_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
811 if (r->parent || (r->flags & mask) != type)
812 continue;
Zhao, Yu022edd82008-10-13 19:24:28 +0800813 r_size = resource_size(r);
Yinghai Lu2aceefc2011-07-25 13:08:40 -0700814#ifdef CONFIG_PCI_IOV
815 /* put SRIOV requested res to the optional list */
Ram Pai9e8bf932011-07-25 13:08:42 -0700816 if (realloc_head && i >= PCI_IOV_RESOURCES &&
Yinghai Lu2aceefc2011-07-25 13:08:40 -0700817 i <= PCI_IOV_RESOURCE_END) {
818 r->end = r->start - 1;
Ram Pai9e8bf932011-07-25 13:08:42 -0700819 add_to_list(realloc_head, dev, r, r_size, 0/* dont' care */);
Yinghai Lu2aceefc2011-07-25 13:08:40 -0700820 children_add_size += r_size;
821 continue;
822 }
823#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 /* For bridges size != alignment */
Chris Wright6faf17f2009-08-28 13:00:06 -0700825 align = pci_resource_alignment(dev, r);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 order = __ffs(align) - 20;
827 if (order > 11) {
Bjorn Helgaas865df572009-11-04 10:32:57 -0700828 dev_warn(&dev->dev, "disabling BAR %d: %pR "
829 "(bad alignment %#llx)\n", i, r,
830 (unsigned long long) align);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 r->flags = 0;
832 continue;
833 }
834 size += r_size;
835 if (order < 0)
836 order = 0;
837 /* Exclude ranges with size > align from
838 calculation of the alignment. */
839 if (r_size == align)
840 aligns[order] += align;
841 if (order > max_order)
842 max_order = order;
Yinghai Lu1f82de12009-04-23 20:48:32 -0700843 mem64_mask &= r->flags & IORESOURCE_MEM_64;
Yinghai Lube768912011-07-25 13:08:38 -0700844
Ram Pai9e8bf932011-07-25 13:08:42 -0700845 if (realloc_head)
846 children_add_size += get_res_add_size(realloc_head, r);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 }
848 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 align = 0;
850 min_align = 0;
851 for (order = 0; order <= max_order; order++) {
Jeremy Fitzhardinge8308c542008-09-11 01:31:50 -0700852 resource_size_t align1 = 1;
853
854 align1 <<= (order + 20);
855
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 if (!align)
857 min_align = align1;
Milind Arun Choudhary6f6f8c22007-07-09 11:55:51 -0700858 else if (ALIGN(align + min_align, min_align) < align1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 min_align = align1 >> 1;
860 align += aligns[order];
861 }
Linus Torvaldsb42282e2011-04-11 10:53:11 -0700862 size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
Yinghai Lube768912011-07-25 13:08:38 -0700863 if (children_add_size > add_size)
864 add_size = children_add_size;
Ram Pai9e8bf932011-07-25 13:08:42 -0700865 size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
Yinghai Lua4ac9fe2012-01-21 02:08:17 -0800866 calculate_memsize(size, min_size, add_size,
Linus Torvaldsb42282e2011-04-11 10:53:11 -0700867 resource_size(b_res), min_align);
Ram Paic8adf9a2011-02-14 17:43:20 -0800868 if (!size0 && !size1) {
Bjorn Helgaas865df572009-11-04 10:32:57 -0700869 if (b_res->start || b_res->end)
870 dev_info(&bus->self->dev, "disabling bridge window "
871 "%pR to [bus %02x-%02x] (unused)\n", b_res,
872 bus->secondary, bus->subordinate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 b_res->flags = 0;
874 return 1;
875 }
876 b_res->start = min_align;
Ram Paic8adf9a2011-02-14 17:43:20 -0800877 b_res->end = size0 + min_align - 1;
878 b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask;
Ram Pai9e8bf932011-07-25 13:08:42 -0700879 if (size1 > size0 && realloc_head)
880 add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 return 1;
882}
883
Ram Pai0a2daa12011-07-25 13:08:41 -0700884unsigned long pci_cardbus_resource_alignment(struct resource *res)
885{
886 if (res->flags & IORESOURCE_IO)
887 return pci_cardbus_io_size;
888 if (res->flags & IORESOURCE_MEM)
889 return pci_cardbus_mem_size;
890 return 0;
891}
892
893static void pci_bus_size_cardbus(struct pci_bus *bus,
Ram Pai9e8bf932011-07-25 13:08:42 -0700894 struct resource_list_x *realloc_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895{
896 struct pci_dev *bridge = bus->self;
897 struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
898 u16 ctrl;
899
900 /*
901 * Reserve some resources for CardBus. We reserve
902 * a fixed amount of bus space for CardBus bridges.
903 */
Linus Torvalds934b7022008-04-22 18:16:30 -0700904 b_res[0].start = 0;
Linus Torvalds934b7022008-04-22 18:16:30 -0700905 b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
Ram Pai9e8bf932011-07-25 13:08:42 -0700906 if (realloc_head)
907 add_to_list(realloc_head, bridge, b_res, pci_cardbus_io_size, 0 /* dont care */);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908
Linus Torvalds934b7022008-04-22 18:16:30 -0700909 b_res[1].start = 0;
Linus Torvalds934b7022008-04-22 18:16:30 -0700910 b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
Ram Pai9e8bf932011-07-25 13:08:42 -0700911 if (realloc_head)
912 add_to_list(realloc_head, bridge, b_res+1, pci_cardbus_io_size, 0 /* dont care */);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913
914 /*
915 * Check whether prefetchable memory is supported
916 * by this bridge.
917 */
918 pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
919 if (!(ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0)) {
920 ctrl |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
921 pci_write_config_word(bridge, PCI_CB_BRIDGE_CONTROL, ctrl);
922 pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
923 }
924
925 /*
926 * If we have prefetchable memory support, allocate
927 * two regions. Otherwise, allocate one region of
928 * twice the size.
929 */
930 if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
Linus Torvalds934b7022008-04-22 18:16:30 -0700931 b_res[2].start = 0;
Linus Torvalds934b7022008-04-22 18:16:30 -0700932 b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN;
Ram Pai9e8bf932011-07-25 13:08:42 -0700933 if (realloc_head)
934 add_to_list(realloc_head, bridge, b_res+2, pci_cardbus_mem_size, 0 /* dont care */);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
Linus Torvalds934b7022008-04-22 18:16:30 -0700936 b_res[3].start = 0;
Linus Torvalds934b7022008-04-22 18:16:30 -0700937 b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
Ram Pai9e8bf932011-07-25 13:08:42 -0700938 if (realloc_head)
939 add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size, 0 /* dont care */);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 } else {
Linus Torvalds934b7022008-04-22 18:16:30 -0700941 b_res[3].start = 0;
Linus Torvalds934b7022008-04-22 18:16:30 -0700942 b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
Ram Pai9e8bf932011-07-25 13:08:42 -0700943 if (realloc_head)
944 add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size * 2, 0 /* dont care */);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 }
Ram Pai0a2daa12011-07-25 13:08:41 -0700946
947 /* set the size of the resource to zero, so that the resource does not
948 * get assigned during required-resource allocation cycle but gets assigned
949 * during the optional-resource allocation cycle.
950 */
951 b_res[0].start = b_res[1].start = b_res[2].start = b_res[3].start = 1;
952 b_res[0].end = b_res[1].end = b_res[2].end = b_res[3].end = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953}
954
Ram Paic8adf9a2011-02-14 17:43:20 -0800955void __ref __pci_bus_size_bridges(struct pci_bus *bus,
Ram Pai9e8bf932011-07-25 13:08:42 -0700956 struct resource_list_x *realloc_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957{
958 struct pci_dev *dev;
959 unsigned long mask, prefmask;
Ram Paic8adf9a2011-02-14 17:43:20 -0800960 resource_size_t additional_mem_size = 0, additional_io_size = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961
962 list_for_each_entry(dev, &bus->devices, bus_list) {
963 struct pci_bus *b = dev->subordinate;
964 if (!b)
965 continue;
966
967 switch (dev->class >> 8) {
968 case PCI_CLASS_BRIDGE_CARDBUS:
Ram Pai9e8bf932011-07-25 13:08:42 -0700969 pci_bus_size_cardbus(b, realloc_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 break;
971
972 case PCI_CLASS_BRIDGE_PCI:
973 default:
Ram Pai9e8bf932011-07-25 13:08:42 -0700974 __pci_bus_size_bridges(b, realloc_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 break;
976 }
977 }
978
979 /* The root bus? */
980 if (!bus->self)
981 return;
982
983 switch (bus->self->class >> 8) {
984 case PCI_CLASS_BRIDGE_CARDBUS:
985 /* don't size cardbuses yet. */
986 break;
987
988 case PCI_CLASS_BRIDGE_PCI:
989 pci_bridge_check_ranges(bus);
Eric W. Biederman28760482009-09-09 14:09:24 -0700990 if (bus->self->is_hotplug_bridge) {
Ram Paic8adf9a2011-02-14 17:43:20 -0800991 additional_io_size = pci_hotplug_io_size;
992 additional_mem_size = pci_hotplug_mem_size;
Eric W. Biederman28760482009-09-09 14:09:24 -0700993 }
Ram Paic8adf9a2011-02-14 17:43:20 -0800994 /*
995 * Follow thru
996 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 default:
Yinghai Lu19aa7ee2012-01-21 02:08:24 -0800998 pbus_size_io(bus, realloc_head ? 0 : additional_io_size,
999 additional_io_size, realloc_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 /* If the bridge supports prefetchable range, size it
1001 separately. If it doesn't, or its prefetchable window
1002 has already been allocated by arch code, try
1003 non-prefetchable range for both types of PCI memory
1004 resources. */
1005 mask = IORESOURCE_MEM;
1006 prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
Yinghai Lu19aa7ee2012-01-21 02:08:24 -08001007 if (pbus_size_mem(bus, prefmask, prefmask,
1008 realloc_head ? 0 : additional_mem_size,
1009 additional_mem_size, realloc_head))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 mask = prefmask; /* Success, size non-prefetch only. */
Eric W. Biederman28760482009-09-09 14:09:24 -07001011 else
Ram Paic8adf9a2011-02-14 17:43:20 -08001012 additional_mem_size += additional_mem_size;
Yinghai Lu19aa7ee2012-01-21 02:08:24 -08001013 pbus_size_mem(bus, mask, IORESOURCE_MEM,
1014 realloc_head ? 0 : additional_mem_size,
1015 additional_mem_size, realloc_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 break;
1017 }
1018}
Ram Paic8adf9a2011-02-14 17:43:20 -08001019
1020void __ref pci_bus_size_bridges(struct pci_bus *bus)
1021{
1022 __pci_bus_size_bridges(bus, NULL);
1023}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024EXPORT_SYMBOL(pci_bus_size_bridges);
1025
Yinghai Lu568ddef2010-01-22 01:02:21 -08001026static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
Ram Pai9e8bf932011-07-25 13:08:42 -07001027 struct resource_list_x *realloc_head,
Yinghai Lu568ddef2010-01-22 01:02:21 -08001028 struct resource_list_x *fail_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029{
1030 struct pci_bus *b;
1031 struct pci_dev *dev;
1032
Ram Pai9e8bf932011-07-25 13:08:42 -07001033 pbus_assign_resources_sorted(bus, realloc_head, fail_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 list_for_each_entry(dev, &bus->devices, bus_list) {
1036 b = dev->subordinate;
1037 if (!b)
1038 continue;
1039
Ram Pai9e8bf932011-07-25 13:08:42 -07001040 __pci_bus_assign_resources(b, realloc_head, fail_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041
1042 switch (dev->class >> 8) {
1043 case PCI_CLASS_BRIDGE_PCI:
Yinghai Lu6841ec62010-01-22 01:02:25 -08001044 if (!pci_is_enabled(dev))
1045 pci_setup_bridge(b);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 break;
1047
1048 case PCI_CLASS_BRIDGE_CARDBUS:
1049 pci_setup_cardbus(b);
1050 break;
1051
1052 default:
Bjorn Helgaas80ccba12008-06-13 10:52:11 -06001053 dev_info(&dev->dev, "not setting up bridge for bus "
1054 "%04x:%02x\n", pci_domain_nr(b), b->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 break;
1056 }
1057 }
1058}
Yinghai Lu568ddef2010-01-22 01:02:21 -08001059
1060void __ref pci_bus_assign_resources(const struct pci_bus *bus)
1061{
Ram Paic8adf9a2011-02-14 17:43:20 -08001062 __pci_bus_assign_resources(bus, NULL, NULL);
Yinghai Lu568ddef2010-01-22 01:02:21 -08001063}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064EXPORT_SYMBOL(pci_bus_assign_resources);
1065
Yinghai Lu6841ec62010-01-22 01:02:25 -08001066static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge,
Yinghai Lu8424d752012-01-21 02:08:21 -08001067 struct resource_list_x *add_head,
Yinghai Lu6841ec62010-01-22 01:02:25 -08001068 struct resource_list_x *fail_head)
1069{
1070 struct pci_bus *b;
1071
Yinghai Lu8424d752012-01-21 02:08:21 -08001072 pdev_assign_resources_sorted((struct pci_dev *)bridge,
1073 add_head, fail_head);
Yinghai Lu6841ec62010-01-22 01:02:25 -08001074
1075 b = bridge->subordinate;
1076 if (!b)
1077 return;
1078
Yinghai Lu8424d752012-01-21 02:08:21 -08001079 __pci_bus_assign_resources(b, add_head, fail_head);
Yinghai Lu6841ec62010-01-22 01:02:25 -08001080
1081 switch (bridge->class >> 8) {
1082 case PCI_CLASS_BRIDGE_PCI:
1083 pci_setup_bridge(b);
1084 break;
1085
1086 case PCI_CLASS_BRIDGE_CARDBUS:
1087 pci_setup_cardbus(b);
1088 break;
1089
1090 default:
1091 dev_info(&bridge->dev, "not setting up bridge for bus "
1092 "%04x:%02x\n", pci_domain_nr(b), b->number);
1093 break;
1094 }
1095}
Yinghai Lu5009b462010-01-22 01:02:20 -08001096static void pci_bridge_release_resources(struct pci_bus *bus,
1097 unsigned long type)
1098{
1099 int idx;
1100 bool changed = false;
1101 struct pci_dev *dev;
1102 struct resource *r;
1103 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
1104 IORESOURCE_PREFETCH;
1105
1106 dev = bus->self;
1107 for (idx = PCI_BRIDGE_RESOURCES; idx <= PCI_BRIDGE_RESOURCE_END;
1108 idx++) {
1109 r = &dev->resource[idx];
1110 if ((r->flags & type_mask) != type)
1111 continue;
1112 if (!r->parent)
1113 continue;
1114 /*
1115 * if there are children under that, we should release them
1116 * all
1117 */
1118 release_child_resources(r);
1119 if (!release_resource(r)) {
1120 dev_printk(KERN_DEBUG, &dev->dev,
1121 "resource %d %pR released\n", idx, r);
1122 /* keep the old size */
1123 r->end = resource_size(r) - 1;
1124 r->start = 0;
1125 r->flags = 0;
1126 changed = true;
1127 }
1128 }
1129
1130 if (changed) {
1131 /* avoiding touch the one without PREF */
1132 if (type & IORESOURCE_PREFETCH)
1133 type = IORESOURCE_PREFETCH;
1134 __pci_setup_bridge(bus, type);
1135 }
1136}
1137
1138enum release_type {
1139 leaf_only,
1140 whole_subtree,
1141};
1142/*
1143 * try to release pci bridge resources that is from leaf bridge,
1144 * so we can allocate big new one later
1145 */
1146static void __ref pci_bus_release_bridge_resources(struct pci_bus *bus,
1147 unsigned long type,
1148 enum release_type rel_type)
1149{
1150 struct pci_dev *dev;
1151 bool is_leaf_bridge = true;
1152
1153 list_for_each_entry(dev, &bus->devices, bus_list) {
1154 struct pci_bus *b = dev->subordinate;
1155 if (!b)
1156 continue;
1157
1158 is_leaf_bridge = false;
1159
1160 if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
1161 continue;
1162
1163 if (rel_type == whole_subtree)
1164 pci_bus_release_bridge_resources(b, type,
1165 whole_subtree);
1166 }
1167
1168 if (pci_is_root_bus(bus))
1169 return;
1170
1171 if ((bus->self->class >> 8) != PCI_CLASS_BRIDGE_PCI)
1172 return;
1173
1174 if ((rel_type == whole_subtree) || is_leaf_bridge)
1175 pci_bridge_release_resources(bus, type);
1176}
1177
Yinghai Lu76fbc262008-06-23 20:33:06 +02001178static void pci_bus_dump_res(struct pci_bus *bus)
1179{
Bjorn Helgaas89a74ec2010-02-23 10:24:31 -07001180 struct resource *res;
1181 int i;
Yinghai Lu76fbc262008-06-23 20:33:06 +02001182
Bjorn Helgaas89a74ec2010-02-23 10:24:31 -07001183 pci_bus_for_each_resource(bus, res, i) {
Yinghai Lu7c9342b2009-12-22 15:02:24 -08001184 if (!res || !res->end || !res->flags)
Yinghai Lu76fbc262008-06-23 20:33:06 +02001185 continue;
1186
Bjorn Helgaasc7dabef2009-10-27 13:26:47 -06001187 dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res);
Yinghai Lu76fbc262008-06-23 20:33:06 +02001188 }
1189}
1190
1191static void pci_bus_dump_resources(struct pci_bus *bus)
1192{
1193 struct pci_bus *b;
1194 struct pci_dev *dev;
1195
1196
1197 pci_bus_dump_res(bus);
1198
1199 list_for_each_entry(dev, &bus->devices, bus_list) {
1200 b = dev->subordinate;
1201 if (!b)
1202 continue;
1203
1204 pci_bus_dump_resources(b);
1205 }
1206}
1207
Yinghai Luda7822e2011-05-12 17:11:37 -07001208static int __init pci_bus_get_depth(struct pci_bus *bus)
1209{
1210 int depth = 0;
1211 struct pci_dev *dev;
1212
1213 list_for_each_entry(dev, &bus->devices, bus_list) {
1214 int ret;
1215 struct pci_bus *b = dev->subordinate;
1216 if (!b)
1217 continue;
1218
1219 ret = pci_bus_get_depth(b);
1220 if (ret + 1 > depth)
1221 depth = ret + 1;
1222 }
1223
1224 return depth;
1225}
1226static int __init pci_get_max_depth(void)
1227{
1228 int depth = 0;
1229 struct pci_bus *bus;
1230
1231 list_for_each_entry(bus, &pci_root_buses, node) {
1232 int ret;
1233
1234 ret = pci_bus_get_depth(bus);
1235 if (ret > depth)
1236 depth = ret;
1237 }
1238
1239 return depth;
1240}
1241
Ram Paif483d392011-07-07 11:19:10 -07001242
Yinghai Luda7822e2011-05-12 17:11:37 -07001243/*
1244 * first try will not touch pci bridge res
1245 * second and later try will clear small leaf bridge res
1246 * will stop till to the max deepth if can not find good one
1247 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248void __init
1249pci_assign_unassigned_resources(void)
1250{
1251 struct pci_bus *bus;
Ram Pai9e8bf932011-07-25 13:08:42 -07001252 struct resource_list_x realloc_list; /* list of resources that
Ram Paic8adf9a2011-02-14 17:43:20 -08001253 want additional resources */
Yinghai Lu19aa7ee2012-01-21 02:08:24 -08001254 struct resource_list_x *add_list = NULL;
Yinghai Luda7822e2011-05-12 17:11:37 -07001255 int tried_times = 0;
1256 enum release_type rel_type = leaf_only;
1257 struct resource_list_x head, *list;
1258 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
1259 IORESOURCE_PREFETCH;
1260 unsigned long failed_type;
Yinghai Lu19aa7ee2012-01-21 02:08:24 -08001261 int pci_try_num = 1;
Yinghai Luda7822e2011-05-12 17:11:37 -07001262
1263 head.next = NULL;
Ram Pai9e8bf932011-07-25 13:08:42 -07001264 realloc_list.next = NULL;
Yinghai Luda7822e2011-05-12 17:11:37 -07001265
Yinghai Lu19aa7ee2012-01-21 02:08:24 -08001266 /* don't realloc if asked to do so */
1267 if (pci_realloc_enabled()) {
1268 int max_depth = pci_get_max_depth();
1269
1270 pci_try_num = max_depth + 1;
1271 printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n",
1272 max_depth, pci_try_num);
1273 }
Yinghai Luda7822e2011-05-12 17:11:37 -07001274
1275again:
Yinghai Lu19aa7ee2012-01-21 02:08:24 -08001276 /*
1277 * last try will use add_list, otherwise will try good to have as
1278 * must have, so can realloc parent bridge resource
1279 */
1280 if (tried_times + 1 == pci_try_num)
1281 add_list = &realloc_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 /* Depth first, calculate sizes and alignments of all
1283 subordinate buses. */
Yinghai Luda7822e2011-05-12 17:11:37 -07001284 list_for_each_entry(bus, &pci_root_buses, node)
Yinghai Lu19aa7ee2012-01-21 02:08:24 -08001285 __pci_bus_size_bridges(bus, add_list);
Ram Paic8adf9a2011-02-14 17:43:20 -08001286
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 /* Depth last, allocate resources and update the hardware. */
Yinghai Luda7822e2011-05-12 17:11:37 -07001288 list_for_each_entry(bus, &pci_root_buses, node)
Yinghai Lu19aa7ee2012-01-21 02:08:24 -08001289 __pci_bus_assign_resources(bus, add_list, &head);
1290 if (add_list)
1291 BUG_ON(add_list->next);
Yinghai Luda7822e2011-05-12 17:11:37 -07001292 tried_times++;
1293
1294 /* any device complain? */
1295 if (!head.next)
1296 goto enable_and_dump;
Ram Paif483d392011-07-07 11:19:10 -07001297
Yinghai Luda7822e2011-05-12 17:11:37 -07001298 failed_type = 0;
1299 for (list = head.next; list;) {
1300 failed_type |= list->flags;
1301 list = list->next;
1302 }
1303 /*
1304 * io port are tight, don't try extra
1305 * or if reach the limit, don't want to try more
1306 */
1307 failed_type &= type_mask;
1308 if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) {
1309 free_list(resource_list_x, &head);
1310 goto enable_and_dump;
1311 }
1312
1313 printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
1314 tried_times + 1);
1315
1316 /* third times and later will not check if it is leaf */
1317 if ((tried_times + 1) > 2)
1318 rel_type = whole_subtree;
1319
1320 /*
1321 * Try to release leaf bridge's resources that doesn't fit resource of
1322 * child device under that bridge
1323 */
1324 for (list = head.next; list;) {
1325 bus = list->dev->bus;
1326 pci_bus_release_bridge_resources(bus, list->flags & type_mask,
1327 rel_type);
1328 list = list->next;
1329 }
1330 /* restore size and flags */
1331 for (list = head.next; list;) {
1332 struct resource *res = list->res;
1333
1334 res->start = list->start;
1335 res->end = list->end;
1336 res->flags = list->flags;
1337 if (list->dev->subordinate)
1338 res->flags = 0;
1339
1340 list = list->next;
1341 }
1342 free_list(resource_list_x, &head);
1343
1344 goto again;
1345
1346enable_and_dump:
1347 /* Depth last, update the hardware. */
1348 list_for_each_entry(bus, &pci_root_buses, node)
1349 pci_enable_bridges(bus);
Yinghai Lu76fbc262008-06-23 20:33:06 +02001350
1351 /* dump the resource on buses */
Yinghai Luda7822e2011-05-12 17:11:37 -07001352 list_for_each_entry(bus, &pci_root_buses, node)
Yinghai Lu76fbc262008-06-23 20:33:06 +02001353 pci_bus_dump_resources(bus);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354}
Yinghai Lu6841ec62010-01-22 01:02:25 -08001355
1356void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
1357{
1358 struct pci_bus *parent = bridge->subordinate;
Yinghai Lu8424d752012-01-21 02:08:21 -08001359 struct resource_list_x add_list; /* list of resources that
1360 want additional resources */
Yinghai Lu32180e402010-01-22 01:02:27 -08001361 int tried_times = 0;
1362 struct resource_list_x head, *list;
Yinghai Lu6841ec62010-01-22 01:02:25 -08001363 int retval;
Yinghai Lu32180e402010-01-22 01:02:27 -08001364 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
1365 IORESOURCE_PREFETCH;
Yinghai Lu6841ec62010-01-22 01:02:25 -08001366
Yinghai Lu32180e402010-01-22 01:02:27 -08001367 head.next = NULL;
Yinghai Lu8424d752012-01-21 02:08:21 -08001368 add_list.next = NULL;
Yinghai Lu32180e402010-01-22 01:02:27 -08001369
1370again:
Yinghai Lu8424d752012-01-21 02:08:21 -08001371 __pci_bus_size_bridges(parent, &add_list);
1372 __pci_bridge_assign_resources(bridge, &add_list, &head);
1373 BUG_ON(add_list.next);
Yinghai Lu32180e402010-01-22 01:02:27 -08001374 tried_times++;
1375
1376 if (!head.next)
Yinghai Lu3f579c32010-05-21 14:35:06 -07001377 goto enable_all;
Yinghai Lu32180e402010-01-22 01:02:27 -08001378
1379 if (tried_times >= 2) {
1380 /* still fail, don't need to try more */
Ram Pai094732a2011-02-14 17:43:18 -08001381 free_list(resource_list_x, &head);
Yinghai Lu3f579c32010-05-21 14:35:06 -07001382 goto enable_all;
Yinghai Lu32180e402010-01-22 01:02:27 -08001383 }
1384
1385 printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
1386 tried_times + 1);
1387
1388 /*
1389 * Try to release leaf bridge's resources that doesn't fit resource of
1390 * child device under that bridge
1391 */
1392 for (list = head.next; list;) {
1393 struct pci_bus *bus = list->dev->bus;
1394 unsigned long flags = list->flags;
1395
1396 pci_bus_release_bridge_resources(bus, flags & type_mask,
1397 whole_subtree);
1398 list = list->next;
1399 }
1400 /* restore size and flags */
1401 for (list = head.next; list;) {
1402 struct resource *res = list->res;
1403
1404 res->start = list->start;
1405 res->end = list->end;
1406 res->flags = list->flags;
1407 if (list->dev->subordinate)
1408 res->flags = 0;
1409
1410 list = list->next;
1411 }
Ram Pai094732a2011-02-14 17:43:18 -08001412 free_list(resource_list_x, &head);
Yinghai Lu32180e402010-01-22 01:02:27 -08001413
1414 goto again;
Yinghai Lu3f579c32010-05-21 14:35:06 -07001415
1416enable_all:
1417 retval = pci_reenable_device(bridge);
1418 pci_set_master(bridge);
1419 pci_enable_bridges(parent);
Yinghai Lu6841ec62010-01-22 01:02:25 -08001420}
1421EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
Yinghai Lu9b030882012-01-21 02:08:23 -08001422
1423#ifdef CONFIG_HOTPLUG
1424/**
1425 * pci_rescan_bus - scan a PCI bus for devices.
1426 * @bus: PCI bus to scan
1427 *
1428 * Scan a PCI bus and child buses for new devices, adds them,
1429 * and enables them.
1430 *
1431 * Returns the max number of subordinate bus discovered.
1432 */
1433unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
1434{
1435 unsigned int max;
1436 struct pci_dev *dev;
1437 struct resource_list_x add_list; /* list of resources that
1438 want additional resources */
1439
1440 max = pci_scan_child_bus(bus);
1441
1442 add_list.next = NULL;
1443 down_read(&pci_bus_sem);
1444 list_for_each_entry(dev, &bus->devices, bus_list)
1445 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
1446 dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
1447 if (dev->subordinate)
1448 __pci_bus_size_bridges(dev->subordinate,
1449 &add_list);
1450 up_read(&pci_bus_sem);
1451 __pci_bus_assign_resources(bus, &add_list, NULL);
1452 BUG_ON(add_list.next);
1453
1454 pci_enable_bridges(bus);
1455 pci_bus_add_devices(bus);
1456
1457 return max;
1458}
1459EXPORT_SYMBOL_GPL(pci_rescan_bus);
1460#endif