aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2012-02-23 22:19:00 -0500
committerBjorn Helgaas <bhelgaas@google.com>2012-02-23 22:19:00 -0500
commit5bfa14ed9f3ca21fcecbcfbf4a848c002b740c41 (patch)
treedc28c99c694007fca535b906c1044101241abb73 /drivers/pci
parent0efd5aab41e18a1175f72641696cfda154ba6c87 (diff)
PCI: convert bus addresses to resource when reading BARs
Some PCI host bridges translate CPU addresses to PCI bus addresses. Previously, we initialized pci_dev resources with PCI bus addresses, then converted them to CPU addresses later in arch-specific code (pcibios_fixup_resources()), which leaves a window of time where the pci_dev resources are incorrect. This patch adds support in the core for this address translation. When the arch creates the root bus, it can supply the host bridge address translation information, and the core can use it to set the pci_dev resources correctly from the beginning. This gives us a way to fix the problem that quirks that run between device discovery and pcibios_fixup_resources() fail because they use pci_dev resources that haven't been converted. The reference below is to one such problem that affected ARM and ia64. Note that this patch has no effect until an arch starts using pci_add_resource_offset() with a non-zero offset: before that, all all host bridge windows have a zero offset and pci_bus_to_resource() copies the pci_bus_region directly to the struct resource. Reference: https://lkml.org/lkml/2009/10/12/405 Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/probe.c129
1 files changed, 104 insertions, 25 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 3f07cb6bae32..3539171d8a98 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -61,6 +61,63 @@ static struct pci_host_bridge *pci_host_bridge(struct pci_dev *dev)
61 return NULL; 61 return NULL;
62} 62}
63 63
64static bool resource_contains(struct resource *res1, struct resource *res2)
65{
66 return res1->start <= res2->start && res1->end >= res2->end;
67}
68
69void pci_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
70 struct resource *res)
71{
72 struct pci_host_bridge *bridge = pci_host_bridge(dev);
73 struct pci_host_bridge_window *window;
74 resource_size_t offset = 0;
75
76 list_for_each_entry(window, &bridge->windows, list) {
77 if (resource_type(res) != resource_type(window->res))
78 continue;
79
80 if (resource_contains(window->res, res)) {
81 offset = window->offset;
82 break;
83 }
84 }
85
86 region->start = res->start - offset;
87 region->end = res->end - offset;
88}
89
90static bool region_contains(struct pci_bus_region *region1,
91 struct pci_bus_region *region2)
92{
93 return region1->start <= region2->start && region1->end >= region2->end;
94}
95
96void pci_bus_to_resource(struct pci_dev *dev, struct resource *res,
97 struct pci_bus_region *region)
98{
99 struct pci_host_bridge *bridge = pci_host_bridge(dev);
100 struct pci_host_bridge_window *window;
101 struct pci_bus_region bus_region;
102 resource_size_t offset = 0;
103
104 list_for_each_entry(window, &bridge->windows, list) {
105 if (resource_type(res) != resource_type(window->res))
106 continue;
107
108 bus_region.start = window->res->start - window->offset;
109 bus_region.end = window->res->end - window->offset;
110
111 if (region_contains(&bus_region, region)) {
112 offset = window->offset;
113 break;
114 }
115 }
116
117 res->start = region->start + offset;
118 res->end = region->end + offset;
119}
120
64/* 121/*
65 * PCI Bus Class 122 * PCI Bus Class
66 */ 123 */
@@ -154,6 +211,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
154{ 211{
155 u32 l, sz, mask; 212 u32 l, sz, mask;
156 u16 orig_cmd; 213 u16 orig_cmd;
214 struct pci_bus_region region;
157 215
158 mask = type ? PCI_ROM_ADDRESS_MASK : ~0; 216 mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
159 217
@@ -233,11 +291,13 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
233 /* Address above 32-bit boundary; disable the BAR */ 291 /* Address above 32-bit boundary; disable the BAR */
234 pci_write_config_dword(dev, pos, 0); 292 pci_write_config_dword(dev, pos, 0);
235 pci_write_config_dword(dev, pos + 4, 0); 293 pci_write_config_dword(dev, pos + 4, 0);
236 res->start = 0; 294 region.start = 0;
237 res->end = sz64; 295 region.end = sz64;
296 pci_bus_to_resource(dev, res, &region);
238 } else { 297 } else {
239 res->start = l64; 298 region.start = l64;
240 res->end = l64 + sz64; 299 region.end = l64 + sz64;
300 pci_bus_to_resource(dev, res, &region);
241 dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", 301 dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n",
242 pos, res); 302 pos, res);
243 } 303 }
@@ -247,8 +307,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
247 if (!sz) 307 if (!sz)
248 goto fail; 308 goto fail;
249 309
250 res->start = l; 310 region.start = l;
251 res->end = l + sz; 311 region.end = l + sz;
312 pci_bus_to_resource(dev, res, &region);
252 313
253 dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res); 314 dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
254 } 315 }
@@ -285,7 +346,8 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
285 struct pci_dev *dev = child->self; 346 struct pci_dev *dev = child->self;
286 u8 io_base_lo, io_limit_lo; 347 u8 io_base_lo, io_limit_lo;
287 unsigned long base, limit; 348 unsigned long base, limit;
288 struct resource *res; 349 struct pci_bus_region region;
350 struct resource *res, res2;
289 351
290 res = child->resource[0]; 352 res = child->resource[0];
291 pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo); 353 pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
@@ -303,10 +365,13 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
303 365
304 if (base && base <= limit) { 366 if (base && base <= limit) {
305 res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO; 367 res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
368 region.start = base;
369 region.end = limit + 0xfff;
370 pci_bus_to_resource(dev, &res2, &region);
306 if (!res->start) 371 if (!res->start)
307 res->start = base; 372 res->start = res2.start;
308 if (!res->end) 373 if (!res->end)
309 res->end = limit + 0xfff; 374 res->end = res2.end;
310 dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); 375 dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
311 } 376 }
312} 377}
@@ -316,6 +381,7 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
316 struct pci_dev *dev = child->self; 381 struct pci_dev *dev = child->self;
317 u16 mem_base_lo, mem_limit_lo; 382 u16 mem_base_lo, mem_limit_lo;
318 unsigned long base, limit; 383 unsigned long base, limit;
384 struct pci_bus_region region;
319 struct resource *res; 385 struct resource *res;
320 386
321 res = child->resource[1]; 387 res = child->resource[1];
@@ -325,8 +391,9 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
325 limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16; 391 limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
326 if (base && base <= limit) { 392 if (base && base <= limit) {
327 res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; 393 res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
328 res->start = base; 394 region.start = base;
329 res->end = limit + 0xfffff; 395 region.end = limit + 0xfffff;
396 pci_bus_to_resource(dev, res, &region);
330 dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); 397 dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
331 } 398 }
332} 399}
@@ -336,6 +403,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
336 struct pci_dev *dev = child->self; 403 struct pci_dev *dev = child->self;
337 u16 mem_base_lo, mem_limit_lo; 404 u16 mem_base_lo, mem_limit_lo;
338 unsigned long base, limit; 405 unsigned long base, limit;
406 struct pci_bus_region region;
339 struct resource *res; 407 struct resource *res;
340 408
341 res = child->resource[2]; 409 res = child->resource[2];
@@ -372,8 +440,9 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
372 IORESOURCE_MEM | IORESOURCE_PREFETCH; 440 IORESOURCE_MEM | IORESOURCE_PREFETCH;
373 if (res->flags & PCI_PREF_RANGE_TYPE_64) 441 if (res->flags & PCI_PREF_RANGE_TYPE_64)
374 res->flags |= IORESOURCE_MEM_64; 442 res->flags |= IORESOURCE_MEM_64;
375 res->start = base; 443 region.start = base;
376 res->end = limit + 0xfffff; 444 region.end = limit + 0xfffff;
445 pci_bus_to_resource(dev, res, &region);
377 dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); 446 dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
378 } 447 }
379} 448}
@@ -919,6 +988,8 @@ int pci_setup_device(struct pci_dev *dev)
919 u8 hdr_type; 988 u8 hdr_type;
920 struct pci_slot *slot; 989 struct pci_slot *slot;
921 int pos = 0; 990 int pos = 0;
991 struct pci_bus_region region;
992 struct resource *res;
922 993
923 if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type)) 994 if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type))
924 return -EIO; 995 return -EIO;
@@ -980,20 +1051,28 @@ int pci_setup_device(struct pci_dev *dev)
980 u8 progif; 1051 u8 progif;
981 pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); 1052 pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
982 if ((progif & 1) == 0) { 1053 if ((progif & 1) == 0) {
983 dev->resource[0].start = 0x1F0; 1054 region.start = 0x1F0;
984 dev->resource[0].end = 0x1F7; 1055 region.end = 0x1F7;
985 dev->resource[0].flags = LEGACY_IO_RESOURCE; 1056 res = &dev->resource[0];
986 dev->resource[1].start = 0x3F6; 1057 res->flags = LEGACY_IO_RESOURCE;
987 dev->resource[1].end = 0x3F6; 1058 pci_bus_to_resource(dev, res, &region);
988 dev->resource[1].flags = LEGACY_IO_RESOURCE; 1059 region.start = 0x3F6;
1060 region.end = 0x3F6;
1061 res = &dev->resource[1];
1062 res->flags = LEGACY_IO_RESOURCE;
1063 pci_bus_to_resource(dev, res, &region);
989 } 1064 }
990 if ((progif & 4) == 0) { 1065 if ((progif & 4) == 0) {
991 dev->resource[2].start = 0x170; 1066 region.start = 0x170;
992 dev->resource[2].end = 0x177; 1067 region.end = 0x177;
993 dev->resource[2].flags = LEGACY_IO_RESOURCE; 1068 res = &dev->resource[2];
994 dev->resource[3].start = 0x376; 1069 res->flags = LEGACY_IO_RESOURCE;
995 dev->resource[3].end = 0x376; 1070 pci_bus_to_resource(dev, res, &region);
996 dev->resource[3].flags = LEGACY_IO_RESOURCE; 1071 region.start = 0x376;
1072 region.end = 0x376;
1073 res = &dev->resource[3];
1074 res->flags = LEGACY_IO_RESOURCE;
1075 pci_bus_to_resource(dev, res, &region);
997 } 1076 }
998 } 1077 }
999 break; 1078 break;