From 179239a7ae805f7695167c62a97eac3efe52d7af Mon Sep 17 00:00:00 2001 From: Tobias Jakobi Date: Tue, 18 Aug 2015 00:51:24 +0200 Subject: drm/exynos: fix size check in g2d_check_buf_desc_is_valid() The size check was incomplete. It only computed the size of area of the drawing rectangle and checked if the size still fit inside the buffer. The correct check is to compute the position of the last byte that the G2D engine is going to access and then check if that position is still contained in the buffer. In particular we need the stride information to determine this. Signed-off-by: Tobias Jakobi Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 51 ++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index ba008391a2fc..85457b33d881 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -48,11 +48,13 @@ /* registers for base address */ #define G2D_SRC_BASE_ADDR 0x0304 +#define G2D_SRC_STRIDE_REG 0x0308 #define G2D_SRC_COLOR_MODE 0x030C #define G2D_SRC_LEFT_TOP 0x0310 #define G2D_SRC_RIGHT_BOTTOM 0x0314 #define G2D_SRC_PLANE2_BASE_ADDR 0x0318 #define G2D_DST_BASE_ADDR 0x0404 +#define G2D_DST_STRIDE_REG 0x0408 #define G2D_DST_COLOR_MODE 0x040C #define G2D_DST_LEFT_TOP 0x0410 #define G2D_DST_RIGHT_BOTTOM 0x0414 @@ -148,6 +150,7 @@ struct g2d_cmdlist { * A structure of buffer description * * @format: color format + * @stride: buffer stride/pitch in bytes * @left_x: the x coordinates of left top corner * @top_y: the y coordinates of left top corner * @right_x: the x coordinates of right bottom corner @@ -156,6 +159,7 @@ struct g2d_cmdlist { */ struct g2d_buf_desc { unsigned int format; + unsigned int stride; unsigned int left_x; unsigned int top_y; unsigned int right_x; @@ -589,6 +593,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset) switch (reg_offset) { case G2D_SRC_BASE_ADDR: + case G2D_SRC_STRIDE_REG: case G2D_SRC_COLOR_MODE: case G2D_SRC_LEFT_TOP: case G2D_SRC_RIGHT_BOTTOM: @@ -598,6 +603,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset) reg_type = REG_TYPE_SRC_PLANE2; break; case G2D_DST_BASE_ADDR: + case G2D_DST_STRIDE_REG: case G2D_DST_COLOR_MODE: case G2D_DST_LEFT_TOP: case G2D_DST_RIGHT_BOTTOM: @@ -652,8 +658,8 @@ static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc, enum g2d_reg_type reg_type, unsigned long size) { - unsigned int width, height; - unsigned long area; + int width, height; + unsigned long bpp, last_pos; /* * check source and destination buffers only. @@ -662,22 +668,37 @@ static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc, if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST) return true; - width = buf_desc->right_x - buf_desc->left_x; + /* This check also makes sure that right_x > left_x. */ + width = (int)buf_desc->right_x - (int)buf_desc->left_x; if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) { - DRM_ERROR("width[%u] is out of range!\n", width); + DRM_ERROR("width[%d] is out of range!\n", width); return false; } - height = buf_desc->bottom_y - buf_desc->top_y; + /* This check also makes sure that bottom_y > top_y. */ + height = (int)buf_desc->bottom_y - (int)buf_desc->top_y; if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) { - DRM_ERROR("height[%u] is out of range!\n", height); + DRM_ERROR("height[%d] is out of range!\n", height); return false; } - area = (unsigned long)width * (unsigned long)height * - g2d_get_buf_bpp(buf_desc->format); - if (area > size) { - DRM_ERROR("area[%lu] is out of range[%lu]!\n", area, size); + bpp = g2d_get_buf_bpp(buf_desc->format); + + /* Compute the position of the last byte that the engine accesses. */ + last_pos = ((unsigned long)buf_desc->bottom_y - 1) * + (unsigned long)buf_desc->stride + + (unsigned long)buf_desc->right_x * bpp - 1; + + /* + * Since right_x > left_x and bottom_y > top_y we already know + * that the first_pos < last_pos (first_pos being the position + * of the first byte the engine accesses), it just remains to + * check if last_pos is smaller then the buffer size. + */ + + if (last_pos >= size) { + DRM_ERROR("last engine access position [%lu] " + "is out of range [%lu]!\n", last_pos, size); return false; } @@ -983,6 +1004,16 @@ static int g2d_check_reg_offset(struct device *dev, } else buf_info->types[reg_type] = BUF_TYPE_GEM; break; + case G2D_SRC_STRIDE_REG: + case G2D_DST_STRIDE_REG: + if (for_addr) + goto err; + + reg_type = g2d_get_reg_type(reg_offset); + + buf_desc = &buf_info->descs[reg_type]; + buf_desc->stride = cmdlist->data[index + 1]; + break; case G2D_SRC_COLOR_MODE: case G2D_DST_COLOR_MODE: if (for_addr) -- cgit v1.2.3 From 7de5c36c2aa9fc7ae1443d144f895ffd044c6b36 Mon Sep 17 00:00:00 2001 From: Tobias Jakobi Date: Tue, 18 Aug 2015 00:51:23 +0200 Subject: drm/exynos: remove superfluous checks in g2d_check_reg_offset() The cases of the switch statement ensure that reg_type can never be REG_TYPE_NONE here. Signed-off-by: Tobias Jakobi Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 85457b33d881..535b4ad6c4b1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -994,8 +994,6 @@ static int g2d_check_reg_offset(struct device *dev, goto err; reg_type = g2d_get_reg_type(reg_offset); - if (reg_type == REG_TYPE_NONE) - goto err; /* check userptr buffer type. */ if ((cmdlist->data[index] & ~0x7fffffff) >> 31) { @@ -1020,8 +1018,6 @@ static int g2d_check_reg_offset(struct device *dev, goto err; reg_type = g2d_get_reg_type(reg_offset); - if (reg_type == REG_TYPE_NONE) - goto err; buf_desc = &buf_info->descs[reg_type]; value = cmdlist->data[index + 1]; @@ -1034,8 +1030,6 @@ static int g2d_check_reg_offset(struct device *dev, goto err; reg_type = g2d_get_reg_type(reg_offset); - if (reg_type == REG_TYPE_NONE) - goto err; buf_desc = &buf_info->descs[reg_type]; value = cmdlist->data[index + 1]; @@ -1049,8 +1043,6 @@ static int g2d_check_reg_offset(struct device *dev, goto err; reg_type = g2d_get_reg_type(reg_offset); - if (reg_type == REG_TYPE_NONE) - goto err; buf_desc = &buf_info->descs[reg_type]; value = cmdlist->data[index + 1]; -- cgit v1.2.3 From 94e30d93f9360051b76e8e2a4b61753cde5e16c8 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 1 Sep 2015 16:22:47 +0900 Subject: drm/exynos: remove exynos_drm_fb_set_buf_cnt() The exynos_drm_fb_set_buf_cnt() is used to set buffer count only in exynos_drm_fbdev_update(). This patch sets directly buffer count in exynos_drm_framebuffer_init() without using exynos_drm_fb_set_buf_cnt(), so there is no any reason to keep exynos_drm_fb_set_buf_cnt(). Signed-off-by: Joonyoung Shim Reviewed-by: Gustavo Padovan Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_fb.c | 13 +++---------- drivers/gpu/drm/exynos/exynos_drm_fb.h | 4 ---- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 3 --- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 59ebbe547290..9cf1701e6bba 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -122,16 +122,6 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = { .dirty = exynos_drm_fb_dirty, }; -void exynos_drm_fb_set_buf_cnt(struct drm_framebuffer *fb, - unsigned int cnt) -{ - struct exynos_drm_fb *exynos_fb; - - exynos_fb = to_exynos_fb(fb); - - exynos_fb->buf_cnt = cnt; -} - unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb) { struct exynos_drm_fb *exynos_fb; @@ -163,6 +153,9 @@ exynos_drm_framebuffer_init(struct drm_device *dev, drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); exynos_fb->exynos_gem_obj[0] = exynos_gem_obj; + /* buffer count to framebuffer always is 1 at booting time. */ + exynos_fb->buf_cnt = 1; + ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); if (ret) { kfree(exynos_fb); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h index 1c9e27c32cd1..897d2cff6287 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.h +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h @@ -25,10 +25,6 @@ struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb, void exynos_drm_mode_config_init(struct drm_device *dev); -/* set a buffer count to drm framebuffer. */ -void exynos_drm_fb_set_buf_cnt(struct drm_framebuffer *fb, - unsigned int cnt); - /* get a buffer count to drm framebuffer. */ unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 624595afbce0..8188b1f32ca0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -103,9 +103,6 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, return -EIO; } - /* buffer count to framebuffer always is 1 at booting time. */ - exynos_drm_fb_set_buf_cnt(fb, 1); - offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); offset += fbi->var.yoffset * fb->pitches[0]; -- cgit v1.2.3 From 39a839f2e65185bcde80f99b5ee5ccd649ba07a2 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 1 Sep 2015 16:22:48 +0900 Subject: drm/exynos: s/exynos_gem_obj/obj in exynos_drm_fbdev.c The variable name "exynos_gem_obj" is too long, so some lines exceed 80 characters. It's simple to use "obj" instead of "exynos_gem_obj". Signed-off-by: Joonyoung Shim Reviewed-by: Gustavo Padovan Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 8188b1f32ca0..25170e22e597 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -32,7 +32,7 @@ struct exynos_drm_fbdev { struct drm_fb_helper drm_fb_helper; - struct exynos_drm_gem_obj *exynos_gem_obj; + struct exynos_drm_gem_obj *obj; }; static int exynos_drm_fb_mmap(struct fb_info *info, @@ -40,7 +40,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info, { struct drm_fb_helper *helper = info->par; struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(helper); - struct exynos_drm_gem_obj *obj = exynos_fbd->exynos_gem_obj; + struct exynos_drm_gem_obj *obj = exynos_fbd->obj; unsigned long vm_size; int ret; @@ -117,7 +117,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper); - struct exynos_drm_gem_obj *exynos_gem_obj; + struct exynos_drm_gem_obj *obj; struct drm_device *dev = helper->dev; struct fb_info *fbi; struct drm_mode_fb_cmd2 mode_cmd = { 0 }; @@ -146,27 +146,25 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, size = mode_cmd.pitches[0] * mode_cmd.height; - exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size); + obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size); /* * If physically contiguous memory allocation fails and if IOMMU is * supported then try to get buffer from non physically contiguous * memory area. */ - if (IS_ERR(exynos_gem_obj) && is_drm_iommu_supported(dev)) { + if (IS_ERR(obj) && is_drm_iommu_supported(dev)) { dev_warn(&pdev->dev, "contiguous FB allocation failed, falling back to non-contiguous\n"); - exynos_gem_obj = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG, - size); + obj = exynos_drm_gem_create(dev, EXYNOS_BO_NONCONTIG, size); } - if (IS_ERR(exynos_gem_obj)) { - ret = PTR_ERR(exynos_gem_obj); + if (IS_ERR(obj)) { + ret = PTR_ERR(obj); goto err_release_fbi; } - exynos_fbdev->exynos_gem_obj = exynos_gem_obj; + exynos_fbdev->obj = obj; - helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, - &exynos_gem_obj->base); + helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, &obj->base); if (IS_ERR(helper->fb)) { DRM_ERROR("failed to create drm framebuffer.\n"); ret = PTR_ERR(helper->fb); @@ -187,7 +185,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, err_destroy_framebuffer: drm_framebuffer_cleanup(helper->fb); err_destroy_gem: - exynos_drm_gem_destroy(exynos_gem_obj); + exynos_drm_gem_destroy(obj); err_release_fbi: drm_fb_helper_release_fbi(helper); @@ -282,11 +280,11 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev, struct drm_fb_helper *fb_helper) { struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(fb_helper); - struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj; + struct exynos_drm_gem_obj *obj = exynos_fbd->obj; struct drm_framebuffer *fb; - if (exynos_gem_obj->kvaddr) - vunmap(exynos_gem_obj->kvaddr); + if (obj->kvaddr) + vunmap(obj->kvaddr); /* release drm framebuffer and real buffer */ if (fb_helper->fb && fb_helper->fb->funcs) { -- cgit v1.2.3 From d76199609823ef0c5ab20ccdc8785df283241fd1 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 1 Sep 2015 16:22:49 +0900 Subject: drm/exynos: cleanup exynos_drm_fbdev_update() It can get exynos_gem object via function argument, so no need to call exynos_drm_fb_gem_obj() in exynos_drm_fbdev_update. It also can get struct drm_framebuffer *fb via helper->fb, so can remove a function argument for it. Signed-off-by: Joonyoung Shim Reviewed-by: Gustavo Padovan Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 25170e22e597..4ef87392f82f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -75,11 +75,11 @@ static struct fb_ops exynos_drm_fb_ops = { }; static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes, - struct drm_framebuffer *fb) + struct drm_fb_helper_surface_size *sizes, + struct exynos_drm_gem_obj *obj) { struct fb_info *fbi = helper->fbdev; - struct exynos_drm_gem_obj *obj; + struct drm_framebuffer *fb = helper->fb; unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); unsigned int nr_pages; unsigned long offset; @@ -87,13 +87,6 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); - /* RGB formats use only one buffer */ - obj = exynos_drm_fb_gem_obj(fb, 0); - if (!obj) { - DRM_DEBUG_KMS("gem object is null.\n"); - return -EFAULT; - } - nr_pages = obj->size >> PAGE_SHIFT; obj->kvaddr = (void __iomem *) vmap(obj->pages, nr_pages, VM_MAP, @@ -175,7 +168,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, fbi->flags = FBINFO_FLAG_DEFAULT; fbi->fbops = &exynos_drm_fb_ops; - ret = exynos_drm_fbdev_update(helper, sizes, helper->fb); + ret = exynos_drm_fbdev_update(helper, sizes, obj); if (ret < 0) goto err_destroy_framebuffer; -- cgit v1.2.3 From ee885ca5c0a34d5212eae9293ee8359e65c73715 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 1 Sep 2015 16:22:50 +0900 Subject: drm/exynos: update fb_info via only one function This patch moves codes to update fb_info into exynos_drm_fbdev_update(), so fb_info is updated via only one function. Signed-off-by: Joonyoung Shim Reviewed-by: Gustavo Padovan Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 4ef87392f82f..133cf5f2701f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -78,12 +78,22 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes, struct exynos_drm_gem_obj *obj) { - struct fb_info *fbi = helper->fbdev; + struct fb_info *fbi; struct drm_framebuffer *fb = helper->fb; unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); unsigned int nr_pages; unsigned long offset; + fbi = drm_fb_helper_alloc_fbi(helper); + if (IS_ERR(fbi)) { + DRM_ERROR("failed to allocate fb info.\n"); + return PTR_ERR(fbi); + } + + fbi->par = helper; + fbi->flags = FBINFO_FLAG_DEFAULT; + fbi->fbops = &exynos_drm_fb_ops; + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); @@ -93,6 +103,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, pgprot_writecombine(PAGE_KERNEL)); if (!obj->kvaddr) { DRM_ERROR("failed to map pages to kernel space.\n"); + drm_fb_helper_release_fbi(helper); return -EIO; } @@ -112,7 +123,6 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper); struct exynos_drm_gem_obj *obj; struct drm_device *dev = helper->dev; - struct fb_info *fbi; struct drm_mode_fb_cmd2 mode_cmd = { 0 }; struct platform_device *pdev = dev->platformdev; unsigned long size; @@ -130,13 +140,6 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, mutex_lock(&dev->struct_mutex); - fbi = drm_fb_helper_alloc_fbi(helper); - if (IS_ERR(fbi)) { - DRM_ERROR("failed to allocate fb info.\n"); - ret = PTR_ERR(fbi); - goto out; - } - size = mode_cmd.pitches[0] * mode_cmd.height; obj = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size); @@ -152,7 +155,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, if (IS_ERR(obj)) { ret = PTR_ERR(obj); - goto err_release_fbi; + goto out; } exynos_fbdev->obj = obj; @@ -164,10 +167,6 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, goto err_destroy_gem; } - fbi->par = helper; - fbi->flags = FBINFO_FLAG_DEFAULT; - fbi->fbops = &exynos_drm_fb_ops; - ret = exynos_drm_fbdev_update(helper, sizes, obj); if (ret < 0) goto err_destroy_framebuffer; @@ -179,8 +178,6 @@ err_destroy_framebuffer: drm_framebuffer_cleanup(helper->fb); err_destroy_gem: exynos_drm_gem_destroy(obj); -err_release_fbi: - drm_fb_helper_release_fbi(helper); /* * if failed, all resources allocated above would be released by -- cgit v1.2.3 From dcbb85a1641771547d83ee3a43230ea76703ed68 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 1 Sep 2015 16:22:51 +0900 Subject: drm/exynos: cleanup to get gem object for fb Current codes get first gem object and then again get remain gem objects. They can be unified to one routine. Signed-off-by: Joonyoung Shim Reviewed-by: Gustavo Padovan Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_fb.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 9cf1701e6bba..33911c10491a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -179,27 +179,18 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, if (!exynos_fb) return ERR_PTR(-ENOMEM); - obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); - if (!obj) { - DRM_ERROR("failed to lookup gem object\n"); - ret = -ENOENT; - goto err_free; - } - - drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); - exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj); exynos_fb->buf_cnt = drm_format_num_planes(mode_cmd->pixel_format); DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); - for (i = 1; i < exynos_fb->buf_cnt; i++) { + for (i = 0; i < exynos_fb->buf_cnt; i++) { obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[i]); if (!obj) { DRM_ERROR("failed to lookup gem object\n"); ret = -ENOENT; exynos_fb->buf_cnt = i; - goto err_unreference; + goto err; } exynos_gem_obj = to_exynos_gem_obj(obj); @@ -207,18 +198,20 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, ret = check_fb_gem_memory_type(dev, exynos_gem_obj); if (ret < 0) - goto err_unreference; + goto err; } + drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); + ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); if (ret) { DRM_ERROR("failed to init framebuffer.\n"); - goto err_unreference; + goto err; } return &exynos_fb->fb; -err_unreference: +err: for (i = 0; i < exynos_fb->buf_cnt; i++) { struct drm_gem_object *obj; @@ -226,7 +219,7 @@ err_unreference: if (obj) drm_gem_object_unreference_unlocked(obj); } -err_free: + kfree(exynos_fb); return ERR_PTR(ret); } -- cgit v1.2.3 From d56125afcbdfde09bcb05d3e07e1d063989b5f74 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 1 Sep 2015 16:22:52 +0900 Subject: drm/exynos: update exynos_drm_framebuffer_init() for multiple buffers This modifies exynos_drm_framebuffer_init() to be possible to support multiple buffers. Then it can be used by exynos_user_fb_create(). Signed-off-by: Joonyoung Shim Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_fb.c | 36 +++++++++++++++++-------------- drivers/gpu/drm/exynos/exynos_drm_fb.h | 5 ++++- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 3 +-- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 33911c10491a..8f94eac93b1d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -23,7 +23,6 @@ #include "exynos_drm_drv.h" #include "exynos_drm_fb.h" #include "exynos_drm_fbdev.h" -#include "exynos_drm_gem.h" #include "exynos_drm_iommu.h" #include "exynos_drm_crtc.h" @@ -134,36 +133,41 @@ unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb) struct drm_framebuffer * exynos_drm_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj) + struct exynos_drm_gem_obj **gem_obj, + int count) { struct exynos_drm_fb *exynos_fb; - struct exynos_drm_gem_obj *exynos_gem_obj; + int i; int ret; - exynos_gem_obj = to_exynos_gem_obj(obj); - - ret = check_fb_gem_memory_type(dev, exynos_gem_obj); - if (ret < 0) - return ERR_PTR(ret); - exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); if (!exynos_fb) return ERR_PTR(-ENOMEM); - drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); - exynos_fb->exynos_gem_obj[0] = exynos_gem_obj; + exynos_fb->buf_cnt = count; + DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); - /* buffer count to framebuffer always is 1 at booting time. */ - exynos_fb->buf_cnt = 1; + for (i = 0; i < count; i++) { + ret = check_fb_gem_memory_type(dev, gem_obj[i]); + if (ret < 0) + goto err; + + exynos_fb->exynos_gem_obj[i] = gem_obj[i]; + } + + drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); - if (ret) { - kfree(exynos_fb); + if (ret < 0) { DRM_ERROR("failed to initialize framebuffer\n"); - return ERR_PTR(ret); + goto err; } return &exynos_fb->fb; + +err: + kfree(exynos_fb); + return ERR_PTR(ret); } static struct drm_framebuffer * diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h index 897d2cff6287..8900f6baf315 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.h +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h @@ -14,10 +14,13 @@ #ifndef _EXYNOS_DRM_FB_H_ #define _EXYNOS_DRM_FB_H +#include "exynos_drm_gem.h" + struct drm_framebuffer * exynos_drm_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj); + struct exynos_drm_gem_obj **gem_obj, + int count); /* get gem object of a drm framebuffer */ struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb, diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 133cf5f2701f..a221f753ad9c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -21,7 +21,6 @@ #include "exynos_drm_drv.h" #include "exynos_drm_fb.h" #include "exynos_drm_fbdev.h" -#include "exynos_drm_gem.h" #include "exynos_drm_iommu.h" #define MAX_CONNECTOR 4 @@ -160,7 +159,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, exynos_fbdev->obj = obj; - helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, &obj->base); + helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, &obj, 1); if (IS_ERR(helper->fb)) { DRM_ERROR("failed to create drm framebuffer.\n"); ret = PTR_ERR(helper->fb); -- cgit v1.2.3 From 8d31758ecfe156fa4775017858613a5087eb57bf Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 1 Sep 2015 16:22:53 +0900 Subject: drm/exynos: cleanup exynos_user_fb_create() Using exynos_drm_framebuffer_init(), redundant codes can be removed. Signed-off-by: Joonyoung Shim Reviewed-by: Gustavo Padovan Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_fb.c | 47 ++++++++++------------------------ 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 8f94eac93b1d..849925ca0cdd 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -174,57 +174,36 @@ static struct drm_framebuffer * exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd) { + struct exynos_drm_gem_obj *gem_objs[MAX_FB_BUFFER]; struct drm_gem_object *obj; - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_fb *exynos_fb; - int i, ret; - - exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); - if (!exynos_fb) - return ERR_PTR(-ENOMEM); - - exynos_fb->buf_cnt = drm_format_num_planes(mode_cmd->pixel_format); - - DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); + struct drm_framebuffer *fb; + int i; + int ret; - for (i = 0; i < exynos_fb->buf_cnt; i++) { + for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) { obj = drm_gem_object_lookup(dev, file_priv, - mode_cmd->handles[i]); + mode_cmd->handles[i]); if (!obj) { DRM_ERROR("failed to lookup gem object\n"); ret = -ENOENT; - exynos_fb->buf_cnt = i; goto err; } - exynos_gem_obj = to_exynos_gem_obj(obj); - exynos_fb->exynos_gem_obj[i] = exynos_gem_obj; - - ret = check_fb_gem_memory_type(dev, exynos_gem_obj); - if (ret < 0) - goto err; + gem_objs[i] = to_exynos_gem_obj(obj); } - drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); - - ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); - if (ret) { - DRM_ERROR("failed to init framebuffer.\n"); + fb = exynos_drm_framebuffer_init(dev, mode_cmd, gem_objs, i); + if (IS_ERR(fb)) { + ret = PTR_ERR(fb); goto err; } - return &exynos_fb->fb; + return fb; err: - for (i = 0; i < exynos_fb->buf_cnt; i++) { - struct drm_gem_object *obj; + while (i--) + drm_gem_object_unreference_unlocked(&gem_objs[i]->base); - obj = &exynos_fb->exynos_gem_obj[i]->base; - if (obj) - drm_gem_object_unreference_unlocked(obj); - } - - kfree(exynos_fb); return ERR_PTR(ret); } -- cgit v1.2.3 From faec262b14f3d92601c06b5c73b45ea71d0d164b Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 1 Sep 2015 16:22:54 +0900 Subject: drm/exynos: remove exynos_drm_fb_get_buf_cnt() We can get buffer count of framebuffer using drm_format_num_planes(), so keeping exynos_drm_fb_get_buf_cnt() is unnecessary. Signed-off-by: Joonyoung Shim Reviewed-by: Gustavo Padovan Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_fb.c | 9 --------- drivers/gpu/drm/exynos/exynos_drm_fb.h | 3 --- drivers/gpu/drm/exynos/exynos_drm_plane.c | 2 +- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 849925ca0cdd..5087f60985f5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -121,15 +121,6 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = { .dirty = exynos_drm_fb_dirty, }; -unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb) -{ - struct exynos_drm_fb *exynos_fb; - - exynos_fb = to_exynos_fb(fb); - - return exynos_fb->buf_cnt; -} - struct drm_framebuffer * exynos_drm_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h index 8900f6baf315..85e4445b920e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.h +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h @@ -28,7 +28,4 @@ struct exynos_drm_gem_obj *exynos_drm_fb_gem_obj(struct drm_framebuffer *fb, void exynos_drm_mode_config_init(struct drm_device *dev); -/* get a buffer count to drm framebuffer. */ -unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb); - #endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 865d6eb0c845..714822441467 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -126,7 +126,7 @@ static int exynos_plane_atomic_check(struct drm_plane *plane, if (!state->fb) return 0; - nr = exynos_drm_fb_get_buf_cnt(state->fb); + nr = drm_format_num_planes(state->fb->pixel_format); for (i = 0; i < nr; i++) { struct exynos_drm_gem_obj *obj = exynos_drm_fb_gem_obj(state->fb, i); -- cgit v1.2.3 From c3058579a2882bb4bb6bf1ab0fe65f5ed070e530 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 1 Sep 2015 16:22:55 +0900 Subject: drm/exynos: remove buf_cnt from struct exynos_drm_fb Looking other drm drivers, there is no the restriction that framebuffer has only one buffer in .create_handle() callback. They use just first buffer. If this limitation is removed, there is no reason keeping buffer count for framebuffer, so we can remove buf_cnt from struct exynos_drm_fb. Signed-off-by: Joonyoung Shim Reviewed-by: Gustavo Padovan Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_fb.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 5087f60985f5..084280859589 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -32,12 +32,10 @@ * exynos specific framebuffer structure. * * @fb: drm framebuffer obejct. - * @buf_cnt: a buffer count to drm framebuffer. * @exynos_gem_obj: array of exynos specific gem object containing a gem object. */ struct exynos_drm_fb { struct drm_framebuffer fb; - unsigned int buf_cnt; struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER]; }; @@ -97,10 +95,6 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb, { struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); - /* This fb should have only one gem object. */ - if (WARN_ON(exynos_fb->buf_cnt != 1)) - return -EINVAL; - return drm_gem_handle_create(file_priv, &exynos_fb->exynos_gem_obj[0]->base, handle); } @@ -135,9 +129,6 @@ exynos_drm_framebuffer_init(struct drm_device *dev, if (!exynos_fb) return ERR_PTR(-ENOMEM); - exynos_fb->buf_cnt = count; - DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); - for (i = 0; i < count; i++) { ret = check_fb_gem_memory_type(dev, gem_obj[i]); if (ret < 0) -- cgit v1.2.3