From patchwork Wed Mar 13 09:04:12 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inki Dae X-Patchwork-Id: 2262471 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 0E5FCDF215 for ; Wed, 13 Mar 2013 09:09:45 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C8461E6835 for ; Wed, 13 Mar 2013 02:09:44 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by gabe.freedesktop.org (Postfix) with ESMTP id 46787E682B for ; Wed, 13 Mar 2013 02:04:20 -0700 (PDT) Received: from epcpsbgr5.samsung.com (u145.gpu120.samsung.co.kr [203.254.230.145]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MJL00MULD6NFTV0@mailout1.samsung.com> for dri-devel@lists.freedesktop.org; Wed, 13 Mar 2013 18:04:13 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [203.254.230.45]) by epcpsbgr5.samsung.com (EPCPMTA) with SMTP id A3.AD.12250.D0140415; Wed, 13 Mar 2013 18:04:13 +0900 (KST) X-AuditID: cbfee691-b7f5f6d000002fda-a5-5140410dbe65 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 18.61.13494.C0140415; Wed, 13 Mar 2013 18:04:13 +0900 (KST) Received: from daeinki-desktop.10.32.193.11 ([10.90.8.53]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MJL00E7HD70BX10@mmp1.samsung.com> for dri-devel@lists.freedesktop.org; Wed, 13 Mar 2013 18:04:12 +0900 (KST) From: Inki Dae To: airlied@linux.ie, dri-devel@lists.freedesktop.org Subject: [PATCH 5/7] drm/exynos: Deal with g2d buffer info more efficiently Date: Wed, 13 Mar 2013 18:04:12 +0900 Message-id: <1363165452-7516-1-git-send-email-inki.dae@samsung.com> X-Mailer: git-send-email 1.7.4.1 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrPLMWRmVeSWpSXmKPExsVy+t8zXV1eR4dAg7UTuCyufH3P5sDocb/7 OFMAYxSXTUpqTmZZapG+XQJXxqcrV1kKTrpVPPg8g62B8ap5FyMnh4SAicSee39ZIWwxiQv3 1rN1MXJxCAksY5TYuG0fO0zRnd3r2CESixgl9i64DuWsY5I48OIfC0gVm4CqxMQV99lAbBEB U4mOSUtZQIqYBboZJZ4/gNghLOAtced+G1gRC1DD/6cdzCA2r4CzxOujk6HWKUgsuPcW7A4J gT1sEoe/v2GCaBCQ+Db5ENBUDqCErMSmA8wQ9ZISB1fcYJnAKLiAkWEVo2hqQXJBcVJ6kale cWJucWleul5yfu4mRkhgTdzBeP+A9SHGZKBxE5mlRJPzgYGZVxJvaGxmZGFqYmpsZG5pRpqw kjiveot1oJBAemJJanZqakFqUXxRaU5q8SFGJg5OqQbGskl9sS/nLIuMPmVl/+fvH5ms2LI6 jl/v5SSW7dL4HeAY0l7iWy+25LhXpgEbd77jM7VZ/5pVBSS2N7MKbUlpqmJcVZ9ose7xskcq EaqxjI3Tn6YUKWfwrbucGOP4se3VHNUzOxImK2TNE5jXevqg04KvKxrmsQTl1fc0BfGWPr4X EKx95qISS3FGoqEWc1FxIgDzku6NQgIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFuphkeLIzCtJLcpLzFFi42I5/e+xgC6vo0OgwfS9zBZXvr5nc2D0uN99 nCmAMaqB0SYjNTEltUghNS85PyUzL91WyTs43jne1MzAUNfQ0sJcSSEvMTfVVsnFJ0DXLTMH aKySQlliTilQKCCxuFhJ3w7ThNAQN10LmMYIXd+QILgeIwM0kLCOMePTlassBSfdKh58nsHW wHjVvIuRk0NCwETizu517BC2mMSFe+vZuhi5OIQEFjFK7F1wnR3CWcckceDFPxaQKjYBVYmJ K+6zgdgiAqYSHZOWsoAUMQt0M0o8f/CXFSQhLOAtced+G1gRC1DD/6cdzCA2r4CzxOujk6HW KUgsuPeWbQIj9wJGhlWMoqkFyQXFSem5RnrFibnFpXnpesn5uZsYwWH7THoH46oGi0OMAhyM Sjy8Emn2gUKsiWXFlbmHGCU4mJVEeL/ZOAQK8aYkVlalFuXHF5XmpBYfYkwG2j6RWUo0OR8Y U3kl8YbGJmZGlkZmxibmxsakCSuJ8x5stQ4UEkhPLEnNTk0tSC2C2cLEwSnVwGjg0ry3ba1l KJfvn1fJGfptG2tNlE8Gv7kw+djUjs+T/r03XLdy159dQgZl74s6bDza5RoSelfPf653wKnf baPA4Wuz043jt38+5LvIdGX35yUnYr8WL+PWfiEWelvF5CY/c7SQSZ3r5vbM9Bem3xU81tpM 2M+uUrn2o51fK+dHNn3tmK8bziixFGckGmoxFxUnAgC8mAX3nwIAAA== DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Cc: kyungmin.park@samsung.com, sw0312.kim@samsung.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org From: YoungJun Cho This patch adds g2d_buf_info structure and buffer relevant variables moves into the g2d_buf_info to manage g2d buffer information more efficiently. Signed-off-by: YoungJun Cho Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 169 +++++++++++++++++++++++-------- 1 files changed, 125 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index ce8e670..b7be3d4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -96,8 +96,6 @@ #define G2D_CMDLIST_POOL_SIZE (G2D_CMDLIST_SIZE * G2D_CMDLIST_NUM) #define G2D_CMDLIST_DATA_NUM (G2D_CMDLIST_SIZE / sizeof(u32) - 2) -#define MAX_BUF_ADDR_NR 6 - /* maximum buffer pool size of userptr is 64MB as default */ #define MAX_POOL (64 * 1024 * 1024) @@ -106,6 +104,17 @@ enum { BUF_TYPE_USERPTR, }; +enum g2d_reg_type { + REG_TYPE_NONE = -1, + REG_TYPE_SRC, + REG_TYPE_SRC_PLANE2, + REG_TYPE_DST, + REG_TYPE_DST_PLANE2, + REG_TYPE_PAT, + REG_TYPE_MSK, + MAX_REG_TYPE_NR +}; + /* cmdlist data structure */ struct g2d_cmdlist { u32 head; @@ -113,6 +122,22 @@ struct g2d_cmdlist { u32 last; /* last data offset */ }; +/* + * A structure of buffer information + * + * @map_nr: manages the number of mapped buffers + * @reg_types: stores regitster type in the order of requested command + * @handles: stores buffer handle in its reg_type position + * @types: stores buffer type in its reg_type position + * + */ +struct g2d_buf_info { + unsigned int map_nr; + enum g2d_reg_type reg_types[MAX_REG_TYPE_NR]; + unsigned long handles[MAX_REG_TYPE_NR]; + unsigned int types[MAX_REG_TYPE_NR]; +}; + struct drm_exynos_pending_g2d_event { struct drm_pending_event base; struct drm_exynos_g2d_event event; @@ -134,10 +159,8 @@ struct g2d_cmdlist_userptr { struct g2d_cmdlist_node { struct list_head list; struct g2d_cmdlist *cmdlist; - unsigned int map_nr; - unsigned long handles[MAX_BUF_ADDR_NR]; - unsigned int buf_type[MAX_BUF_ADDR_NR]; dma_addr_t dma_addr; + struct g2d_buf_info buf_info; struct drm_exynos_pending_g2d_event *event; }; @@ -185,7 +208,8 @@ static int g2d_init_cmdlist(struct g2d_data *g2d) struct device *dev = g2d->dev; struct g2d_cmdlist_node *node = g2d->cmdlist_node; struct exynos_drm_subdrv *subdrv = &g2d->subdrv; - int nr, ret; + struct g2d_buf_info *buf_info; + int nr, ret, i; init_dma_attrs(&g2d->cmdlist_dma_attrs); dma_set_attr(DMA_ATTR_WRITE_COMBINE, &g2d->cmdlist_dma_attrs); @@ -212,6 +236,10 @@ static int g2d_init_cmdlist(struct g2d_data *g2d) node[nr].dma_addr = g2d->cmdlist_pool + nr * G2D_CMDLIST_SIZE; + buf_info = &node[nr].buf_info; + for (i = 0; i < MAX_REG_TYPE_NR; i++) + buf_info->reg_types[i] = REG_TYPE_NONE; + list_add_tail(&node[nr].list, &g2d->free_cmdlist); } @@ -506,36 +534,78 @@ static void g2d_userptr_free_all(struct drm_device *drm_dev, g2d->current_pool = 0; } +static enum g2d_reg_type g2d_get_reg_type(int reg_offset) +{ + enum g2d_reg_type reg_type; + + switch (reg_offset) { + case G2D_SRC_BASE_ADDR: + reg_type = REG_TYPE_SRC; + break; + case G2D_SRC_PLANE2_BASE_ADDR: + reg_type = REG_TYPE_SRC_PLANE2; + break; + case G2D_DST_BASE_ADDR: + reg_type = REG_TYPE_DST; + break; + case G2D_DST_PLANE2_BASE_ADDR: + reg_type = REG_TYPE_DST_PLANE2; + break; + case G2D_PAT_BASE_ADDR: + reg_type = REG_TYPE_PAT; + break; + case G2D_MSK_BASE_ADDR: + reg_type = REG_TYPE_MSK; + break; + default: + reg_type = REG_TYPE_NONE; + DRM_ERROR("Unknown register offset![%d]\n", reg_offset); + break; + }; + + return reg_type; +} + static int g2d_map_cmdlist_gem(struct g2d_data *g2d, struct g2d_cmdlist_node *node, struct drm_device *drm_dev, struct drm_file *file) { struct g2d_cmdlist *cmdlist = node->cmdlist; - int i; + struct g2d_buf_info *buf_info = &node->buf_info; + int ret, i; - for (i = 0; i < node->map_nr; i++) { - int offset; + for (i = 0; i < buf_info->map_nr; i++) { + enum g2d_reg_type reg_type; + int reg_pos, reg_offset; unsigned long handle; dma_addr_t *addr; - offset = cmdlist->last - (i * 2 + 1); - handle = cmdlist->data[offset]; + reg_pos = cmdlist->last - 2 * (i + 1); + + reg_offset = cmdlist->data[reg_pos]; + handle = cmdlist->data[reg_pos + 1]; + + reg_type = g2d_get_reg_type(reg_offset); + if (reg_type == REG_TYPE_NONE) { + ret = -EFAULT; + goto err; + } - if (node->buf_type[i] == BUF_TYPE_GEM) { + if (buf_info->types[reg_type] == BUF_TYPE_GEM) { addr = exynos_drm_gem_get_dma_addr(drm_dev, handle, file); if (IS_ERR(addr)) { - node->map_nr = i; - return -EFAULT; + ret = -EFAULT; + goto err; } } else { struct drm_exynos_g2d_userptr g2d_userptr; if (copy_from_user(&g2d_userptr, (void __user *)handle, sizeof(struct drm_exynos_g2d_userptr))) { - node->map_nr = i; - return -EFAULT; + ret = -EFAULT; + goto err; } addr = g2d_userptr_get_dma_addr(drm_dev, @@ -544,16 +614,21 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d, file, &handle); if (IS_ERR(addr)) { - node->map_nr = i; - return -EFAULT; + ret = -EFAULT; + goto err; } } - cmdlist->data[offset] = *addr; - node->handles[i] = handle; + cmdlist->data[reg_pos + 1] = *addr; + buf_info->reg_types[i] = reg_type; + buf_info->handles[reg_type] = handle; } return 0; + +err: + buf_info->map_nr = i; + return ret; } static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, @@ -561,23 +636,30 @@ static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, struct drm_file *filp) { struct exynos_drm_subdrv *subdrv = &g2d->subdrv; + struct g2d_buf_info *buf_info = &node->buf_info; int i; - for (i = 0; i < node->map_nr; i++) { - unsigned long handle = node->handles[i]; + for (i = 0; i < buf_info->map_nr; i++) { + enum g2d_reg_type reg_type; + unsigned long handle; + + reg_type = buf_info->reg_types[i]; - if (node->buf_type[i] == BUF_TYPE_GEM) + handle = buf_info->handles[reg_type]; + + if (buf_info->types[reg_type] == BUF_TYPE_GEM) exynos_drm_gem_put_dma_addr(subdrv->drm_dev, handle, filp); else g2d_userptr_put_dma_addr(subdrv->drm_dev, handle, false); - node->handles[i] = 0; - node->buf_type[i] = 0; + buf_info->reg_types[i] = REG_TYPE_NONE; + buf_info->handles[reg_type] = 0; + buf_info->types[reg_type] = 0; } - node->map_nr = 0; + buf_info->map_nr = 0; } static void g2d_dma_start(struct g2d_data *g2d, @@ -719,25 +801,16 @@ static int g2d_check_reg_offset(struct device *dev, int nr, bool for_addr) { struct g2d_cmdlist *cmdlist = node->cmdlist; - int index, i; + int reg_pos, i; for (i = 0; i < nr; i++) { + struct g2d_buf_info *buf_info = &node->buf_info; + enum g2d_reg_type reg_type; int reg_offset; - index = cmdlist->last - 2 * (i + 1); - - if (for_addr) { - /* check userptr buffer type. */ - reg_offset = (cmdlist->data[index] & - ~0x7fffffff) >> 31; - if (reg_offset) { - node->buf_type[i] = BUF_TYPE_USERPTR; - cmdlist->data[index] &= ~G2D_BUF_USERPTR; - } - } - - reg_offset = cmdlist->data[index] & ~0xfffff000; + reg_pos = cmdlist->last - 2 * (i + 1); + reg_offset = cmdlist->data[reg_pos] & ~0xfffff000; if (reg_offset < G2D_VALID_START || reg_offset > G2D_VALID_END) goto err; if (reg_offset % 4) @@ -753,8 +826,16 @@ static int g2d_check_reg_offset(struct device *dev, if (!for_addr) goto err; - if (node->buf_type[i] != BUF_TYPE_USERPTR) - node->buf_type[i] = BUF_TYPE_GEM; + reg_type = g2d_get_reg_type(reg_offset); + if (reg_type == REG_TYPE_NONE) + goto err; + + /* check userptr buffer type. */ + if ((cmdlist->data[reg_pos] & ~0x7fffffff) >> 31) { + buf_info->types[reg_type] = BUF_TYPE_USERPTR; + cmdlist->data[reg_pos] &= ~G2D_BUF_USERPTR; + } else + buf_info->types[reg_type] = BUF_TYPE_GEM; break; default: if (for_addr) @@ -766,7 +847,7 @@ static int g2d_check_reg_offset(struct device *dev, return 0; err: - dev_err(dev, "Bad register offset: 0x%lx\n", cmdlist->data[index]); + dev_err(dev, "Bad register offset: 0x%lx\n", cmdlist->data[reg_pos]); return -EINVAL; } @@ -889,7 +970,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, if (ret < 0) goto err_free_event; - node->map_nr = req->cmd_buf_nr; + node->buf_info.map_nr = req->cmd_buf_nr; if (req->cmd_buf_nr) { struct drm_exynos_g2d_cmd *cmd_buf;