Add PCIe devices of R-Car Gen3/4 into devices_allowlist. For a PCI device, ipmmu_attach_device() has to avoid enabling uTLB because the uTLB has already been enabled by the parent device. Otherwise, enable a wrong uTLB ID. Also ipmmu_device_is_allowed() has to check whether the parent device is the PCIe host controller or not, to use the IOMMU's dma_ops from a PCI device. Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx> --- drivers/iommu/ipmmu-vmsa.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 9f64c5c9f5b9..c635c9b192f4 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -19,6 +19,7 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_platform.h> +#include <linux/pci.h> #include <linux/platform_device.h> #include <linux/sizes.h> #include <linux/slab.h> @@ -624,6 +625,10 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain, if (ret < 0) return ret; + /* Avoid to enable utlb if this is a PCI device */ + if (dev_is_pci(dev)) + return 0; + for (i = 0; i < fwspec->num_ids; ++i) ipmmu_utlb_enable(domain, fwspec->ids[i]); @@ -702,10 +707,14 @@ static const struct soc_device_attribute soc_denylist[] = { }; static const char * const devices_allowlist[] = { + "e65d0000.pcie", /* R-Car Gen4 */ + "e65d8000.pcie", /* R-Car Gen4 */ "ee100000.mmc", "ee120000.mmc", "ee140000.mmc", - "ee160000.mmc" + "ee160000.mmc", + "ee800000.pcie", /* R-Car Gen3 */ + "fe000000.pcie", /* R-Car Gen3 */ }; static bool ipmmu_device_is_allowed(struct device *dev) @@ -723,12 +732,22 @@ static bool ipmmu_device_is_allowed(struct device *dev) if (soc_device_match(soc_denylist)) return false; +retry: /* Check whether this device can work with the IPMMU */ for (i = 0; i < ARRAY_SIZE(devices_allowlist); i++) { if (!strcmp(dev_name(dev), devices_allowlist[i])) return true; } + /* + * Check whether this device has the parent device like a PCI device + * except "soc". + */ + if (dev->parent && strcmp(dev_name(dev->parent), "soc")) { + dev = dev->parent; + goto retry; + } + /* Otherwise, do not allow use of IPMMU */ return false; } -- 2.25.1