aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos
diff options
context:
space:
mode:
authorCarlo Caione <carlo@caione.org>2015-02-04 04:23:19 -0500
committerInki Dae <inki.dae@samsung.com>2015-02-07 02:38:41 -0500
commita5d7ac30fa9ffa923e3603309692a36e3b3b3ae1 (patch)
tree6306790667cadc1cc34c5a5a5b39e7385863259a /drivers/gpu/drm/exynos
parent129046c6ecb662e902a241bbbcb1da4206986370 (diff)
drm/exynos: fix DMA_ATTR_NO_KERNEL_MAPPING usage
The Exynos DRM driver doesn't follow the correct API when dealing with dma_{alloc, mmap, free}_attrs functions and the DMA_ATTR_NO_KERNEL_MAPPING attribute. When a IOMMU is not available and the DMA_ATTR_NO_KERNEL_MAPPING is used, the driver should use the pointer returned by dma_alloc_attr() as a cookie. The Exynos DRM driver directly uses the non-requested virtual kernel address returned by the DMA mapping subsystem. This just works now because the non-IOMMU codepath doesn't obey DMA_ATTR_NO_KERNEL_MAPPING but we need to fix it before fixing the DMA layer. Signed-off-by: Carlo Caione <carlo@caione.org> Acked-by: Marek Szyprowski <m.szyprowski@samsung.com> Acked-by: Joonyoung Shim <jy0922.shim@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_buf.c6
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c29
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.h2
3 files changed, 14 insertions, 23 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c
index 9c8088462c26..24994ba10e28 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_buf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c
@@ -63,11 +63,11 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
63 return -ENOMEM; 63 return -ENOMEM;
64 } 64 }
65 65
66 buf->kvaddr = (void __iomem *)dma_alloc_attrs(dev->dev, 66 buf->cookie = dma_alloc_attrs(dev->dev,
67 buf->size, 67 buf->size,
68 &buf->dma_addr, GFP_KERNEL, 68 &buf->dma_addr, GFP_KERNEL,
69 &buf->dma_attrs); 69 &buf->dma_attrs);
70 if (!buf->kvaddr) { 70 if (!buf->cookie) {
71 DRM_ERROR("failed to allocate buffer.\n"); 71 DRM_ERROR("failed to allocate buffer.\n");
72 ret = -ENOMEM; 72 ret = -ENOMEM;
73 goto err_free; 73 goto err_free;
@@ -132,7 +132,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
132 buf->sgt = NULL; 132 buf->sgt = NULL;
133 133
134 if (!is_drm_iommu_supported(dev)) { 134 if (!is_drm_iommu_supported(dev)) {
135 dma_free_attrs(dev->dev, buf->size, buf->kvaddr, 135 dma_free_attrs(dev->dev, buf->size, buf->cookie,
136 (dma_addr_t)buf->dma_addr, &buf->dma_attrs); 136 (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
137 drm_free_large(buf->pages); 137 drm_free_large(buf->pages);
138 } else 138 } else
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index e12ea90c6237..84f8dfe1c5ec 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -79,9 +79,9 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
79 struct drm_framebuffer *fb) 79 struct drm_framebuffer *fb)
80{ 80{
81 struct fb_info *fbi = helper->fbdev; 81 struct fb_info *fbi = helper->fbdev;
82 struct drm_device *dev = helper->dev;
83 struct exynos_drm_gem_buf *buffer; 82 struct exynos_drm_gem_buf *buffer;
84 unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); 83 unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
84 unsigned int nr_pages;
85 unsigned long offset; 85 unsigned long offset;
86 86
87 drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); 87 drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
@@ -94,25 +94,14 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
94 return -EFAULT; 94 return -EFAULT;
95 } 95 }
96 96
97 /* map pages with kernel virtual space. */ 97 nr_pages = buffer->size >> PAGE_SHIFT;
98
99 buffer->kvaddr = (void __iomem *) vmap(buffer->pages,
100 nr_pages, VM_MAP,
101 pgprot_writecombine(PAGE_KERNEL));
98 if (!buffer->kvaddr) { 102 if (!buffer->kvaddr) {
99 if (is_drm_iommu_supported(dev)) { 103 DRM_ERROR("failed to map pages to kernel space.\n");
100 unsigned int nr_pages = buffer->size >> PAGE_SHIFT; 104 return -EIO;
101
102 buffer->kvaddr = (void __iomem *) vmap(buffer->pages,
103 nr_pages, VM_MAP,
104 pgprot_writecombine(PAGE_KERNEL));
105 } else {
106 phys_addr_t dma_addr = buffer->dma_addr;
107 if (dma_addr)
108 buffer->kvaddr = (void __iomem *)phys_to_virt(dma_addr);
109 else
110 buffer->kvaddr = (void __iomem *)NULL;
111 }
112 if (!buffer->kvaddr) {
113 DRM_ERROR("failed to map pages to kernel space.\n");
114 return -EIO;
115 }
116 } 105 }
117 106
118 /* buffer count to framebuffer always is 1 at booting time. */ 107 /* buffer count to framebuffer always is 1 at booting time. */
@@ -313,7 +302,7 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
313 struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj; 302 struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj;
314 struct drm_framebuffer *fb; 303 struct drm_framebuffer *fb;
315 304
316 if (is_drm_iommu_supported(dev) && exynos_gem_obj->buffer->kvaddr) 305 if (exynos_gem_obj->buffer->kvaddr)
317 vunmap(exynos_gem_obj->buffer->kvaddr); 306 vunmap(exynos_gem_obj->buffer->kvaddr);
318 307
319 /* release drm framebuffer and real buffer */ 308 /* release drm framebuffer and real buffer */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index ec58fe9c40df..308173cb4f0a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -22,6 +22,7 @@
22/* 22/*
23 * exynos drm gem buffer structure. 23 * exynos drm gem buffer structure.
24 * 24 *
25 * @cookie: cookie returned by dma_alloc_attrs
25 * @kvaddr: kernel virtual address to allocated memory region. 26 * @kvaddr: kernel virtual address to allocated memory region.
26 * *userptr: user space address. 27 * *userptr: user space address.
27 * @dma_addr: bus address(accessed by dma) to allocated memory region. 28 * @dma_addr: bus address(accessed by dma) to allocated memory region.
@@ -35,6 +36,7 @@
35 * VM_PFNMAP or not. 36 * VM_PFNMAP or not.
36 */ 37 */
37struct exynos_drm_gem_buf { 38struct exynos_drm_gem_buf {
39 void *cookie;
38 void __iomem *kvaddr; 40 void __iomem *kvaddr;
39 unsigned long userptr; 41 unsigned long userptr;
40 dma_addr_t dma_addr; 42 dma_addr_t dma_addr;