@@ -3111,4 +3111,5 @@ struct platform_driver tegra_dc_driver = {
},
.probe = tegra_dc_probe,
.remove = tegra_dc_remove,
+ .suppress_auto_claim_dma_owner = true,
};
@@ -928,12 +928,15 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
return 0;
}
+/*
+ * Clients which use this function must set suppress_auto_claim_dma_owner in
+ * their platform_driver's device_driver struct.
+ */
int host1x_client_iommu_attach(struct host1x_client *client)
{
struct iommu_domain *domain = iommu_get_domain_for_dev(client->dev);
struct drm_device *drm = dev_get_drvdata(client->host);
struct tegra_drm *tegra = drm->dev_private;
- struct iommu_group *group = NULL;
int err;
/*
@@ -941,48 +944,44 @@ int host1x_client_iommu_attach(struct host1x_client *client)
* not the shared IOMMU domain, don't try to attach it to a different
* domain. This allows using the IOMMU-backed DMA API.
*/
- if (domain && domain != tegra->domain)
+ client->group = NULL;
+ if (!client->dev->iommu_group || (domain && domain != tegra->domain))
+ return iommu_device_set_dma_owner(client->dev,
+ DMA_OWNER_DMA_API, NULL);
+
+ if (!tegra->domain)
return 0;
- if (tegra->domain) {
- group = iommu_group_get(client->dev);
- if (!group)
- return -ENODEV;
-
- if (domain != tegra->domain) {
- err = iommu_attach_group(tegra->domain, group);
- if (err < 0) {
- iommu_group_put(group);
- return err;
- }
- }
+ err = iommu_device_set_dma_owner(client->dev,
+ DMA_OWNER_PRIVATE_DOMAIN, NULL);
+ if (err)
+ return err;
- tegra->use_explicit_iommu = true;
+ err = iommu_attach_device_shared(tegra->domain, client->dev);
+ if (err) {
+ iommu_device_release_dma_owner(client->dev,
+ DMA_OWNER_PRIVATE_DOMAIN);
+ return err;
}
- client->group = group;
-
+ tegra->use_explicit_iommu = true;
+ client->group = client->dev->iommu_group;
return 0;
}
void host1x_client_iommu_detach(struct host1x_client *client)
{
+ struct iommu_domain *domain = iommu_get_domain_for_dev(client->dev);
struct drm_device *drm = dev_get_drvdata(client->host);
struct tegra_drm *tegra = drm->dev_private;
- struct iommu_domain *domain;
if (client->group) {
- /*
- * Devices that are part of the same group may no longer be
- * attached to a domain at this point because their group may
- * have been detached by an earlier client.
- */
- domain = iommu_get_domain_for_dev(client->dev);
- if (domain)
- iommu_detach_group(tegra->domain, client->group);
-
- iommu_group_put(client->group);
+ iommu_detach_device_shared(tegra->domain, client->dev);
+ iommu_device_release_dma_owner(client->dev,
+ DMA_OWNER_PRIVATE_DOMAIN);
client->group = NULL;
+ } else {
+ iommu_device_release_dma_owner(client->dev, DMA_OWNER_DMA_API);
}
}
@@ -271,4 +271,5 @@ struct platform_driver tegra_gr2d_driver = {
},
.probe = gr2d_probe,
.remove = gr2d_remove,
+ .suppress_auto_claim_dma_owner = true,
};
@@ -400,4 +400,5 @@ struct platform_driver tegra_gr3d_driver = {
},
.probe = gr3d_probe,
.remove = gr3d_remove,
+ .suppress_auto_claim_dma_owner = true,
};
@@ -527,6 +527,7 @@ struct platform_driver tegra_vic_driver = {
},
.probe = vic_probe,
.remove = vic_remove,
+ .suppress_auto_claim_dma_owner = true,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC)