PCI: Unify ACS quirk desired vs provided checking

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>
This commit is contained in:
Bjorn Helgaas 2019-09-06 18:36:06 -05:00
parent c8de8ed2dc
commit 7cf2cba43f

View File

@ -4296,6 +4296,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, DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
quirk_chelsio_T5_disable_root_port_attributes); 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 * 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 * in any system where they are found in the southbridge with an AMD
@ -4339,7 +4357,7 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
/* Filter out flags not applicable to multifunction */ /* Filter out flags not applicable to multifunction */
acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT); 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 #else
return -ENODEV; return -ENODEV;
#endif #endif
@ -4377,9 +4395,8 @@ static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags)
* hardware implements and enables equivalent ACS functionality for * hardware implements and enables equivalent ACS functionality for
* these flags. * these flags.
*/ */
acs_flags &= ~(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); return pci_acs_ctrl_enabled(acs_flags,
PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
return acs_flags ? 0 : 1;
} }
static int pci_quirk_xgene_acs(struct pci_dev *dev, u16 acs_flags) static int pci_quirk_xgene_acs(struct pci_dev *dev, u16 acs_flags)
@ -4389,9 +4406,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 * transactions with others, allowing masking out these bits as if they
* were unimplemented in the ACS capability. * were unimplemented in the ACS capability.
*/ */
acs_flags &= ~(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); return pci_acs_ctrl_enabled(acs_flags,
PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
return acs_flags ? 0 : 1;
} }
/* /*
@ -4443,17 +4459,16 @@ static bool pci_quirk_intel_pch_acs_match(struct pci_dev *dev)
return false; 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) static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
{ {
if (!pci_quirk_intel_pch_acs_match(dev)) if (!pci_quirk_intel_pch_acs_match(dev))
return -ENOTTY; return -ENOTTY;
if (dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK) 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);
} }
/* /*
@ -4468,9 +4483,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) 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 pci_acs_ctrl_enabled(acs_flags,
PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
return acs_flags ? 0 : 1;
} }
static int pci_quirk_al_acs(struct pci_dev *dev, u16 acs_flags) static int pci_quirk_al_acs(struct pci_dev *dev, u16 acs_flags)
@ -4571,7 +4585,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); 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) static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags)
@ -4585,10 +4599,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 * perform peer-to-peer with other functions, allowing us to mask out
* these bits as if they were unimplemented in the ACS capability. * these bits as if they were unimplemented in the ACS capability.
*/ */
acs_flags &= ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR | return pci_acs_ctrl_enabled(acs_flags,
PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT); PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR |
PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT);
return acs_flags ? 0 : 1;
} }
static int pci_quirk_brcm_acs(struct pci_dev *dev, u16 acs_flags) static int pci_quirk_brcm_acs(struct pci_dev *dev, u16 acs_flags)
@ -4599,9 +4612,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 * Allow each Root Port to be in a separate IOMMU group by masking
* SV/RR/CR/UF bits. * SV/RR/CR/UF bits.
*/ */
acs_flags &= ~(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF); return pci_acs_ctrl_enabled(acs_flags,
PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
return acs_flags ? 0 : 1;
} }
static const struct pci_dev_acs_enabled { static const struct pci_dev_acs_enabled {
@ -4703,6 +4715,17 @@ static const struct pci_dev_acs_enabled {
{ 0 } { 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) int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)
{ {
const struct pci_dev_acs_enabled *i; const struct pci_dev_acs_enabled *i;