aboutsummaryrefslogtreecommitdiff
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org> 2020-08-07 18:48:15 -0700
committerGravatar Linus Torvalds <torvalds@linux-foundation.org> 2020-08-07 18:48:15 -0700
commit049eb096da48db0421dd5e358b9b082a1a8a2025 (patch)
tree19c1713c656396b2fb9a861985aef80d8d521bec /drivers/pci/pci.c
parentMerge tag 'trace-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/roste... (diff)
parentMerge branch 'pci/irq-error' (diff)
downloadlinux-049eb096da48db0421dd5e358b9b082a1a8a2025.tar.gz
linux-049eb096da48db0421dd5e358b9b082a1a8a2025.tar.bz2
linux-049eb096da48db0421dd5e358b9b082a1a8a2025.zip
Merge tag 'pci-v5.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas: "Enumeration: - Fix pci_cfg_wait queue locking problem (Bjorn Helgaas) - Convert PCIe capability PCIBIOS errors to errno (Bolarinwa Olayemi Saheed) - Align PCIe capability and PCI accessor return values (Bolarinwa Olayemi Saheed) - Fix pci_create_slot() reference count leak (Qiushi Wu) - Announce device after early fixups (Tiezhu Yang) PCI device hotplug: - Make rpadlpar functions static (Wei Yongjun) Driver binding: - Add device even if driver attach failed (Rajat Jain) Virtualization: - xen: Remove redundant initialization of irq (Colin Ian King) IOMMU: - Add pci_pri_supported() to check device or associated PF (Ashok Raj) - Release IVRS table in AMD ACS quirk (Hanjun Guo) - Mark AMD Navi10 GPU rev 0x00 ATS as broken (Kai-Heng Feng) - Treat "external-facing" devices themselves as internal (Rajat Jain) MSI: - Forward MSI-X error code in pci_alloc_irq_vectors_affinity() (Piotr Stankiewicz) Error handling: - Clear PCIe Device Status errors only if OS owns AER (Jonathan Cameron) - Log correctable errors as warning, not error (Matt Jolly) - Use 'pci_channel_state_t' instead of 'enum pci_channel_state' (Luc Van Oostenryck) Peer-to-peer DMA: - Allow P2PDMA on AMD Zen and newer CPUs (Logan Gunthorpe) ASPM: - Add missing newline in sysfs 'policy' (Xiongfeng Wang) Native PCIe controllers: - Convert to devm_platform_ioremap_resource_byname() (Dejin Zheng) - Convert to devm_platform_ioremap_resource() (Dejin Zheng) - Remove duplicate error message from devm_pci_remap_cfg_resource() callers (Dejin Zheng) - Fix runtime PM imbalance on error (Dinghao Liu) - Remove dev_err() when handing an error from platform_get_irq() (Krzysztof Wilczyński) - Use pci_host_bridge.windows list directly instead of splicing in a temporary list for cadence, mvebu, host-common (Rob Herring) - Use pci_host_probe() instead of open-coding all the pieces for altera, brcmstb, iproc, mobiveil, rcar, rockchip, tegra, v3, versatile, xgene, xilinx, xilinx-nwl (Rob Herring) - Default host bridge parent device to the platform device (Rob Herring) - Use pci_is_root_bus() instead of tracking root bus number separately in aardvark, designware (imx6, keystone, designware-host), mobiveil, xilinx-nwl, xilinx, rockchip, rcar (Rob Herring) - Set host bridge bus number in pci_scan_root_bus_bridge() instead of each driver for aardvark, designware-host, host-common, mediatek, rcar, tegra, v3-semi (Rob Herring) - Move DT resource setup into devm_pci_alloc_host_bridge() (Rob Herring) - Set bridge map_irq and swizzle_irq to default functions; drivers that don't support legacy IRQs (iproc) need to undo this (Rob Herring) ARM Versatile PCIe controller driver: - Drop flag PCI_ENABLE_PROC_DOMAINS (Rob Herring) Cadence PCIe controller driver: - Use "dma-ranges" instead of "cdns,no-bar-match-nbits" property (Kishon Vijay Abraham I) - Remove "mem" from reg binding (Kishon Vijay Abraham I) - Fix cdns_pcie_{host|ep}_setup() error path (Kishon Vijay Abraham I) - Convert all r/w accessors to perform only 32-bit accesses (Kishon Vijay Abraham I) - Add support to start link and verify link status (Kishon Vijay Abraham I) - Allow pci_host_bridge to have custom pci_ops (Kishon Vijay Abraham I) - Add new *ops* for CPU addr fixup (Kishon Vijay Abraham I) - Fix updating Vendor ID and Subsystem Vendor ID register (Kishon Vijay Abraham I) - Use bridge resources for outbound window setup (Rob Herring) - Remove private bus number and range storage (Rob Herring) Cadence PCIe endpoint driver: - Add MSI-X support (Alan Douglas) HiSilicon PCIe controller driver: - Remove non-ECAM HiSilicon hip05/hip06 driver (Rob Herring) Intel VMD host bridge driver: - Use Shadow MEMBAR registers for QEMU/KVM guests (Jon Derrick) Loongson PCIe controller driver: - Use DECLARE_PCI_FIXUP_EARLY for bridge_class_quirk() (Tiezhu Yang) Marvell Aardvark PCIe controller driver: - Indicate error in 'val' when config read fails (Pali Rohár) - Don't touch PCIe registers if no card connected (Pali Rohár) Marvell MVEBU PCIe controller driver: - Setup BAR0 in order to fix MSI (Shmuel Hazan) Microsoft Hyper-V host bridge driver: - Fix a timing issue which causes kdump to fail occasionally (Wei Hu) - Make some functions static (Wei Yongjun) NVIDIA Tegra PCIe controller driver: - Revert tegra124 raw_violation_fixup (Nicolas Chauvet) - Remove PLL power supplies (Thierry Reding) Qualcomm PCIe controller driver: - Change duplicate PCI reset to phy reset (Abhishek Sahu) - Add missing ipq806x clocks in PCIe driver (Ansuel Smith) - Add missing reset for ipq806x (Ansuel Smith) - Add ext reset (Ansuel Smith) - Use bulk clk API and assert on error (Ansuel Smith) - Add support for tx term offset for rev 2.1.0 (Ansuel Smith) - Define some PARF params needed for ipq8064 SoC (Ansuel Smith) - Add ipq8064 rev2 variant (Ansuel Smith) - Support PCI speed set for ipq806x (Sham Muthayyan) Renesas R-Car PCIe controller driver: - Use devm_pci_alloc_host_bridge() (Rob Herring) - Use struct pci_host_bridge.windows list directly (Rob Herring) - Convert rcar-gen2 to use modern host bridge probe functions (Rob Herring) TI J721E PCIe driver: - Add TI J721E PCIe host and endpoint driver (Kishon Vijay Abraham I) Xilinx Versal CPM PCIe controller driver: - Add Versal CPM Root Port driver and YAML schema (Bharat Kumar Gogada) MicroSemi Switchtec management driver: - Add missing __iomem and __user tags to fix sparse warnings (Logan Gunthorpe) Miscellaneous: - Replace http:// links with https:// (Alexander A. Klimov) - Replace lkml.org, spinics, gmane with lore.kernel.org (Bjorn Helgaas) - Remove unused pci_lost_interrupt() (Heiner Kallweit) - Move PCI_VENDOR_ID_REDHAT definition to pci_ids.h (Huacai Chen) - Fix kerneldoc warnings (Krzysztof Kozlowski)" * tag 'pci-v5.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (113 commits) PCI: Fix kerneldoc warnings PCI: xilinx-cpm: Add Versal CPM Root Port driver PCI: xilinx-cpm: Add YAML schemas for Versal CPM Root Port PCI: Set bridge map_irq and swizzle_irq to default functions PCI: Move DT resource setup into devm_pci_alloc_host_bridge() PCI: rcar-gen2: Convert to use modern host bridge probe functions PCI: Remove dev_err() when handing an error from platform_get_irq() MAINTAINERS: Add Kishon Vijay Abraham I for TI J721E SoC PCIe misc: pci_endpoint_test: Add J721E in pci_device_id table PCI: j721e: Add TI J721E PCIe driver PCI: switchtec: Add missing __iomem tag to fix sparse warnings PCI: switchtec: Add missing __iomem and __user tags to fix sparse warnings PCI: rpadlpar: Make functions static PCI/P2PDMA: Allow P2PDMA on AMD Zen and newer CPUs PCI: Release IVRS table in AMD ACS quirk PCI: Announce device after early fixups PCI: Mark AMD Navi10 GPU rev 0x00 ATS as broken PCI: Remove unused pci_lost_interrupt() dt-bindings: PCI: Add EP mode dt-bindings for TI's J721E SoC dt-bindings: PCI: Add host mode dt-bindings for TI's J721E SoC ...
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c286
1 files changed, 156 insertions, 130 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c9338f914a0e..a458c46d7e39 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -777,6 +777,133 @@ int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask)
return 0;
}
+static int pci_acs_enable;
+
+/**
+ * pci_request_acs - ask for ACS to be enabled if supported
+ */
+void pci_request_acs(void)
+{
+ pci_acs_enable = 1;
+}
+
+static const char *disable_acs_redir_param;
+
+/**
+ * pci_disable_acs_redir - disable ACS redirect capabilities
+ * @dev: the PCI device
+ *
+ * For only devices specified in the disable_acs_redir parameter.
+ */
+static void pci_disable_acs_redir(struct pci_dev *dev)
+{
+ int ret = 0;
+ const char *p;
+ int pos;
+ u16 ctrl;
+
+ if (!disable_acs_redir_param)
+ return;
+
+ p = disable_acs_redir_param;
+ while (*p) {
+ ret = pci_dev_str_match(dev, p, &p);
+ if (ret < 0) {
+ pr_info_once("PCI: Can't parse disable_acs_redir parameter: %s\n",
+ disable_acs_redir_param);
+
+ break;
+ } else if (ret == 1) {
+ /* Found a match */
+ break;
+ }
+
+ if (*p != ';' && *p != ',') {
+ /* End of param or invalid format */
+ break;
+ }
+ p++;
+ }
+
+ if (ret != 1)
+ return;
+
+ if (!pci_dev_specific_disable_acs_redir(dev))
+ return;
+
+ pos = dev->acs_cap;
+ if (!pos) {
+ pci_warn(dev, "cannot disable ACS redirect for this hardware as it does not have ACS capabilities\n");
+ return;
+ }
+
+ pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
+
+ /* P2P Request & Completion Redirect */
+ ctrl &= ~(PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC);
+
+ pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+
+ pci_info(dev, "disabled ACS redirect\n");
+}
+
+/**
+ * pci_std_enable_acs - enable ACS on devices using standard ACS capabilities
+ * @dev: the PCI device
+ */
+static void pci_std_enable_acs(struct pci_dev *dev)
+{
+ int pos;
+ u16 cap;
+ u16 ctrl;
+
+ pos = dev->acs_cap;
+ if (!pos)
+ return;
+
+ pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
+ pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
+
+ /* Source Validation */
+ ctrl |= (cap & PCI_ACS_SV);
+
+ /* P2P Request Redirect */
+ ctrl |= (cap & PCI_ACS_RR);
+
+ /* P2P Completion Redirect */
+ ctrl |= (cap & PCI_ACS_CR);
+
+ /* Upstream Forwarding */
+ ctrl |= (cap & PCI_ACS_UF);
+
+ pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+}
+
+/**
+ * pci_enable_acs - enable ACS if hardware support it
+ * @dev: the PCI device
+ */
+static void pci_enable_acs(struct pci_dev *dev)
+{
+ if (!pci_acs_enable)
+ goto disable_acs_redir;
+
+ if (!pci_dev_specific_enable_acs(dev))
+ goto disable_acs_redir;
+
+ pci_std_enable_acs(dev);
+
+disable_acs_redir:
+ /*
+ * Note: pci_disable_acs_redir() must be called even if ACS was not
+ * enabled by the kernel because it may have been enabled by
+ * platform firmware. So if we are told to disable it, we should
+ * always disable it after setting the kernel's default
+ * preferences.
+ */
+ pci_disable_acs_redir(dev);
+}
+
/**
* pci_restore_bars - restore a device's BAR values (e.g. after wake-up)
* @dev: PCI device to have its BARs restored
@@ -2046,6 +2173,14 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
}
EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
+void pcie_clear_device_status(struct pci_dev *dev)
+{
+ u16 sta;
+
+ pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &sta);
+ pcie_capability_write_word(dev, PCI_EXP_DEVSTA, sta);
+}
+
/**
* pcie_clear_root_pme_status - Clear root port PME interrupt status.
* @dev: PCIe root port or event collector.
@@ -3230,139 +3365,12 @@ void pci_configure_ari(struct pci_dev *dev)
}
}
-static int pci_acs_enable;
-
-/**
- * pci_request_acs - ask for ACS to be enabled if supported
- */
-void pci_request_acs(void)
-{
- pci_acs_enable = 1;
-}
-
-static const char *disable_acs_redir_param;
-
-/**
- * pci_disable_acs_redir - disable ACS redirect capabilities
- * @dev: the PCI device
- *
- * For only devices specified in the disable_acs_redir parameter.
- */
-static void pci_disable_acs_redir(struct pci_dev *dev)
-{
- int ret = 0;
- const char *p;
- int pos;
- u16 ctrl;
-
- if (!disable_acs_redir_param)
- return;
-
- p = disable_acs_redir_param;
- while (*p) {
- ret = pci_dev_str_match(dev, p, &p);
- if (ret < 0) {
- pr_info_once("PCI: Can't parse disable_acs_redir parameter: %s\n",
- disable_acs_redir_param);
-
- break;
- } else if (ret == 1) {
- /* Found a match */
- break;
- }
-
- if (*p != ';' && *p != ',') {
- /* End of param or invalid format */
- break;
- }
- p++;
- }
-
- if (ret != 1)
- return;
-
- if (!pci_dev_specific_disable_acs_redir(dev))
- return;
-
- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
- if (!pos) {
- pci_warn(dev, "cannot disable ACS redirect for this hardware as it does not have ACS capabilities\n");
- return;
- }
-
- pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
-
- /* P2P Request & Completion Redirect */
- ctrl &= ~(PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC);
-
- pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
-
- pci_info(dev, "disabled ACS redirect\n");
-}
-
-/**
- * pci_std_enable_acs - enable ACS on devices using standard ACS capabilities
- * @dev: the PCI device
- */
-static void pci_std_enable_acs(struct pci_dev *dev)
-{
- int pos;
- u16 cap;
- u16 ctrl;
-
- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
- if (!pos)
- return;
-
- pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
- pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
-
- /* Source Validation */
- ctrl |= (cap & PCI_ACS_SV);
-
- /* P2P Request Redirect */
- ctrl |= (cap & PCI_ACS_RR);
-
- /* P2P Completion Redirect */
- ctrl |= (cap & PCI_ACS_CR);
-
- /* Upstream Forwarding */
- ctrl |= (cap & PCI_ACS_UF);
-
- pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
-}
-
-/**
- * pci_enable_acs - enable ACS if hardware support it
- * @dev: the PCI device
- */
-void pci_enable_acs(struct pci_dev *dev)
-{
- if (!pci_acs_enable)
- goto disable_acs_redir;
-
- if (!pci_dev_specific_enable_acs(dev))
- goto disable_acs_redir;
-
- pci_std_enable_acs(dev);
-
-disable_acs_redir:
- /*
- * Note: pci_disable_acs_redir() must be called even if ACS was not
- * enabled by the kernel because it may have been enabled by
- * platform firmware. So if we are told to disable it, we should
- * always disable it after setting the kernel's default
- * preferences.
- */
- pci_disable_acs_redir(dev);
-}
-
static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
{
int pos;
u16 cap, ctrl;
- pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS);
+ pos = pdev->acs_cap;
if (!pos)
return false;
@@ -3488,6 +3496,18 @@ bool pci_acs_path_enabled(struct pci_dev *start,
}
/**
+ * pci_acs_init - Initialize ACS if hardware supports it
+ * @dev: the PCI device
+ */
+void pci_acs_init(struct pci_dev *dev)
+{
+ dev->acs_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
+
+ if (dev->acs_cap)
+ pci_enable_acs(dev);
+}
+
+/**
* pci_rebar_find_pos - find position of resize ctrl reg for BAR
* @pdev: PCI device
* @bar: BAR to find
@@ -5676,6 +5696,7 @@ EXPORT_SYMBOL(pcie_get_readrq);
int pcie_set_readrq(struct pci_dev *dev, int rq)
{
u16 v;
+ int ret;
if (rq < 128 || rq > 4096 || !is_power_of_2(rq))
return -EINVAL;
@@ -5694,8 +5715,10 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
v = (ffs(rq) - 8) << 12;
- return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
+ ret = pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
PCI_EXP_DEVCTL_READRQ, v);
+
+ return pcibios_err_to_errno(ret);
}
EXPORT_SYMBOL(pcie_set_readrq);
@@ -5726,6 +5749,7 @@ EXPORT_SYMBOL(pcie_get_mps);
int pcie_set_mps(struct pci_dev *dev, int mps)
{
u16 v;
+ int ret;
if (mps < 128 || mps > 4096 || !is_power_of_2(mps))
return -EINVAL;
@@ -5735,8 +5759,10 @@ int pcie_set_mps(struct pci_dev *dev, int mps)
return -EINVAL;
v <<= 5;
- return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
+ ret = pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
PCI_EXP_DEVCTL_PAYLOAD, v);
+
+ return pcibios_err_to_errno(ret);
}
EXPORT_SYMBOL(pcie_set_mps);