aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2016-08-19 17:43:40 -0400
committerLucas Stach <l.stach@pengutronix.de>2016-09-15 09:29:39 -0400
commit90969c9aa97700663d03c51031652e131df3bd9b (patch)
tree7aebc968d6a871440492fad01fcf9d1c076ee9da /drivers/gpu
parent229855b650bd0716a3d9e82a68ebedee20a35020 (diff)
drm/etnaviv: split out iova search and MMU reaping logic
With MMUv2 the command buffers need to be mapped through the MMU. Split out the iova search and MMU reaping logic so it can be reused for the cmdbuf mapping, where no GEM object is involved. Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.c62
1 files changed, 37 insertions, 25 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
index d62125eb30d8..69ea0a0a70c2 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -103,41 +103,21 @@ static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu *mmu,
103 drm_mm_remove_node(&mapping->vram_node); 103 drm_mm_remove_node(&mapping->vram_node);
104} 104}
105 105
106int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu, 106static int etnaviv_iommu_find_iova(struct etnaviv_iommu *mmu,
107 struct etnaviv_gem_object *etnaviv_obj, u32 memory_base, 107 struct drm_mm_node *node, size_t size)
108 struct etnaviv_vram_mapping *mapping)
109{ 108{
110 struct etnaviv_vram_mapping *free = NULL; 109 struct etnaviv_vram_mapping *free = NULL;
111 struct sg_table *sgt = etnaviv_obj->sgt;
112 struct drm_mm_node *node;
113 int ret; 110 int ret;
114 111
115 lockdep_assert_held(&etnaviv_obj->lock); 112 lockdep_assert_held(&mmu->lock);
116
117 mutex_lock(&mmu->lock);
118 113
119 /* v1 MMU can optimize single entry (contiguous) scatterlists */
120 if (mmu->version == ETNAVIV_IOMMU_V1 &&
121 sgt->nents == 1 && !(etnaviv_obj->flags & ETNA_BO_FORCE_MMU)) {
122 u32 iova;
123
124 iova = sg_dma_address(sgt->sgl) - memory_base;
125 if (iova < 0x80000000 - sg_dma_len(sgt->sgl)) {
126 mapping->iova = iova;
127 list_add_tail(&mapping->mmu_node, &mmu->mappings);
128 mutex_unlock(&mmu->lock);
129 return 0;
130 }
131 }
132
133 node = &mapping->vram_node;
134 while (1) { 114 while (1) {
135 struct etnaviv_vram_mapping *m, *n; 115 struct etnaviv_vram_mapping *m, *n;
136 struct list_head list; 116 struct list_head list;
137 bool found; 117 bool found;
138 118
139 ret = drm_mm_insert_node_in_range(&mmu->mm, node, 119 ret = drm_mm_insert_node_in_range(&mmu->mm, node,
140 etnaviv_obj->base.size, 0, mmu->last_iova, ~0UL, 120 size, 0, mmu->last_iova, ~0UL,
141 DRM_MM_SEARCH_DEFAULT); 121 DRM_MM_SEARCH_DEFAULT);
142 122
143 if (ret != -ENOSPC) 123 if (ret != -ENOSPC)
@@ -154,7 +134,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
154 } 134 }
155 135
156 /* Try to retire some entries */ 136 /* Try to retire some entries */
157 drm_mm_init_scan(&mmu->mm, etnaviv_obj->base.size, 0, 0); 137 drm_mm_init_scan(&mmu->mm, size, 0, 0);
158 138
159 found = 0; 139 found = 0;
160 INIT_LIST_HEAD(&list); 140 INIT_LIST_HEAD(&list);
@@ -215,6 +195,38 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
215 mmu->need_flush = true; 195 mmu->need_flush = true;
216 } 196 }
217 197
198 return ret;
199}
200
201int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
202 struct etnaviv_gem_object *etnaviv_obj, u32 memory_base,
203 struct etnaviv_vram_mapping *mapping)
204{
205 struct sg_table *sgt = etnaviv_obj->sgt;
206 struct drm_mm_node *node;
207 int ret;
208
209 lockdep_assert_held(&etnaviv_obj->lock);
210
211 mutex_lock(&mmu->lock);
212
213 /* v1 MMU can optimize single entry (contiguous) scatterlists */
214 if (mmu->version == ETNAVIV_IOMMU_V1 &&
215 sgt->nents == 1 && !(etnaviv_obj->flags & ETNA_BO_FORCE_MMU)) {
216 u32 iova;
217
218 iova = sg_dma_address(sgt->sgl) - memory_base;
219 if (iova < 0x80000000 - sg_dma_len(sgt->sgl)) {
220 mapping->iova = iova;
221 list_add_tail(&mapping->mmu_node, &mmu->mappings);
222 mutex_unlock(&mmu->lock);
223 return 0;
224 }
225 }
226
227 node = &mapping->vram_node;
228
229 ret = etnaviv_iommu_find_iova(mmu, node, etnaviv_obj->base.size);
218 if (ret < 0) { 230 if (ret < 0) {
219 mutex_unlock(&mmu->lock); 231 mutex_unlock(&mmu->lock);
220 return ret; 232 return ret;