PCI updates for v3.18:

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)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJUbkCkAAoJEFmIoMA60/r8HHcQAMBeaF4pbUYotzpd8kwjFQ2x
 d9DPU3bAfeMY3U4qKRkp/GXV1F1ueVP2KgwaKlV9ytrILFwVYlsy2DZ/JIS3ggw2
 BfjPTVB6rADzhfZB0HNSQQGOcGbKezd4sM45E6hsZqxzlgnVJQ5oL0u/PL5fuvC1
 +1goznoJwOhLMn9bsSS+b/2bgmPG1HYonFu1ehiSTt/g9e0Q2YsMkCZDo8R3i6nl
 W25g93m1yP7KO3AnPsnE9dm9oDEcbqVbfSu+Z8X2NllN8/+e6+z7CtDZx5OfMpRI
 GBQrLuPXi0NxFeFcj+gbAfhV8ZsFDdqNXPHuqC7pOKlveCmyk8tBhXcIr9gTnGQF
 /UjxgWDekH6Cb8DjFVQCj84D5f1U7RNRbpkeEr6gXtoM7vPDfQaCROC5qhBKGV+P
 XAQ4ujGkCe3A9ve2XNsgHzLQgRoRopfI6aN2VZxQYaxvobm+QzuMW7BtKJ72dUKJ
 LIPnlc+X1ccwg+ZyWFvgLByMKCriklTjeFA2UMP6WI7xD3r5N+Y0QP0no4zVPIMN
 no5RAx7sv71yE97Y/SSosirfjQ3YlJ55KJRJY2+j2obD9wLCCEwJuiNnrYU+EB6c
 Z/cPmZhGKZnBcDJMazjULe2gldVDRokIRk069ySob4iUdZ4n/vIdCbNR5Z0f6dAr
 w7SfdPXK2ARn0ulqzdT1
 =smv9
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2014-11-21 16:36:42 -08:00
commit 08685897b3
5 changed files with 37 additions and 15 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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;
} }

View File

@ -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);

View File

@ -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)
* 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)
~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);