aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/probe.c')
-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;