@@ -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))
@@ -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(-)