diff options
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 5ed99309c758..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; |
@@ -1323,7 +1327,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) | |||
1323 | ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or); | 1327 | ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or); |
1324 | 1328 | ||
1325 | /* Initialize Link Control Register */ | 1329 | /* Initialize Link Control Register */ |
1326 | if (dev->subordinate) | 1330 | if (pcie_cap_has_lnkctl(dev)) |
1327 | pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, | 1331 | pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, |
1328 | ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or); | 1332 | ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or); |
1329 | 1333 | ||