diff options
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 87 |
1 files changed, 41 insertions, 46 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 9ab492f21f86..795c9026d55f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -68,21 +68,6 @@ static int __init pcibus_class_init(void) | |||
68 | } | 68 | } |
69 | postcore_initcall(pcibus_class_init); | 69 | postcore_initcall(pcibus_class_init); |
70 | 70 | ||
71 | /* | ||
72 | * Translate the low bits of the PCI base | ||
73 | * to the resource type | ||
74 | */ | ||
75 | static inline unsigned int pci_calc_resource_flags(unsigned int flags) | ||
76 | { | ||
77 | if (flags & PCI_BASE_ADDRESS_SPACE_IO) | ||
78 | return IORESOURCE_IO; | ||
79 | |||
80 | if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) | ||
81 | return IORESOURCE_MEM | IORESOURCE_PREFETCH; | ||
82 | |||
83 | return IORESOURCE_MEM; | ||
84 | } | ||
85 | |||
86 | static u64 pci_size(u64 base, u64 maxbase, u64 mask) | 71 | static u64 pci_size(u64 base, u64 maxbase, u64 mask) |
87 | { | 72 | { |
88 | u64 size = mask & maxbase; /* Find the significant bits */ | 73 | u64 size = mask & maxbase; /* Find the significant bits */ |
@@ -101,18 +86,39 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask) | |||
101 | return size; | 86 | return size; |
102 | } | 87 | } |
103 | 88 | ||
104 | static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar) | 89 | static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar) |
105 | { | 90 | { |
91 | u32 mem_type; | ||
92 | unsigned long flags; | ||
93 | |||
106 | if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { | 94 | if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { |
107 | res->flags = bar & ~PCI_BASE_ADDRESS_IO_MASK; | 95 | flags = bar & ~PCI_BASE_ADDRESS_IO_MASK; |
108 | return pci_bar_io; | 96 | flags |= IORESOURCE_IO; |
97 | return flags; | ||
109 | } | 98 | } |
110 | 99 | ||
111 | res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; | 100 | flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; |
101 | flags |= IORESOURCE_MEM; | ||
102 | if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) | ||
103 | flags |= IORESOURCE_PREFETCH; | ||
112 | 104 | ||
113 | if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) | 105 | mem_type = bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK; |
114 | return pci_bar_mem64; | 106 | switch (mem_type) { |
115 | return pci_bar_mem32; | 107 | case PCI_BASE_ADDRESS_MEM_TYPE_32: |
108 | break; | ||
109 | case PCI_BASE_ADDRESS_MEM_TYPE_1M: | ||
110 | dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n"); | ||
111 | break; | ||
112 | case PCI_BASE_ADDRESS_MEM_TYPE_64: | ||
113 | flags |= IORESOURCE_MEM_64; | ||
114 | break; | ||
115 | default: | ||
116 | dev_warn(&dev->dev, | ||
117 | "mem unknown type %x treated as 32-bit BAR\n", | ||
118 | mem_type); | ||
119 | break; | ||
120 | } | ||
121 | return flags; | ||
116 | } | 122 | } |
117 | 123 | ||
118 | /** | 124 | /** |
@@ -165,9 +171,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
165 | l = 0; | 171 | l = 0; |
166 | 172 | ||
167 | if (type == pci_bar_unknown) { | 173 | if (type == pci_bar_unknown) { |
168 | type = decode_bar(res, l); | 174 | res->flags = decode_bar(dev, l); |
169 | res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN; | 175 | res->flags |= IORESOURCE_SIZEALIGN; |
170 | if (type == pci_bar_io) { | 176 | if (res->flags & IORESOURCE_IO) { |
171 | l &= PCI_BASE_ADDRESS_IO_MASK; | 177 | l &= PCI_BASE_ADDRESS_IO_MASK; |
172 | mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; | 178 | mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; |
173 | } else { | 179 | } else { |
@@ -180,7 +186,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
180 | mask = (u32)PCI_ROM_ADDRESS_MASK; | 186 | mask = (u32)PCI_ROM_ADDRESS_MASK; |
181 | } | 187 | } |
182 | 188 | ||
183 | if (type == pci_bar_mem64) { | 189 | if (res->flags & IORESOURCE_MEM_64) { |
184 | u64 l64 = l; | 190 | u64 l64 = l; |
185 | u64 sz64 = sz; | 191 | u64 sz64 = sz; |
186 | u64 mask64 = mask | (u64)~0 << 32; | 192 | u64 mask64 = mask | (u64)~0 << 32; |
@@ -204,7 +210,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
204 | goto fail; | 210 | goto fail; |
205 | } | 211 | } |
206 | 212 | ||
207 | res->flags |= IORESOURCE_MEM_64; | ||
208 | if ((sizeof(resource_size_t) < 8) && l) { | 213 | if ((sizeof(resource_size_t) < 8) && l) { |
209 | /* Address above 32-bit boundary; disable the BAR */ | 214 | /* Address above 32-bit boundary; disable the BAR */ |
210 | pci_write_config_dword(dev, pos, 0); | 215 | pci_write_config_dword(dev, pos, 0); |
@@ -230,7 +235,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
230 | } | 235 | } |
231 | 236 | ||
232 | out: | 237 | out: |
233 | return (type == pci_bar_mem64) ? 1 : 0; | 238 | return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; |
234 | fail: | 239 | fail: |
235 | res->flags = 0; | 240 | res->flags = 0; |
236 | goto out; | 241 | goto out; |
@@ -284,10 +289,6 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child) | |||
284 | if (!res->end) | 289 | if (!res->end) |
285 | res->end = limit + 0xfff; | 290 | res->end = limit + 0xfff; |
286 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 291 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
287 | } else { | ||
288 | dev_printk(KERN_DEBUG, &dev->dev, | ||
289 | " bridge window [io %#06lx-%#06lx] (disabled)\n", | ||
290 | base, limit); | ||
291 | } | 292 | } |
292 | } | 293 | } |
293 | 294 | ||
@@ -308,10 +309,6 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child) | |||
308 | res->start = base; | 309 | res->start = base; |
309 | res->end = limit + 0xfffff; | 310 | res->end = limit + 0xfffff; |
310 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 311 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
311 | } else { | ||
312 | dev_printk(KERN_DEBUG, &dev->dev, | ||
313 | " bridge window [mem %#010lx-%#010lx] (disabled)\n", | ||
314 | base, limit + 0xfffff); | ||
315 | } | 312 | } |
316 | } | 313 | } |
317 | 314 | ||
@@ -359,10 +356,6 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child) | |||
359 | res->start = base; | 356 | res->start = base; |
360 | res->end = limit + 0xfffff; | 357 | res->end = limit + 0xfffff; |
361 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); | 358 | dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res); |
362 | } else { | ||
363 | dev_printk(KERN_DEBUG, &dev->dev, | ||
364 | " bridge window [mem %#010lx-%#010lx pref] (disabled)\n", | ||
365 | base, limit + 0xfffff); | ||
366 | } | 359 | } |
367 | } | 360 | } |
368 | 361 | ||
@@ -725,12 +718,14 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, | |||
725 | pci_write_config_word(dev, PCI_STATUS, 0xffff); | 718 | pci_write_config_word(dev, PCI_STATUS, 0xffff); |
726 | 719 | ||
727 | /* Prevent assigning a bus number that already exists. | 720 | /* Prevent assigning a bus number that already exists. |
728 | * This can happen when a bridge is hot-plugged */ | 721 | * This can happen when a bridge is hot-plugged, so in |
729 | if (pci_find_bus(pci_domain_nr(bus), max+1)) | 722 | * this case we only re-scan this bus. */ |
730 | goto out; | 723 | child = pci_find_bus(pci_domain_nr(bus), max+1); |
731 | child = pci_add_new_bus(bus, dev, ++max); | 724 | if (!child) { |
732 | if (!child) | 725 | child = pci_add_new_bus(bus, dev, ++max); |
733 | goto out; | 726 | if (!child) |
727 | goto out; | ||
728 | } | ||
734 | buses = (buses & 0xff000000) | 729 | buses = (buses & 0xff000000) |
735 | | ((unsigned int)(child->primary) << 0) | 730 | | ((unsigned int)(child->primary) << 0) |
736 | | ((unsigned int)(child->secondary) << 8) | 731 | | ((unsigned int)(child->secondary) << 8) |