drm/exynos: fixed page align and code clean.

1M section, 64k page count also should be rounded up so this patch
rounds up them and caculates page count of them properly and also
checks memory flags from user.

Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
This commit is contained in:
Inki Dae 2012-04-03 21:27:58 +09:00
parent 62fb376e21
commit dcf9af8228
4 changed files with 45 additions and 18 deletions

View File

@ -41,7 +41,7 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
if (flags & EXYNOS_BO_NONCONTIG) { if (IS_NONCONTIG_BUFFER(flags)) {
DRM_DEBUG_KMS("not support allocation type.\n"); DRM_DEBUG_KMS("not support allocation type.\n");
return -EINVAL; return -EINVAL;
} }
@ -52,13 +52,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
} }
if (buf->size >= SZ_1M) { if (buf->size >= SZ_1M) {
npages = (buf->size >> SECTION_SHIFT) + 1; npages = buf->size >> SECTION_SHIFT;
page_size = SECTION_SIZE; page_size = SECTION_SIZE;
} else if (buf->size >= SZ_64K) { } else if (buf->size >= SZ_64K) {
npages = (buf->size >> 16) + 1; npages = buf->size >> 16;
page_size = SZ_64K; page_size = SZ_64K;
} else { } else {
npages = (buf->size >> PAGE_SHIFT) + 1; npages = buf->size >> PAGE_SHIFT;
page_size = PAGE_SIZE; page_size = PAGE_SIZE;
} }
@ -119,9 +119,6 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
buf->pages[i] = phys_to_page(start_addr); buf->pages[i] = phys_to_page(start_addr);
sgl = sg_next(sgl);
sg_set_page(sgl, buf->pages[i+1], end_addr - start_addr, 0);
DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n", DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
(unsigned long)buf->kvaddr, (unsigned long)buf->kvaddr,
(unsigned long)buf->dma_addr, (unsigned long)buf->dma_addr,
@ -150,7 +147,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
* non-continuous memory would be released by exynos * non-continuous memory would be released by exynos
* gem framework. * gem framework.
*/ */
if (flags & EXYNOS_BO_NONCONTIG) { if (IS_NONCONTIG_BUFFER(flags)) {
DRM_DEBUG_KMS("not support allocation type.\n"); DRM_DEBUG_KMS("not support allocation type.\n");
return; return;
} }

View File

@ -56,9 +56,28 @@ static unsigned int convert_to_vm_err_msg(int msg)
return out_msg; return out_msg;
} }
static unsigned int mask_gem_flags(unsigned int flags) static int check_gem_flags(unsigned int flags)
{ {
return flags &= EXYNOS_BO_NONCONTIG; if (flags & ~(EXYNOS_BO_MASK)) {
DRM_ERROR("invalid flags.\n");
return -EINVAL;
}
return 0;
}
static unsigned long roundup_gem_size(unsigned long size, unsigned int flags)
{
if (!IS_NONCONTIG_BUFFER(flags)) {
if (size >= SZ_1M)
return roundup(size, SECTION_SIZE);
else if (size >= SZ_64K)
return roundup(size, SZ_64K);
else
goto out;
}
out:
return roundup(size, PAGE_SIZE);
} }
static struct page **exynos_gem_get_pages(struct drm_gem_object *obj, static struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
@ -319,10 +338,17 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
struct exynos_drm_gem_buf *buf; struct exynos_drm_gem_buf *buf;
int ret; int ret;
size = roundup(size, PAGE_SIZE); if (!size) {
DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size); DRM_ERROR("invalid size.\n");
return ERR_PTR(-EINVAL);
}
flags = mask_gem_flags(flags); size = roundup_gem_size(size, flags);
DRM_DEBUG_KMS("%s\n", __FILE__);
ret = check_gem_flags(flags);
if (ret)
return ERR_PTR(ret);
buf = exynos_drm_init_buf(dev, size); buf = exynos_drm_init_buf(dev, size);
if (!buf) if (!buf)
@ -331,7 +357,7 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
exynos_gem_obj = exynos_drm_gem_init(dev, size); exynos_gem_obj = exynos_drm_gem_init(dev, size);
if (!exynos_gem_obj) { if (!exynos_gem_obj) {
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err_fini_buf;
} }
exynos_gem_obj->buffer = buf; exynos_gem_obj->buffer = buf;
@ -347,18 +373,19 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base); ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base);
if (ret < 0) { if (ret < 0) {
drm_gem_object_release(&exynos_gem_obj->base); drm_gem_object_release(&exynos_gem_obj->base);
goto err; goto err_fini_buf;
} }
} else { } else {
ret = exynos_drm_alloc_buf(dev, buf, flags); ret = exynos_drm_alloc_buf(dev, buf, flags);
if (ret < 0) { if (ret < 0) {
drm_gem_object_release(&exynos_gem_obj->base); drm_gem_object_release(&exynos_gem_obj->base);
goto err; goto err_fini_buf;
} }
} }
return exynos_gem_obj; return exynos_gem_obj;
err:
err_fini_buf:
exynos_drm_fini_buf(dev, buf); exynos_drm_fini_buf(dev, buf);
return ERR_PTR(ret); return ERR_PTR(ret);
} }

View File

@ -29,6 +29,8 @@
#define to_exynos_gem_obj(x) container_of(x,\ #define to_exynos_gem_obj(x) container_of(x,\
struct exynos_drm_gem_obj, base) struct exynos_drm_gem_obj, base)
#define IS_NONCONTIG_BUFFER(f) (f & EXYNOS_BO_NONCONTIG)
/* /*
* exynos drm gem buffer structure. * exynos drm gem buffer structure.
* *

View File

@ -96,7 +96,8 @@ struct drm_exynos_plane_set_zpos {
/* memory type definitions. */ /* memory type definitions. */
enum e_drm_exynos_gem_mem_type { enum e_drm_exynos_gem_mem_type {
/* Physically Non-Continuous memory. */ /* Physically Non-Continuous memory. */
EXYNOS_BO_NONCONTIG = 1 << 0 EXYNOS_BO_NONCONTIG = 1 << 0,
EXYNOS_BO_MASK = EXYNOS_BO_NONCONTIG
}; };
#define DRM_EXYNOS_GEM_CREATE 0x00 #define DRM_EXYNOS_GEM_CREATE 0x00