aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2017-10-12 11:43:33 -0400
committerThierry Reding <treding@nvidia.com>2017-12-21 08:52:36 -0500
commitbc8828bd08bd2a645caeb64d299d67faca7a3b4f (patch)
treeab80c8b65bbe315992209e8bcb53fdff2019ead6
parent41c3068cc2fd0ce179b910c4500934786e8156ba (diff)
drm/tegra: Use IOMMU groups
In order to support IOMMUs more generically and transparently handle the ARM SMMU on Tegra186, move to using groups instead of devices for domain attachment. An IOMMU group is a set of devices that share the same IOMMU domain and is therefore a good match to represent what Tegra DRM needs. Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--drivers/gpu/drm/tegra/dc.c27
-rw-r--r--drivers/gpu/drm/tegra/drm.h1
-rw-r--r--drivers/gpu/drm/tegra/vic.c18
3 files changed, 28 insertions, 18 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index d118094a96c1..dc91911094fc 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1748,6 +1748,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
1748static int tegra_dc_init(struct host1x_client *client) 1748static int tegra_dc_init(struct host1x_client *client)
1749{ 1749{
1750 struct drm_device *drm = dev_get_drvdata(client->parent); 1750 struct drm_device *drm = dev_get_drvdata(client->parent);
1751 struct iommu_group *group = iommu_group_get(client->dev);
1751 unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; 1752 unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
1752 struct tegra_dc *dc = host1x_client_to_dc(client); 1753 struct tegra_dc *dc = host1x_client_to_dc(client);
1753 struct tegra_drm *tegra = drm->dev_private; 1754 struct tegra_drm *tegra = drm->dev_private;
@@ -1759,12 +1760,17 @@ static int tegra_dc_init(struct host1x_client *client)
1759 if (!dc->syncpt) 1760 if (!dc->syncpt)
1760 dev_warn(dc->dev, "failed to allocate syncpoint\n"); 1761 dev_warn(dc->dev, "failed to allocate syncpoint\n");
1761 1762
1762 if (tegra->domain) { 1763 if (group && tegra->domain) {
1763 err = iommu_attach_device(tegra->domain, dc->dev); 1764 if (group != tegra->group) {
1764 if (err < 0) { 1765 err = iommu_attach_group(tegra->domain, group);
1765 dev_err(dc->dev, "failed to attach to domain: %d\n", 1766 if (err < 0) {
1766 err); 1767 dev_err(dc->dev,
1767 return err; 1768 "failed to attach to domain: %d\n",
1769 err);
1770 return err;
1771 }
1772
1773 tegra->group = group;
1768 } 1774 }
1769 1775
1770 dc->domain = tegra->domain; 1776 dc->domain = tegra->domain;
@@ -1825,8 +1831,8 @@ cleanup:
1825 if (!IS_ERR(primary)) 1831 if (!IS_ERR(primary))
1826 drm_plane_cleanup(primary); 1832 drm_plane_cleanup(primary);
1827 1833
1828 if (tegra->domain) { 1834 if (group && tegra->domain) {
1829 iommu_detach_device(tegra->domain, dc->dev); 1835 iommu_detach_group(tegra->domain, group);
1830 dc->domain = NULL; 1836 dc->domain = NULL;
1831 } 1837 }
1832 1838
@@ -1835,6 +1841,7 @@ cleanup:
1835 1841
1836static int tegra_dc_exit(struct host1x_client *client) 1842static int tegra_dc_exit(struct host1x_client *client)
1837{ 1843{
1844 struct iommu_group *group = iommu_group_get(client->dev);
1838 struct tegra_dc *dc = host1x_client_to_dc(client); 1845 struct tegra_dc *dc = host1x_client_to_dc(client);
1839 int err; 1846 int err;
1840 1847
@@ -1846,8 +1853,8 @@ static int tegra_dc_exit(struct host1x_client *client)
1846 return err; 1853 return err;
1847 } 1854 }
1848 1855
1849 if (dc->domain) { 1856 if (group && dc->domain) {
1850 iommu_detach_device(dc->domain, dc->dev); 1857 iommu_detach_group(dc->domain, group);
1851 dc->domain = NULL; 1858 dc->domain = NULL;
1852 } 1859 }
1853 1860
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index c52bc5978d1c..da3d8c141aee 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -60,6 +60,7 @@ struct tegra_drm {
60 struct drm_device *drm; 60 struct drm_device *drm;
61 61
62 struct iommu_domain *domain; 62 struct iommu_domain *domain;
63 struct iommu_group *group;
63 struct mutex mm_lock; 64 struct mutex mm_lock;
64 struct drm_mm mm; 65 struct drm_mm mm;
65 66
diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index d9664a34fb43..f5794dd49f3b 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -138,13 +138,14 @@ static const struct falcon_ops vic_falcon_ops = {
138static int vic_init(struct host1x_client *client) 138static int vic_init(struct host1x_client *client)
139{ 139{
140 struct tegra_drm_client *drm = host1x_to_drm_client(client); 140 struct tegra_drm_client *drm = host1x_to_drm_client(client);
141 struct iommu_group *group = iommu_group_get(client->dev);
141 struct drm_device *dev = dev_get_drvdata(client->parent); 142 struct drm_device *dev = dev_get_drvdata(client->parent);
142 struct tegra_drm *tegra = dev->dev_private; 143 struct tegra_drm *tegra = dev->dev_private;
143 struct vic *vic = to_vic(drm); 144 struct vic *vic = to_vic(drm);
144 int err; 145 int err;
145 146
146 if (tegra->domain) { 147 if (group && tegra->domain) {
147 err = iommu_attach_device(tegra->domain, vic->dev); 148 err = iommu_attach_group(tegra->domain, group);
148 if (err < 0) { 149 if (err < 0) {
149 dev_err(vic->dev, "failed to attach to domain: %d\n", 150 dev_err(vic->dev, "failed to attach to domain: %d\n",
150 err); 151 err);
@@ -158,13 +159,13 @@ static int vic_init(struct host1x_client *client)
158 vic->falcon.data = tegra; 159 vic->falcon.data = tegra;
159 err = falcon_load_firmware(&vic->falcon); 160 err = falcon_load_firmware(&vic->falcon);
160 if (err < 0) 161 if (err < 0)
161 goto detach_device; 162 goto detach;
162 } 163 }
163 164
164 vic->channel = host1x_channel_request(client->dev); 165 vic->channel = host1x_channel_request(client->dev);
165 if (!vic->channel) { 166 if (!vic->channel) {
166 err = -ENOMEM; 167 err = -ENOMEM;
167 goto detach_device; 168 goto detach;
168 } 169 }
169 170
170 client->syncpts[0] = host1x_syncpt_request(client, 0); 171 client->syncpts[0] = host1x_syncpt_request(client, 0);
@@ -183,9 +184,9 @@ free_syncpt:
183 host1x_syncpt_free(client->syncpts[0]); 184 host1x_syncpt_free(client->syncpts[0]);
184free_channel: 185free_channel:
185 host1x_channel_put(vic->channel); 186 host1x_channel_put(vic->channel);
186detach_device: 187detach:
187 if (tegra->domain) 188 if (group && tegra->domain)
188 iommu_detach_device(tegra->domain, vic->dev); 189 iommu_detach_group(tegra->domain, group);
189 190
190 return err; 191 return err;
191} 192}
@@ -193,6 +194,7 @@ detach_device:
193static int vic_exit(struct host1x_client *client) 194static int vic_exit(struct host1x_client *client)
194{ 195{
195 struct tegra_drm_client *drm = host1x_to_drm_client(client); 196 struct tegra_drm_client *drm = host1x_to_drm_client(client);
197 struct iommu_group *group = iommu_group_get(client->dev);
196 struct drm_device *dev = dev_get_drvdata(client->parent); 198 struct drm_device *dev = dev_get_drvdata(client->parent);
197 struct tegra_drm *tegra = dev->dev_private; 199 struct tegra_drm *tegra = dev->dev_private;
198 struct vic *vic = to_vic(drm); 200 struct vic *vic = to_vic(drm);
@@ -206,7 +208,7 @@ static int vic_exit(struct host1x_client *client)
206 host1x_channel_put(vic->channel); 208 host1x_channel_put(vic->channel);
207 209
208 if (vic->domain) { 210 if (vic->domain) {
209 iommu_detach_device(vic->domain, vic->dev); 211 iommu_detach_group(vic->domain, group);
210 vic->domain = NULL; 212 vic->domain = NULL;
211 } 213 }
212 214