aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorInki Dae <inki.dae@samsung.com>2012-12-07 03:51:27 -0500
committerInki Dae <daeinki@gmail.com>2012-12-13 09:05:45 -0500
commit4744ad2414bd890d37a99df4726be733137aa3f7 (patch)
tree3c06797a1a8899d5687064aff27030e2d1b2f80b /drivers/gpu/drm
parent662aa6d7632cab054277bafda67d13d9a8a81929 (diff)
drm/exynos: use DMA_ATTR_NO_KERNEL_MAPPING attribute
Changelog v3: just code cleanup. Changelog v2: fix argument to dma_mmap_attr function. - use pages instead of kvaddr because kvaddr is 0 with DMA_ATTR_NO_KERNEL_MAPPING. Changelog v1: When gem allocation is requested, kernel space mapping isn't needed. But if need, such as console framebuffer, the physical pages would be mapped with kernel space though vmap function. Signed-off-by: Inki Dae <inki.dae@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_buf.c31
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c18
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.h2
5 files changed, 32 insertions, 25 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c
index 72bf97b96ba..9732043d91e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_buf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c
@@ -35,6 +35,7 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
35{ 35{
36 int ret = 0; 36 int ret = 0;
37 enum dma_attr attr = DMA_ATTR_FORCE_CONTIGUOUS; 37 enum dma_attr attr = DMA_ATTR_FORCE_CONTIGUOUS;
38 unsigned int nr_pages;
38 39
39 DRM_DEBUG_KMS("%s\n", __FILE__); 40 DRM_DEBUG_KMS("%s\n", __FILE__);
40 41
@@ -49,40 +50,31 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
49 attr = DMA_ATTR_WRITE_COMBINE; 50 attr = DMA_ATTR_WRITE_COMBINE;
50 51
51 dma_set_attr(attr, &buf->dma_attrs); 52 dma_set_attr(attr, &buf->dma_attrs);
53 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);
52 54
53 buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size, 55 buf->pages = dma_alloc_attrs(dev->dev, buf->size,
54 &buf->dma_addr, GFP_KERNEL, &buf->dma_attrs); 56 &buf->dma_addr, GFP_KERNEL, &buf->dma_attrs);
55 if (!buf->kvaddr) { 57 if (!buf->pages) {
56 DRM_ERROR("failed to allocate buffer.\n"); 58 DRM_ERROR("failed to allocate buffer.\n");
57 return -ENOMEM; 59 return -ENOMEM;
58 } 60 }
59 61
60 buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); 62 nr_pages = buf->size >> PAGE_SHIFT;
63 buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages);
61 if (!buf->sgt) { 64 if (!buf->sgt) {
62 DRM_ERROR("failed to allocate sg table.\n"); 65 DRM_ERROR("failed to get sg table.\n");
63 ret = -ENOMEM; 66 ret = -ENOMEM;
64 goto err_free_attrs; 67 goto err_free_attrs;
65 } 68 }
66 69
67 ret = dma_get_sgtable(dev->dev, buf->sgt, buf->kvaddr, buf->dma_addr, 70 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
68 buf->size);
69 if (ret < 0) {
70 DRM_ERROR("failed to get sgtable.\n");
71 goto err_free_sgt;
72 }
73
74 DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
75 (unsigned long)buf->kvaddr,
76 (unsigned long)buf->dma_addr, 71 (unsigned long)buf->dma_addr,
77 buf->size); 72 buf->size);
78 73
79 return ret; 74 return ret;
80 75
81err_free_sgt:
82 kfree(buf->sgt);
83 buf->sgt = NULL;
84err_free_attrs: 76err_free_attrs:
85 dma_free_attrs(dev->dev, buf->size, buf->kvaddr, 77 dma_free_attrs(dev->dev, buf->size, buf->pages,
86 (dma_addr_t)buf->dma_addr, &buf->dma_attrs); 78 (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
87 buf->dma_addr = (dma_addr_t)NULL; 79 buf->dma_addr = (dma_addr_t)NULL;
88 80
@@ -99,8 +91,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
99 return; 91 return;
100 } 92 }
101 93
102 DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", 94 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
103 (unsigned long)buf->kvaddr,
104 (unsigned long)buf->dma_addr, 95 (unsigned long)buf->dma_addr,
105 buf->size); 96 buf->size);
106 97
@@ -109,7 +100,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
109 kfree(buf->sgt); 100 kfree(buf->sgt);
110 buf->sgt = NULL; 101 buf->sgt = NULL;
111 102
112 dma_free_attrs(dev->dev, buf->size, buf->kvaddr, 103 dma_free_attrs(dev->dev, buf->size, buf->pages,
113 (dma_addr_t)buf->dma_addr, &buf->dma_attrs); 104 (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
114 buf->dma_addr = (dma_addr_t)NULL; 105 buf->dma_addr = (dma_addr_t)NULL;
115} 106}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 7413f4b729b..764571c9625 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -297,9 +297,7 @@ struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
297 if (!buffer) 297 if (!buffer)
298 return NULL; 298 return NULL;
299 299
300 DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n", 300 DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)buffer->dma_addr);
301 (unsigned long)buffer->kvaddr,
302 (unsigned long)buffer->dma_addr);
303 301
304 return buffer; 302 return buffer;
305} 303}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 885ef235d59..f433eb7533a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -65,7 +65,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
65 if (vm_size > buffer->size) 65 if (vm_size > buffer->size)
66 return -EINVAL; 66 return -EINVAL;
67 67
68 ret = dma_mmap_attrs(helper->dev->dev, vma, buffer->kvaddr, 68 ret = dma_mmap_attrs(helper->dev->dev, vma, buffer->pages,
69 buffer->dma_addr, buffer->size, &buffer->dma_attrs); 69 buffer->dma_addr, buffer->size, &buffer->dma_attrs);
70 if (ret < 0) { 70 if (ret < 0) {
71 DRM_ERROR("failed to mmap.\n"); 71 DRM_ERROR("failed to mmap.\n");
@@ -109,6 +109,17 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
109 return -EFAULT; 109 return -EFAULT;
110 } 110 }
111 111
112 /* map pages with kernel virtual space. */
113 if (!buffer->kvaddr) {
114 unsigned int nr_pages = buffer->size >> PAGE_SHIFT;
115 buffer->kvaddr = vmap(buffer->pages, nr_pages, VM_MAP,
116 pgprot_writecombine(PAGE_KERNEL));
117 if (!buffer->kvaddr) {
118 DRM_ERROR("failed to map pages to kernel space.\n");
119 return -EIO;
120 }
121 }
122
112 /* buffer count to framebuffer always is 1 at booting time. */ 123 /* buffer count to framebuffer always is 1 at booting time. */
113 exynos_drm_fb_set_buf_cnt(fb, 1); 124 exynos_drm_fb_set_buf_cnt(fb, 1);
114 125
@@ -305,8 +316,13 @@ err_init:
305static void exynos_drm_fbdev_destroy(struct drm_device *dev, 316static void exynos_drm_fbdev_destroy(struct drm_device *dev,
306 struct drm_fb_helper *fb_helper) 317 struct drm_fb_helper *fb_helper)
307{ 318{
319 struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(fb_helper);
320 struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj;
308 struct drm_framebuffer *fb; 321 struct drm_framebuffer *fb;
309 322
323 if (exynos_gem_obj->buffer->kvaddr)
324 vunmap(exynos_gem_obj->buffer->kvaddr);
325
310 /* release drm framebuffer and real buffer */ 326 /* release drm framebuffer and real buffer */
311 if (fb_helper->fb && fb_helper->fb->funcs) { 327 if (fb_helper->fb && fb_helper->fb->funcs) {
312 fb = fb_helper->fb; 328 fb = fb_helper->fb;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 99227246ce8..d48183e7e05 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -400,7 +400,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
400 if (vm_size > buffer->size) 400 if (vm_size > buffer->size)
401 return -EINVAL; 401 return -EINVAL;
402 402
403 ret = dma_mmap_attrs(drm_dev->dev, vma, buffer->kvaddr, 403 ret = dma_mmap_attrs(drm_dev->dev, vma, buffer->pages,
404 buffer->dma_addr, buffer->size, 404 buffer->dma_addr, buffer->size,
405 &buffer->dma_attrs); 405 &buffer->dma_attrs);
406 if (ret < 0) { 406 if (ret < 0) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index d3ea106a9a7..f11f2afd5bf 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -40,6 +40,7 @@
40 * - this address could be physical address without IOMMU and 40 * - this address could be physical address without IOMMU and
41 * device address with IOMMU. 41 * device address with IOMMU.
42 * @write: whether pages will be written to by the caller. 42 * @write: whether pages will be written to by the caller.
43 * @pages: Array of backing pages.
43 * @sgt: sg table to transfer page data. 44 * @sgt: sg table to transfer page data.
44 * @size: size of allocated memory region. 45 * @size: size of allocated memory region.
45 * @pfnmap: indicate whether memory region from userptr is mmaped with 46 * @pfnmap: indicate whether memory region from userptr is mmaped with
@@ -51,6 +52,7 @@ struct exynos_drm_gem_buf {
51 dma_addr_t dma_addr; 52 dma_addr_t dma_addr;
52 struct dma_attrs dma_attrs; 53 struct dma_attrs dma_attrs;
53 unsigned int write; 54 unsigned int write;
55 struct page **pages;
54 struct sg_table *sgt; 56 struct sg_table *sgt;
55 unsigned long size; 57 unsigned long size;
56 bool pfnmap; 58 bool pfnmap;