]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/pci/quirks.c
pinctrl: lynxpoint: Reuse struct intel_pinctrl in the driver
[linux.git] / drivers / pci / quirks.c
index 5d5e6f2f783746d45c091f6f9659f871906b87fd..4937a088d7d8460da6ed8fcf2c79494db9b7941b 100644 (file)
@@ -4033,7 +4033,6 @@ static void quirk_fixed_dma_alias(struct pci_dev *dev)
        if (id)
                pci_add_dma_alias(dev, id->driver_data);
 }
-
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ADAPTEC2, 0x0285, quirk_fixed_dma_alias);
 
 /*
@@ -4080,6 +4079,40 @@ static void quirk_mic_x200_dma_alias(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2260, quirk_mic_x200_dma_alias);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2264, quirk_mic_x200_dma_alias);
 
+/*
+ * Intel Visual Compute Accelerator (VCA) is a family of PCIe add-in devices
+ * exposing computational units via Non Transparent Bridges (NTB, PEX 87xx).
+ *
+ * Similarly to MIC x200, we need to add DMA aliases to allow buffer access
+ * when IOMMU is enabled.  These aliases allow computational unit access to
+ * host memory.  These aliases mark the whole VCA device as one IOMMU
+ * group.
+ *
+ * All possible slot numbers (0x20) are used, since we are unable to tell
+ * what slot is used on other side.  This quirk is intended for both host
+ * and computational unit sides.  The VCA devices have up to five functions
+ * (four for DMA channels and one additional).
+ */
+static void quirk_pex_vca_alias(struct pci_dev *pdev)
+{
+       const unsigned int num_pci_slots = 0x20;
+       unsigned int slot;
+
+       for (slot = 0; slot < num_pci_slots; slot++) {
+               pci_add_dma_alias(pdev, PCI_DEVFN(slot, 0x0));
+               pci_add_dma_alias(pdev, PCI_DEVFN(slot, 0x1));
+               pci_add_dma_alias(pdev, PCI_DEVFN(slot, 0x2));
+               pci_add_dma_alias(pdev, PCI_DEVFN(slot, 0x3));
+               pci_add_dma_alias(pdev, PCI_DEVFN(slot, 0x4));
+       }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2954, quirk_pex_vca_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2955, quirk_pex_vca_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2956, quirk_pex_vca_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2958, quirk_pex_vca_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2959, quirk_pex_vca_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x295A, quirk_pex_vca_alias);
+
 /*
  * The IOMMU and interrupt controller on Broadcom Vulcan/Cavium ThunderX2 are
  * associated not at the root bus, but at a bridge below. This quirk avoids
@@ -4262,6 +4295,24 @@ static void quirk_chelsio_T5_disable_root_port_attributes(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
                         quirk_chelsio_T5_disable_root_port_attributes);
 
+/*
+ * pci_acs_ctrl_enabled - compare desired ACS controls with those provided
+ *                       by a device
+ * @acs_ctrl_req: Bitmask of desired ACS controls
+ * @acs_ctrl_ena: Bitmask of ACS controls enabled or provided implicitly by
+ *               the hardware design
+ *
+ * Return 1 if all ACS controls in the @acs_ctrl_req bitmask are included
+ * in @acs_ctrl_ena, i.e., the device provides all the access controls the
+ * caller desires.  Return 0 otherwise.
+ */
+static int pci_acs_ctrl_enabled(u16 acs_ctrl_req, u16 acs_ctrl_ena)
+{
+       if ((acs_ctrl_req & acs_ctrl_ena) == acs_ctrl_req)
+               return 1;
+       return 0;
+}
+
 /*
  * AMD has indicated that the devices below do not support peer-to-peer
  * in any system where they are found in the southbridge with an AMD
@@ -4305,7 +4356,7 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
        /* Filter out flags not applicable to multifunction */
        acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT);
 
-       return acs_flags & ~(PCI_ACS_RR | PCI_ACS_CR) ? 0 : 1;
+       return pci_acs_ctrl_enabled(acs_flags, PCI_ACS_RR | PCI_ACS_CR);
 #else
        return -ENODEV;
 #endif
@@ -4313,33 +4364,38 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
 
 static bool pci_quirk_cavium_acs_match(struct pci_dev *dev)
 {
+       if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
+               return false;
+
+       switch (dev->device) {
        /*
-        * Effectively selects all downstream ports for whole ThunderX 1
-        * family by 0xf800 mask (which represents 8 SoCs), while the lower
-        * bits of device ID are used to indicate which subdevice is used
-        * within the SoC.
+        * Effectively selects all downstream ports for whole ThunderX1
+        * (which represents 8 SoCs).
         */
-       return (pci_is_pcie(dev) &&
-               (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) &&
-               ((dev->device & 0xf800) == 0xa000));
+       case 0xa000 ... 0xa7ff: /* ThunderX1 */
+       case 0xaf84:  /* ThunderX2 */
+       case 0xb884:  /* ThunderX3 */
+               return true;
+       default:
+               return false;
+       }
 }
 
 static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags)
 {
+       if (!pci_quirk_cavium_acs_match(dev))
+               return -ENOTTY;
+
        /*
-        * Cavium root ports don't advertise an ACS capability.  However,
+        * Cavium Root Ports don't advertise an ACS capability.  However,
         * the RTL internally implements similar protection as if ACS had
-        * Request Redirection, Completion Redirection, Source Validation,
+        * Source Validation, Request Redirection, Completion Redirection,
         * and Upstream Forwarding features enabled.  Assert that the
         * hardware implements and enables equivalent ACS functionality for
         * these flags.
         */
-       acs_flags &= ~(PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_SV | PCI_ACS_UF);
-
-       if (!pci_quirk_cavium_acs_match(dev))
-               return -ENOTTY;
-
-       return acs_flags ? 0 : 1;
+       return pci_acs_ctrl_enabled(acs_flags,
+               PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
 }
 
 static int pci_quirk_xgene_acs(struct pci_dev *dev, u16 acs_flags)
@@ -4349,13 +4405,12 @@ static int pci_quirk_xgene_acs(struct pci_dev *dev, u16 acs_flags)
         * transactions with others, allowing masking out these bits as if they
         * were unimplemented in the ACS capability.
         */
-       acs_flags &= ~(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
-
-       return acs_flags ? 0 : 1;
+       return pci_acs_ctrl_enabled(acs_flags,
+               PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
 }
 
 /*
- * Many Intel PCH root ports do provide ACS-like features to disable peer
+ * Many Intel PCH Root Ports do provide ACS-like features to disable peer
  * transactions and validate bus numbers in requests, but do not provide an
  * actual PCIe ACS capability.  This is the list of device IDs known to fall
  * into that category as provided by Intel in Red Hat bugzilla 1037684.
@@ -4403,37 +4458,32 @@ static bool pci_quirk_intel_pch_acs_match(struct pci_dev *dev)
        return false;
 }
 
-#define INTEL_PCH_ACS_FLAGS (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_SV)
-
 static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
 {
-       u16 flags = dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK ?
-                   INTEL_PCH_ACS_FLAGS : 0;
-
        if (!pci_quirk_intel_pch_acs_match(dev))
                return -ENOTTY;
 
-       return acs_flags & ~flags ? 0 : 1;
+       if (dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK)
+               return pci_acs_ctrl_enabled(acs_flags,
+                       PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
+
+       return pci_acs_ctrl_enabled(acs_flags, 0);
 }
 
 /*
- * These QCOM root ports do provide ACS-like features to disable peer
+ * These QCOM Root Ports do provide ACS-like features to disable peer
  * transactions and validate bus numbers in requests, but do not provide an
  * actual PCIe ACS capability.  Hardware supports source validation but it
  * will report the issue as Completer Abort instead of ACS Violation.
- * Hardware doesn't support peer-to-peer and each root port is a root
- * complex with unique segment numbers.  It is not possible for one root
- * port to pass traffic to another root port.  All PCIe transactions are
- * terminated inside the root port.
+ * Hardware doesn't support peer-to-peer and each Root Port is a Root
+ * Complex with unique segment numbers.  It is not possible for one Root
+ * Port to pass traffic to another Root Port.  All PCIe transactions are
+ * terminated inside the Root Port.
  */
 static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags)
 {
-       u16 flags = (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_SV);
-       int ret = acs_flags & ~flags ? 0 : 1;
-
-       pci_info(dev, "Using QCOM ACS Quirk (%d)\n", ret);
-
-       return ret;
+       return pci_acs_ctrl_enabled(acs_flags,
+               PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
 }
 
 static int pci_quirk_al_acs(struct pci_dev *dev, u16 acs_flags)
@@ -4534,7 +4584,7 @@ static int pci_quirk_intel_spt_pch_acs(struct pci_dev *dev, u16 acs_flags)
 
        pci_read_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, &ctrl);
 
-       return acs_flags & ~ctrl ? 0 : 1;
+       return pci_acs_ctrl_enabled(acs_flags, ctrl);
 }
 
 static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags)
@@ -4548,10 +4598,9 @@ static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags)
         * perform peer-to-peer with other functions, allowing us to mask out
         * these bits as if they were unimplemented in the ACS capability.
         */
-       acs_flags &= ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR |
-                      PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT);
-
-       return acs_flags ? 0 : 1;
+       return pci_acs_ctrl_enabled(acs_flags,
+               PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR |
+               PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT);
 }
 
 static int pci_quirk_brcm_acs(struct pci_dev *dev, u16 acs_flags)
@@ -4562,9 +4611,8 @@ static int pci_quirk_brcm_acs(struct pci_dev *dev, u16 acs_flags)
         * Allow each Root Port to be in a separate IOMMU group by masking
         * SV/RR/CR/UF bits.
         */
-       acs_flags &= ~(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
-
-       return acs_flags ? 0 : 1;
+       return pci_acs_ctrl_enabled(acs_flags,
+               PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
 }
 
 static const struct pci_dev_acs_enabled {
@@ -4666,6 +4714,17 @@ static const struct pci_dev_acs_enabled {
        { 0 }
 };
 
+/*
+ * pci_dev_specific_acs_enabled - check whether device provides ACS controls
+ * @dev:       PCI device
+ * @acs_flags: Bitmask of desired ACS controls
+ *
+ * Returns:
+ *   -ENOTTY:  No quirk applies to this device; we can't tell whether the
+ *             device provides the desired controls
+ *   0:                Device does not provide all the desired controls
+ *   >0:       Device provides all the controls in @acs_flags
+ */
 int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)
 {
        const struct pci_dev_acs_enabled *i;
@@ -4706,7 +4765,7 @@ int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)
 #define INTEL_BSPR_REG_BPPD  (1 << 9)
 
 /* Upstream Peer Decode Configuration Register */
-#define INTEL_UPDCR_REG 0x1114
+#define INTEL_UPDCR_REG 0x1014
 /* 5:0 Peer Decode Enable bits */
 #define INTEL_UPDCR_REG_MASK 0x3f