diff options
| -rw-r--r-- | drivers/pci/probe.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6244b1834dfe..c8ca98c2b480 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -407,15 +407,16 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) | |||
| 407 | { | 407 | { |
| 408 | struct pci_dev *dev = child->self; | 408 | struct pci_dev *dev = child->self; |
| 409 | u16 mem_base_lo, mem_limit_lo; | 409 | u16 mem_base_lo, mem_limit_lo; |
| 410 | unsigned long base, limit; | 410 | u64 base64, limit64; |
| 411 | dma_addr_t base, limit; | ||
| 411 | struct pci_bus_region region; | 412 | struct pci_bus_region region; |
| 412 | struct resource *res; | 413 | struct resource *res; |
| 413 | 414 | ||
| 414 | res = child->resource[2]; | 415 | res = child->resource[2]; |
| 415 | pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); | 416 | pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); |
| 416 | pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); | 417 | pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); |
| 417 | base = ((unsigned long) mem_base_lo & PCI_PREF_RANGE_MASK) << 16; | 418 | base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; |
| 418 | limit = ((unsigned long) mem_limit_lo & PCI_PREF_RANGE_MASK) << 16; | 419 | limit64 = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16; |
| 419 | 420 | ||
| 420 | if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { | 421 | if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { |
| 421 | u32 mem_base_hi, mem_limit_hi; | 422 | u32 mem_base_hi, mem_limit_hi; |
| @@ -429,17 +430,20 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) | |||
| 429 | * this, just assume they are not being used. | 430 | * this, just assume they are not being used. |
| 430 | */ | 431 | */ |
| 431 | if (mem_base_hi <= mem_limit_hi) { | 432 | if (mem_base_hi <= mem_limit_hi) { |
| 432 | #if BITS_PER_LONG == 64 | 433 | base64 |= (u64) mem_base_hi << 32; |
| 433 | base |= ((unsigned long) mem_base_hi) << 32; | 434 | limit64 |= (u64) mem_limit_hi << 32; |
| 434 | limit |= ((unsigned long) mem_limit_hi) << 32; | ||
| 435 | #else | ||
| 436 | if (mem_base_hi || mem_limit_hi) { | ||
| 437 | dev_err(&dev->dev, "can't handle 64-bit address space for bridge\n"); | ||
| 438 | return; | ||
| 439 | } | ||
| 440 | #endif | ||
| 441 | } | 435 | } |
| 442 | } | 436 | } |
| 437 | |||
| 438 | base = (dma_addr_t) base64; | ||
| 439 | limit = (dma_addr_t) limit64; | ||
| 440 | |||
| 441 | if (base != base64) { | ||
| 442 | dev_err(&dev->dev, "can't handle bridge window above 4GB (bus address %#010llx)\n", | ||
| 443 | (unsigned long long) base64); | ||
| 444 | return; | ||
| 445 | } | ||
| 446 | |||
| 443 | if (base <= limit) { | 447 | if (base <= limit) { |
| 444 | res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | | 448 | res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | |
| 445 | IORESOURCE_MEM | IORESOURCE_PREFETCH; | 449 | IORESOURCE_MEM | IORESOURCE_PREFETCH; |
