| From 89fa2a019d2d3bba15a9162074861c05db2d7b17 Mon Sep 17 00:00:00 2001 |
| From: Bjorn Helgaas <bhelgaas@google.com> |
| Date: Fri, 6 Sep 2019 18:36:06 -0500 |
| Subject: [PATCH] PCI: Unify ACS quirk desired vs provided checking |
| |
| 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c |
| index 046ff091d26e..21a99bce8e2b 100644 |
| --- a/drivers/pci/quirks.c |
| +++ b/drivers/pci/quirks.c |
| @@ -4283,6 +4283,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 |
| @@ -4325,7 +4343,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 |
| @@ -4363,9 +4381,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) |
| @@ -4375,9 +4392,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); |
| } |
| |
| /* |
| @@ -4429,17 +4445,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); |
| } |
| |
| /* |
| @@ -4454,9 +4469,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); |
| } |
| |
| /* |
| @@ -4539,7 +4553,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) |
| @@ -4553,10 +4567,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) |
| @@ -4567,9 +4580,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 { |
| @@ -4669,6 +4681,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; |
| -- |
| 2.7.4 |
| |