aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/setup-bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r--drivers/pci/setup-bus.c70
1 files changed, 53 insertions, 17 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 704608945780..7c443b4583ab 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -25,9 +25,9 @@
25#include <linux/ioport.h> 25#include <linux/ioport.h>
26#include <linux/cache.h> 26#include <linux/cache.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include "pci.h"
28 29
29 30static void pbus_assign_resources_sorted(const struct pci_bus *bus)
30static void pbus_assign_resources_sorted(struct pci_bus *bus)
31{ 31{
32 struct pci_dev *dev; 32 struct pci_dev *dev;
33 struct resource *res; 33 struct resource *res;
@@ -58,7 +58,6 @@ static void pbus_assign_resources_sorted(struct pci_bus *bus)
58 res = list->res; 58 res = list->res;
59 idx = res - &list->dev->resource[0]; 59 idx = res - &list->dev->resource[0];
60 if (pci_assign_resource(list->dev, idx)) { 60 if (pci_assign_resource(list->dev, idx)) {
61 /* FIXME: get rid of this */
62 res->start = 0; 61 res->start = 0;
63 res->end = 0; 62 res->end = 0;
64 res->flags = 0; 63 res->flags = 0;
@@ -143,6 +142,10 @@ static void pci_setup_bridge(struct pci_bus *bus)
143 struct pci_dev *bridge = bus->self; 142 struct pci_dev *bridge = bus->self;
144 struct pci_bus_region region; 143 struct pci_bus_region region;
145 u32 l, bu, lu, io_upper16; 144 u32 l, bu, lu, io_upper16;
145 int pref_mem64;
146
147 if (pci_is_enabled(bridge))
148 return;
146 149
147 dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n", 150 dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n",
148 pci_domain_nr(bus), bus->number); 151 pci_domain_nr(bus), bus->number);
@@ -195,16 +198,22 @@ static void pci_setup_bridge(struct pci_bus *bus)
195 pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); 198 pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
196 199
197 /* Set up PREF base/limit. */ 200 /* Set up PREF base/limit. */
201 pref_mem64 = 0;
198 bu = lu = 0; 202 bu = lu = 0;
199 pcibios_resource_to_bus(bridge, &region, bus->resource[2]); 203 pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
200 if (bus->resource[2]->flags & IORESOURCE_PREFETCH) { 204 if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
205 int width = 8;
201 l = (region.start >> 16) & 0xfff0; 206 l = (region.start >> 16) & 0xfff0;
202 l |= region.end & 0xfff00000; 207 l |= region.end & 0xfff00000;
203 bu = upper_32_bits(region.start); 208 if (bus->resource[2]->flags & IORESOURCE_MEM_64) {
204 lu = upper_32_bits(region.end); 209 pref_mem64 = 1;
205 dev_info(&bridge->dev, " PREFETCH window: %#016llx-%#016llx\n", 210 bu = upper_32_bits(region.start);
206 (unsigned long long)region.start, 211 lu = upper_32_bits(region.end);
207 (unsigned long long)region.end); 212 width = 16;
213 }
214 dev_info(&bridge->dev, " PREFETCH window: %#0*llx-%#0*llx\n",
215 width, (unsigned long long)region.start,
216 width, (unsigned long long)region.end);
208 } 217 }
209 else { 218 else {
210 l = 0x0000fff0; 219 l = 0x0000fff0;
@@ -212,9 +221,11 @@ static void pci_setup_bridge(struct pci_bus *bus)
212 } 221 }
213 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); 222 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
214 223
215 /* Set the upper 32 bits of PREF base & limit. */ 224 if (pref_mem64) {
216 pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); 225 /* Set the upper 32 bits of PREF base & limit. */
217 pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); 226 pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
227 pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
228 }
218 229
219 pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); 230 pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
220} 231}
@@ -252,8 +263,25 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
252 pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem); 263 pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
253 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0); 264 pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);
254 } 265 }
255 if (pmem) 266 if (pmem) {
256 b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; 267 b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
268 if ((pmem & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64)
269 b_res[2].flags |= IORESOURCE_MEM_64;
270 }
271
272 /* double check if bridge does support 64 bit pref */
273 if (b_res[2].flags & IORESOURCE_MEM_64) {
274 u32 mem_base_hi, tmp;
275 pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32,
276 &mem_base_hi);
277 pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
278 0xffffffff);
279 pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp);
280 if (!tmp)
281 b_res[2].flags &= ~IORESOURCE_MEM_64;
282 pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
283 mem_base_hi);
284 }
257} 285}
258 286
259/* Helper function for sizing routines: find first available 287/* Helper function for sizing routines: find first available
@@ -333,6 +361,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
333 resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ 361 resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */
334 int order, max_order; 362 int order, max_order;
335 struct resource *b_res = find_free_bus_resource(bus, type); 363 struct resource *b_res = find_free_bus_resource(bus, type);
364 unsigned int mem64_mask = 0;
336 365
337 if (!b_res) 366 if (!b_res)
338 return 0; 367 return 0;
@@ -341,9 +370,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
341 max_order = 0; 370 max_order = 0;
342 size = 0; 371 size = 0;
343 372
373 mem64_mask = b_res->flags & IORESOURCE_MEM_64;
374 b_res->flags &= ~IORESOURCE_MEM_64;
375
344 list_for_each_entry(dev, &bus->devices, bus_list) { 376 list_for_each_entry(dev, &bus->devices, bus_list) {
345 int i; 377 int i;
346 378
347 for (i = 0; i < PCI_NUM_RESOURCES; i++) { 379 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
348 struct resource *r = &dev->resource[i]; 380 struct resource *r = &dev->resource[i];
349 resource_size_t r_size; 381 resource_size_t r_size;
@@ -352,7 +384,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
352 continue; 384 continue;
353 r_size = resource_size(r); 385 r_size = resource_size(r);
354 /* For bridges size != alignment */ 386 /* For bridges size != alignment */
355 align = resource_alignment(r); 387 align = pci_resource_alignment(dev, r);
356 order = __ffs(align) - 20; 388 order = __ffs(align) - 20;
357 if (order > 11) { 389 if (order > 11) {
358 dev_warn(&dev->dev, "BAR %d bad alignment %llx: " 390 dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
@@ -369,6 +401,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
369 aligns[order] += align; 401 aligns[order] += align;
370 if (order > max_order) 402 if (order > max_order)
371 max_order = order; 403 max_order = order;
404 mem64_mask &= r->flags & IORESOURCE_MEM_64;
372 } 405 }
373 } 406 }
374 407
@@ -393,6 +426,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
393 b_res->start = min_align; 426 b_res->start = min_align;
394 b_res->end = size + min_align - 1; 427 b_res->end = size + min_align - 1;
395 b_res->flags |= IORESOURCE_STARTALIGN; 428 b_res->flags |= IORESOURCE_STARTALIGN;
429 b_res->flags |= mem64_mask;
396 return 1; 430 return 1;
397} 431}
398 432
@@ -495,7 +529,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
495} 529}
496EXPORT_SYMBOL(pci_bus_size_bridges); 530EXPORT_SYMBOL(pci_bus_size_bridges);
497 531
498void __ref pci_bus_assign_resources(struct pci_bus *bus) 532void __ref pci_bus_assign_resources(const struct pci_bus *bus)
499{ 533{
500 struct pci_bus *b; 534 struct pci_bus *b;
501 struct pci_dev *dev; 535 struct pci_dev *dev;
@@ -533,11 +567,13 @@ static void pci_bus_dump_res(struct pci_bus *bus)
533 567
534 for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { 568 for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
535 struct resource *res = bus->resource[i]; 569 struct resource *res = bus->resource[i];
536 if (!res) 570 if (!res || !res->end)
537 continue; 571 continue;
538 572
539 dev_printk(KERN_DEBUG, &bus->dev, "resource %d %s %pR\n", i, 573 dev_printk(KERN_DEBUG, &bus->dev, "resource %d %s %pR\n", i,
540 (res->flags & IORESOURCE_IO) ? "io: " : "mem:", res); 574 (res->flags & IORESOURCE_IO) ? "io: " :
575 ((res->flags & IORESOURCE_PREFETCH)? "pref mem":"mem:"),
576 res);
541 } 577 }
542} 578}
543 579