From: Magnus Damm <damm+rene...@opensource.se>

Rework the IPMMU code to validate devices in ->xlate() instead of
accepting all devices in xlate() and instead validating devices
in ->add_device(). This makes it possible for the IPMMU device
driver to reject slave devices based on software policy.

Once a slave device is rejected by the ->xlate() callback the shared
function of_iommu_configure() will fail as well which in turn disables
per-device IOMMU handing in the arch-specific mapping code by not
passing any IOMMU callbacks to arch_setup_dma_ops().

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 TODO: Make sure this does not break R-Car Gen2 support

 drivers/iommu/ipmmu-vmsa.c |   27 +++++++--------------------
 1 file changed, 7 insertions(+), 20 deletions(-)

--- 0007/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c     2017-01-27 13:11:35.970607110 +0900
@@ -1007,16 +1007,14 @@ static int ipmmu_add_device_dma(struct d
        struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
        struct iommu_group *group;
 
-       /* only accept devices with iommus property */
-       if (of_count_phandle_with_args(dev->of_node, "iommus",
-                                      "#iommu-cells") < 0)
+       /* The device needs to be verified in xlate() */
+       if (!archdata)
                return -ENODEV;
 
        group = iommu_group_get_for_dev(dev);
        if (IS_ERR(group))
                return PTR_ERR(group);
 
-       archdata = dev->archdata.iommu;
        spin_lock(&ipmmu_slave_devices_lock);
        list_add(&archdata->list, &ipmmu_slave_devices);
        spin_unlock(&ipmmu_slave_devices_lock);
@@ -1034,24 +1032,13 @@ static void ipmmu_remove_device_dma(stru
        iommu_group_remove_device(dev);
 }
 
-static struct iommu_group *ipmmu_device_group_dma(struct device *dev)
-{
-       struct iommu_group *group;
-       int ret;
-
-       ret = ipmmu_init_platform_device(dev);
-       if (!ret)
-               group = ipmmu_find_group(dev);
-       else
-               group = ERR_PTR(ret);
-
-       return group;
-}
-
 static int ipmmu_of_xlate_dma(struct device *dev,
                              struct of_phandle_args *spec)
 {
-       return 0;
+       /* For now only tested on R-Car Gen3 with ARM64 arch init order
+        * TODO: Test R-Car Gen2 with ARM32 arch init order
+        */
+       return ipmmu_init_platform_device(dev);
 }
 
 static const struct iommu_ops ipmmu_ops = {
@@ -1065,7 +1052,7 @@ static const struct iommu_ops ipmmu_ops
        .iova_to_phys = ipmmu_iova_to_phys,
        .add_device = ipmmu_add_device_dma,
        .remove_device = ipmmu_remove_device_dma,
-       .device_group = ipmmu_device_group_dma,
+       .device_group = ipmmu_find_group,
        .pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
        .of_xlate = ipmmu_of_xlate_dma,
 };

Reply via email to