Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+25 -20
+1 -1
drivers/gpu/drm/tegra/dc.c
··· 2014 2014 if (!dc->syncpt) 2015 2015 dev_warn(dc->dev, "failed to allocate syncpoint\n"); 2016 2016 2017 - err = host1x_client_iommu_attach(client, true); 2017 + err = host1x_client_iommu_attach(client); 2018 2018 if (err < 0) { 2019 2019 dev_err(client->dev, "failed to attach to domain: %d\n", err); 2020 2020 return err;
+20 -14
drivers/gpu/drm/tegra/drm.c
··· 904 904 return 0; 905 905 } 906 906 907 - int host1x_client_iommu_attach(struct host1x_client *client, bool shared) 907 + int host1x_client_iommu_attach(struct host1x_client *client) 908 908 { 909 909 struct drm_device *drm = dev_get_drvdata(client->parent); 910 910 struct tegra_drm *tegra = drm->dev_private; ··· 912 912 int err; 913 913 914 914 if (tegra->domain) { 915 + struct iommu_domain *domain; 916 + 915 917 group = iommu_group_get(client->dev); 916 918 if (!group) { 917 919 dev_err(client->dev, "failed to get IOMMU group\n"); 918 920 return -ENODEV; 919 921 } 920 922 921 - if (!shared || (shared && (group != tegra->group))) { 922 923 #if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) 923 - if (client->dev->archdata.mapping) { 924 - struct dma_iommu_mapping *mapping = 925 - to_dma_iommu_mapping(client->dev); 926 - arm_iommu_detach_device(client->dev); 927 - arm_iommu_release_mapping(mapping); 928 - } 924 + if (client->dev->archdata.mapping) { 925 + struct dma_iommu_mapping *mapping = 926 + to_dma_iommu_mapping(client->dev); 927 + arm_iommu_detach_device(client->dev); 928 + arm_iommu_release_mapping(mapping); 929 + } 929 930 #endif 931 + 932 + domain = iommu_get_domain_for_dev(client->dev); 933 + if (domain != tegra->domain) { 930 934 err = iommu_attach_group(tegra->domain, group); 931 935 if (err < 0) { 932 936 iommu_group_put(group); 933 937 return err; 934 938 } 935 - 936 - if (shared && !tegra->group) 937 - tegra->group = group; 938 939 } 939 940 } 940 941 ··· 948 947 { 949 948 struct drm_device *drm = dev_get_drvdata(client->parent); 950 949 struct tegra_drm *tegra = drm->dev_private; 950 + struct iommu_domain *domain; 951 951 952 952 if (client->group) { 953 - if (client->group == tegra->group) { 953 + /* 954 + * Devices that are part of the same group may no longer be 955 + * attached to a domain at this point because their group may 956 + * have been detached by an earlier client. 957 + */ 958 + domain = iommu_get_domain_for_dev(client->dev); 959 + if (domain) 954 960 iommu_detach_group(tegra->domain, client->group); 955 - tegra->group = NULL; 956 - } 957 961 958 962 iommu_group_put(client->group); 959 963 }
+1 -2
drivers/gpu/drm/tegra/drm.h
··· 36 36 struct drm_device *drm; 37 37 38 38 struct iommu_domain *domain; 39 - struct iommu_group *group; 40 39 struct mutex mm_lock; 41 40 struct drm_mm mm; 42 41 ··· 99 100 struct tegra_drm_client *client); 100 101 int tegra_drm_unregister_client(struct tegra_drm *tegra, 101 102 struct tegra_drm_client *client); 102 - int host1x_client_iommu_attach(struct host1x_client *client, bool shared); 103 + int host1x_client_iommu_attach(struct host1x_client *client); 103 104 void host1x_client_iommu_detach(struct host1x_client *client); 104 105 105 106 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
+1 -1
drivers/gpu/drm/tegra/gr2d.c
··· 50 50 goto put; 51 51 } 52 52 53 - err = host1x_client_iommu_attach(client, false); 53 + err = host1x_client_iommu_attach(client); 54 54 if (err < 0) { 55 55 dev_err(client->dev, "failed to attach to domain: %d\n", err); 56 56 goto free;
+1 -1
drivers/gpu/drm/tegra/gr3d.c
··· 59 59 goto put; 60 60 } 61 61 62 - err = host1x_client_iommu_attach(client, false); 62 + err = host1x_client_iommu_attach(client); 63 63 if (err < 0) { 64 64 dev_err(client->dev, "failed to attach to domain: %d\n", err); 65 65 goto free;
+1 -1
drivers/gpu/drm/tegra/vic.c
··· 187 187 struct vic *vic = to_vic(drm); 188 188 int err; 189 189 190 - err = host1x_client_iommu_attach(client, false); 190 + err = host1x_client_iommu_attach(client); 191 191 if (err < 0) { 192 192 dev_err(vic->dev, "failed to attach to domain: %d\n", err); 193 193 return err;