diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/gpu/ion')
-rw-r--r-- | ANDROID_3.4.5/drivers/gpu/ion/Kconfig | 13 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/gpu/ion/Makefile | 3 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/gpu/ion/ion.c | 1358 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/gpu/ion/ion_carveout_heap.c | 182 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/gpu/ion/ion_heap.c | 72 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/gpu/ion/ion_page_pool.c | 281 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/gpu/ion/ion_priv.h | 257 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/gpu/ion/ion_system_heap.c | 492 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/gpu/ion/ion_system_mapper.c | 114 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/gpu/ion/tegra/Makefile | 1 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/gpu/ion/tegra/tegra_ion.c | 96 |
11 files changed, 0 insertions, 2869 deletions
diff --git a/ANDROID_3.4.5/drivers/gpu/ion/Kconfig b/ANDROID_3.4.5/drivers/gpu/ion/Kconfig deleted file mode 100644 index b5bfdb47..00000000 --- a/ANDROID_3.4.5/drivers/gpu/ion/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -menuconfig ION - tristate "Ion Memory Manager" - select GENERIC_ALLOCATOR - select DMA_SHARED_BUFFER - help - Chose this option to enable the ION Memory Manager. - -config ION_TEGRA - tristate "Ion for Tegra" - depends on ARCH_TEGRA && ION - help - Choose this option if you wish to use ion on an nVidia Tegra. - diff --git a/ANDROID_3.4.5/drivers/gpu/ion/Makefile b/ANDROID_3.4.5/drivers/gpu/ion/Makefile deleted file mode 100644 index d1ddebb7..00000000 --- a/ANDROID_3.4.5/drivers/gpu/ion/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \ - ion_carveout_heap.o -obj-$(CONFIG_ION_TEGRA) += tegra/ diff --git a/ANDROID_3.4.5/drivers/gpu/ion/ion.c b/ANDROID_3.4.5/drivers/gpu/ion/ion.c deleted file mode 100644 index 6aa817aa..00000000 --- a/ANDROID_3.4.5/drivers/gpu/ion/ion.c +++ /dev/null @@ -1,1358 +0,0 @@ -/* - * drivers/gpu/ion/ion.c - * - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/device.h> -#include <linux/file.h> -#include <linux/fs.h> -#include <linux/anon_inodes.h> -#include <linux/ion.h> -#include <linux/list.h> -#include <linux/memblock.h> -#include <linux/miscdevice.h> -#include <linux/export.h> -#include <linux/mm.h> -#include <linux/mm_types.h> -#include <linux/rbtree.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/seq_file.h> -#include <linux/uaccess.h> -#include <linux/debugfs.h> -#include <linux/dma-buf.h> - -#include "ion_priv.h" - -/** - * struct ion_device - the metadata of the ion device node - * @dev: the actual misc device - * @buffers: an rb tree of all the existing buffers - * @buffer_lock: lock protecting the tree of buffers - * @lock: rwsem protecting the tree of heaps and clients - * @heaps: list of all the heaps in the system - * @user_clients: list of all the clients created from userspace - */ -struct ion_device { - struct miscdevice dev; - struct rb_root buffers; - struct mutex buffer_lock; - struct rw_semaphore lock; - struct rb_root heaps; - long (*custom_ioctl) (struct ion_client *client, unsigned int cmd, - unsigned long arg); - struct rb_root clients; - struct dentry *debug_root; -}; - -/** - * struct ion_client - a process/hw block local address space - * @node: node in the tree of all clients - * @dev: backpointer to ion device - * @handles: an rb tree of all the handles in this client - * @lock: lock protecting the tree of handles - * @heap_mask: mask of all supported heaps - * @name: used for debugging - * @task: used for debugging - * - * A client represents a list of buffers this client may access. - * The mutex stored here is used to protect both handles tree - * as well as the handles themselves, and should be held while modifying either. - */ -struct ion_client { - struct rb_node node; - struct ion_device *dev; - struct rb_root handles; - struct mutex lock; - unsigned int heap_mask; - const char *name; - struct task_struct *task; - pid_t pid; - struct dentry *debug_root; -}; - -/** - * ion_handle - a client local reference to a buffer - * @ref: reference count - * @client: back pointer to the client the buffer resides in - * @buffer: pointer to the buffer - * @node: node in the client's handle rbtree - * @kmap_cnt: count of times this client has mapped to kernel - * @dmap_cnt: count of times this client has mapped for dma - * - * Modifications to node, map_cnt or mapping should be protected by the - * lock in the client. Other fields are never changed after initialization. - */ -struct ion_handle { - struct kref ref; - struct ion_client *client; - struct ion_buffer *buffer; - struct rb_node node; - unsigned int kmap_cnt; -}; - -bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer) -{ - return ((buffer->flags & ION_FLAG_CACHED) && - !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)); -} - -bool ion_buffer_cached(struct ion_buffer *buffer) -{ - return !!(buffer->flags & ION_FLAG_CACHED); -} - -/* this function should only be called while dev->lock is held */ -static void ion_buffer_add(struct ion_device *dev, - struct ion_buffer *buffer) -{ - struct rb_node **p = &dev->buffers.rb_node; - struct rb_node *parent = NULL; - struct ion_buffer *entry; - - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_buffer, node); - - if (buffer < entry) { - p = &(*p)->rb_left; - } else if (buffer > entry) { - p = &(*p)->rb_right; - } else { - pr_err("%s: buffer already found.", __func__); - BUG(); - } - } - - rb_link_node(&buffer->node, parent, p); - rb_insert_color(&buffer->node, &dev->buffers); -} - -static int ion_buffer_alloc_dirty(struct ion_buffer *buffer); - -/* this function should only be called while dev->lock is held */ -static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, - struct ion_device *dev, - unsigned long len, - unsigned long align, - unsigned long flags) -{ - struct ion_buffer *buffer; - struct sg_table *table; - struct scatterlist *sg; - int i, ret; - - buffer = kzalloc(sizeof(struct ion_buffer), GFP_KERNEL); - if (!buffer) - return ERR_PTR(-ENOMEM); - - buffer->heap = heap; - buffer->flags = flags; - kref_init(&buffer->ref); - - ret = heap->ops->allocate(heap, buffer, len, align, flags); - if (ret) { - kfree(buffer); - return ERR_PTR(ret); - } - - buffer->dev = dev; - buffer->size = len; - - table = heap->ops->map_dma(heap, buffer); - if (IS_ERR_OR_NULL(table)) { - heap->ops->free(buffer); - kfree(buffer); - return ERR_PTR(PTR_ERR(table)); - } - buffer->sg_table = table; - if (ion_buffer_fault_user_mappings(buffer)) { - for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, - i) { - if (sg_dma_len(sg) == PAGE_SIZE) - continue; - pr_err("%s: cached mappings that will be faulted in " - "must have pagewise sg_lists\n", __func__); - ret = -EINVAL; - goto err; - } - - ret = ion_buffer_alloc_dirty(buffer); - if (ret) - goto err; - } - - buffer->dev = dev; - buffer->size = len; - INIT_LIST_HEAD(&buffer->vmas); - mutex_init(&buffer->lock); - /* this will set up dma addresses for the sglist -- it is not - technically correct as per the dma api -- a specific - device isn't really taking ownership here. However, in practice on - our systems the only dma_address space is physical addresses. - Additionally, we can't afford the overhead of invalidating every - allocation via dma_map_sg. The implicit contract here is that - memory comming from the heaps is ready for dma, ie if it has a - cached mapping that mapping has been invalidated */ - for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) - sg_dma_address(sg) = sg_phys(sg); - mutex_lock(&dev->buffer_lock); - ion_buffer_add(dev, buffer); - mutex_unlock(&dev->buffer_lock); - return buffer; - -err: - heap->ops->unmap_dma(heap, buffer); - heap->ops->free(buffer); - kfree(buffer); - return ERR_PTR(ret); -} - -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); - buffer->heap->ops->unmap_dma(buffer->heap, buffer); - buffer->heap->ops->free(buffer); - mutex_lock(&dev->buffer_lock); - rb_erase(&buffer->node, &dev->buffers); - mutex_unlock(&dev->buffer_lock); - if (buffer->flags & ION_FLAG_CACHED) - kfree(buffer->dirty); - kfree(buffer); -} - -static void ion_buffer_get(struct ion_buffer *buffer) -{ - kref_get(&buffer->ref); -} - -static int ion_buffer_put(struct ion_buffer *buffer) -{ - return kref_put(&buffer->ref, ion_buffer_destroy); -} - -static void ion_buffer_add_to_handle(struct ion_buffer *buffer) -{ - mutex_lock(&buffer->lock); - buffer->handle_count++; - mutex_unlock(&buffer->lock); -} - -static void ion_buffer_remove_from_handle(struct ion_buffer *buffer) -{ - /* - * when a buffer is removed from a handle, if it is not in - * any other handles, copy the taskcomm and the pid of the - * process it's being removed from into the buffer. At this - * point there will be no way to track what processes this buffer is - * being used by, it only exists as a dma_buf file descriptor. - * The taskcomm and pid can provide a debug hint as to where this fd - * is in the system - */ - mutex_lock(&buffer->lock); - buffer->handle_count--; - BUG_ON(buffer->handle_count < 0); - if (!buffer->handle_count) { - struct task_struct *task; - - task = current->group_leader; - get_task_comm(buffer->task_comm, task); - buffer->pid = task_pid_nr(task); - } - mutex_unlock(&buffer->lock); -} - -static struct ion_handle *ion_handle_create(struct ion_client *client, - struct ion_buffer *buffer) -{ - struct ion_handle *handle; - - handle = kzalloc(sizeof(struct ion_handle), GFP_KERNEL); - if (!handle) - return ERR_PTR(-ENOMEM); - kref_init(&handle->ref); - rb_init_node(&handle->node); - handle->client = client; - ion_buffer_get(buffer); - ion_buffer_add_to_handle(buffer); - handle->buffer = buffer; - - return handle; -} - -static void ion_handle_kmap_put(struct ion_handle *); - -static void ion_handle_destroy(struct kref *kref) -{ - struct ion_handle *handle = container_of(kref, struct ion_handle, ref); - struct ion_client *client = handle->client; - struct ion_buffer *buffer = handle->buffer; - - mutex_lock(&buffer->lock); - while (handle->kmap_cnt) - ion_handle_kmap_put(handle); - mutex_unlock(&buffer->lock); - - if (!RB_EMPTY_NODE(&handle->node)) - rb_erase(&handle->node, &client->handles); - - ion_buffer_remove_from_handle(buffer); - ion_buffer_put(buffer); - - kfree(handle); -} - -struct ion_buffer *ion_handle_buffer(struct ion_handle *handle) -{ - return handle->buffer; -} - -static void ion_handle_get(struct ion_handle *handle) -{ - kref_get(&handle->ref); -} - -static int ion_handle_put(struct ion_handle *handle) -{ - return kref_put(&handle->ref, ion_handle_destroy); -} - -static struct ion_handle *ion_handle_lookup(struct ion_client *client, - struct ion_buffer *buffer) -{ - struct rb_node *n; - - for (n = rb_first(&client->handles); n; n = rb_next(n)) { - struct ion_handle *handle = rb_entry(n, struct ion_handle, - node); - if (handle->buffer == buffer) - return handle; - } - return NULL; -} - -static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle) -{ - struct rb_node *n = client->handles.rb_node; - - while (n) { - struct ion_handle *handle_node = rb_entry(n, struct ion_handle, - node); - if (handle < handle_node) - n = n->rb_left; - else if (handle > handle_node) - n = n->rb_right; - else - return true; - } - return false; -} - -static void ion_handle_add(struct ion_client *client, struct ion_handle *handle) -{ - struct rb_node **p = &client->handles.rb_node; - struct rb_node *parent = NULL; - struct ion_handle *entry; - - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_handle, node); - - if (handle < entry) - p = &(*p)->rb_left; - else if (handle > entry) - p = &(*p)->rb_right; - else - WARN(1, "%s: buffer already found.", __func__); - } - - rb_link_node(&handle->node, parent, p); - rb_insert_color(&handle->node, &client->handles); -} - -struct ion_handle *ion_alloc(struct ion_client *client, size_t len, - size_t align, unsigned int heap_mask, - unsigned int flags) -{ - struct rb_node *n; - struct ion_handle *handle; - struct ion_device *dev = client->dev; - struct ion_buffer *buffer = NULL; - - pr_debug("%s: len %d align %d heap_mask %u flags %x\n", __func__, len, - align, heap_mask, flags); - /* - * traverse the list of heaps available in this system in priority - * order. If the heap type is supported by the client, and matches the - * 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); - - down_read(&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); - /* if the client doesn't support this heap type */ - if (!((1 << heap->type) & client->heap_mask)) - continue; - /* if the caller didn't specify this heap type */ - if (!((1 << heap->id) & heap_mask)) - continue; - buffer = ion_buffer_create(heap, dev, len, align, flags); - if (!IS_ERR_OR_NULL(buffer)) - break; - } - up_read(&dev->lock); - - if (buffer == NULL) - return ERR_PTR(-ENODEV); - - if (IS_ERR(buffer)) - return ERR_PTR(PTR_ERR(buffer)); - - handle = ion_handle_create(client, buffer); - - /* - * 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; -} -EXPORT_SYMBOL(ion_alloc); - -void ion_free(struct ion_client *client, struct ion_handle *handle) -{ - bool valid_handle; - - BUG_ON(client != handle->client); - - mutex_lock(&client->lock); - valid_handle = ion_handle_validate(client, handle); - - if (!valid_handle) { - WARN(1, "%s: invalid handle passed to free.\n", __func__); - mutex_unlock(&client->lock); - return; - } - ion_handle_put(handle); - mutex_unlock(&client->lock); -} -EXPORT_SYMBOL(ion_free); - -int ion_phys(struct ion_client *client, struct ion_handle *handle, - ion_phys_addr_t *addr, size_t *len) -{ - struct ion_buffer *buffer; - int ret; - - mutex_lock(&client->lock); - if (!ion_handle_validate(client, handle)) { - mutex_unlock(&client->lock); - return -EINVAL; - } - - buffer = handle->buffer; - - if (!buffer->heap->ops->phys) { - pr_err("%s: ion_phys is not implemented by this heap.\n", - __func__); - mutex_unlock(&client->lock); - return -ENODEV; - } - mutex_unlock(&client->lock); - ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len); - return ret; -} -EXPORT_SYMBOL(ion_phys); - -static void *ion_buffer_kmap_get(struct ion_buffer *buffer) -{ - void *vaddr; - - if (buffer->kmap_cnt) { - buffer->kmap_cnt++; - return buffer->vaddr; - } - vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); - if (IS_ERR_OR_NULL(vaddr)) - return vaddr; - buffer->vaddr = vaddr; - buffer->kmap_cnt++; - return vaddr; -} - -static void *ion_handle_kmap_get(struct ion_handle *handle) -{ - struct ion_buffer *buffer = handle->buffer; - void *vaddr; - - if (handle->kmap_cnt) { - handle->kmap_cnt++; - return buffer->vaddr; - } - vaddr = ion_buffer_kmap_get(buffer); - if (IS_ERR_OR_NULL(vaddr)) - return vaddr; - handle->kmap_cnt++; - return vaddr; -} - -static void ion_buffer_kmap_put(struct ion_buffer *buffer) -{ - buffer->kmap_cnt--; - if (!buffer->kmap_cnt) { - buffer->heap->ops->unmap_kernel(buffer->heap, buffer); - buffer->vaddr = NULL; - } -} - -static void ion_handle_kmap_put(struct ion_handle *handle) -{ - struct ion_buffer *buffer = handle->buffer; - - handle->kmap_cnt--; - if (!handle->kmap_cnt) - ion_buffer_kmap_put(buffer); -} - -void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) -{ - struct ion_buffer *buffer; - void *vaddr; - - mutex_lock(&client->lock); - if (!ion_handle_validate(client, handle)) { - pr_err("%s: invalid handle passed to map_kernel.\n", - __func__); - mutex_unlock(&client->lock); - return ERR_PTR(-EINVAL); - } - - buffer = handle->buffer; - - if (!handle->buffer->heap->ops->map_kernel) { - pr_err("%s: map_kernel is not implemented by this heap.\n", - __func__); - mutex_unlock(&client->lock); - return ERR_PTR(-ENODEV); - } - - mutex_lock(&buffer->lock); - vaddr = ion_handle_kmap_get(handle); - mutex_unlock(&buffer->lock); - mutex_unlock(&client->lock); - return vaddr; -} -EXPORT_SYMBOL(ion_map_kernel); - -void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) -{ - struct ion_buffer *buffer; - - mutex_lock(&client->lock); - buffer = handle->buffer; - mutex_lock(&buffer->lock); - ion_handle_kmap_put(handle); - mutex_unlock(&buffer->lock); - mutex_unlock(&client->lock); -} -EXPORT_SYMBOL(ion_unmap_kernel); - -static int ion_debug_client_show(struct seq_file *s, void *unused) -{ - struct ion_client *client = s->private; - struct rb_node *n; - size_t sizes[ION_NUM_HEAPS] = {0}; - const char *names[ION_NUM_HEAPS] = {0}; - int i; - - mutex_lock(&client->lock); - for (n = rb_first(&client->handles); n; n = rb_next(n)) { - struct ion_handle *handle = rb_entry(n, struct ion_handle, - node); - enum ion_heap_type type = handle->buffer->heap->type; - - if (!names[type]) - names[type] = handle->buffer->heap->name; - sizes[type] += handle->buffer->size; - } - mutex_unlock(&client->lock); - - seq_printf(s, "%16.16s: %16.16s\n", "heap_name", "size_in_bytes"); - for (i = 0; i < ION_NUM_HEAPS; i++) { - if (!names[i]) - continue; - seq_printf(s, "%16.16s: %16u\n", names[i], sizes[i]); - } - return 0; -} - -static int ion_debug_client_open(struct inode *inode, struct file *file) -{ - return single_open(file, ion_debug_client_show, inode->i_private); -} - -static const struct file_operations debug_client_fops = { - .open = ion_debug_client_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -struct ion_client *ion_client_create(struct ion_device *dev, - unsigned int heap_mask, - const char *name) -{ - struct ion_client *client; - struct task_struct *task; - struct rb_node **p; - struct rb_node *parent = NULL; - struct ion_client *entry; - char debug_name[64]; - pid_t pid; - - get_task_struct(current->group_leader); - task_lock(current->group_leader); - pid = task_pid_nr(current->group_leader); - /* don't bother to store task struct for kernel threads, - they can't be killed anyway */ - if (current->group_leader->flags & PF_KTHREAD) { - put_task_struct(current->group_leader); - task = NULL; - } else { - task = current->group_leader; - } - task_unlock(current->group_leader); - - client = kzalloc(sizeof(struct ion_client), GFP_KERNEL); - if (!client) { - if (task) - put_task_struct(current->group_leader); - return ERR_PTR(-ENOMEM); - } - - client->dev = dev; - client->handles = RB_ROOT; - mutex_init(&client->lock); - client->name = name; - client->heap_mask = heap_mask; - client->task = task; - client->pid = pid; - - down_write(&dev->lock); - p = &dev->clients.rb_node; - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_client, node); - - if (client < entry) - p = &(*p)->rb_left; - else if (client > entry) - p = &(*p)->rb_right; - } - rb_link_node(&client->node, parent, p); - rb_insert_color(&client->node, &dev->clients); - - snprintf(debug_name, 64, "%u", client->pid); - client->debug_root = debugfs_create_file(debug_name, 0664, - dev->debug_root, client, - &debug_client_fops); - up_write(&dev->lock); - - return client; -} - -void ion_client_destroy(struct ion_client *client) -{ - struct ion_device *dev = client->dev; - struct rb_node *n; - - pr_debug("%s: %d\n", __func__, __LINE__); - while ((n = rb_first(&client->handles))) { - struct ion_handle *handle = rb_entry(n, struct ion_handle, - node); - ion_handle_destroy(&handle->ref); - } - down_write(&dev->lock); - if (client->task) - put_task_struct(client->task); - rb_erase(&client->node, &dev->clients); - debugfs_remove_recursive(client->debug_root); - up_write(&dev->lock); - - kfree(client); -} -EXPORT_SYMBOL(ion_client_destroy); - -struct sg_table *ion_sg_table(struct ion_client *client, - struct ion_handle *handle) -{ - struct ion_buffer *buffer; - struct sg_table *table; - - mutex_lock(&client->lock); - if (!ion_handle_validate(client, handle)) { - pr_err("%s: invalid handle passed to map_dma.\n", - __func__); - mutex_unlock(&client->lock); - return ERR_PTR(-EINVAL); - } - buffer = handle->buffer; - table = buffer->sg_table; - mutex_unlock(&client->lock); - return table; -} -EXPORT_SYMBOL(ion_sg_table); - -static void ion_buffer_sync_for_device(struct ion_buffer *buffer, - struct device *dev, - enum dma_data_direction direction); - -static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, - enum dma_data_direction direction) -{ - struct dma_buf *dmabuf = attachment->dmabuf; - struct ion_buffer *buffer = dmabuf->priv; - - ion_buffer_sync_for_device(buffer, attachment->dev, direction); - return buffer->sg_table; -} - -static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, - struct sg_table *table, - enum dma_data_direction direction) -{ -} - -static int ion_buffer_alloc_dirty(struct ion_buffer *buffer) -{ - unsigned long pages = buffer->sg_table->nents; - unsigned long length = (pages + BITS_PER_LONG - 1)/BITS_PER_LONG; - - buffer->dirty = kzalloc(length * sizeof(unsigned long), GFP_KERNEL); - if (!buffer->dirty) - return -ENOMEM; - return 0; -} - -struct ion_vma_list { - struct list_head list; - struct vm_area_struct *vma; -}; - -static void ion_buffer_sync_for_device(struct ion_buffer *buffer, - struct device *dev, - enum dma_data_direction dir) -{ - struct scatterlist *sg; - int i; - struct ion_vma_list *vma_list; - - pr_debug("%s: syncing for device %s\n", __func__, - dev ? dev_name(dev) : "null"); - - if (!ion_buffer_fault_user_mappings(buffer)) - return; - - mutex_lock(&buffer->lock); - for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { - if (!test_bit(i, buffer->dirty)) - continue; - dma_sync_sg_for_device(dev, sg, 1, dir); - clear_bit(i, buffer->dirty); - } - list_for_each_entry(vma_list, &buffer->vmas, list) { - struct vm_area_struct *vma = vma_list->vma; - - zap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, - NULL); - } - mutex_unlock(&buffer->lock); -} - -int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct ion_buffer *buffer = vma->vm_private_data; - struct scatterlist *sg; - int i; - - mutex_lock(&buffer->lock); - set_bit(vmf->pgoff, buffer->dirty); - - for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { - if (i != vmf->pgoff) - continue; - dma_sync_sg_for_cpu(NULL, sg, 1, DMA_BIDIRECTIONAL); - vm_insert_page(vma, (unsigned long)vmf->virtual_address, - sg_page(sg)); - break; - } - mutex_unlock(&buffer->lock); - return VM_FAULT_NOPAGE; -} - -static void ion_vm_open(struct vm_area_struct *vma) -{ - struct ion_buffer *buffer = vma->vm_private_data; - struct ion_vma_list *vma_list; - - vma_list = kmalloc(sizeof(struct ion_vma_list), GFP_KERNEL); - if (!vma_list) - return; - vma_list->vma = vma; - mutex_lock(&buffer->lock); - list_add(&vma_list->list, &buffer->vmas); - mutex_unlock(&buffer->lock); - pr_debug("%s: adding %p\n", __func__, vma); -} - -static void ion_vm_close(struct vm_area_struct *vma) -{ - struct ion_buffer *buffer = vma->vm_private_data; - struct ion_vma_list *vma_list, *tmp; - - pr_debug("%s\n", __func__); - mutex_lock(&buffer->lock); - list_for_each_entry_safe(vma_list, tmp, &buffer->vmas, list) { - if (vma_list->vma != vma) - continue; - list_del(&vma_list->list); - kfree(vma_list); - pr_debug("%s: deleting %p\n", __func__, vma); - break; - } - mutex_unlock(&buffer->lock); -} - -struct vm_operations_struct ion_vma_ops = { - .open = ion_vm_open, - .close = ion_vm_close, - .fault = ion_vm_fault, -}; - -static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) -{ - struct ion_buffer *buffer = dmabuf->priv; - int ret = 0; - - if (!buffer->heap->ops->map_user) { - pr_err("%s: this heap does not define a method for mapping " - "to userspace\n", __func__); - return -EINVAL; - } - - if (ion_buffer_fault_user_mappings(buffer)) { - vma->vm_private_data = buffer; - vma->vm_ops = &ion_vma_ops; - ion_vm_open(vma); - return 0; - } - - if (!(buffer->flags & ION_FLAG_CACHED)) - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - - mutex_lock(&buffer->lock); - /* now map it to userspace */ - ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma); - mutex_unlock(&buffer->lock); - - if (ret) - pr_err("%s: failure mapping buffer to userspace\n", - __func__); - - return ret; -} - -static void ion_dma_buf_release(struct dma_buf *dmabuf) -{ - struct ion_buffer *buffer = dmabuf->priv; - ion_buffer_put(buffer); -} - -static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) -{ - struct ion_buffer *buffer = dmabuf->priv; - return buffer->vaddr + offset * PAGE_SIZE; -} - -static void ion_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset, - void *ptr) -{ - return; -} - -static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start, - size_t len, - enum dma_data_direction direction) -{ - struct ion_buffer *buffer = dmabuf->priv; - void *vaddr; - - if (!buffer->heap->ops->map_kernel) { - pr_err("%s: map kernel is not implemented by this heap.\n", - __func__); - return -ENODEV; - } - - mutex_lock(&buffer->lock); - vaddr = ion_buffer_kmap_get(buffer); - mutex_unlock(&buffer->lock); - if (IS_ERR(vaddr)) - return PTR_ERR(vaddr); - if (!vaddr) - return -ENOMEM; - return 0; -} - -static void ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start, - size_t len, - enum dma_data_direction direction) -{ - struct ion_buffer *buffer = dmabuf->priv; - - mutex_lock(&buffer->lock); - ion_buffer_kmap_put(buffer); - mutex_unlock(&buffer->lock); -} - -struct dma_buf_ops dma_buf_ops = { - .map_dma_buf = ion_map_dma_buf, - .unmap_dma_buf = ion_unmap_dma_buf, - .mmap = ion_mmap, - .release = ion_dma_buf_release, - .begin_cpu_access = ion_dma_buf_begin_cpu_access, - .end_cpu_access = ion_dma_buf_end_cpu_access, - .kmap_atomic = ion_dma_buf_kmap, - .kunmap_atomic = ion_dma_buf_kunmap, - .kmap = ion_dma_buf_kmap, - .kunmap = ion_dma_buf_kunmap, -}; - -int ion_share_dma_buf(struct ion_client *client, struct ion_handle *handle) -{ - struct ion_buffer *buffer; - struct dma_buf *dmabuf; - bool valid_handle; - int fd; - - mutex_lock(&client->lock); - valid_handle = ion_handle_validate(client, handle); - mutex_unlock(&client->lock); - if (!valid_handle) { - WARN(1, "%s: invalid handle passed to share.\n", __func__); - return -EINVAL; - } - - buffer = handle->buffer; - ion_buffer_get(buffer); - dmabuf = dma_buf_export(buffer, &dma_buf_ops, buffer->size, O_RDWR); - if (IS_ERR(dmabuf)) { - ion_buffer_put(buffer); - return PTR_ERR(dmabuf); - } - fd = dma_buf_fd(dmabuf, O_CLOEXEC); - if (fd < 0) - dma_buf_put(dmabuf); - - return fd; -} -EXPORT_SYMBOL(ion_share_dma_buf); - -struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) -{ - struct dma_buf *dmabuf; - struct ion_buffer *buffer; - struct ion_handle *handle; - - dmabuf = dma_buf_get(fd); - if (IS_ERR_OR_NULL(dmabuf)) - return ERR_PTR(PTR_ERR(dmabuf)); - /* if this memory came from ion */ - - if (dmabuf->ops != &dma_buf_ops) { - pr_err("%s: can not import dmabuf from another exporter\n", - __func__); - dma_buf_put(dmabuf); - return ERR_PTR(-EINVAL); - } - buffer = dmabuf->priv; - - mutex_lock(&client->lock); - /* if a handle exists for this buffer just take a reference to it */ - handle = ion_handle_lookup(client, buffer); - if (!IS_ERR_OR_NULL(handle)) { - ion_handle_get(handle); - goto end; - } - handle = ion_handle_create(client, buffer); - if (IS_ERR_OR_NULL(handle)) - goto end; - ion_handle_add(client, handle); -end: - mutex_unlock(&client->lock); - dma_buf_put(dmabuf); - return handle; -} -EXPORT_SYMBOL(ion_import_dma_buf); - -static int ion_sync_for_device(struct ion_client *client, int fd) -{ - struct dma_buf *dmabuf; - struct ion_buffer *buffer; - - dmabuf = dma_buf_get(fd); - if (IS_ERR_OR_NULL(dmabuf)) - return PTR_ERR(dmabuf); - - /* if this memory came from ion */ - if (dmabuf->ops != &dma_buf_ops) { - pr_err("%s: can not sync dmabuf from another exporter\n", - __func__); - dma_buf_put(dmabuf); - return -EINVAL; - } - buffer = dmabuf->priv; - - dma_sync_sg_for_device(NULL, buffer->sg_table->sgl, - buffer->sg_table->nents, DMA_BIDIRECTIONAL); - dma_buf_put(dmabuf); - return 0; -} - -static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct ion_client *client = filp->private_data; - - switch (cmd) { - case ION_IOC_ALLOC: - { - struct ion_allocation_data data; - - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) - return -EFAULT; - data.handle = ion_alloc(client, data.len, data.align, - data.heap_mask, data.flags); - - 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: - { - struct ion_handle_data data; - bool valid; - - if (copy_from_user(&data, (void __user *)arg, - sizeof(struct ion_handle_data))) - return -EFAULT; - mutex_lock(&client->lock); - valid = ion_handle_validate(client, data.handle); - mutex_unlock(&client->lock); - if (!valid) - return -EINVAL; - ion_free(client, data.handle); - break; - } - case ION_IOC_SHARE: - { - struct ion_fd_data data; - - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) - return -EFAULT; - data.fd = ion_share_dma_buf(client, data.handle); - if (copy_to_user((void __user *)arg, &data, sizeof(data))) - return -EFAULT; - if (data.fd < 0) - return data.fd; - break; - } - case ION_IOC_IMPORT: - { - struct ion_fd_data data; - int ret = 0; - if (copy_from_user(&data, (void __user *)arg, - sizeof(struct ion_fd_data))) - return -EFAULT; - data.handle = ion_import_dma_buf(client, data.fd); - if (IS_ERR(data.handle)) { - ret = PTR_ERR(data.handle); - data.handle = NULL; - } - if (copy_to_user((void __user *)arg, &data, - sizeof(struct ion_fd_data))) - return -EFAULT; - if (ret < 0) - return ret; - break; - } - case ION_IOC_SYNC: - { - struct ion_fd_data data; - if (copy_from_user(&data, (void __user *)arg, - sizeof(struct ion_fd_data))) - return -EFAULT; - ion_sync_for_device(client, data.fd); - break; - } - case ION_IOC_CUSTOM: - { - struct ion_device *dev = client->dev; - struct ion_custom_data data; - - if (!dev->custom_ioctl) - return -ENOTTY; - if (copy_from_user(&data, (void __user *)arg, - sizeof(struct ion_custom_data))) - return -EFAULT; - return dev->custom_ioctl(client, data.cmd, data.arg); - } - default: - return -ENOTTY; - } - return 0; -} - -static int ion_release(struct inode *inode, struct file *file) -{ - struct ion_client *client = file->private_data; - - pr_debug("%s: %d\n", __func__, __LINE__); - ion_client_destroy(client); - return 0; -} - -static int ion_open(struct inode *inode, struct file *file) -{ - struct miscdevice *miscdev = file->private_data; - struct ion_device *dev = container_of(miscdev, struct ion_device, dev); - struct ion_client *client; - - pr_debug("%s: %d\n", __func__, __LINE__); - client = ion_client_create(dev, -1, "user"); - if (IS_ERR_OR_NULL(client)) - return PTR_ERR(client); - file->private_data = client; - - return 0; -} - -static const struct file_operations ion_fops = { - .owner = THIS_MODULE, - .open = ion_open, - .release = ion_release, - .unlocked_ioctl = ion_ioctl, -}; - -static size_t ion_debug_heap_total(struct ion_client *client, - enum ion_heap_type type) -{ - size_t size = 0; - struct rb_node *n; - - mutex_lock(&client->lock); - for (n = rb_first(&client->handles); n; n = rb_next(n)) { - struct ion_handle *handle = rb_entry(n, - struct ion_handle, - node); - if (handle->buffer->heap->type == type) - size += handle->buffer->size; - } - mutex_unlock(&client->lock); - return size; -} - -static int ion_debug_heap_show(struct seq_file *s, void *unused) -{ - struct ion_heap *heap = s->private; - struct ion_device *dev = heap->dev; - struct rb_node *n; - size_t total_size = 0; - size_t total_orphaned_size = 0; - - seq_printf(s, "%16.s %16.s %16.s\n", "client", "pid", "size"); - seq_printf(s, "----------------------------------------------------\n"); - - for (n = rb_first(&dev->clients); n; n = rb_next(n)) { - struct ion_client *client = rb_entry(n, struct ion_client, - node); - size_t size = ion_debug_heap_total(client, heap->type); - if (!size) - continue; - if (client->task) { - char task_comm[TASK_COMM_LEN]; - - get_task_comm(task_comm, client->task); - seq_printf(s, "%16.s %16u %16u\n", task_comm, - client->pid, size); - } else { - seq_printf(s, "%16.s %16u %16u\n", client->name, - client->pid, size); - } - } - seq_printf(s, "----------------------------------------------------\n"); - seq_printf(s, "orphaned allocations (info is from last known client):" - "\n"); - mutex_lock(&dev->buffer_lock); - for (n = rb_first(&dev->buffers); n; n = rb_next(n)) { - struct ion_buffer *buffer = rb_entry(n, struct ion_buffer, - node); - if (buffer->heap->type != heap->type) - continue; - total_size += buffer->size; - if (!buffer->handle_count) { - seq_printf(s, "%16.s %16u %16u %d %d\n", buffer->task_comm, - buffer->pid, buffer->size, buffer->kmap_cnt, - atomic_read(&buffer->ref.refcount)); - total_orphaned_size += buffer->size; - } - } - mutex_unlock(&dev->buffer_lock); - seq_printf(s, "----------------------------------------------------\n"); - seq_printf(s, "%16.s %16u\n", "total orphaned", - total_orphaned_size); - seq_printf(s, "%16.s %16u\n", "total ", total_size); - seq_printf(s, "----------------------------------------------------\n"); - - if (heap->debug_show) - heap->debug_show(heap, s, unused); - - return 0; -} - -static int ion_debug_heap_open(struct inode *inode, struct file *file) -{ - return single_open(file, ion_debug_heap_show, inode->i_private); -} - -static const struct file_operations debug_heap_fops = { - .open = ion_debug_heap_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) -{ - struct rb_node **p = &dev->heaps.rb_node; - struct rb_node *parent = NULL; - struct ion_heap *entry; - - if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma || - !heap->ops->unmap_dma) - pr_err("%s: can not add heap with invalid ops struct.\n", - __func__); - - heap->dev = dev; - down_write(&dev->lock); - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_heap, node); - - if (heap->id < entry->id) { - p = &(*p)->rb_left; - } else if (heap->id > entry->id ) { - p = &(*p)->rb_right; - } else { - pr_err("%s: can not insert multiple heaps with " - "id %d\n", __func__, heap->id); - goto end; - } - } - - rb_link_node(&heap->node, parent, p); - rb_insert_color(&heap->node, &dev->heaps); - debugfs_create_file(heap->name, 0664, dev->debug_root, heap, - &debug_heap_fops); -end: - up_write(&dev->lock); -} - -struct ion_device *ion_device_create(long (*custom_ioctl) - (struct ion_client *client, - unsigned int cmd, - unsigned long arg)) -{ - struct ion_device *idev; - int ret; - - idev = kzalloc(sizeof(struct ion_device), GFP_KERNEL); - if (!idev) - return ERR_PTR(-ENOMEM); - - idev->dev.minor = MISC_DYNAMIC_MINOR; - idev->dev.name = "ion"; - idev->dev.fops = &ion_fops; - idev->dev.parent = NULL; - ret = misc_register(&idev->dev); - if (ret) { - pr_err("ion: failed to register misc device.\n"); - return ERR_PTR(ret); - } - - idev->debug_root = debugfs_create_dir("ion", NULL); - if (IS_ERR_OR_NULL(idev->debug_root)) - pr_err("ion: failed to create debug files.\n"); - - idev->custom_ioctl = custom_ioctl; - idev->buffers = RB_ROOT; - mutex_init(&idev->buffer_lock); - init_rwsem(&idev->lock); - idev->heaps = RB_ROOT; - idev->clients = RB_ROOT; - return idev; -} - -void ion_device_destroy(struct ion_device *dev) -{ - misc_deregister(&dev->dev); - /* XXX need to free the heaps and clients ? */ - kfree(dev); -} - -void __init ion_reserve(struct ion_platform_data *data) -{ - int i, ret; - - for (i = 0; i < data->nr; i++) { - if (data->heaps[i].size == 0) - continue; - ret = memblock_reserve(data->heaps[i].base, - data->heaps[i].size); - if (ret) - pr_err("memblock reserve of %x@%lx failed\n", - data->heaps[i].size, - data->heaps[i].base); - } -} diff --git a/ANDROID_3.4.5/drivers/gpu/ion/ion_carveout_heap.c b/ANDROID_3.4.5/drivers/gpu/ion/ion_carveout_heap.c deleted file mode 100644 index ce8d3119..00000000 --- a/ANDROID_3.4.5/drivers/gpu/ion/ion_carveout_heap.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * drivers/gpu/ion/ion_carveout_heap.c - * - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ -#include <linux/spinlock.h> - -#include <linux/err.h> -#include <linux/genalloc.h> -#include <linux/io.h> -#include <linux/ion.h> -#include <linux/mm.h> -#include <linux/scatterlist.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include "ion_priv.h" - -#include <asm/mach/map.h> - -struct ion_carveout_heap { - struct ion_heap heap; - struct gen_pool *pool; - ion_phys_addr_t base; -}; - -ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, - unsigned long size, - unsigned long align) -{ - struct ion_carveout_heap *carveout_heap = - container_of(heap, struct ion_carveout_heap, heap); - unsigned long offset = gen_pool_alloc(carveout_heap->pool, size); - - if (!offset) - return ION_CARVEOUT_ALLOCATE_FAIL; - - return offset; -} - -void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, - unsigned long size) -{ - struct ion_carveout_heap *carveout_heap = - container_of(heap, struct ion_carveout_heap, heap); - - if (addr == ION_CARVEOUT_ALLOCATE_FAIL) - return; - gen_pool_free(carveout_heap->pool, addr, size); -} - -static int ion_carveout_heap_phys(struct ion_heap *heap, - struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len) -{ - *addr = buffer->priv_phys; - *len = buffer->size; - return 0; -} - -static int ion_carveout_heap_allocate(struct ion_heap *heap, - struct ion_buffer *buffer, - unsigned long size, unsigned long align, - unsigned long flags) -{ - buffer->priv_phys = ion_carveout_allocate(heap, size, align); - return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0; -} - -static void ion_carveout_heap_free(struct ion_buffer *buffer) -{ - struct ion_heap *heap = buffer->heap; - - ion_carveout_free(heap, buffer->priv_phys, buffer->size); - buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL; -} - -struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - struct sg_table *table; - int ret; - - table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!table) - return ERR_PTR(-ENOMEM); - ret = sg_alloc_table(table, 1, GFP_KERNEL); - if (ret) { - kfree(table); - return ERR_PTR(ret); - } - sg_set_page(table->sgl, phys_to_page(buffer->priv_phys), buffer->size, - 0); - return table; -} - -void ion_carveout_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - sg_free_table(buffer->sg_table); -} - -void *ion_carveout_heap_map_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - int mtype = MT_MEMORY_NONCACHED; - - if (buffer->flags & ION_FLAG_CACHED) - mtype = MT_MEMORY; - - return __arm_ioremap(buffer->priv_phys, buffer->size, - mtype); -} - -void ion_carveout_heap_unmap_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - __arm_iounmap(buffer->vaddr); - buffer->vaddr = NULL; - return; -} - -int ion_carveout_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, - struct vm_area_struct *vma) -{ - return remap_pfn_range(vma, vma->vm_start, - __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff, - vma->vm_end - vma->vm_start, - pgprot_noncached(vma->vm_page_prot)); -} - -static struct ion_heap_ops carveout_heap_ops = { - .allocate = ion_carveout_heap_allocate, - .free = ion_carveout_heap_free, - .phys = ion_carveout_heap_phys, - .map_dma = ion_carveout_heap_map_dma, - .unmap_dma = ion_carveout_heap_unmap_dma, - .map_user = ion_carveout_heap_map_user, - .map_kernel = ion_carveout_heap_map_kernel, - .unmap_kernel = ion_carveout_heap_unmap_kernel, -}; - -struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) -{ - struct ion_carveout_heap *carveout_heap; - - carveout_heap = kzalloc(sizeof(struct ion_carveout_heap), GFP_KERNEL); - if (!carveout_heap) - return ERR_PTR(-ENOMEM); - - carveout_heap->pool = gen_pool_create(12, -1); - if (!carveout_heap->pool) { - kfree(carveout_heap); - return ERR_PTR(-ENOMEM); - } - carveout_heap->base = heap_data->base; - gen_pool_add(carveout_heap->pool, carveout_heap->base, heap_data->size, - -1); - carveout_heap->heap.ops = &carveout_heap_ops; - carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT; - - return &carveout_heap->heap; -} - -void ion_carveout_heap_destroy(struct ion_heap *heap) -{ - struct ion_carveout_heap *carveout_heap = - container_of(heap, struct ion_carveout_heap, heap); - - gen_pool_destroy(carveout_heap->pool); - kfree(carveout_heap); - carveout_heap = NULL; -} diff --git a/ANDROID_3.4.5/drivers/gpu/ion/ion_heap.c b/ANDROID_3.4.5/drivers/gpu/ion/ion_heap.c deleted file mode 100644 index 8ce3c190..00000000 --- a/ANDROID_3.4.5/drivers/gpu/ion/ion_heap.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * drivers/gpu/ion/ion_heap.c - * - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/err.h> -#include <linux/ion.h> -#include "ion_priv.h" - -struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) -{ - struct ion_heap *heap = NULL; - - switch (heap_data->type) { - case ION_HEAP_TYPE_SYSTEM_CONTIG: - heap = ion_system_contig_heap_create(heap_data); - break; - case ION_HEAP_TYPE_SYSTEM: - heap = ion_system_heap_create(heap_data); - break; - case ION_HEAP_TYPE_CARVEOUT: - heap = ion_carveout_heap_create(heap_data); - break; - default: - pr_err("%s: Invalid heap type %d\n", __func__, - heap_data->type); - return ERR_PTR(-EINVAL); - } - - if (IS_ERR_OR_NULL(heap)) { - pr_err("%s: error creating heap %s type %d base %lu size %u\n", - __func__, heap_data->name, heap_data->type, - heap_data->base, heap_data->size); - return ERR_PTR(-EINVAL); - } - - heap->name = heap_data->name; - heap->id = heap_data->id; - return heap; -} - -void ion_heap_destroy(struct ion_heap *heap) -{ - if (!heap) - return; - - switch (heap->type) { - case ION_HEAP_TYPE_SYSTEM_CONTIG: - ion_system_contig_heap_destroy(heap); - break; - case ION_HEAP_TYPE_SYSTEM: - ion_system_heap_destroy(heap); - break; - case ION_HEAP_TYPE_CARVEOUT: - ion_carveout_heap_destroy(heap); - break; - default: - pr_err("%s: Invalid heap type %d\n", __func__, - heap->type); - } -} diff --git a/ANDROID_3.4.5/drivers/gpu/ion/ion_page_pool.c b/ANDROID_3.4.5/drivers/gpu/ion/ion_page_pool.c deleted file mode 100644 index cd57b30e..00000000 --- a/ANDROID_3.4.5/drivers/gpu/ion/ion_page_pool.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * drivers/gpu/ion/ion_mem_pool.c - * - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/debugfs.h> -#include <linux/dma-mapping.h> -#include <linux/err.h> -#include <linux/fs.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/shrinker.h> -#include "ion_priv.h" - -/* #define DEBUG_PAGE_POOL_SHRINKER */ - -static struct plist_head pools = PLIST_HEAD_INIT(pools); -static struct shrinker shrinker; - -struct ion_page_pool_item { - struct page *page; - struct list_head list; -}; - -static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) -{ - struct page *page = alloc_pages(pool->gfp_mask, pool->order); - - if (!page) - return NULL; - /* this is only being used to flush the page for dma, - this api is not really suitable for calling from a driver - but no better way to flush a page for dma exist at this time */ - __dma_page_cpu_to_dev(page, 0, PAGE_SIZE << pool->order, - DMA_BIDIRECTIONAL); - return page; -} - -static void ion_page_pool_free_pages(struct ion_page_pool *pool, - struct page *page) -{ - __free_pages(page, pool->order); -} - -static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page) -{ - struct ion_page_pool_item *item; - - item = kmalloc(sizeof(struct ion_page_pool_item), GFP_KERNEL); - if (!item) - return -ENOMEM; - - mutex_lock(&pool->mutex); - item->page = page; - if (PageHighMem(page)) { - list_add_tail(&item->list, &pool->high_items); - pool->high_count++; - } else { - list_add_tail(&item->list, &pool->low_items); - pool->low_count++; - } - mutex_unlock(&pool->mutex); - return 0; -} - -static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high) -{ - struct ion_page_pool_item *item; - struct page *page; - - if (high) { - BUG_ON(!pool->high_count); - item = list_first_entry(&pool->high_items, - struct ion_page_pool_item, list); - pool->high_count--; - } else { - BUG_ON(!pool->low_count); - item = list_first_entry(&pool->low_items, - struct ion_page_pool_item, list); - pool->low_count--; - } - - list_del(&item->list); - page = item->page; - kfree(item); - return page; -} - -void *ion_page_pool_alloc(struct ion_page_pool *pool) -{ - struct page *page = NULL; - - BUG_ON(!pool); - - mutex_lock(&pool->mutex); - if (pool->high_count) - page = ion_page_pool_remove(pool, true); - else if (pool->low_count) - page = ion_page_pool_remove(pool, false); - mutex_unlock(&pool->mutex); - - if (!page) - page = ion_page_pool_alloc_pages(pool); - - return page; -} - -void ion_page_pool_free(struct ion_page_pool *pool, struct page* page) -{ - int ret; - - ret = ion_page_pool_add(pool, page); - if (ret) - ion_page_pool_free_pages(pool, page); -} - -#ifdef DEBUG_PAGE_POOL_SHRINKER -static int debug_drop_pools_set(void *data, u64 val) -{ - struct shrink_control sc; - int objs; - - sc.gfp_mask = -1; - sc.nr_to_scan = 0; - - if (!val) - return 0; - - objs = shrinker.shrink(&shrinker, &sc); - sc.nr_to_scan = objs; - - shrinker.shrink(&shrinker, &sc); - return 0; -} - -static int debug_drop_pools_get(void *data, u64 *val) -{ - struct shrink_control sc; - int objs; - - sc.gfp_mask = -1; - sc.nr_to_scan = 0; - - objs = shrinker.shrink(&shrinker, &sc); - *val = objs; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_drop_pools_fops, debug_drop_pools_get, - debug_drop_pools_set, "%llu\n"); - -static int debug_grow_pools_set(void *data, u64 val) -{ - struct ion_page_pool *pool; - struct page *page; - - plist_for_each_entry(pool, &pools, list) { - if (val != pool->list.prio) - continue; - page = ion_page_pool_alloc_pages(pool); - if (page) - ion_page_pool_add(pool, page); - } - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_grow_pools_fops, debug_drop_pools_get, - debug_grow_pools_set, "%llu\n"); -#endif - -static int ion_page_pool_total(bool high) -{ - struct ion_page_pool *pool; - int total = 0; - - plist_for_each_entry(pool, &pools, list) { - total += high ? (pool->high_count + pool->low_count) * - (1 << pool->order) : - pool->low_count * (1 << pool->order); - } - return total; -} - -static int ion_page_pool_shrink(struct shrinker *shrinker, - struct shrink_control *sc) -{ - struct ion_page_pool *pool; - int nr_freed = 0; - int i; - bool high; - int nr_to_scan = sc->nr_to_scan; - - if (sc->gfp_mask & __GFP_HIGHMEM) - high = true; - - if (nr_to_scan == 0) - return ion_page_pool_total(high); - - plist_for_each_entry(pool, &pools, list) { - for (i = 0; i < nr_to_scan; i++) { - struct page *page; - - mutex_lock(&pool->mutex); - if (high && pool->high_count) { - page = ion_page_pool_remove(pool, true); - } else if (pool->low_count) { - page = ion_page_pool_remove(pool, false); - } else { - mutex_unlock(&pool->mutex); - break; - } - mutex_unlock(&pool->mutex); - ion_page_pool_free_pages(pool, page); - nr_freed += (1 << pool->order); - } - nr_to_scan -= i; - } - - return ion_page_pool_total(high); -} - -struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) -{ - struct ion_page_pool *pool = kmalloc(sizeof(struct ion_page_pool), - GFP_KERNEL); - if (!pool) - return NULL; - pool->high_count = 0; - pool->low_count = 0; - INIT_LIST_HEAD(&pool->low_items); - INIT_LIST_HEAD(&pool->high_items); - pool->gfp_mask = gfp_mask; - pool->order = order; - mutex_init(&pool->mutex); - plist_node_init(&pool->list, order); - plist_add(&pool->list, &pools); - - return pool; -} - -void ion_page_pool_destroy(struct ion_page_pool *pool) -{ - plist_del(&pool->list, &pools); - kfree(pool); -} - -static int __init ion_page_pool_init(void) -{ - shrinker.shrink = ion_page_pool_shrink; - shrinker.seeks = DEFAULT_SEEKS; - shrinker.batch = 0; - register_shrinker(&shrinker); -#ifdef DEBUG_PAGE_POOL_SHRINKER - debugfs_create_file("ion_pools_shrink", 0644, NULL, NULL, - &debug_drop_pools_fops); - debugfs_create_file("ion_pools_grow", 0644, NULL, NULL, - &debug_grow_pools_fops); -#endif - return 0; -} - -static void __exit ion_page_pool_exit(void) -{ - unregister_shrinker(&shrinker); -} - -module_init(ion_page_pool_init); -module_exit(ion_page_pool_exit); diff --git a/ANDROID_3.4.5/drivers/gpu/ion/ion_priv.h b/ANDROID_3.4.5/drivers/gpu/ion/ion_priv.h deleted file mode 100644 index 21c19630..00000000 --- a/ANDROID_3.4.5/drivers/gpu/ion/ion_priv.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * drivers/gpu/ion/ion_priv.h - * - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _ION_PRIV_H -#define _ION_PRIV_H - -#include <linux/ion.h> -#include <linux/kref.h> -#include <linux/mm_types.h> -#include <linux/mutex.h> -#include <linux/rbtree.h> -#include <linux/sched.h> -#include <linux/shrinker.h> -#include <linux/types.h> - -struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); - -/** - * struct ion_buffer - metadata for a particular buffer - * @ref: refernce count - * @node: node in the ion_device buffers tree - * @dev: back pointer to the ion_device - * @heap: back pointer to the heap the buffer came from - * @flags: buffer specific flags - * @size: size of the buffer - * @priv_virt: private data to the buffer representable as - * a void * - * @priv_phys: private data to the buffer representable as - * an ion_phys_addr_t (and someday a phys_addr_t) - * @lock: protects the buffers cnt fields - * @kmap_cnt: number of times the buffer is mapped to the kernel - * @vaddr: the kenrel mapping if kmap_cnt is not zero - * @dmap_cnt: number of times the buffer is mapped for dma - * @sg_table: the sg table for the buffer if dmap_cnt is not zero - * @dirty: bitmask representing which pages of this buffer have - * been dirtied by the cpu and need cache maintenance - * before dma - * @vmas: list of vma's mapping this buffer - * @handle_count: count of handles referencing this buffer - * @task_comm: taskcomm of last client to reference this buffer in a - * handle, used for debugging - * @pid: pid of last client to reference this buffer in a - * handle, used for debugging -*/ -struct ion_buffer { - struct kref ref; - struct rb_node node; - struct ion_device *dev; - struct ion_heap *heap; - unsigned long flags; - size_t size; - union { - void *priv_virt; - ion_phys_addr_t priv_phys; - }; - struct mutex lock; - int kmap_cnt; - void *vaddr; - int dmap_cnt; - struct sg_table *sg_table; - unsigned long *dirty; - struct list_head vmas; - /* used to track orphaned buffers */ - int handle_count; - char task_comm[TASK_COMM_LEN]; - pid_t pid; -}; - -/** - * struct ion_heap_ops - ops to operate on a given heap - * @allocate: allocate memory - * @free: free memory - * @phys get physical address of a buffer (only define on - * physically contiguous heaps) - * @map_dma map the memory for dma to a scatterlist - * @unmap_dma unmap the memory for dma - * @map_kernel map memory to the kernel - * @unmap_kernel unmap memory to the kernel - * @map_user map memory to userspace - */ -struct ion_heap_ops { - int (*allocate) (struct ion_heap *heap, - struct ion_buffer *buffer, unsigned long len, - unsigned long align, unsigned long flags); - void (*free) (struct ion_buffer *buffer); - int (*phys) (struct ion_heap *heap, struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len); - struct sg_table *(*map_dma) (struct ion_heap *heap, - struct ion_buffer *buffer); - void (*unmap_dma) (struct ion_heap *heap, struct ion_buffer *buffer); - void * (*map_kernel) (struct ion_heap *heap, struct ion_buffer *buffer); - void (*unmap_kernel) (struct ion_heap *heap, struct ion_buffer *buffer); - int (*map_user) (struct ion_heap *mapper, struct ion_buffer *buffer, - struct vm_area_struct *vma); -}; - -/** - * struct ion_heap - represents a heap in the system - * @node: rb node to put the heap on the device's tree of heaps - * @dev: back pointer to the ion_device - * @type: type of heap - * @ops: ops struct as above - * @id: id of heap, also indicates priority of this heap when - * allocating. These are specified by platform data and - * MUST be unique - * @name: used for debugging - * @debug_show: called when heap debug file is read to add any - * heap specific debug info to output - * - * Represents a pool of memory from which buffers can be made. In some - * systems the only heap is regular system memory allocated via vmalloc. - * On others, some blocks might require large physically contiguous buffers - * that are allocated from a specially reserved heap. - */ -struct ion_heap { - struct rb_node node; - struct ion_device *dev; - enum ion_heap_type type; - struct ion_heap_ops *ops; - int id; - const char *name; - int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *); -}; - -/** - * ion_buffer_cached - this ion buffer is cached - * @buffer: buffer - * - * indicates whether this ion buffer is cached - */ -bool ion_buffer_cached(struct ion_buffer *buffer); - -/** - * ion_buffer_fault_user_mappings - fault in user mappings of this buffer - * @buffer: buffer - * - * indicates whether userspace mappings of this buffer will be faulted - * in, this can affect how buffers are allocated from the heap. - */ -bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer); - -/** - * ion_device_create - allocates and returns an ion device - * @custom_ioctl: arch specific ioctl function if applicable - * - * returns a valid device or -PTR_ERR - */ -struct ion_device *ion_device_create(long (*custom_ioctl) - (struct ion_client *client, - unsigned int cmd, - unsigned long arg)); - -/** - * ion_device_destroy - free and device and it's resource - * @dev: the device - */ -void ion_device_destroy(struct ion_device *dev); - -/** - * ion_device_add_heap - adds a heap to the ion device - * @dev: the device - * @heap: the heap to add - */ -void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap); - -/** - * functions for creating and destroying the built in ion heaps. - * architectures can add their own custom architecture specific - * heaps as appropriate. - */ - -struct ion_heap *ion_heap_create(struct ion_platform_heap *); -void ion_heap_destroy(struct ion_heap *); - -struct ion_heap *ion_system_heap_create(struct ion_platform_heap *); -void ion_system_heap_destroy(struct ion_heap *); - -struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *); -void ion_system_contig_heap_destroy(struct ion_heap *); - -struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *); -void ion_carveout_heap_destroy(struct ion_heap *); -/** - * kernel api to allocate/free from carveout -- used when carveout is - * used to back an architecture specific custom heap - */ -ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, unsigned long size, - unsigned long align); -void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, - unsigned long size); -/** - * The carveout heap returns physical addresses, since 0 may be a valid - * physical address, this is used to indicate allocation failed - */ -#define ION_CARVEOUT_ALLOCATE_FAIL -1 - -/** - * functions for creating and destroying a heap pool -- allows you - * to keep a pool of pre allocated memory to use from your heap. Keeping - * a pool of memory that is ready for dma, ie any cached mapping have been - * invalidated from the cache, provides a significant peformance benefit on - * many systems */ - -/** - * struct ion_page_pool - pagepool struct - * @high_count: number of highmem items in the pool - * @low_count: number of lowmem items in the pool - * @high_items: list of highmem items - * @low_items: list of lowmem items - * @shrinker: a shrinker for the items - * @mutex: lock protecting this struct and especially the count - * item list - * @alloc: function to be used to allocate pageory when the pool - * is empty - * @free: function to be used to free pageory back to the system - * when the shrinker fires - * @gfp_mask: gfp_mask to use from alloc - * @order: order of pages in the pool - * @list: plist node for list of pools - * - * Allows you to keep a pool of pre allocated pages to use from your heap. - * Keeping a pool of pages that is ready for dma, ie any cached mapping have - * been invalidated from the cache, provides a significant peformance benefit - * on many systems - */ -struct ion_page_pool { - int high_count; - int low_count; - struct list_head high_items; - struct list_head low_items; - struct mutex mutex; - void *(*alloc)(struct ion_page_pool *pool); - void (*free)(struct ion_page_pool *pool, struct page *page); - gfp_t gfp_mask; - unsigned int order; - struct plist_node list; -}; - -struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order); -void ion_page_pool_destroy(struct ion_page_pool *); -void *ion_page_pool_alloc(struct ion_page_pool *); -void ion_page_pool_free(struct ion_page_pool *, struct page *); - -#endif /* _ION_PRIV_H */ diff --git a/ANDROID_3.4.5/drivers/gpu/ion/ion_system_heap.c b/ANDROID_3.4.5/drivers/gpu/ion/ion_system_heap.c deleted file mode 100644 index 2a85df9e..00000000 --- a/ANDROID_3.4.5/drivers/gpu/ion/ion_system_heap.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * drivers/gpu/ion/ion_system_heap.c - * - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <asm/page.h> -#include <linux/dma-mapping.h> -#include <linux/err.h> -#include <linux/highmem.h> -#include <linux/ion.h> -#include <linux/mm.h> -#include <linux/scatterlist.h> -#include <linux/seq_file.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include "ion_priv.h" - -static unsigned int high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | - __GFP_NOWARN | __GFP_NORETRY | - __GFP_NO_KSWAPD) & ~__GFP_WAIT; -static unsigned int low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | - __GFP_NOWARN); -static const unsigned int orders[] = {8, 4, 0}; -static const int num_orders = ARRAY_SIZE(orders); -static int order_to_index(unsigned int order) -{ - int i; - for (i = 0; i < num_orders; i++) - if (order == orders[i]) - return i; - BUG(); - return -1; -} - -static unsigned int order_to_size(int order) -{ - return PAGE_SIZE << order; -} - -struct ion_system_heap { - struct ion_heap heap; - struct ion_page_pool **pools; -}; - -struct page_info { - struct page *page; - unsigned int order; - struct list_head list; -}; - -static struct page *alloc_buffer_page(struct ion_system_heap *heap, - struct ion_buffer *buffer, - unsigned long order) -{ - bool cached = ion_buffer_cached(buffer); - bool split_pages = ion_buffer_fault_user_mappings(buffer); - struct ion_page_pool *pool = heap->pools[order_to_index(order)]; - struct page *page; - - if (!cached) { - page = ion_page_pool_alloc(pool); - } else { - gfp_t gfp_flags = low_order_gfp_flags; - - if (order > 4) - gfp_flags = high_order_gfp_flags; - page = alloc_pages(gfp_flags, order); - if (!page) - return 0; - __dma_page_cpu_to_dev(page, 0, PAGE_SIZE << order, - DMA_BIDIRECTIONAL); - } - if (!page) - return 0; - - if (split_pages) - split_page(page, order); - return page; -} - -static void free_buffer_page(struct ion_system_heap *heap, - struct ion_buffer *buffer, struct page *page, - unsigned int order) -{ - bool cached = ion_buffer_cached(buffer); - bool split_pages = ion_buffer_fault_user_mappings(buffer); - int i; - - if (!cached) { - struct ion_page_pool *pool = heap->pools[order_to_index(order)]; - /* zero the pages before returning them to the pool for - security. This uses vmap as we want to set the pgprot so - the writes to occur to noncached mappings, as the pool's - purpose is to keep the pages out of the cache */ - for (i = 0; i < (1 << order); i++) { - struct page *sub_page = page + i; - void *addr = vmap(&sub_page, 1, VM_MAP, - pgprot_writecombine(PAGE_KERNEL)); - memset(addr, 0, PAGE_SIZE); - vunmap(addr); - } - ion_page_pool_free(pool, page); - } else if (split_pages) { - for (i = 0; i < (1 << order); i++) - __free_page(page + i); - } else { - __free_pages(page, order); - } -} - - -static struct page_info *alloc_largest_available(struct ion_system_heap *heap, - struct ion_buffer *buffer, - unsigned long size, - unsigned int max_order) -{ - struct page *page; - struct page_info *info; - int i; - - for (i = 0; i < num_orders; i++) { - if (size < order_to_size(orders[i])) - continue; - if (max_order < orders[i]) - continue; - - page = alloc_buffer_page(heap, buffer, orders[i]); - if (!page) - continue; - - info = kmalloc(sizeof(struct page_info), GFP_KERNEL); - info->page = page; - info->order = orders[i]; - return info; - } - return NULL; -} - -static int ion_system_heap_allocate(struct ion_heap *heap, - struct ion_buffer *buffer, - unsigned long size, unsigned long align, - unsigned long flags) -{ - struct ion_system_heap *sys_heap = container_of(heap, - struct ion_system_heap, - heap); - struct sg_table *table; - struct scatterlist *sg; - int ret; - struct list_head pages; - struct page_info *info, *tmp_info; - int i = 0; - long size_remaining = PAGE_ALIGN(size); - unsigned int max_order = orders[0]; - bool split_pages = ion_buffer_fault_user_mappings(buffer); - - INIT_LIST_HEAD(&pages); - while (size_remaining > 0) { - info = alloc_largest_available(sys_heap, buffer, size_remaining, max_order); - if (!info) - goto err; - list_add_tail(&info->list, &pages); - size_remaining -= (1 << info->order) * PAGE_SIZE; - max_order = info->order; - i++; - } - - table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!table) - goto err; - - if (split_pages) - ret = sg_alloc_table(table, PAGE_ALIGN(size) / PAGE_SIZE, - GFP_KERNEL); - else - ret = sg_alloc_table(table, i, GFP_KERNEL); - - if (ret) - goto err1; - - sg = table->sgl; - list_for_each_entry_safe(info, tmp_info, &pages, list) { - struct page *page = info->page; - if (split_pages) { - for (i = 0; i < (1 << info->order); i++) { - sg_set_page(sg, page + i, PAGE_SIZE, 0); - sg = sg_next(sg); - } - } else { - sg_set_page(sg, page, (1 << info->order) * PAGE_SIZE, - 0); - sg = sg_next(sg); - } - list_del(&info->list); - kfree(info); - } - - buffer->priv_virt = table; - return 0; -err1: - kfree(table); -err: - list_for_each_entry(info, &pages, list) { - free_buffer_page(sys_heap, buffer, info->page, info->order); - kfree(info); - } - return -ENOMEM; -} - -void ion_system_heap_free(struct ion_buffer *buffer) -{ - struct ion_heap *heap = buffer->heap; - struct ion_system_heap *sys_heap = container_of(heap, - struct ion_system_heap, - heap); - struct sg_table *table = buffer->priv_virt; - struct scatterlist *sg; - LIST_HEAD(pages); - int i; - - for_each_sg(table->sgl, sg, table->nents, i) - free_buffer_page(sys_heap, buffer, sg_page(sg), get_order(sg_dma_len(sg))); - sg_free_table(table); - kfree(table); -} - -struct sg_table *ion_system_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - return buffer->priv_virt; -} - -void ion_system_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - return; -} - -void *ion_system_heap_map_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - struct scatterlist *sg; - int i, j; - void *vaddr; - pgprot_t pgprot; - struct sg_table *table = buffer->priv_virt; - int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; - struct page **pages = vmalloc(sizeof(struct page *) * npages); - struct page **tmp = pages; - - if (!pages) - return 0; - - if (buffer->flags & ION_FLAG_CACHED) - pgprot = PAGE_KERNEL; - else - pgprot = pgprot_writecombine(PAGE_KERNEL); - - for_each_sg(table->sgl, sg, table->nents, i) { - int npages_this_entry = PAGE_ALIGN(sg_dma_len(sg)) / PAGE_SIZE; - struct page *page = sg_page(sg); - BUG_ON(i >= npages); - for (j = 0; j < npages_this_entry; j++) { - *(tmp++) = page++; - } - } - vaddr = vmap(pages, npages, VM_MAP, pgprot); - vfree(pages); - - return vaddr; -} - -void ion_system_heap_unmap_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - vunmap(buffer->vaddr); -} - -int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, - struct vm_area_struct *vma) -{ - struct sg_table *table = buffer->priv_virt; - unsigned long addr = vma->vm_start; - unsigned long offset = vma->vm_pgoff * PAGE_SIZE; - struct scatterlist *sg; - int i; - - for_each_sg(table->sgl, sg, table->nents, i) { - struct page *page = sg_page(sg); - unsigned long remainder = vma->vm_end - addr; - unsigned long len = sg_dma_len(sg); - - if (offset >= sg_dma_len(sg)) { - offset -= sg_dma_len(sg); - continue; - } else if (offset) { - page += offset / PAGE_SIZE; - len = sg_dma_len(sg) - offset; - offset = 0; - } - len = min(len, remainder); - remap_pfn_range(vma, addr, page_to_pfn(page), len, - vma->vm_page_prot); - addr += len; - if (addr >= vma->vm_end) - return 0; - } - return 0; -} - -static struct ion_heap_ops system_heap_ops = { - .allocate = ion_system_heap_allocate, - .free = ion_system_heap_free, - .map_dma = ion_system_heap_map_dma, - .unmap_dma = ion_system_heap_unmap_dma, - .map_kernel = ion_system_heap_map_kernel, - .unmap_kernel = ion_system_heap_unmap_kernel, - .map_user = ion_system_heap_map_user, -}; - -static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, - void *unused) -{ - - struct ion_system_heap *sys_heap = container_of(heap, - struct ion_system_heap, - heap); - int i; - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool = sys_heap->pools[i]; - seq_printf(s, "%d order %u highmem pages in pool = %lu total\n", - pool->high_count, pool->order, - (1 << pool->order) * PAGE_SIZE * pool->high_count); - seq_printf(s, "%d order %u lowmem pages in pool = %lu total\n", - pool->low_count, pool->order, - (1 << pool->order) * PAGE_SIZE * pool->low_count); - } - return 0; -} - -struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) -{ - struct ion_system_heap *heap; - int i; - - heap = kzalloc(sizeof(struct ion_system_heap), GFP_KERNEL); - if (!heap) - return ERR_PTR(-ENOMEM); - heap->heap.ops = &system_heap_ops; - heap->heap.type = ION_HEAP_TYPE_SYSTEM; - heap->pools = kzalloc(sizeof(struct ion_page_pool *) * num_orders, - GFP_KERNEL); - if (!heap->pools) - goto err_alloc_pools; - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool; - gfp_t gfp_flags = low_order_gfp_flags; - - if (orders[i] > 4) - gfp_flags = high_order_gfp_flags; - pool = ion_page_pool_create(gfp_flags, orders[i]); - if (!pool) - goto err_create_pool; - heap->pools[i] = pool; - } - heap->heap.debug_show = ion_system_heap_debug_show; - return &heap->heap; -err_create_pool: - for (i = 0; i < num_orders; i++) - if (heap->pools[i]) - ion_page_pool_destroy(heap->pools[i]); - kfree(heap->pools); -err_alloc_pools: - kfree(heap); - return ERR_PTR(-ENOMEM); -} - -void ion_system_heap_destroy(struct ion_heap *heap) -{ - struct ion_system_heap *sys_heap = container_of(heap, - struct ion_system_heap, - heap); - int i; - - for (i = 0; i < num_orders; i++) - ion_page_pool_destroy(sys_heap->pools[i]); - kfree(sys_heap->pools); - kfree(sys_heap); -} - -static int ion_system_contig_heap_allocate(struct ion_heap *heap, - struct ion_buffer *buffer, - unsigned long len, - unsigned long align, - unsigned long flags) -{ - buffer->priv_virt = kzalloc(len, GFP_KERNEL); - if (!buffer->priv_virt) - return -ENOMEM; - return 0; -} - -void ion_system_contig_heap_free(struct ion_buffer *buffer) -{ - kfree(buffer->priv_virt); -} - -static int ion_system_contig_heap_phys(struct ion_heap *heap, - struct ion_buffer *buffer, - ion_phys_addr_t *addr, size_t *len) -{ - *addr = virt_to_phys(buffer->priv_virt); - *len = buffer->size; - return 0; -} - -struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - struct sg_table *table; - int ret; - - table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!table) - return ERR_PTR(-ENOMEM); - ret = sg_alloc_table(table, 1, GFP_KERNEL); - if (ret) { - kfree(table); - return ERR_PTR(ret); - } - sg_set_page(table->sgl, virt_to_page(buffer->priv_virt), buffer->size, - 0); - return table; -} - -void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - sg_free_table(buffer->sg_table); - kfree(buffer->sg_table); -} - -int ion_system_contig_heap_map_user(struct ion_heap *heap, - struct ion_buffer *buffer, - struct vm_area_struct *vma) -{ - unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv_virt)); - return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); - -} - -static struct ion_heap_ops kmalloc_ops = { - .allocate = ion_system_contig_heap_allocate, - .free = ion_system_contig_heap_free, - .phys = ion_system_contig_heap_phys, - .map_dma = ion_system_contig_heap_map_dma, - .unmap_dma = ion_system_contig_heap_unmap_dma, - .map_kernel = ion_system_heap_map_kernel, - .unmap_kernel = ion_system_heap_unmap_kernel, - .map_user = ion_system_contig_heap_map_user, -}; - -struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused) -{ - struct ion_heap *heap; - - heap = kzalloc(sizeof(struct ion_heap), GFP_KERNEL); - if (!heap) - return ERR_PTR(-ENOMEM); - heap->ops = &kmalloc_ops; - heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG; - return heap; -} - -void ion_system_contig_heap_destroy(struct ion_heap *heap) -{ - kfree(heap); -} - diff --git a/ANDROID_3.4.5/drivers/gpu/ion/ion_system_mapper.c b/ANDROID_3.4.5/drivers/gpu/ion/ion_system_mapper.c deleted file mode 100644 index 692458e0..00000000 --- a/ANDROID_3.4.5/drivers/gpu/ion/ion_system_mapper.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * drivers/gpu/ion/ion_system_mapper.c - * - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/err.h> -#include <linux/ion.h> -#include <linux/memory.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include "ion_priv.h" -/* - * This mapper is valid for any heap that allocates memory that already has - * a kernel mapping, this includes vmalloc'd memory, kmalloc'd memory, - * pages obtained via io_remap, etc. - */ -static void *ion_kernel_mapper_map(struct ion_mapper *mapper, - struct ion_buffer *buffer, - struct ion_mapping **mapping) -{ - if (!((1 << buffer->heap->type) & mapper->heap_mask)) { - pr_err("%s: attempting to map an unsupported heap\n", __func__); - return ERR_PTR(-EINVAL); - } - /* XXX REVISIT ME!!! */ - *((unsigned long *)mapping) = (unsigned long)buffer->priv; - return buffer->priv; -} - -static void ion_kernel_mapper_unmap(struct ion_mapper *mapper, - struct ion_buffer *buffer, - struct ion_mapping *mapping) -{ - if (!((1 << buffer->heap->type) & mapper->heap_mask)) - pr_err("%s: attempting to unmap an unsupported heap\n", - __func__); -} - -static void *ion_kernel_mapper_map_kernel(struct ion_mapper *mapper, - struct ion_buffer *buffer, - struct ion_mapping *mapping) -{ - if (!((1 << buffer->heap->type) & mapper->heap_mask)) { - pr_err("%s: attempting to unmap an unsupported heap\n", - __func__); - return ERR_PTR(-EINVAL); - } - return buffer->priv; -} - -static int ion_kernel_mapper_map_user(struct ion_mapper *mapper, - struct ion_buffer *buffer, - struct vm_area_struct *vma, - struct ion_mapping *mapping) -{ - int ret; - - switch (buffer->heap->type) { - case ION_HEAP_KMALLOC: - { - unsigned long pfn = __phys_to_pfn(virt_to_phys(buffer->priv)); - ret = remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); - break; - } - case ION_HEAP_VMALLOC: - ret = remap_vmalloc_range(vma, buffer->priv, vma->vm_pgoff); - break; - default: - pr_err("%s: attempting to map unsupported heap to userspace\n", - __func__); - return -EINVAL; - } - - return ret; -} - -static struct ion_mapper_ops ops = { - .map = ion_kernel_mapper_map, - .map_kernel = ion_kernel_mapper_map_kernel, - .map_user = ion_kernel_mapper_map_user, - .unmap = ion_kernel_mapper_unmap, -}; - -struct ion_mapper *ion_system_mapper_create(void) -{ - struct ion_mapper *mapper; - mapper = kzalloc(sizeof(struct ion_mapper), GFP_KERNEL); - if (!mapper) - return ERR_PTR(-ENOMEM); - mapper->type = ION_SYSTEM_MAPPER; - mapper->ops = &ops; - mapper->heap_mask = (1 << ION_HEAP_VMALLOC) | (1 << ION_HEAP_KMALLOC); - return mapper; -} - -void ion_system_mapper_destroy(struct ion_mapper *mapper) -{ - kfree(mapper); -} - diff --git a/ANDROID_3.4.5/drivers/gpu/ion/tegra/Makefile b/ANDROID_3.4.5/drivers/gpu/ion/tegra/Makefile deleted file mode 100644 index 11cd003f..00000000 --- a/ANDROID_3.4.5/drivers/gpu/ion/tegra/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += tegra_ion.o diff --git a/ANDROID_3.4.5/drivers/gpu/ion/tegra/tegra_ion.c b/ANDROID_3.4.5/drivers/gpu/ion/tegra/tegra_ion.c deleted file mode 100644 index 7af6e168..00000000 --- a/ANDROID_3.4.5/drivers/gpu/ion/tegra/tegra_ion.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * drivers/gpu/tegra/tegra_ion.c - * - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/err.h> -#include <linux/ion.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include "../ion_priv.h" - -struct ion_device *idev; -struct ion_mapper *tegra_user_mapper; -int num_heaps; -struct ion_heap **heaps; - -int tegra_ion_probe(struct platform_device *pdev) -{ - struct ion_platform_data *pdata = pdev->dev.platform_data; - int err; - int i; - - num_heaps = pdata->nr; - - heaps = kzalloc(sizeof(struct ion_heap *) * pdata->nr, GFP_KERNEL); - - idev = ion_device_create(NULL); - if (IS_ERR_OR_NULL(idev)) { - kfree(heaps); - return PTR_ERR(idev); - } - - /* create the heaps as specified in the board file */ - for (i = 0; i < num_heaps; i++) { - struct ion_platform_heap *heap_data = &pdata->heaps[i]; - - heaps[i] = ion_heap_create(heap_data); - if (IS_ERR_OR_NULL(heaps[i])) { - err = PTR_ERR(heaps[i]); - goto err; - } - ion_device_add_heap(idev, heaps[i]); - } - platform_set_drvdata(pdev, idev); - return 0; -err: - for (i = 0; i < num_heaps; i++) { - if (heaps[i]) - ion_heap_destroy(heaps[i]); - } - kfree(heaps); - return err; -} - -int tegra_ion_remove(struct platform_device *pdev) -{ - struct ion_device *idev = platform_get_drvdata(pdev); - int i; - - ion_device_destroy(idev); - for (i = 0; i < num_heaps; i++) - ion_heap_destroy(heaps[i]); - kfree(heaps); - return 0; -} - -static struct platform_driver ion_driver = { - .probe = tegra_ion_probe, - .remove = tegra_ion_remove, - .driver = { .name = "ion-tegra" } -}; - -static int __init ion_init(void) -{ - return platform_driver_register(&ion_driver); -} - -static void __exit ion_exit(void) -{ - platform_driver_unregister(&ion_driver); -} - -module_init(ion_init); -module_exit(ion_exit); - |