From 303cb72aa4efd8b7f6b9f71cc4b61afe1ebc81c4 Mon Sep 17 00:00:00 2001 From: kfx Date: Thu, 19 Apr 2012 20:07:17 +0800 Subject: [PATCH] ion: Fix race condition with import and map_addr_list --- drivers/gpu/ion/ion.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c index 954a765a8db4..4053a0b35ba5 100755 --- a/drivers/gpu/ion/ion.c +++ b/drivers/gpu/ion/ion.c @@ -207,10 +207,8 @@ static void ion_handle_destroy(struct kref *kref) if (handle->map_cnt) unmap */ ion_buffer_put(handle->buffer); - mutex_lock(&handle->client->lock); if (!RB_EMPTY_NODE(&handle->node)) rb_erase(&handle->node, &handle->client->handles); - mutex_unlock(&handle->client->lock); kfree(handle); } @@ -345,13 +343,13 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) mutex_lock(&client->lock); valid_handle = ion_handle_validate(client, handle); - mutex_unlock(&client->lock); - if (!valid_handle) { + mutex_unlock(&client->lock); WARN("%s: invalid handle passed to free.\n", __func__); return; } ion_handle_put(handle); + mutex_unlock(&client->lock); } static void ion_client_get(struct ion_client *client); @@ -407,7 +405,9 @@ int ion_phys(struct ion_client *client, struct ion_handle *handle, return -ENODEV; } mutex_unlock(&client->lock); + mutex_lock(&buffer->lock); ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len); + mutex_unlock(&buffer->lock); return ret; } @@ -821,19 +821,23 @@ static void ion_vma_close(struct vm_area_struct *vma) atomic_read(&client->ref.refcount), atomic_read(&handle->ref.refcount), atomic_read(&buffer->ref.refcount)); + mutex_lock(&client->lock); ion_handle_put(handle); + mutex_unlock(&client->lock); ion_client_put(client); pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n", __func__, __LINE__, atomic_read(&client->ref.refcount), atomic_read(&handle->ref.refcount), atomic_read(&buffer->ref.refcount)); + mutex_lock(&buffer->lock); list_for_each_entry(map, &buffer->map_addr, list) if(map->vaddr == vma->vm_start){ list_del(&map->list); kfree(map); break; } + mutex_unlock(&buffer->lock); } static struct vm_operations_struct ion_vm_ops = { @@ -903,7 +907,9 @@ static int ion_share_mmap(struct file *file, struct vm_area_struct *vma) goto err1; map->vaddr = vma->vm_start; map->size = buffer->size; + mutex_lock(&buffer->lock); list_add_tail(&map->list, &buffer->map_addr); + mutex_unlock(&buffer->lock); pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n", __func__, __LINE__, atomic_read(&client->ref.refcount), @@ -914,7 +920,9 @@ static int ion_share_mmap(struct file *file, struct vm_area_struct *vma) err1: /* drop the reference to the handle */ + mutex_lock(&client->lock); ion_handle_put(handle); + mutex_unlock(&client->lock); err: /* drop the reference to the client */ ion_client_put(client); @@ -946,9 +954,11 @@ static long ion_share_ioctl(struct file *filp, unsigned int cmd, unsigned long a sizeof(struct ion_pmem_region))) return -EFAULT; if(!(region.offset & 0xf0000000)) { + mutex_lock(&buffer->lock); list_for_each_entry(map, &buffer->map_addr, list) { dmac_flush_range((void *)map->vaddr, (void *)(map->vaddr + map->size)); } + mutex_unlock(&buffer->lock); }else { dmac_flush_range((void *)region.offset, (void *)(region.offset + region.len)); } @@ -1009,7 +1019,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) data.flags); if (IS_ERR_OR_NULL(data.handle)) { pr_err("%s: alloc 0x%x bytes failed\n", __func__, data.len); - return -ENOMEM; + return -ENOMEM; } if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; @@ -1040,8 +1050,8 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EFAULT; mutex_lock(&client->lock); if (!ion_handle_validate(client, data.handle)) { - pr_err("%s: invalid handle passed to share ioctl.\n", - __func__); + pr_err("%s: invalid handle(%p) passed to share ioctl\n", + __func__, data.handle); mutex_unlock(&client->lock); return -EINVAL; } @@ -1109,7 +1119,9 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if(ion_handle_validate(client, data.handle)){ buffer = data.handle->buffer; if(buffer->heap->ops->cache_op){ + mutex_lock(&buffer->lock); buffer->heap->ops->cache_op(buffer->heap, buffer, data.virt, data.type); + mutex_unlock(&buffer->lock); err = 0; } } -- 2.34.1