mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
drm/tegra: Simplify IOMMU group selection
All the devices that make up the DRM device are now part of the same IOMMU group. This simplifies the handling of the IOMMU attachment and also avoids exhausting the number of IOMMUs available on early Tegra SoC generations. Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
parent
a7303f7735
commit
7edd7961e5
@ -2014,7 +2014,7 @@ static int tegra_dc_init(struct host1x_client *client)
|
|||||||
if (!dc->syncpt)
|
if (!dc->syncpt)
|
||||||
dev_warn(dc->dev, "failed to allocate syncpoint\n");
|
dev_warn(dc->dev, "failed to allocate syncpoint\n");
|
||||||
|
|
||||||
err = host1x_client_iommu_attach(client, true);
|
err = host1x_client_iommu_attach(client);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(client->dev, "failed to attach to domain: %d\n", err);
|
dev_err(client->dev, "failed to attach to domain: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
|
@ -904,7 +904,7 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int host1x_client_iommu_attach(struct host1x_client *client, bool shared)
|
int host1x_client_iommu_attach(struct host1x_client *client)
|
||||||
{
|
{
|
||||||
struct drm_device *drm = dev_get_drvdata(client->parent);
|
struct drm_device *drm = dev_get_drvdata(client->parent);
|
||||||
struct tegra_drm *tegra = drm->dev_private;
|
struct tegra_drm *tegra = drm->dev_private;
|
||||||
@ -912,29 +912,30 @@ int host1x_client_iommu_attach(struct host1x_client *client, bool shared)
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (tegra->domain) {
|
if (tegra->domain) {
|
||||||
|
struct iommu_domain *domain;
|
||||||
|
|
||||||
group = iommu_group_get(client->dev);
|
group = iommu_group_get(client->dev);
|
||||||
if (!group) {
|
if (!group) {
|
||||||
dev_err(client->dev, "failed to get IOMMU group\n");
|
dev_err(client->dev, "failed to get IOMMU group\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shared || (shared && (group != tegra->group))) {
|
|
||||||
#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
|
#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
|
||||||
if (client->dev->archdata.mapping) {
|
if (client->dev->archdata.mapping) {
|
||||||
struct dma_iommu_mapping *mapping =
|
struct dma_iommu_mapping *mapping =
|
||||||
to_dma_iommu_mapping(client->dev);
|
to_dma_iommu_mapping(client->dev);
|
||||||
arm_iommu_detach_device(client->dev);
|
arm_iommu_detach_device(client->dev);
|
||||||
arm_iommu_release_mapping(mapping);
|
arm_iommu_release_mapping(mapping);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
domain = iommu_get_domain_for_dev(client->dev);
|
||||||
|
if (domain != tegra->domain) {
|
||||||
err = iommu_attach_group(tegra->domain, group);
|
err = iommu_attach_group(tegra->domain, group);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
iommu_group_put(group);
|
iommu_group_put(group);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shared && !tegra->group)
|
|
||||||
tegra->group = group;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -947,12 +948,17 @@ void host1x_client_iommu_detach(struct host1x_client *client)
|
|||||||
{
|
{
|
||||||
struct drm_device *drm = dev_get_drvdata(client->parent);
|
struct drm_device *drm = dev_get_drvdata(client->parent);
|
||||||
struct tegra_drm *tegra = drm->dev_private;
|
struct tegra_drm *tegra = drm->dev_private;
|
||||||
|
struct iommu_domain *domain;
|
||||||
|
|
||||||
if (client->group) {
|
if (client->group) {
|
||||||
if (client->group == tegra->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_detach_group(tegra->domain, client->group);
|
||||||
tegra->group = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
iommu_group_put(client->group);
|
iommu_group_put(client->group);
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@ struct tegra_drm {
|
|||||||
struct drm_device *drm;
|
struct drm_device *drm;
|
||||||
|
|
||||||
struct iommu_domain *domain;
|
struct iommu_domain *domain;
|
||||||
struct iommu_group *group;
|
|
||||||
struct mutex mm_lock;
|
struct mutex mm_lock;
|
||||||
struct drm_mm mm;
|
struct drm_mm mm;
|
||||||
|
|
||||||
@ -100,7 +99,7 @@ int tegra_drm_register_client(struct tegra_drm *tegra,
|
|||||||
struct tegra_drm_client *client);
|
struct tegra_drm_client *client);
|
||||||
int tegra_drm_unregister_client(struct tegra_drm *tegra,
|
int tegra_drm_unregister_client(struct tegra_drm *tegra,
|
||||||
struct tegra_drm_client *client);
|
struct tegra_drm_client *client);
|
||||||
int host1x_client_iommu_attach(struct host1x_client *client, bool shared);
|
int host1x_client_iommu_attach(struct host1x_client *client);
|
||||||
void host1x_client_iommu_detach(struct host1x_client *client);
|
void host1x_client_iommu_detach(struct host1x_client *client);
|
||||||
|
|
||||||
int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
|
int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
|
||||||
|
@ -50,7 +50,7 @@ static int gr2d_init(struct host1x_client *client)
|
|||||||
goto put;
|
goto put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = host1x_client_iommu_attach(client, false);
|
err = host1x_client_iommu_attach(client);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(client->dev, "failed to attach to domain: %d\n", err);
|
dev_err(client->dev, "failed to attach to domain: %d\n", err);
|
||||||
goto free;
|
goto free;
|
||||||
|
@ -59,7 +59,7 @@ static int gr3d_init(struct host1x_client *client)
|
|||||||
goto put;
|
goto put;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = host1x_client_iommu_attach(client, false);
|
err = host1x_client_iommu_attach(client);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(client->dev, "failed to attach to domain: %d\n", err);
|
dev_err(client->dev, "failed to attach to domain: %d\n", err);
|
||||||
goto free;
|
goto free;
|
||||||
|
@ -187,7 +187,7 @@ static int vic_init(struct host1x_client *client)
|
|||||||
struct vic *vic = to_vic(drm);
|
struct vic *vic = to_vic(drm);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = host1x_client_iommu_attach(client, false);
|
err = host1x_client_iommu_attach(client);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(vic->dev, "failed to attach to domain: %d\n", err);
|
dev_err(vic->dev, "failed to attach to domain: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
|
Loading…
Reference in New Issue
Block a user