Message ID | 20200311124506.208376-6-jean-philippe@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | PCI/ATS: Device-tree support and other improvements | expand |
On Wed, Mar 11, 2020 at 01:45:00PM +0100, Jean-Philippe Brucker wrote: > IOMMU drivers need to perform several tests when checking if a device > supports ATS. Move them all into a new function that returns true when > a device and its host bridge support ATS. > > Since pci_enable_ats() now calls pci_ats_supported(), the following > new checks are now common: > * whether a device is trusted. Devices plugged into external-facing > ports such as thunderbolt are untrusted. > * whether the host bridge supports ATS, which defaults to true unless > the firmware description states that ATS isn't supported by the host > bridge. > > Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Acked-by: Bjorn Helgaas <bhelgaas@google.com> > --- > drivers/pci/ats.c | 30 +++++++++++++++++++++++++++++- > include/linux/pci-ats.h | 3 +++ > 2 files changed, 32 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c > index 390e92f2d8d1..bbfd0d42b8b9 100644 > --- a/drivers/pci/ats.c > +++ b/drivers/pci/ats.c > @@ -30,6 +30,34 @@ void pci_ats_init(struct pci_dev *dev) > dev->ats_cap = pos; > } > > +/** > + * pci_ats_supported - check if the device can use ATS > + * @dev: the PCI device > + * > + * Returns true if the device supports ATS and is allowed to use it, false > + * otherwise. > + */ > +bool pci_ats_supported(struct pci_dev *dev) > +{ > + struct pci_host_bridge *bridge; > + > + if (!dev->ats_cap) > + return false; > + > + if (dev->untrusted) > + return false; > + > + bridge = pci_find_host_bridge(dev->bus); > + if (!bridge) > + return false; > + > + if (!bridge->ats_supported) > + return false; > + > + return true; I assume this is the same as return bridge->ats_supported; Only "assuming" because I'm not a C language lawyer, but I assume it does the obvious conversion from unsigned:1 to bool. > +}
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 390e92f2d8d1..bbfd0d42b8b9 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -30,6 +30,34 @@ void pci_ats_init(struct pci_dev *dev) dev->ats_cap = pos; } +/** + * pci_ats_supported - check if the device can use ATS + * @dev: the PCI device + * + * Returns true if the device supports ATS and is allowed to use it, false + * otherwise. + */ +bool pci_ats_supported(struct pci_dev *dev) +{ + struct pci_host_bridge *bridge; + + if (!dev->ats_cap) + return false; + + if (dev->untrusted) + return false; + + bridge = pci_find_host_bridge(dev->bus); + if (!bridge) + return false; + + if (!bridge->ats_supported) + return false; + + return true; +} +EXPORT_SYMBOL_GPL(pci_ats_supported); + /** * pci_enable_ats - enable the ATS capability * @dev: the PCI device @@ -42,7 +70,7 @@ int pci_enable_ats(struct pci_dev *dev, int ps) u16 ctrl; struct pci_dev *pdev; - if (!dev->ats_cap) + if (!pci_ats_supported(dev)) return -EINVAL; if (WARN_ON(dev->ats_enabled)) diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h index d08f0869f121..f75c307f346d 100644 --- a/include/linux/pci-ats.h +++ b/include/linux/pci-ats.h @@ -6,11 +6,14 @@ #ifdef CONFIG_PCI_ATS /* Address Translation Service */ +bool pci_ats_supported(struct pci_dev *dev); int pci_enable_ats(struct pci_dev *dev, int ps); void pci_disable_ats(struct pci_dev *dev); int pci_ats_queue_depth(struct pci_dev *dev); int pci_ats_page_aligned(struct pci_dev *dev); #else /* CONFIG_PCI_ATS */ +static inline bool pci_ats_supported(struct pci_dev *d) +{ return false; } static inline int pci_enable_ats(struct pci_dev *d, int ps) { return -ENODEV; } static inline void pci_disable_ats(struct pci_dev *d) { }
IOMMU drivers need to perform several tests when checking if a device supports ATS. Move them all into a new function that returns true when a device and its host bridge support ATS. Since pci_enable_ats() now calls pci_ats_supported(), the following new checks are now common: * whether a device is trusted. Devices plugged into external-facing ports such as thunderbolt are untrusted. * whether the host bridge supports ATS, which defaults to true unless the firmware description states that ATS isn't supported by the host bridge. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> --- drivers/pci/ats.c | 30 +++++++++++++++++++++++++++++- include/linux/pci-ats.h | 3 +++ 2 files changed, 32 insertions(+), 1 deletion(-)