]> 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 2544e210b98402fe7f84d2e0e9b052b7bf447c71..4937a088d7d8460da6ed8fcf2c79494db9b7941b 100644 (file)
@@ -474,7 +474,7 @@ static void quirk_extend_bar_to_page(struct pci_dev *dev)
 {
        int i;
 
-       for (i = 0; i <= PCI_STD_RESOURCE_END; i++) {
+       for (i = 0; i < PCI_STD_NUM_BARS; i++) {
                struct resource *r = &dev->resource[i];
 
                if (r->flags & IORESOURCE_MEM && resource_size(r) < PAGE_SIZE) {
@@ -1809,7 +1809,7 @@ static void quirk_alder_ioapic(struct pci_dev *pdev)
         * The next five BARs all seem to be rubbish, so just clean
         * them out.
         */
-       for (i = 1; i < 6; i++)
+       for (i = 1; i < PCI_STD_NUM_BARS; i++)
                memset(&pdev->resource[i], 0, sizeof(pdev->resource[i]));
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_EESSC,      quirk_alder_ioapic);
@@ -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);
 
 /*
@@ -4296,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
@@ -4339,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
@@ -4366,20 +4383,19 @@ static bool pci_quirk_cavium_acs_match(struct pci_dev *dev)
 
 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)
@@ -4389,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.
@@ -4443,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)
@@ -4574,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)
@@ -4588,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)
@@ -4602,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 {
@@ -4706,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;