diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-11-21 19:36:42 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-11-21 19:36:42 -0500 |
| commit | 08685897b3586aad622cb48fe1fb07bc19bb78f5 (patch) | |
| tree | 64eab4dfa420b498409aa24d3cb4182d08d81cb3 | |
| parent | a46171d0100eafc0c276962d80f470406d66dcdd (diff) | |
| parent | 7fc986d8a9727e5d40da3c2c1c343da6142e82a9 (diff) | |
Merge tag 'pci-v3.18-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI fixes from Bjorn Helgaas:
"These are fixes for an issue with 64-bit PCI bus addresses on 32-bit
PAE kernels, an APM X-Gene problem (it depended on a generic change we
removed before merging), a fix for my hotplug device configuration
changes, and a devicetree documentation update.
Resource management:
- Support 64-bit bridge windows if we have 64-bit dma_addr_t (Yinghai Lu)
PCI device hotplug:
- Apply _HPX Link Control settings to all devices with a link (Yinghai Lu)
Generic host bridge driver:
- Add DT binding for "linux,pci-domain" property (Lucas Stach)
APM X-Gene:
- Assign resources to bus before adding new devices (Duc Dang)"
* tag 'pci-v3.18-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
PCI: Support 64-bit bridge windows if we have 64-bit dma_addr_t
PCI: Apply _HPX Link Control settings to all devices with a link
PCI: Add missing DT binding for "linux,pci-domain" property
PCI: xgene: Assign resources to bus before adding new devices
| -rw-r--r-- | Documentation/devicetree/bindings/pci/pci.txt | 11 | ||||
| -rw-r--r-- | drivers/pci/access.c | 2 | ||||
| -rw-r--r-- | drivers/pci/host/pci-xgene.c | 7 | ||||
| -rw-r--r-- | drivers/pci/pci.h | 2 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 30 |
5 files changed, 37 insertions, 15 deletions
diff --git a/Documentation/devicetree/bindings/pci/pci.txt b/Documentation/devicetree/bindings/pci/pci.txt index 41aeed38926d..f8fbe9af7b2f 100644 --- a/Documentation/devicetree/bindings/pci/pci.txt +++ b/Documentation/devicetree/bindings/pci/pci.txt | |||
| @@ -7,3 +7,14 @@ And for the interrupt mapping part: | |||
| 7 | 7 | ||
| 8 | Open Firmware Recommended Practice: Interrupt Mapping | 8 | Open Firmware Recommended Practice: Interrupt Mapping |
| 9 | http://www.openfirmware.org/1275/practice/imap/imap0_9d.pdf | 9 | http://www.openfirmware.org/1275/practice/imap/imap0_9d.pdf |
| 10 | |||
| 11 | Additionally to the properties specified in the above standards a host bridge | ||
| 12 | driver implementation may support the following properties: | ||
| 13 | |||
| 14 | - linux,pci-domain: | ||
| 15 | If present this property assigns a fixed PCI domain number to a host bridge, | ||
| 16 | otherwise an unstable (across boots) unique number will be assigned. | ||
| 17 | It is required to either not set this property at all or set it for all | ||
| 18 | host bridges in the system, otherwise potentially conflicting domain numbers | ||
| 19 | may be assigned to root buses behind different host bridges. The domain | ||
| 20 | number for each host bridge in the system must be unique. | ||
diff --git a/drivers/pci/access.c b/drivers/pci/access.c index d292d7cb3417..49dd766852ba 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c | |||
| @@ -444,7 +444,7 @@ static inline int pcie_cap_version(const struct pci_dev *dev) | |||
| 444 | return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS; | 444 | return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS; |
| 445 | } | 445 | } |
| 446 | 446 | ||
| 447 | static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev) | 447 | bool pcie_cap_has_lnkctl(const struct pci_dev *dev) |
| 448 | { | 448 | { |
| 449 | int type = pci_pcie_type(dev); | 449 | int type = pci_pcie_type(dev); |
| 450 | 450 | ||
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c index 9ecabfa8c634..2988fe136c1e 100644 --- a/drivers/pci/host/pci-xgene.c +++ b/drivers/pci/host/pci-xgene.c | |||
| @@ -631,10 +631,15 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev) | |||
| 631 | if (ret) | 631 | if (ret) |
| 632 | return ret; | 632 | return ret; |
| 633 | 633 | ||
| 634 | bus = pci_scan_root_bus(&pdev->dev, 0, &xgene_pcie_ops, port, &res); | 634 | bus = pci_create_root_bus(&pdev->dev, 0, |
| 635 | &xgene_pcie_ops, port, &res); | ||
| 635 | if (!bus) | 636 | if (!bus) |
| 636 | return -ENOMEM; | 637 | return -ENOMEM; |
| 637 | 638 | ||
| 639 | pci_scan_child_bus(bus); | ||
| 640 | pci_assign_unassigned_bus_resources(bus); | ||
| 641 | pci_bus_add_devices(bus); | ||
| 642 | |||
| 638 | platform_set_drvdata(pdev, port); | 643 | platform_set_drvdata(pdev, port); |
| 639 | return 0; | 644 | return 0; |
| 640 | } | 645 | } |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 0601890db22d..4a3902d8e6fe 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | extern const unsigned char pcie_link_speed[]; | 7 | extern const unsigned char pcie_link_speed[]; |
| 8 | 8 | ||
| 9 | bool pcie_cap_has_lnkctl(const struct pci_dev *dev); | ||
| 10 | |||
| 9 | /* Functions internal to the PCI core code */ | 11 | /* Functions internal to the PCI core code */ |
| 10 | 12 | ||
| 11 | int pci_create_sysfs_dev_files(struct pci_dev *pdev); | 13 | int pci_create_sysfs_dev_files(struct pci_dev *pdev); |
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 | ||
