diff options
author | Carlo Caione <carlo@caione.org> | 2015-02-04 04:23:19 -0500 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2015-02-07 02:38:41 -0500 |
commit | a5d7ac30fa9ffa923e3603309692a36e3b3b3ae1 (patch) | |
tree | 6306790667cadc1cc34c5a5a5b39e7385863259a /drivers/gpu/drm/exynos | |
parent | 129046c6ecb662e902a241bbbcb1da4206986370 (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.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 29 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.h | 2 |
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 | */ |
37 | struct exynos_drm_gem_buf { | 38 | struct 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; |