diff options
author | Dmitry Osipenko <digetx@gmail.com> | 2018-05-04 02:47:21 +0300 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2018-05-04 14:20:09 +0200 |
commit | c9ac52175b38e7f22fe37b9f943973d9095e53b7 (patch) | |
tree | 86030fc54c72f6c8be7a1c47125ffefd676ae660 /drivers/gpu/drm/tegra | |
parent | 5fda01b50d769d600c34cb00ab15ce1b6a66c028 (diff) |
drm/tegra: gr3d: Add IOMMU support
Attach GR3D to the displays IOMMU group in order to provide GR3D access
to BO's IOVA.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r-- | drivers/gpu/drm/tegra/gr3d.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index 28c4ef63065b..ce5120683091 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c @@ -9,6 +9,7 @@ #include <linux/clk.h> #include <linux/host1x.h> +#include <linux/iommu.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/reset.h> @@ -20,6 +21,7 @@ #include "gr3d.h" struct gr3d { + struct iommu_group *group; struct tegra_drm_client client; struct host1x_channel *channel; struct clk *clk_secondary; @@ -40,7 +42,9 @@ static int gr3d_init(struct host1x_client *client) struct tegra_drm_client *drm = host1x_to_drm_client(client); struct drm_device *dev = dev_get_drvdata(client->parent); unsigned long flags = HOST1X_SYNCPT_HAS_BASE; + struct tegra_drm *tegra = dev->dev_private; struct gr3d *gr3d = to_gr3d(drm); + int err; gr3d->channel = host1x_channel_request(client->dev); if (!gr3d->channel) @@ -52,6 +56,23 @@ static int gr3d_init(struct host1x_client *client) return -ENOMEM; } + if (tegra->domain) { + gr3d->group = iommu_group_get(client->dev); + + if (gr3d->group) { + err = iommu_attach_group(tegra->domain, gr3d->group); + if (err < 0) { + dev_err(client->dev, + "failed to attach to domain: %d\n", + err); + host1x_syncpt_free(client->syncpts[0]); + host1x_channel_put(gr3d->channel); + iommu_group_put(gr3d->group); + return err; + } + } + } + return tegra_drm_register_client(dev->dev_private, drm); } @@ -59,6 +80,7 @@ static int gr3d_exit(struct host1x_client *client) { struct tegra_drm_client *drm = host1x_to_drm_client(client); struct drm_device *dev = dev_get_drvdata(client->parent); + struct tegra_drm *tegra = dev->dev_private; struct gr3d *gr3d = to_gr3d(drm); int err; @@ -69,6 +91,11 @@ static int gr3d_exit(struct host1x_client *client) host1x_syncpt_free(client->syncpts[0]); host1x_channel_put(gr3d->channel); + if (gr3d->group) { + iommu_detach_group(tegra->domain, gr3d->group); + iommu_group_put(gr3d->group); + } + return 0; } |