204 lines
5.9 KiB
Diff
204 lines
5.9 KiB
Diff
From 421be3ee36a497949a4b564cd1e4f7f9fe755f57 Mon Sep 17 00:00:00 2001
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
Date: Tue, 5 Apr 2022 15:32:50 +0100
|
|
Subject: [PATCH] drm/rockchip: Refactor IOMMU initialisation
|
|
|
|
Defer the IOMMU domain setup until after successfully binding
|
|
components, so we can figure out IOMMU support directly from the VOP
|
|
devices themselves, rather than manually inferring it from the DT (which
|
|
also fails to account for whether the IOMMU driver is actually loaded).
|
|
Although this is somewhat of a logical cleanup, the main motivation is
|
|
to prepare for a change in the iommu_domain_alloc() interface.
|
|
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
|
|
Link: https://patchwork.freedesktop.org/patch/msgid/94eee7ab434fe11eb0787f691e9f1ab03a2e91be.1649168685.git.robin.murphy@arm.com
|
|
---
|
|
drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 60 +++++++++------------
|
|
drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 3 ++
|
|
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 +
|
|
3 files changed, 31 insertions(+), 34 deletions(-)
|
|
|
|
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
|
|
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
|
|
@@ -7,7 +7,6 @@
|
|
*/
|
|
|
|
#include <linux/dma-mapping.h>
|
|
-#include <linux/dma-iommu.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of_graph.h>
|
|
@@ -35,7 +34,6 @@
|
|
#define DRIVER_MAJOR 1
|
|
#define DRIVER_MINOR 0
|
|
|
|
-static bool is_support_iommu = true;
|
|
static const struct drm_driver rockchip_drm_driver;
|
|
|
|
/*
|
|
@@ -49,7 +47,7 @@ int rockchip_drm_dma_attach_device(struc
|
|
struct rockchip_drm_private *private = drm_dev->dev_private;
|
|
int ret;
|
|
|
|
- if (!is_support_iommu)
|
|
+ if (!private->domain)
|
|
return 0;
|
|
|
|
ret = iommu_attach_device(private->domain, dev);
|
|
@@ -65,12 +63,22 @@ void rockchip_drm_dma_detach_device(stru
|
|
struct device *dev)
|
|
{
|
|
struct rockchip_drm_private *private = drm_dev->dev_private;
|
|
- struct iommu_domain *domain = private->domain;
|
|
|
|
- if (!is_support_iommu)
|
|
+ if (!private->domain)
|
|
return;
|
|
|
|
- iommu_detach_device(domain, dev);
|
|
+ iommu_detach_device(private->domain, dev);
|
|
+}
|
|
+
|
|
+void rockchip_drm_dma_init_device(struct drm_device *drm_dev,
|
|
+ struct device *dev)
|
|
+{
|
|
+ struct rockchip_drm_private *private = drm_dev->dev_private;
|
|
+
|
|
+ if (!device_iommu_mapped(dev))
|
|
+ private->iommu_dev = ERR_PTR(-ENODEV);
|
|
+ else if (!private->iommu_dev)
|
|
+ private->iommu_dev = dev;
|
|
}
|
|
|
|
static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
|
|
@@ -79,10 +87,10 @@ static int rockchip_drm_init_iommu(struc
|
|
struct iommu_domain_geometry *geometry;
|
|
u64 start, end;
|
|
|
|
- if (!is_support_iommu)
|
|
+ if (IS_ERR_OR_NULL(private->iommu_dev))
|
|
return 0;
|
|
|
|
- private->domain = iommu_domain_alloc(&platform_bus_type);
|
|
+ private->domain = iommu_domain_alloc(private->iommu_dev->bus);
|
|
if (!private->domain)
|
|
return -ENOMEM;
|
|
|
|
@@ -102,7 +110,7 @@ static void rockchip_iommu_cleanup(struc
|
|
{
|
|
struct rockchip_drm_private *private = drm_dev->dev_private;
|
|
|
|
- if (!is_support_iommu)
|
|
+ if (!private->domain)
|
|
return;
|
|
|
|
drm_mm_takedown(&private->mm);
|
|
@@ -141,25 +149,25 @@ static int rockchip_drm_bind(struct devi
|
|
INIT_LIST_HEAD(&private->psr_list);
|
|
mutex_init(&private->psr_list_lock);
|
|
|
|
- ret = rockchip_drm_init_iommu(drm_dev);
|
|
- if (ret)
|
|
- goto err_free;
|
|
-
|
|
ret = drmm_mode_config_init(drm_dev);
|
|
if (ret)
|
|
- goto err_iommu_cleanup;
|
|
+ goto err_free;
|
|
|
|
rockchip_drm_mode_config_init(drm_dev);
|
|
|
|
/* Try to bind all sub drivers. */
|
|
ret = component_bind_all(dev, drm_dev);
|
|
if (ret)
|
|
- goto err_iommu_cleanup;
|
|
+ goto err_free;
|
|
|
|
- ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
|
|
+ ret = rockchip_drm_init_iommu(drm_dev);
|
|
if (ret)
|
|
goto err_unbind_all;
|
|
|
|
+ ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
|
|
+ if (ret)
|
|
+ goto err_iommu_cleanup;
|
|
+
|
|
drm_mode_config_reset(drm_dev);
|
|
|
|
ret = rockchip_drm_fbdev_init(drm_dev);
|
|
@@ -177,10 +185,10 @@ static int rockchip_drm_bind(struct devi
|
|
err_kms_helper_poll_fini:
|
|
drm_kms_helper_poll_fini(drm_dev);
|
|
rockchip_drm_fbdev_fini(drm_dev);
|
|
-err_unbind_all:
|
|
- component_unbind_all(dev, drm_dev);
|
|
err_iommu_cleanup:
|
|
rockchip_iommu_cleanup(drm_dev);
|
|
+err_unbind_all:
|
|
+ component_unbind_all(dev, drm_dev);
|
|
err_free:
|
|
drm_dev_put(drm_dev);
|
|
return ret;
|
|
@@ -358,8 +366,6 @@ static int rockchip_drm_platform_of_prob
|
|
return -ENODEV;
|
|
|
|
for (i = 0;; i++) {
|
|
- struct device_node *iommu;
|
|
-
|
|
port = of_parse_phandle(np, "ports", i);
|
|
if (!port)
|
|
break;
|
|
@@ -369,21 +375,7 @@ static int rockchip_drm_platform_of_prob
|
|
continue;
|
|
}
|
|
|
|
- iommu = of_parse_phandle(port->parent, "iommus", 0);
|
|
- if (!iommu || !of_device_is_available(iommu->parent)) {
|
|
- DRM_DEV_DEBUG(dev,
|
|
- "no iommu attached for %pOF, using non-iommu buffers\n",
|
|
- port->parent);
|
|
- /*
|
|
- * if there is a crtc not support iommu, force set all
|
|
- * crtc use non-iommu buffer.
|
|
- */
|
|
- is_support_iommu = false;
|
|
- }
|
|
-
|
|
found = true;
|
|
-
|
|
- of_node_put(iommu);
|
|
of_node_put(port);
|
|
}
|
|
|
|
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
|
|
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
|
|
@@ -46,6 +46,7 @@ struct rockchip_drm_private {
|
|
struct drm_fb_helper fbdev_helper;
|
|
struct drm_gem_object *fbdev_bo;
|
|
struct iommu_domain *domain;
|
|
+ struct device *iommu_dev;
|
|
struct mutex mm_lock;
|
|
struct drm_mm mm;
|
|
struct list_head psr_list;
|
|
@@ -56,6 +57,8 @@ int rockchip_drm_dma_attach_device(struc
|
|
struct device *dev);
|
|
void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
|
|
struct device *dev);
|
|
+void rockchip_drm_dma_init_device(struct drm_device *drm_dev,
|
|
+ struct device *dev);
|
|
int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout);
|
|
|
|
int rockchip_drm_endpoint_is_subdriver(struct device_node *ep);
|
|
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
|
|
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
|
|
@@ -2189,6 +2189,8 @@ static int vop_bind(struct device *dev,
|
|
}
|
|
}
|
|
|
|
+ rockchip_drm_dma_init_device(drm_dev, dev);
|
|
+
|
|
return 0;
|
|
|
|
err_disable_pm_runtime:
|