Commit 08685897 authored by Linus Torvalds's avatar Linus Torvalds

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
parents a46171d0 7fc986d8
...@@ -7,3 +7,14 @@ And for the interrupt mapping part: ...@@ -7,3 +7,14 @@ And for the interrupt mapping part:
Open Firmware Recommended Practice: Interrupt Mapping Open Firmware Recommended Practice: Interrupt Mapping
http://www.openfirmware.org/1275/practice/imap/imap0_9d.pdf http://www.openfirmware.org/1275/practice/imap/imap0_9d.pdf
Additionally to the properties specified in the above standards a host bridge
driver implementation may support the following properties:
- linux,pci-domain:
If present this property assigns a fixed PCI domain number to a host bridge,
otherwise an unstable (across boots) unique number will be assigned.
It is required to either not set this property at all or set it for all
host bridges in the system, otherwise potentially conflicting domain numbers
may be assigned to root buses behind different host bridges. The domain
number for each host bridge in the system must be unique.
...@@ -444,7 +444,7 @@ static inline int pcie_cap_version(const struct pci_dev *dev) ...@@ -444,7 +444,7 @@ static inline int pcie_cap_version(const struct pci_dev *dev)
return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS; return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
} }
static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev) bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
{ {
int type = pci_pcie_type(dev); int type = pci_pcie_type(dev);
......
...@@ -631,10 +631,15 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev) ...@@ -631,10 +631,15 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
bus = pci_scan_root_bus(&pdev->dev, 0, &xgene_pcie_ops, port, &res); bus = pci_create_root_bus(&pdev->dev, 0,
&xgene_pcie_ops, port, &res);
if (!bus) if (!bus)
return -ENOMEM; return -ENOMEM;
pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus);
pci_bus_add_devices(bus);
platform_set_drvdata(pdev, port); platform_set_drvdata(pdev, port);
return 0; return 0;
} }
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
extern const unsigned char pcie_link_speed[]; extern const unsigned char pcie_link_speed[];
bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
/* Functions internal to the PCI core code */ /* Functions internal to the PCI core code */
int pci_create_sysfs_dev_files(struct pci_dev *pdev); int pci_create_sysfs_dev_files(struct pci_dev *pdev);
......
...@@ -407,15 +407,16 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) ...@@ -407,15 +407,16 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child)
{ {
struct pci_dev *dev = child->self; struct pci_dev *dev = child->self;
u16 mem_base_lo, mem_limit_lo; u16 mem_base_lo, mem_limit_lo;
unsigned long base, limit; u64 base64, limit64;
dma_addr_t base, limit;
struct pci_bus_region region; struct pci_bus_region region;
struct resource *res; struct resource *res;
res = child->resource[2]; res = child->resource[2];
pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
base = ((unsigned long) mem_base_lo & PCI_PREF_RANGE_MASK) << 16; base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
limit = ((unsigned long) mem_limit_lo & PCI_PREF_RANGE_MASK) << 16; limit64 = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
u32 mem_base_hi, mem_limit_hi; u32 mem_base_hi, mem_limit_hi;
...@@ -429,17 +430,20 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) ...@@ -429,17 +430,20 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child)
* this, just assume they are not being used. * this, just assume they are not being used.
*/ */
if (mem_base_hi <= mem_limit_hi) { if (mem_base_hi <= mem_limit_hi) {
#if BITS_PER_LONG == 64 base64 |= (u64) mem_base_hi << 32;
base |= ((unsigned long) mem_base_hi) << 32; limit64 |= (u64) mem_limit_hi << 32;
limit |= ((unsigned long) mem_limit_hi) << 32;
#else
if (mem_base_hi || mem_limit_hi) {
dev_err(&dev->dev, "can't handle 64-bit address space for bridge\n");
return;
}
#endif
} }
} }
base = (dma_addr_t) base64;
limit = (dma_addr_t) limit64;
if (base != base64) {
dev_err(&dev->dev, "can't handle bridge window above 4GB (bus address %#010llx)\n",
(unsigned long long) base64);
return;
}
if (base <= limit) { if (base <= limit) {
res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) |
IORESOURCE_MEM | IORESOURCE_PREFETCH; IORESOURCE_MEM | IORESOURCE_PREFETCH;
...@@ -1323,7 +1327,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) ...@@ -1323,7 +1327,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or); ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
/* Initialize Link Control Register */ /* Initialize Link Control Register */
if (dev->subordinate) if (pcie_cap_has_lnkctl(dev))
pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or); ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment