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.c77
1 files changed, 34 insertions, 43 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index eb927c04e290..a9e34ca119e1 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -174,7 +174,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
174 u64 l64, sz64, mask64; 174 u64 l64, sz64, mask64;
175 u16 orig_cmd; 175 u16 orig_cmd;
176 struct pci_bus_region region, inverted_region; 176 struct pci_bus_region region, inverted_region;
177 bool bar_too_big = false, bar_too_high = false, bar_invalid = false;
178 177
179 mask = type ? PCI_ROM_ADDRESS_MASK : ~0; 178 mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
180 179
@@ -200,8 +199,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
200 * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit 199 * memory BAR or a ROM, bit 0 must be clear; if it's an io BAR, bit
201 * 1 must be clear. 200 * 1 must be clear.
202 */ 201 */
203 if (!sz || sz == 0xffffffff) 202 if (sz == 0xffffffff)
204 goto fail; 203 sz = 0;
205 204
206 /* 205 /*
207 * I don't know how l can have all bits set. Copied from old code. 206 * I don't know how l can have all bits set. Copied from old code.
@@ -214,23 +213,22 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
214 res->flags = decode_bar(dev, l); 213 res->flags = decode_bar(dev, l);
215 res->flags |= IORESOURCE_SIZEALIGN; 214 res->flags |= IORESOURCE_SIZEALIGN;
216 if (res->flags & IORESOURCE_IO) { 215 if (res->flags & IORESOURCE_IO) {
217 l &= PCI_BASE_ADDRESS_IO_MASK; 216 l64 = l & PCI_BASE_ADDRESS_IO_MASK;
218 mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; 217 sz64 = sz & PCI_BASE_ADDRESS_IO_MASK;
218 mask64 = PCI_BASE_ADDRESS_IO_MASK & (u32)IO_SPACE_LIMIT;
219 } else { 219 } else {
220 l &= PCI_BASE_ADDRESS_MEM_MASK; 220 l64 = l & PCI_BASE_ADDRESS_MEM_MASK;
221 mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; 221 sz64 = sz & PCI_BASE_ADDRESS_MEM_MASK;
222 mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK;
222 } 223 }
223 } else { 224 } else {
224 res->flags |= (l & IORESOURCE_ROM_ENABLE); 225 res->flags |= (l & IORESOURCE_ROM_ENABLE);
225 l &= PCI_ROM_ADDRESS_MASK; 226 l64 = l & PCI_ROM_ADDRESS_MASK;
226 mask = (u32)PCI_ROM_ADDRESS_MASK; 227 sz64 = sz & PCI_ROM_ADDRESS_MASK;
228 mask64 = (u32)PCI_ROM_ADDRESS_MASK;
227 } 229 }
228 230
229 if (res->flags & IORESOURCE_MEM_64) { 231 if (res->flags & IORESOURCE_MEM_64) {
230 l64 = l;
231 sz64 = sz;
232 mask64 = mask | (u64)~0 << 32;
233
234 pci_read_config_dword(dev, pos + 4, &l); 232 pci_read_config_dword(dev, pos + 4, &l);
235 pci_write_config_dword(dev, pos + 4, ~0); 233 pci_write_config_dword(dev, pos + 4, ~0);
236 pci_read_config_dword(dev, pos + 4, &sz); 234 pci_read_config_dword(dev, pos + 4, &sz);
@@ -238,18 +236,30 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
238 236
239 l64 |= ((u64)l << 32); 237 l64 |= ((u64)l << 32);
240 sz64 |= ((u64)sz << 32); 238 sz64 |= ((u64)sz << 32);
239 mask64 |= ((u64)~0 << 32);
240 }
241 241
242 sz64 = pci_size(l64, sz64, mask64); 242 if (!dev->mmio_always_on && (orig_cmd & PCI_COMMAND_DECODE_ENABLE))
243 pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
243 244
244 if (!sz64) 245 if (!sz64)
245 goto fail; 246 goto fail;
246 247
248 sz64 = pci_size(l64, sz64, mask64);
249 if (!sz64) {
250 dev_info(&dev->dev, FW_BUG "reg 0x%x: invalid BAR (can't size)\n",
251 pos);
252 goto fail;
253 }
254
255 if (res->flags & IORESOURCE_MEM_64) {
247 if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) && 256 if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) &&
248 sz64 > 0x100000000ULL) { 257 sz64 > 0x100000000ULL) {
249 res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; 258 res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
250 res->start = 0; 259 res->start = 0;
251 res->end = 0; 260 res->end = 0;
252 bar_too_big = true; 261 dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n",
262 pos, (unsigned long long)sz64);
253 goto out; 263 goto out;
254 } 264 }
255 265
@@ -258,22 +268,15 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
258 res->flags |= IORESOURCE_UNSET; 268 res->flags |= IORESOURCE_UNSET;
259 res->start = 0; 269 res->start = 0;
260 res->end = sz64; 270 res->end = sz64;
261 bar_too_high = true; 271 dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4GB (bus address %#010llx)\n",
272 pos, (unsigned long long)l64);
262 goto out; 273 goto out;
263 } else {
264 region.start = l64;
265 region.end = l64 + sz64;
266 } 274 }
267 } else {
268 sz = pci_size(l, sz, mask);
269
270 if (!sz)
271 goto fail;
272
273 region.start = l;
274 region.end = l + sz;
275 } 275 }
276 276
277 region.start = l64;
278 region.end = l64 + sz64;
279
277 pcibios_bus_to_resource(dev->bus, res, &region); 280 pcibios_bus_to_resource(dev->bus, res, &region);
278 pcibios_resource_to_bus(dev->bus, &inverted_region, res); 281 pcibios_resource_to_bus(dev->bus, &inverted_region, res);
279 282
@@ -292,7 +295,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
292 res->flags |= IORESOURCE_UNSET; 295 res->flags |= IORESOURCE_UNSET;
293 res->start = 0; 296 res->start = 0;
294 res->end = region.end - region.start; 297 res->end = region.end - region.start;
295 bar_invalid = true; 298 dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n",
299 pos, (unsigned long long)region.start);
296 } 300 }
297 301
298 goto out; 302 goto out;
@@ -301,19 +305,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
301fail: 305fail:
302 res->flags = 0; 306 res->flags = 0;
303out: 307out:
304 if (!dev->mmio_always_on &&
305 (orig_cmd & PCI_COMMAND_DECODE_ENABLE))
306 pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
307
308 if (bar_too_big)
309 dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n",
310 pos, (unsigned long long) sz64);
311 if (bar_too_high)
312 dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4G (bus address %#010llx)\n",
313 pos, (unsigned long long) l64);
314 if (bar_invalid)
315 dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n",
316 pos, (unsigned long long) region.start);
317 if (res->flags) 308 if (res->flags)
318 dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res); 309 dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);
319 310