Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54ac0784 authored by KyongHo Cho's avatar KyongHo Cho Committed by Greg Kroah-Hartman
Browse files

gpu: ion: several bugfixes and enhancements of ION



1. Verifying if the size of memory allocation in ion_alloc() is aligned
by PAGE_SIZE at least. If it is not, this change makes the size to be
aligned by PAGE_SIZE.

2. Unmaps all mappings to the kernel and DMA address spaces when
destroying ion_buffer in ion_buffer_destroy(). This prevents leaks in
those virtual address spaces.

3. Makes the return value of ion_alloc() to be explicit Linux error code
when it fails to allocate a buffer.

4. Makes ion_alloc() implementation simpler. Removes 'goto' statement and
relavant call to ion_buffer_put().

5. Checks if the task is valid before calling put_task_struct() due
to failure on creating a ion client in ion_client_create().

6. Returns error when buffer allocation requested by userspace is failed.

Signed-off-by: default avatarKyongHo Cho <pullip.cho@samsung.com>
[jstultz: modified patch to apply to staging directory]
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2991b7a0
Loading
Loading
Loading
Loading
+39 −13
Original line number Diff line number Diff line
@@ -166,6 +166,12 @@ static void ion_buffer_destroy(struct kref *kref)
	struct ion_buffer *buffer = container_of(kref, struct ion_buffer, ref);
	struct ion_device *dev = buffer->dev;

	if (WARN_ON(buffer->kmap_cnt > 0))
		buffer->heap->ops->unmap_kernel(buffer->heap, buffer);

	if (WARN_ON(buffer->dmap_cnt > 0))
		buffer->heap->ops->unmap_dma(buffer->heap, buffer);

	buffer->heap->ops->free(buffer);
	mutex_lock(&dev->lock);
	rb_erase(&buffer->node, &dev->buffers);
@@ -296,6 +302,11 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
	 * request of the caller allocate from it.  Repeat until allocate has
	 * succeeded or all heaps have been tried
	 */
	if (WARN_ON(!len))
		return ERR_PTR(-EINVAL);

	len = PAGE_ALIGN(len);

	mutex_lock(&dev->lock);
	for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) {
		struct ion_heap *heap = rb_entry(n, struct ion_heap, node);
@@ -311,27 +322,26 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len,
	}
	mutex_unlock(&dev->lock);

	if (IS_ERR_OR_NULL(buffer))
	if (buffer == NULL)
		return ERR_PTR(-ENODEV);

	if (IS_ERR(buffer))
		return ERR_PTR(PTR_ERR(buffer));

	handle = ion_handle_create(client, buffer);

	if (IS_ERR_OR_NULL(handle))
		goto end;

	/*
	 * ion_buffer_create will create a buffer with a ref_cnt of 1,
	 * and ion_handle_create will take a second reference, drop one here
	 */
	ion_buffer_put(buffer);

	if (!IS_ERR(handle)) {
		mutex_lock(&client->lock);
		ion_handle_add(client, handle);
		mutex_unlock(&client->lock);
	return handle;
	}

end:
	ion_buffer_put(buffer);
	return handle;
}

@@ -680,6 +690,7 @@ struct ion_client *ion_client_create(struct ion_device *dev,

	client = kzalloc(sizeof(struct ion_client), GFP_KERNEL);
	if (!client) {
		if (task)
			put_task_struct(current->group_leader);
		return ERR_PTR(-ENOMEM);
	}
@@ -798,6 +809,15 @@ static void ion_vma_open(struct vm_area_struct *vma)
		vma->vm_private_data = NULL;
		return;
	}

	if (!ion_handle_validate(client, handle)) {
		ion_client_put(client);
		vma->vm_private_data = NULL;
		return;
	}

	ion_handle_get(handle);

	pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
		 __func__, __LINE__,
		 atomic_read(&client->ref.refcount),
@@ -919,7 +939,7 @@ static int ion_ioctl_share(struct file *parent, struct ion_client *client,
	struct file *file;

	if (fd < 0)
		return -ENFILE;
		return fd;

	file = anon_inode_getfile("ion_share_fd", &ion_share_fops,
				  handle->buffer, O_RDWR);
@@ -948,8 +968,14 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
			return -EFAULT;
		data.handle = ion_alloc(client, data.len, data.align,
					     data.flags);
		if (copy_to_user((void __user *)arg, &data, sizeof(data)))

		if (IS_ERR(data.handle))
			return PTR_ERR(data.handle);

		if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
			ion_free(client, data.handle);
			return -EFAULT;
		}
		break;
	}
	case ION_IOC_FREE: