ge2d: fix ge2d buffer index error caused crash issue [2/2]
authorPengcheng Chen <pengcheng.chen@amlogic.com>
Thu, 14 Mar 2019 10:02:35 +0000 (18:02 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Wed, 20 Mar 2019 09:46:14 +0000 (01:46 -0800)
PD#SWPL-5685

Problem:
ge2d buffer index error when dma alloc called simultaneously

Solution:
add lock to ge2d buffer index

Verify:
verified by w400

Change-Id: I1efa4127fbcb939ade457a890769d59a146a0798
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c

index 2e8a8a7..9a6087a 100644 (file)
@@ -53,7 +53,8 @@ static void aml_dma_put(void *buf_priv)
        clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index);
        put_device(buf->dev);
        kfree(buf);
-       ge2d_log_dbg("ge2d aml_dma_put free!\n");
+       ge2d_log_dbg("ge2d free:aml_dma_buf=0x%p,buf->index=%d\n",
+               buf, buf->index);
 }
 
 static void *aml_dma_alloc(struct device *dev, unsigned long attrs,
@@ -88,8 +89,8 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs,
        buf->dma_dir = dma_dir;
 
        atomic_inc(&buf->refcount);
-       ge2d_log_dbg("aml_dma_alloc, refcont=%d\n",
-               atomic_read(&buf->refcount));
+       ge2d_log_dbg("aml_dma_buf=0x%p, refcont=%d\n",
+               buf, atomic_read(&buf->refcount));
 
        return buf;
 }
@@ -343,7 +344,11 @@ static int find_empty_dma_buffer(struct aml_dma_buffer *buffer)
 
 static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index)
 {
+       mutex_lock(&(buffer->lock));
+       buffer->gd_buffer[index].mem_priv = NULL;
+       buffer->gd_buffer[index].index = 0;
        buffer->gd_buffer[index].alloc = 0;
+       mutex_unlock(&(buffer->lock));
 }
 
 void *ge2d_dma_buffer_create(void)
@@ -373,6 +378,7 @@ int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer,
        struct device *dev,
        struct ge2d_dmabuf_req_s *ge2d_req_buf)
 {
+       struct aml_dma_buf *dma_buf;
        void *buf;
        unsigned int size;
        int index;
@@ -388,19 +394,23 @@ int ge2d_dma_buffer_alloc(struct aml_dma_buffer *buffer,
        if (size == 0)
                return (-EINVAL);
 
+       buf = aml_dma_alloc(dev, 0, size, ge2d_req_buf->dma_dir,
+               GFP_HIGHUSER | __GFP_ZERO);
+       if (!buf)
+               return (-ENOMEM);
+       dma_buf = (struct aml_dma_buf *)buf;
+       mutex_lock(&(buffer->lock));
        index = find_empty_dma_buffer(buffer);
        if ((index < 0) || (index >= AML_MAX_DMABUF)) {
                pr_err("no empty buffer found\n");
+               dma_free_attrs(dev, dma_buf->size, dma_buf->cookie,
+                              dma_buf->dma_addr,
+                              dma_buf->attrs);
+               mutex_unlock(&(buffer->lock));
                return (-ENOMEM);
        }
-
-       buf = aml_dma_alloc(dev, 0, size, ge2d_req_buf->dma_dir,
-               GFP_HIGHUSER | __GFP_ZERO);
-       if (!buf)
-               return (-ENOMEM);
        ((struct aml_dma_buf *)buf)->priv = buffer;
        ((struct aml_dma_buf *)buf)->index = index;
-       mutex_lock(&(buffer->lock));
        buffer->gd_buffer[index].mem_priv = buf;
        buffer->gd_buffer[index].index = index;
        buffer->gd_buffer[index].alloc = 1;
@@ -490,19 +500,19 @@ int ge2d_dma_buffer_map(struct aml_dma_cfg *cfg)
        dir = cfg->dir;
 
        dbuf = dma_buf_get(fd);
-       if (dbuf == NULL) {
+       if (IS_ERR(dbuf)) {
                pr_err("failed to get dma buffer");
                return -EINVAL;
        }
 
        d_att = dma_buf_attach(dbuf, dev);
-       if (d_att == NULL) {
+       if (IS_ERR(d_att)) {
                pr_err("failed to set dma attach");
                goto attach_err;
        }
 
        sg = dma_buf_map_attachment(d_att, dir);
-       if (sg == NULL) {
+       if (IS_ERR(sg)) {
                pr_err("failed to get dma sg");
                goto map_attach_err;
        }