UPSTREAM: drm/rockchip: support non-iommu buffer path
authorMark Yao <mark.yao@rock-chips.com>
Tue, 19 Apr 2016 02:13:27 +0000 (10:13 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Wed, 7 Dec 2016 06:29:53 +0000 (14:29 +0800)
Some rockchip vop not support iommu, need use non-iommu
buffer for it. And if we get iommu issues, we can compare
the issues with non-iommu path, that would help the debug.

Conflicts:
drivers/gpu/drm/rockchip/rockchip_drm_drv.c

Change-Id: I843f087281300359b07faac1de156cd648325b45
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
(cherry picked from commit 2d90d477430d3a20df74f2d11c21378e64e1d508)

drivers/gpu/drm/rockchip/rockchip_drm_drv.c

index 04081b3784dc8a6eee66cafdb76454c294902dc5..2b236a533152930f1482bc9e63eac3589374af8a 100644 (file)
@@ -44,6 +44,8 @@
 #define DRIVER_MAJOR   1
 #define DRIVER_MINOR   0
 
 #define DRIVER_MAJOR   1
 #define DRIVER_MINOR   0
 
+static bool is_support_iommu = true;
+
 static LIST_HEAD(rockchip_drm_subdrv_list);
 static DEFINE_MUTEX(subdrv_list_mutex);
 
 static LIST_HEAD(rockchip_drm_subdrv_list);
 static DEFINE_MUTEX(subdrv_list_mutex);
 
@@ -617,6 +619,9 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
        struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
        int ret;
 
        struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
        int ret;
 
+       if (!is_support_iommu)
+               return 0;
+
        ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
        if (ret)
                return ret;
        ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
        if (ret)
                return ret;
@@ -629,6 +634,9 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
                                    struct device *dev)
 {
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
                                    struct device *dev)
 {
+       if (!is_support_iommu)
+               return;
+
        arm_iommu_detach_device(dev);
 }
 
        arm_iommu_detach_device(dev);
 }
 
@@ -697,7 +705,7 @@ static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev,
 static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
 {
        struct rockchip_drm_private *private;
 static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
 {
        struct rockchip_drm_private *private;
-       struct dma_iommu_mapping *mapping;
+       struct dma_iommu_mapping *mapping = NULL;
        struct device *dev = drm_dev->dev;
        struct drm_connector *connector;
        int ret;
        struct device *dev = drm_dev->dev;
        struct drm_connector *connector;
        int ret;
@@ -727,23 +735,26 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
                goto err_config_cleanup;
        }
 
                goto err_config_cleanup;
        }
 
-       /* TODO(djkurtz): fetch the mapping start/size from somewhere */
-       mapping = arm_iommu_create_mapping(&platform_bus_type, 0x00000000,
-                                          SZ_2G);
-       if (IS_ERR(mapping)) {
-               ret = PTR_ERR(mapping);
-               goto err_config_cleanup;
-       }
+       if (is_support_iommu) {
+               /* TODO(djkurtz): fetch the mapping start/size from somewhere */
+               mapping = arm_iommu_create_mapping(&platform_bus_type,
+                                                  0x00000000,
+                                                  SZ_2G);
+               if (IS_ERR(mapping)) {
+                       ret = PTR_ERR(mapping);
+                       goto err_config_cleanup;
+               }
 
 
-       ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
-       if (ret)
-               goto err_release_mapping;
+               ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+               if (ret)
+                       goto err_release_mapping;
 
 
-       dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+               dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
 
 
-       ret = arm_iommu_attach_device(dev, mapping);
-       if (ret)
-               goto err_release_mapping;
+               ret = arm_iommu_attach_device(dev, mapping);
+               if (ret)
+                       goto err_release_mapping;
+       }
 
        /* Try to bind all sub drivers. */
        ret = component_bind_all(dev, drm_dev);
 
        /* Try to bind all sub drivers. */
        ret = component_bind_all(dev, drm_dev);
@@ -797,7 +808,8 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
 
        drm_dev->mode_config.allow_fb_modifiers = true;
 
 
        drm_dev->mode_config.allow_fb_modifiers = true;
 
-       arm_iommu_release_mapping(mapping);
+       if (is_support_iommu)
+               arm_iommu_release_mapping(mapping);
        return 0;
 err_vblank_cleanup:
        drm_vblank_cleanup(drm_dev);
        return 0;
 err_vblank_cleanup:
        drm_vblank_cleanup(drm_dev);
@@ -806,9 +818,11 @@ err_kms_helper_poll_fini:
 err_unbind:
        component_unbind_all(dev, drm_dev);
 err_detach_device:
 err_unbind:
        component_unbind_all(dev, drm_dev);
 err_detach_device:
-       arm_iommu_detach_device(dev);
+       if (is_support_iommu)
+               arm_iommu_detach_device(dev);
 err_release_mapping:
 err_release_mapping:
-       arm_iommu_release_mapping(mapping);
+       if (is_support_iommu)
+               arm_iommu_release_mapping(mapping);
 err_config_cleanup:
        drm_mode_config_cleanup(drm_dev);
        drm_dev->dev_private = NULL;
 err_config_cleanup:
        drm_mode_config_cleanup(drm_dev);
        drm_dev->dev_private = NULL;
@@ -823,7 +837,8 @@ static int rockchip_drm_unload(struct drm_device *drm_dev)
        drm_vblank_cleanup(drm_dev);
        drm_kms_helper_poll_fini(drm_dev);
        component_unbind_all(dev, drm_dev);
        drm_vblank_cleanup(drm_dev);
        drm_kms_helper_poll_fini(drm_dev);
        component_unbind_all(dev, drm_dev);
-       arm_iommu_detach_device(dev);
+       if (is_support_iommu)
+               arm_iommu_detach_device(dev);
        drm_mode_config_cleanup(drm_dev);
        drm_dev->dev_private = NULL;
 
        drm_mode_config_cleanup(drm_dev);
        drm_dev->dev_private = NULL;
 
@@ -1163,6 +1178,8 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
         * works as expected.
         */
        for (i = 0;; i++) {
         * works as expected.
         */
        for (i = 0;; i++) {
+               struct device_node *iommu;
+
                port = of_parse_phandle(np, "ports", i);
                if (!port)
                        break;
                port = of_parse_phandle(np, "ports", i);
                if (!port)
                        break;
@@ -1172,6 +1189,17 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
                        continue;
                }
 
                        continue;
                }
 
+               iommu = of_parse_phandle(port->parent, "iommus", 0);
+               if (!iommu || !of_device_is_available(iommu->parent)) {
+                       dev_dbg(dev, "no iommu attached for %s, using non-iommu buffers\n",
+                               port->parent->full_name);
+                       /*
+                        * if there is a crtc not support iommu, force set all
+                        * crtc use non-iommu buffer.
+                        */
+                       is_support_iommu = false;
+               }
+
                component_match_add(dev, &match, compare_of, port->parent);
                of_node_put(port);
        }
                component_match_add(dev, &match, compare_of, port->parent);
                of_node_put(port);
        }