[PATCH] iommu/ipmmu-vmsa: Allow PCIe devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux