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 #include +#include #include #include #include @@ -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; }