aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-06-26 15:41:53 -0400
committerThierry Reding <treding@nvidia.com>2014-11-13 10:14:48 -0500
commitdf06b759f2cf4690fa9991edb1504ba39932b2bb (patch)
tree0365d27fb82b94d4569c8b86dd775838bedc5ff1 /drivers/gpu/drm/tegra
parent1d1e6fe9b5cd9e51c0b064b60f673a973cac38ba (diff)
drm/tegra: Add IOMMU support
When an IOMMU device is available on the platform bus, allocate an IOMMU domain and attach the display controllers to it. The display controllers can then scan out non-contiguous buffers by mapping them through the IOMMU. Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r--drivers/gpu/drm/tegra/dc.c17
-rw-r--r--drivers/gpu/drm/tegra/drm.c24
-rw-r--r--drivers/gpu/drm/tegra/drm.h5
-rw-r--r--drivers/gpu/drm/tegra/fb.c16
-rw-r--r--drivers/gpu/drm/tegra/gem.c275
-rw-r--r--drivers/gpu/drm/tegra/gem.h6
6 files changed, 309 insertions, 34 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 4a015232e2e8..5f138b7c81bf 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -9,6 +9,7 @@
9 9
10#include <linux/clk.h> 10#include <linux/clk.h>
11#include <linux/debugfs.h> 11#include <linux/debugfs.h>
12#include <linux/iommu.h>
12#include <linux/reset.h> 13#include <linux/reset.h>
13 14
14#include <soc/tegra/pmc.h> 15#include <soc/tegra/pmc.h>
@@ -1290,6 +1291,17 @@ static int tegra_dc_init(struct host1x_client *client)
1290 struct tegra_drm *tegra = drm->dev_private; 1291 struct tegra_drm *tegra = drm->dev_private;
1291 int err; 1292 int err;
1292 1293
1294 if (tegra->domain) {
1295 err = iommu_attach_device(tegra->domain, dc->dev);
1296 if (err < 0) {
1297 dev_err(dc->dev, "failed to attach to domain: %d\n",
1298 err);
1299 return err;
1300 }
1301
1302 dc->domain = tegra->domain;
1303 }
1304
1293 drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); 1305 drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
1294 drm_mode_crtc_set_gamma_size(&dc->base, 256); 1306 drm_mode_crtc_set_gamma_size(&dc->base, 256);
1295 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); 1307 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
@@ -1347,6 +1359,11 @@ static int tegra_dc_exit(struct host1x_client *client)
1347 return err; 1359 return err;
1348 } 1360 }
1349 1361
1362 if (dc->domain) {
1363 iommu_detach_device(dc->domain, dc->dev);
1364 dc->domain = NULL;
1365 }
1366
1350 return 0; 1367 return 0;
1351} 1368}
1352 1369
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index e1632fb03a89..6c9df794b3be 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -8,6 +8,7 @@
8 */ 8 */
9 9
10#include <linux/host1x.h> 10#include <linux/host1x.h>
11#include <linux/iommu.h>
11 12
12#include "drm.h" 13#include "drm.h"
13#include "gem.h" 14#include "gem.h"
@@ -33,6 +34,17 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
33 if (!tegra) 34 if (!tegra)
34 return -ENOMEM; 35 return -ENOMEM;
35 36
37 if (iommu_present(&platform_bus_type)) {
38 tegra->domain = iommu_domain_alloc(&platform_bus_type);
39 if (IS_ERR(tegra->domain)) {
40 err = PTR_ERR(tegra->domain);
41 goto free;
42 }
43
44 DRM_DEBUG("IOMMU context initialized\n");
45 drm_mm_init(&tegra->mm, 0, SZ_2G);
46 }
47
36 mutex_init(&tegra->clients_lock); 48 mutex_init(&tegra->clients_lock);
37 INIT_LIST_HEAD(&tegra->clients); 49 INIT_LIST_HEAD(&tegra->clients);
38 drm->dev_private = tegra; 50 drm->dev_private = tegra;
@@ -76,6 +88,12 @@ fbdev:
76 tegra_drm_fb_free(drm); 88 tegra_drm_fb_free(drm);
77config: 89config:
78 drm_mode_config_cleanup(drm); 90 drm_mode_config_cleanup(drm);
91
92 if (tegra->domain) {
93 iommu_domain_free(tegra->domain);
94 drm_mm_takedown(&tegra->mm);
95 }
96free:
79 kfree(tegra); 97 kfree(tegra);
80 return err; 98 return err;
81} 99}
@@ -83,6 +101,7 @@ config:
83static int tegra_drm_unload(struct drm_device *drm) 101static int tegra_drm_unload(struct drm_device *drm)
84{ 102{
85 struct host1x_device *device = to_host1x_device(drm->dev); 103 struct host1x_device *device = to_host1x_device(drm->dev);
104 struct tegra_drm *tegra = drm->dev_private;
86 int err; 105 int err;
87 106
88 drm_kms_helper_poll_fini(drm); 107 drm_kms_helper_poll_fini(drm);
@@ -94,6 +113,11 @@ static int tegra_drm_unload(struct drm_device *drm)
94 if (err < 0) 113 if (err < 0)
95 return err; 114 return err;
96 115
116 if (tegra->domain) {
117 iommu_domain_free(tegra->domain);
118 drm_mm_takedown(&tegra->mm);
119 }
120
97 return 0; 121 return 0;
98} 122}
99 123
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index ef2faaef5936..96ff47d586a2 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -39,6 +39,9 @@ struct tegra_fbdev {
39struct tegra_drm { 39struct tegra_drm {
40 struct drm_device *drm; 40 struct drm_device *drm;
41 41
42 struct iommu_domain *domain;
43 struct drm_mm mm;
44
42 struct mutex clients_lock; 45 struct mutex clients_lock;
43 struct list_head clients; 46 struct list_head clients;
44 47
@@ -121,6 +124,8 @@ struct tegra_dc {
121 struct drm_pending_vblank_event *event; 124 struct drm_pending_vblank_event *event;
122 125
123 const struct tegra_dc_soc_info *soc; 126 const struct tegra_dc_soc_info *soc;
127
128 struct iommu_domain *domain;
124}; 129};
125 130
126static inline struct tegra_dc * 131static inline struct tegra_dc *
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index 0474241ac2a4..fab39eb2dae8 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -65,8 +65,12 @@ static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
65 for (i = 0; i < fb->num_planes; i++) { 65 for (i = 0; i < fb->num_planes; i++) {
66 struct tegra_bo *bo = fb->planes[i]; 66 struct tegra_bo *bo = fb->planes[i];
67 67
68 if (bo) 68 if (bo) {
69 if (bo->pages && bo->vaddr)
70 vunmap(bo->vaddr);
71
69 drm_gem_object_unreference_unlocked(&bo->gem); 72 drm_gem_object_unreference_unlocked(&bo->gem);
73 }
70 } 74 }
71 75
72 drm_framebuffer_cleanup(framebuffer); 76 drm_framebuffer_cleanup(framebuffer);
@@ -254,6 +258,16 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
254 offset = info->var.xoffset * bytes_per_pixel + 258 offset = info->var.xoffset * bytes_per_pixel +
255 info->var.yoffset * fb->pitches[0]; 259 info->var.yoffset * fb->pitches[0];
256 260
261 if (bo->pages) {
262 bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP,
263 pgprot_writecombine(PAGE_KERNEL));
264 if (!bo->vaddr) {
265 dev_err(drm->dev, "failed to vmap() framebuffer\n");
266 err = -ENOMEM;
267 goto destroy;
268 }
269 }
270
257 drm->mode_config.fb_base = (resource_size_t)bo->paddr; 271 drm->mode_config.fb_base = (resource_size_t)bo->paddr;
258 info->screen_base = (void __iomem *)bo->vaddr + offset; 272 info->screen_base = (void __iomem *)bo->vaddr + offset;
259 info->screen_size = size; 273 info->screen_size = size;
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index 9905598ebfc4..8b1095d05c58 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -14,6 +14,7 @@
14 */ 14 */
15 15
16#include <linux/dma-buf.h> 16#include <linux/dma-buf.h>
17#include <linux/iommu.h>
17#include <drm/tegra_drm.h> 18#include <drm/tegra_drm.h>
18 19
19#include "drm.h" 20#include "drm.h"
@@ -91,6 +92,88 @@ static const struct host1x_bo_ops tegra_bo_ops = {
91 .kunmap = tegra_bo_kunmap, 92 .kunmap = tegra_bo_kunmap,
92}; 93};
93 94
95/*
96 * A generic iommu_map_sg() function is being reviewed and will hopefully be
97 * merged soon. At that point this function can be dropped in favour of the
98 * one provided by the IOMMU API.
99 */
100static ssize_t __iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
101 struct scatterlist *sg, unsigned int nents,
102 int prot)
103{
104 struct scatterlist *s;
105 size_t offset = 0;
106 unsigned int i;
107 int err;
108
109 for_each_sg(sg, s, nents, i) {
110 phys_addr_t phys = page_to_phys(sg_page(s));
111 size_t length = s->offset + s->length;
112
113 err = iommu_map(domain, iova + offset, phys, length, prot);
114 if (err < 0) {
115 iommu_unmap(domain, iova, offset);
116 return err;
117 }
118
119 offset += length;
120 }
121
122 return offset;
123}
124
125static int tegra_bo_iommu_map(struct tegra_drm *tegra, struct tegra_bo *bo)
126{
127 int prot = IOMMU_READ | IOMMU_WRITE;
128 ssize_t err;
129
130 if (bo->mm)
131 return -EBUSY;
132
133 bo->mm = kzalloc(sizeof(*bo->mm), GFP_KERNEL);
134 if (!bo->mm)
135 return -ENOMEM;
136
137 err = drm_mm_insert_node_generic(&tegra->mm, bo->mm, bo->gem.size,
138 PAGE_SIZE, 0, 0, 0);
139 if (err < 0) {
140 dev_err(tegra->drm->dev, "out of I/O virtual memory: %zd\n",
141 err);
142 goto free;
143 }
144
145 bo->paddr = bo->mm->start;
146
147 err = __iommu_map_sg(tegra->domain, bo->paddr, bo->sgt->sgl,
148 bo->sgt->nents, prot);
149 if (err < 0) {
150 dev_err(tegra->drm->dev, "failed to map buffer: %zd\n", err);
151 goto remove;
152 }
153
154 bo->size = err;
155
156 return 0;
157
158remove:
159 drm_mm_remove_node(bo->mm);
160free:
161 kfree(bo->mm);
162 return err;
163}
164
165static int tegra_bo_iommu_unmap(struct tegra_drm *tegra, struct tegra_bo *bo)
166{
167 if (!bo->mm)
168 return 0;
169
170 iommu_unmap(tegra->domain, bo->paddr, bo->size);
171 drm_mm_remove_node(bo->mm);
172 kfree(bo->mm);
173
174 return 0;
175}
176
94static struct tegra_bo *tegra_bo_alloc_object(struct drm_device *drm, 177static struct tegra_bo *tegra_bo_alloc_object(struct drm_device *drm,
95 size_t size) 178 size_t size)
96{ 179{
@@ -121,9 +204,64 @@ free:
121 return ERR_PTR(err); 204 return ERR_PTR(err);
122} 205}
123 206
124static void tegra_bo_destroy(struct drm_device *drm, struct tegra_bo *bo) 207static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo)
208{
209 if (bo->pages) {
210 drm_gem_put_pages(&bo->gem, bo->pages, true, true);
211 sg_free_table(bo->sgt);
212 kfree(bo->sgt);
213 } else {
214 dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr,
215 bo->paddr);
216 }
217}
218
219static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo,
220 size_t size)
221{
222 bo->pages = drm_gem_get_pages(&bo->gem);
223 if (IS_ERR(bo->pages))
224 return PTR_ERR(bo->pages);
225
226 bo->num_pages = size >> PAGE_SHIFT;
227
228 bo->sgt = drm_prime_pages_to_sg(bo->pages, bo->num_pages);
229 if (IS_ERR(bo->sgt)) {
230 drm_gem_put_pages(&bo->gem, bo->pages, false, false);
231 return PTR_ERR(bo->sgt);
232 }
233
234 return 0;
235}
236
237static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo,
238 size_t size)
125{ 239{
126 dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr, bo->paddr); 240 struct tegra_drm *tegra = drm->dev_private;
241 int err;
242
243 if (tegra->domain) {
244 err = tegra_bo_get_pages(drm, bo, size);
245 if (err < 0)
246 return err;
247
248 err = tegra_bo_iommu_map(tegra, bo);
249 if (err < 0) {
250 tegra_bo_free(drm, bo);
251 return err;
252 }
253 } else {
254 bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr,
255 GFP_KERNEL | __GFP_NOWARN);
256 if (!bo->vaddr) {
257 dev_err(drm->dev,
258 "failed to allocate buffer of size %zu\n",
259 size);
260 return -ENOMEM;
261 }
262 }
263
264 return 0;
127} 265}
128 266
129struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size, 267struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
@@ -136,14 +274,9 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
136 if (IS_ERR(bo)) 274 if (IS_ERR(bo))
137 return bo; 275 return bo;
138 276
139 bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr, 277 err = tegra_bo_alloc(drm, bo, size);
140 GFP_KERNEL | __GFP_NOWARN); 278 if (err < 0)
141 if (!bo->vaddr) { 279 goto release;
142 dev_err(drm->dev, "failed to allocate buffer with size %u\n",
143 size);
144 err = -ENOMEM;
145 goto err_dma;
146 }
147 280
148 if (flags & DRM_TEGRA_GEM_CREATE_TILED) 281 if (flags & DRM_TEGRA_GEM_CREATE_TILED)
149 bo->tiling.mode = TEGRA_BO_TILING_MODE_TILED; 282 bo->tiling.mode = TEGRA_BO_TILING_MODE_TILED;
@@ -153,9 +286,9 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
153 286
154 return bo; 287 return bo;
155 288
156err_dma: 289release:
290 drm_gem_object_release(&bo->gem);
157 kfree(bo); 291 kfree(bo);
158
159 return ERR_PTR(err); 292 return ERR_PTR(err);
160} 293}
161 294
@@ -186,6 +319,7 @@ struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
186static struct tegra_bo *tegra_bo_import(struct drm_device *drm, 319static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
187 struct dma_buf *buf) 320 struct dma_buf *buf)
188{ 321{
322 struct tegra_drm *tegra = drm->dev_private;
189 struct dma_buf_attachment *attach; 323 struct dma_buf_attachment *attach;
190 struct tegra_bo *bo; 324 struct tegra_bo *bo;
191 int err; 325 int err;
@@ -213,12 +347,19 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
213 goto detach; 347 goto detach;
214 } 348 }
215 349
216 if (bo->sgt->nents > 1) { 350 if (tegra->domain) {
217 err = -EINVAL; 351 err = tegra_bo_iommu_map(tegra, bo);
218 goto detach; 352 if (err < 0)
353 goto detach;
354 } else {
355 if (bo->sgt->nents > 1) {
356 err = -EINVAL;
357 goto detach;
358 }
359
360 bo->paddr = sg_dma_address(bo->sgt->sgl);
219 } 361 }
220 362
221 bo->paddr = sg_dma_address(bo->sgt->sgl);
222 bo->gem.import_attach = attach; 363 bo->gem.import_attach = attach;
223 364
224 return bo; 365 return bo;
@@ -237,14 +378,18 @@ free:
237 378
238void tegra_bo_free_object(struct drm_gem_object *gem) 379void tegra_bo_free_object(struct drm_gem_object *gem)
239{ 380{
381 struct tegra_drm *tegra = gem->dev->dev_private;
240 struct tegra_bo *bo = to_tegra_bo(gem); 382 struct tegra_bo *bo = to_tegra_bo(gem);
241 383
384 if (tegra->domain)
385 tegra_bo_iommu_unmap(tegra, bo);
386
242 if (gem->import_attach) { 387 if (gem->import_attach) {
243 dma_buf_unmap_attachment(gem->import_attach, bo->sgt, 388 dma_buf_unmap_attachment(gem->import_attach, bo->sgt,
244 DMA_TO_DEVICE); 389 DMA_TO_DEVICE);
245 drm_prime_gem_destroy(gem, NULL); 390 drm_prime_gem_destroy(gem, NULL);
246 } else { 391 } else {
247 tegra_bo_destroy(gem->dev, bo); 392 tegra_bo_free(gem->dev, bo);
248 } 393 }
249 394
250 drm_gem_object_release(gem); 395 drm_gem_object_release(gem);
@@ -299,14 +444,44 @@ int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
299 return 0; 444 return 0;
300} 445}
301 446
447static int tegra_bo_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
448{
449 struct drm_gem_object *gem = vma->vm_private_data;
450 struct tegra_bo *bo = to_tegra_bo(gem);
451 struct page *page;
452 pgoff_t offset;
453 int err;
454
455 if (!bo->pages)
456 return VM_FAULT_SIGBUS;
457
458 offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> PAGE_SHIFT;
459 page = bo->pages[offset];
460
461 err = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page);
462 switch (err) {
463 case -EAGAIN:
464 case 0:
465 case -ERESTARTSYS:
466 case -EINTR:
467 case -EBUSY:
468 return VM_FAULT_NOPAGE;
469
470 case -ENOMEM:
471 return VM_FAULT_OOM;
472 }
473
474 return VM_FAULT_SIGBUS;
475}
476
302const struct vm_operations_struct tegra_bo_vm_ops = { 477const struct vm_operations_struct tegra_bo_vm_ops = {
478 .fault = tegra_bo_fault,
303 .open = drm_gem_vm_open, 479 .open = drm_gem_vm_open,
304 .close = drm_gem_vm_close, 480 .close = drm_gem_vm_close,
305}; 481};
306 482
307int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma) 483int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
308{ 484{
309 unsigned long vm_pgoff = vma->vm_pgoff;
310 struct drm_gem_object *gem; 485 struct drm_gem_object *gem;
311 struct tegra_bo *bo; 486 struct tegra_bo *bo;
312 int ret; 487 int ret;
@@ -318,17 +493,28 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
318 gem = vma->vm_private_data; 493 gem = vma->vm_private_data;
319 bo = to_tegra_bo(gem); 494 bo = to_tegra_bo(gem);
320 495
321 vma->vm_flags &= ~VM_PFNMAP; 496 if (!bo->pages) {
322 vma->vm_pgoff = 0; 497 unsigned long vm_pgoff = vma->vm_pgoff;
323 498
324 ret = dma_mmap_writecombine(gem->dev->dev, vma, bo->vaddr, bo->paddr, 499 vma->vm_flags &= ~VM_PFNMAP;
325 gem->size); 500 vma->vm_pgoff = 0;
326 if (ret) {
327 drm_gem_vm_close(vma);
328 return ret;
329 }
330 501
331 vma->vm_pgoff = vm_pgoff; 502 ret = dma_mmap_writecombine(gem->dev->dev, vma, bo->vaddr,
503 bo->paddr, gem->size);
504 if (ret) {
505 drm_gem_vm_close(vma);
506 return ret;
507 }
508
509 vma->vm_pgoff = vm_pgoff;
510 } else {
511 pgprot_t prot = vm_get_page_prot(vma->vm_flags);
512
513 vma->vm_flags |= VM_MIXEDMAP;
514 vma->vm_flags &= ~VM_PFNMAP;
515
516 vma->vm_page_prot = pgprot_writecombine(prot);
517 }
332 518
333 return 0; 519 return 0;
334} 520}
@@ -345,21 +531,44 @@ tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
345 if (!sgt) 531 if (!sgt)
346 return NULL; 532 return NULL;
347 533
348 if (sg_alloc_table(sgt, 1, GFP_KERNEL)) { 534 if (bo->pages) {
349 kfree(sgt); 535 struct scatterlist *sg;
350 return NULL; 536 unsigned int i;
351 } 537
538 if (sg_alloc_table(sgt, bo->num_pages, GFP_KERNEL))
539 goto free;
352 540
353 sg_dma_address(sgt->sgl) = bo->paddr; 541 for_each_sg(sgt->sgl, sg, bo->num_pages, i)
354 sg_dma_len(sgt->sgl) = gem->size; 542 sg_set_page(sg, bo->pages[i], PAGE_SIZE, 0);
543
544 if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0)
545 goto free;
546 } else {
547 if (sg_alloc_table(sgt, 1, GFP_KERNEL))
548 goto free;
549
550 sg_dma_address(sgt->sgl) = bo->paddr;
551 sg_dma_len(sgt->sgl) = gem->size;
552 }
355 553
356 return sgt; 554 return sgt;
555
556free:
557 sg_free_table(sgt);
558 kfree(sgt);
559 return NULL;
357} 560}
358 561
359static void tegra_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach, 562static void tegra_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
360 struct sg_table *sgt, 563 struct sg_table *sgt,
361 enum dma_data_direction dir) 564 enum dma_data_direction dir)
362{ 565{
566 struct drm_gem_object *gem = attach->dmabuf->priv;
567 struct tegra_bo *bo = to_tegra_bo(gem);
568
569 if (bo->pages)
570 dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
571
363 sg_free_table(sgt); 572 sg_free_table(sgt);
364 kfree(sgt); 573 kfree(sgt);
365} 574}
diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h
index 6538b56780c2..3dd4165f812a 100644
--- a/drivers/gpu/drm/tegra/gem.h
+++ b/drivers/gpu/drm/tegra/gem.h
@@ -38,6 +38,12 @@ struct tegra_bo {
38 dma_addr_t paddr; 38 dma_addr_t paddr;
39 void *vaddr; 39 void *vaddr;
40 40
41 struct drm_mm_node *mm;
42 unsigned long num_pages;
43 struct page **pages;
44 /* size of IOMMU mapping */
45 size_t size;
46
41 struct tegra_bo_tiling tiling; 47 struct tegra_bo_tiling tiling;
42}; 48};
43 49