Merge tag 'pci-v4.4-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas: "Resource management: - Add support for Enhanced Allocation devices (Sean O. Stalley) - Add Enhanced Allocation register entries (Sean O. Stalley) - Handle IORESOURCE_PCI_FIXED when sizing resources (David Daney) - Handle IORESOURCE_PCI_FIXED when assigning resources (David Daney) - Handle Enhanced Allocation capability for SR-IOV devices (David Daney) - Clear IORESOURCE_UNSET when reverting to firmware-assigned address (Bjorn Helgaas) - Make Enhanced Allocation bitmasks more obvious (Bjorn Helgaas) - Expand Enhanced Allocation BAR output (Bjorn Helgaas) - Add of_pci_check_probe_only to parse "linux,pci-probe-only" (Marc Zyngier) - Fix lookup of linux,pci-probe-only property (Marc Zyngier) - Add sparc mem64 resource parsing for root bus (Yinghai Lu) PCI device hotplug: - pciehp: Queue power work requests in dedicated function (Guenter Roeck) Driver binding: - Add builtin_pci_driver() to avoid registration boilerplate (Paul Gortmaker) Virtualization: - Set SR-IOV NumVFs to zero after enumeration (Alexander Duyck) - Remove redundant validation of SR-IOV offset/stride registers (Alexander Duyck) - Remove VFs in reverse order if virtfn_add() fails (Alexander Duyck) - Reorder pcibios_sriov_disable() (Alexander Duyck) - Wait 1 second between disabling VFs and clearing NumVFs (Alexander Duyck) - Fix sriov_enable() error path for pcibios_enable_sriov() failures (Alexander Duyck) - Enable SR-IOV ARI Capable Hierarchy before reading TotalVFs (Ben Shelton) - Don't try to restore VF BARs (Wei Yang) MSI: - Don't alloc pcibios-irq when MSI is enabled (Joerg Roedel) - Add msi_controller setup_irqs() method for special multivector setup (Lucas Stach) - Export all remapped MSIs to sysfs attributes (Romain Bezut) - Disable MSI on SiS 761 (Ondrej Zary) AER: - Clear error status registers during enumeration and restore (Taku Izumi) Generic host bridge driver: - Fix lookup of linux,pci-probe-only property (Marc Zyngier) - Allow multiple hosts with different map_bus() methods (David Daney) - Pass starting bus number to pci_scan_root_bus() (David Daney) - Fix address window calculation for non-zero starting bus (David Daney) Altera host bridge driver: - Add msi.h to ARM Kbuild (Ley Foon Tan) - Add Altera PCIe host controller driver (Ley Foon Tan) - Add Altera PCIe MSI driver (Ley Foon Tan) APM X-Gene host bridge driver: - Remove msi_controller assignment (Duc Dang) Broadcom iProc host bridge driver: - Fix header comment "Corporation" misspelling (Florian Fainelli) - Fix code comment to match code (Ray Jui) - Remove unused struct iproc_pcie.irqs[] (Ray Jui) - Call pci_fixup_irqs() for ARM64 as well as ARM (Ray Jui) - Fix PCIe reset logic (Ray Jui) - Improve link detection logic (Ray Jui) - Update PCIe device tree bindings (Ray Jui) - Add outbound mapping support (Ray Jui) Freescale i.MX6 host bridge driver: - Return real error code from imx6_add_pcie_port() (Fabio Estevam) - Add PCIE_PHY_RX_ASIC_OUT_VALID definition (Fabio Estevam) Freescale Layerscape host bridge driver: - Remove ls_pcie_establish_link() (Minghuan Lian) - Ignore PCIe controllers in Endpoint mode (Minghuan Lian) - Factor out SCFG related function (Minghuan Lian) - Update ls_add_pcie_port() (Minghuan Lian) - Remove unused fields from struct ls_pcie (Minghuan Lian) - Add support for LS1043a and LS2080a (Minghuan Lian) - Add ls_pcie_msi_host_init() (Minghuan Lian) HiSilicon host bridge driver: - Add HiSilicon SoC Hip05 PCIe driver (Zhou Wang) Marvell MVEBU host bridge driver: - Return zero for reserved or unimplemented config space (Russell King) - Use exact config access size; don't read/modify/write (Russell King) - Use of_get_available_child_count() (Russell King) - Use for_each_available_child_of_node() to walk child nodes (Russell King) - Report full node name when reporting a DT error (Russell King) - Use port->name rather than "PCIe%d.%d" (Russell King) - Move port parsing and resource claiming to separate function (Russell King) - Fix memory leaks and refcount leaks (Russell King) - Split port parsing and resource claiming from port setup (Russell King) - Use gpio_set_value_cansleep() (Russell King) - Use devm_kcalloc() to allocate an array (Russell King) - Use gpio_desc to carry around gpio (Russell King) - Improve clock/reset handling (Russell King) - Add PCI Express root complex capability block (Russell King) - Remove code restricting accesses to slot 0 (Russell King) NVIDIA Tegra host bridge driver: - Wrap static pgprot_t initializer with __pgprot() (Ard Biesheuvel) Renesas R-Car host bridge driver: - Build pci-rcar-gen2.c only on ARM (Geert Uytterhoeven) - Build pcie-rcar.c only on ARM (Geert Uytterhoeven) - Make PCI aware of the I/O resources (Phil Edworthy) - Remove dependency on ARM-specific struct hw_pci (Phil Edworthy) - Set root bus nr to that provided in DT (Phil Edworthy) - Fix I/O offset for multiple host bridges (Phil Edworthy) ST Microelectronics SPEAr13xx host bridge driver: - Fix dw_pcie_cfg_read/write() usage (Gabriele Paoloni) Synopsys DesignWare host bridge driver: - Make "clocks" and "clock-names" optional DT properties (Bhupesh Sharma) - Use exact access size in dw_pcie_cfg_read() (Gabriele Paoloni) - Simplify dw_pcie_cfg_read/write() interfaces (Gabriele Paoloni) - Require config accesses to be naturally aligned (Gabriele Paoloni) - Make "num-lanes" an optional DT property (Gabriele Paoloni) - Move calculation of bus addresses to DRA7xx (Gabriele Paoloni) - Replace ARM pci_sys_data->align_resource with global function pointer (Gabriele Paoloni) - Factor out MSI msg setup (Lucas Stach) - Implement multivector MSI IRQ setup (Lucas Stach) - Make get_msi_addr() return phys_addr_t, not u32 (Lucas Stach) - Set up high part of MSI target address (Lucas Stach) - Fix PORT_LOGIC_LINK_WIDTH_MASK (Zhou Wang) - Revert "PCI: designware: Program ATU with untranslated address" (Zhou Wang) - Use of_pci_get_host_bridge_resources() to parse DT (Zhou Wang) - Make driver arch-agnostic (Zhou Wang) Miscellaneous: - Make x86 pci_subsys_init() static (Alexander Kuleshov) - Turn off Request Attributes to avoid Chelsio T5 Completion erratum (Hariprasad Shenai)" * tag 'pci-v4.4-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (94 commits) PCI: altera: Add Altera PCIe MSI driver PCI: hisi: Add HiSilicon SoC Hip05 PCIe driver PCI: layerscape: Add ls_pcie_msi_host_init() PCI: layerscape: Add support for LS1043a and LS2080a PCI: layerscape: Remove unused fields from struct ls_pcie PCI: layerscape: Update ls_add_pcie_port() PCI: layerscape: Factor out SCFG related function PCI: layerscape: Ignore PCIe controllers in Endpoint mode PCI: layerscape: Remove ls_pcie_establish_link() PCI: designware: Make "clocks" and "clock-names" optional DT properties PCI: designware: Make driver arch-agnostic ARM/PCI: Replace pci_sys_data->align_resource with global function pointer PCI: designware: Use of_pci_get_host_bridge_resources() to parse DT Revert "PCI: designware: Program ATU with untranslated address" PCI: designware: Move calculation of bus addresses to DRA7xx PCI: designware: Make "num-lanes" an optional DT property PCI: designware: Require config accesses to be naturally aligned PCI: designware: Simplify dw_pcie_cfg_read/write() interfaces PCI: designware: Use exact access size in dw_pcie_cfg_read() PCI: spear: Fix dw_pcie_cfg_read/write() usage ...
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
#include <linux/pci_hotplug.h>
|
||||
#include <asm-generic/pci-bridge.h>
|
||||
#include <asm/setup.h>
|
||||
#include <linux/aer.h>
|
||||
#include "pci.h"
|
||||
|
||||
const char *pci_power_names[] = {
|
||||
@@ -457,6 +458,30 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev,
|
||||
}
|
||||
EXPORT_SYMBOL(pci_find_parent_resource);
|
||||
|
||||
/**
|
||||
* pci_find_pcie_root_port - return PCIe Root Port
|
||||
* @dev: PCI device to query
|
||||
*
|
||||
* Traverse up the parent chain and return the PCIe Root Port PCI Device
|
||||
* for a given PCI Device.
|
||||
*/
|
||||
struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *bridge, *highest_pcie_bridge = NULL;
|
||||
|
||||
bridge = pci_upstream_bridge(dev);
|
||||
while (bridge && pci_is_pcie(bridge)) {
|
||||
highest_pcie_bridge = bridge;
|
||||
bridge = pci_upstream_bridge(bridge);
|
||||
}
|
||||
|
||||
if (pci_pcie_type(highest_pcie_bridge) != PCI_EXP_TYPE_ROOT_PORT)
|
||||
return NULL;
|
||||
|
||||
return highest_pcie_bridge;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_find_pcie_root_port);
|
||||
|
||||
/**
|
||||
* pci_wait_for_pending - wait for @mask bit(s) to clear in status word @pos
|
||||
* @dev: the PCI device to operate on
|
||||
@@ -484,7 +509,7 @@ int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask)
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_restore_bars - restore a devices BAR values (e.g. after wake-up)
|
||||
* pci_restore_bars - restore a device's BAR values (e.g. after wake-up)
|
||||
* @dev: PCI device to have its BARs restored
|
||||
*
|
||||
* Restore the BAR values for a given device, so as to make it
|
||||
@@ -494,6 +519,10 @@ static void pci_restore_bars(struct pci_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */
|
||||
if (dev->is_virtfn)
|
||||
return;
|
||||
|
||||
for (i = 0; i < PCI_BRIDGE_RESOURCES; i++)
|
||||
pci_update_resource(dev, i);
|
||||
}
|
||||
@@ -1099,6 +1128,8 @@ void pci_restore_state(struct pci_dev *dev)
|
||||
pci_restore_ats_state(dev);
|
||||
pci_restore_vc_state(dev);
|
||||
|
||||
pci_cleanup_aer_error_status_regs(dev);
|
||||
|
||||
pci_restore_config_space(dev);
|
||||
|
||||
pci_restore_pcix_state(dev);
|
||||
@@ -2196,6 +2227,198 @@ void pci_pm_init(struct pci_dev *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long pci_ea_flags(struct pci_dev *dev, u8 prop)
|
||||
{
|
||||
unsigned long flags = IORESOURCE_PCI_FIXED;
|
||||
|
||||
switch (prop) {
|
||||
case PCI_EA_P_MEM:
|
||||
case PCI_EA_P_VF_MEM:
|
||||
flags |= IORESOURCE_MEM;
|
||||
break;
|
||||
case PCI_EA_P_MEM_PREFETCH:
|
||||
case PCI_EA_P_VF_MEM_PREFETCH:
|
||||
flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
|
||||
break;
|
||||
case PCI_EA_P_IO:
|
||||
flags |= IORESOURCE_IO;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static struct resource *pci_ea_get_resource(struct pci_dev *dev, u8 bei,
|
||||
u8 prop)
|
||||
{
|
||||
if (bei <= PCI_EA_BEI_BAR5 && prop <= PCI_EA_P_IO)
|
||||
return &dev->resource[bei];
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5 &&
|
||||
(prop == PCI_EA_P_VF_MEM || prop == PCI_EA_P_VF_MEM_PREFETCH))
|
||||
return &dev->resource[PCI_IOV_RESOURCES +
|
||||
bei - PCI_EA_BEI_VF_BAR0];
|
||||
#endif
|
||||
else if (bei == PCI_EA_BEI_ROM)
|
||||
return &dev->resource[PCI_ROM_RESOURCE];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read an Enhanced Allocation (EA) entry */
|
||||
static int pci_ea_read(struct pci_dev *dev, int offset)
|
||||
{
|
||||
struct resource *res;
|
||||
int ent_size, ent_offset = offset;
|
||||
resource_size_t start, end;
|
||||
unsigned long flags;
|
||||
u32 dw0, bei, base, max_offset;
|
||||
u8 prop;
|
||||
bool support_64 = (sizeof(resource_size_t) >= 8);
|
||||
|
||||
pci_read_config_dword(dev, ent_offset, &dw0);
|
||||
ent_offset += 4;
|
||||
|
||||
/* Entry size field indicates DWORDs after 1st */
|
||||
ent_size = ((dw0 & PCI_EA_ES) + 1) << 2;
|
||||
|
||||
if (!(dw0 & PCI_EA_ENABLE)) /* Entry not enabled */
|
||||
goto out;
|
||||
|
||||
bei = (dw0 & PCI_EA_BEI) >> 4;
|
||||
prop = (dw0 & PCI_EA_PP) >> 8;
|
||||
|
||||
/*
|
||||
* If the Property is in the reserved range, try the Secondary
|
||||
* Property instead.
|
||||
*/
|
||||
if (prop > PCI_EA_P_BRIDGE_IO && prop < PCI_EA_P_MEM_RESERVED)
|
||||
prop = (dw0 & PCI_EA_SP) >> 16;
|
||||
if (prop > PCI_EA_P_BRIDGE_IO)
|
||||
goto out;
|
||||
|
||||
res = pci_ea_get_resource(dev, bei, prop);
|
||||
if (!res) {
|
||||
dev_err(&dev->dev, "Unsupported EA entry BEI: %u\n", bei);
|
||||
goto out;
|
||||
}
|
||||
|
||||
flags = pci_ea_flags(dev, prop);
|
||||
if (!flags) {
|
||||
dev_err(&dev->dev, "Unsupported EA properties: %#x\n", prop);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Read Base */
|
||||
pci_read_config_dword(dev, ent_offset, &base);
|
||||
start = (base & PCI_EA_FIELD_MASK);
|
||||
ent_offset += 4;
|
||||
|
||||
/* Read MaxOffset */
|
||||
pci_read_config_dword(dev, ent_offset, &max_offset);
|
||||
ent_offset += 4;
|
||||
|
||||
/* Read Base MSBs (if 64-bit entry) */
|
||||
if (base & PCI_EA_IS_64) {
|
||||
u32 base_upper;
|
||||
|
||||
pci_read_config_dword(dev, ent_offset, &base_upper);
|
||||
ent_offset += 4;
|
||||
|
||||
flags |= IORESOURCE_MEM_64;
|
||||
|
||||
/* entry starts above 32-bit boundary, can't use */
|
||||
if (!support_64 && base_upper)
|
||||
goto out;
|
||||
|
||||
if (support_64)
|
||||
start |= ((u64)base_upper << 32);
|
||||
}
|
||||
|
||||
end = start + (max_offset | 0x03);
|
||||
|
||||
/* Read MaxOffset MSBs (if 64-bit entry) */
|
||||
if (max_offset & PCI_EA_IS_64) {
|
||||
u32 max_offset_upper;
|
||||
|
||||
pci_read_config_dword(dev, ent_offset, &max_offset_upper);
|
||||
ent_offset += 4;
|
||||
|
||||
flags |= IORESOURCE_MEM_64;
|
||||
|
||||
/* entry too big, can't use */
|
||||
if (!support_64 && max_offset_upper)
|
||||
goto out;
|
||||
|
||||
if (support_64)
|
||||
end += ((u64)max_offset_upper << 32);
|
||||
}
|
||||
|
||||
if (end < start) {
|
||||
dev_err(&dev->dev, "EA Entry crosses address boundary\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ent_size != ent_offset - offset) {
|
||||
dev_err(&dev->dev,
|
||||
"EA Entry Size (%d) does not match length read (%d)\n",
|
||||
ent_size, ent_offset - offset);
|
||||
goto out;
|
||||
}
|
||||
|
||||
res->name = pci_name(dev);
|
||||
res->start = start;
|
||||
res->end = end;
|
||||
res->flags = flags;
|
||||
|
||||
if (bei <= PCI_EA_BEI_BAR5)
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
|
||||
bei, res, prop);
|
||||
else if (bei == PCI_EA_BEI_ROM)
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "ROM: %pR (from Enhanced Allocation, properties %#02x)\n",
|
||||
res, prop);
|
||||
else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5)
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "VF BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",
|
||||
bei - PCI_EA_BEI_VF_BAR0, res, prop);
|
||||
else
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "BEI %d res: %pR (from Enhanced Allocation, properties %#02x)\n",
|
||||
bei, res, prop);
|
||||
|
||||
out:
|
||||
return offset + ent_size;
|
||||
}
|
||||
|
||||
/* Enhanced Allocation Initalization */
|
||||
void pci_ea_init(struct pci_dev *dev)
|
||||
{
|
||||
int ea;
|
||||
u8 num_ent;
|
||||
int offset;
|
||||
int i;
|
||||
|
||||
/* find PCI EA capability in list */
|
||||
ea = pci_find_capability(dev, PCI_CAP_ID_EA);
|
||||
if (!ea)
|
||||
return;
|
||||
|
||||
/* determine the number of entries */
|
||||
pci_bus_read_config_byte(dev->bus, dev->devfn, ea + PCI_EA_NUM_ENT,
|
||||
&num_ent);
|
||||
num_ent &= PCI_EA_NUM_ENT_MASK;
|
||||
|
||||
offset = ea + PCI_EA_FIRST_ENT;
|
||||
|
||||
/* Skip DWORD 2 for type 1 functions */
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
|
||||
offset += 4;
|
||||
|
||||
/* parse each EA entry */
|
||||
for (i = 0; i < num_ent; ++i)
|
||||
offset = pci_ea_read(dev, offset);
|
||||
}
|
||||
|
||||
static void pci_add_saved_cap(struct pci_dev *pci_dev,
|
||||
struct pci_cap_saved_state *new_cap)
|
||||
{
|
||||
|
Reference in New Issue
Block a user