PCI: Unify ACS quirk desired vs provided checking
authorBjorn Helgaas <bhelgaas@google.com>
Fri, 6 Sep 2019 23:36:06 +0000 (18:36 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 2 May 2020 06:48:49 +0000 (08:48 +0200)
commit 7cf2cba43f15c74bac46dc5f0326805d25ef514d upstream.

Most of the ACS quirks have a similar pattern of:

  acs_flags &= ~( <controls provided by this device> );
  return acs_flags ? 0 : 1;

Pull this out into a helper function to simplify the quirks slightly.  The
helper function is also a convenient place for comments about what the list
of ACS controls means.  No functional change intended.

Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/pci/quirks.c

index 2b413a3..fbbf6c3 100644 (file)
@@ -4353,6 +4353,24 @@ 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
  * IOMMU in the system.  Multifunction devices that do not support
@@ -4395,7 +4413,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
@@ -4433,9 +4451,8 @@ static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags)
         * hardware implements and enables equivalent ACS functionality for
         * these flags.
         */
-       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 int pci_quirk_xgene_acs(struct pci_dev *dev, u16 acs_flags)
@@ -4445,9 +4462,8 @@ 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);
 }
 
 /*
@@ -4499,17 +4515,16 @@ static bool pci_quirk_intel_pch_acs_match(struct pci_dev *dev)
        return false;
 }
 
-#define INTEL_PCH_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
-
 static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
 {
        if (!pci_quirk_intel_pch_acs_match(dev))
                return -ENOTTY;
 
        if (dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK)
-               acs_flags &= ~(INTEL_PCH_ACS_FLAGS);
+               return pci_acs_ctrl_enabled(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, 0);
 }
 
 /*
@@ -4524,9 +4539,8 @@ static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
  */
 static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags)
 {
-       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 int pci_quirk_al_acs(struct pci_dev *dev, u16 acs_flags)
@@ -4627,7 +4641,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)
@@ -4641,10 +4655,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)
@@ -4655,9 +4668,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 {
@@ -4763,6 +4775,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;