diff options
Diffstat (limited to 'drivers/staging/android/ion')
21 files changed, 124 insertions, 1346 deletions
diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index c8fb413..206c4de 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -10,45 +10,3 @@ menuconfig ION If you're not using Android its probably safe to say N here. -config ION_TEST - tristate "Ion Test Device" - depends on ION - help - Choose this option to create a device that can be used to test the - kernel and device side ION functions. - -config ION_DUMMY - bool "Dummy Ion driver" - depends on ION - help - Provides a dummy ION driver that registers the - /dev/ion device and some basic heaps. This can - be used for testing the ION infrastructure if - one doesn't have access to hardware drivers that - use ION. - -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. - -config ION_HISI - tristate "Ion for Hisilicon" - depends on ARCH_HISI && ION - select ION_OF - help - Choose this option if you wish to use ion on Hisilicon Platform. - -source "drivers/staging/android/ion/hisilicon/Kconfig" - -config ION_OF - bool "Devicetree support for Ion" - depends on ION && OF_ADDRESS - help - Provides base support for defining Ion heaps in devicetree - and setting them up. Also includes functions for platforms - to parse the devicetree and expand for their own custom - extensions - - If using Ion and devicetree, you should say Y here diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 5d630a0..26672a0 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,13 +1,6 @@ obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \ ion_page_pool.o ion_system_heap.o \ ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o -obj-$(CONFIG_ION_TEST) += ion_test.o ifdef CONFIG_COMPAT obj-$(CONFIG_ION) += compat_ion.o endif - -obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o -obj-$(CONFIG_ION_TEGRA) += tegra/ -obj-$(CONFIG_ION_HISI) += hisilicon/ -obj-$(CONFIG_ION_OF) += ion_of.o - diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c index 9a978d2..5037ddd 100644 --- a/drivers/staging/android/ion/compat_ion.c +++ b/drivers/staging/android/ion/compat_ion.c @@ -30,11 +30,6 @@ struct compat_ion_allocation_data { compat_int_t handle; }; -struct compat_ion_custom_data { - compat_uint_t cmd; - compat_ulong_t arg; -}; - struct compat_ion_handle_data { compat_int_t handle; }; @@ -43,8 +38,6 @@ struct compat_ion_handle_data { struct compat_ion_allocation_data) #define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, \ struct compat_ion_handle_data) -#define COMPAT_ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, \ - struct compat_ion_custom_data) static int compat_get_ion_allocation_data( struct compat_ion_allocation_data __user *data32, @@ -105,22 +98,6 @@ static int compat_put_ion_allocation_data( return err; } -static int compat_get_ion_custom_data( - struct compat_ion_custom_data __user *data32, - struct ion_custom_data __user *data) -{ - compat_uint_t cmd; - compat_ulong_t arg; - int err; - - err = get_user(cmd, &data32->cmd); - err |= put_user(cmd, &data->cmd); - err |= get_user(arg, &data32->arg); - err |= put_user(arg, &data->arg); - - return err; -}; - long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { long ret; @@ -166,27 +143,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return filp->f_op->unlocked_ioctl(filp, ION_IOC_FREE, (unsigned long)data); } - case COMPAT_ION_IOC_CUSTOM: { - struct compat_ion_custom_data __user *data32; - struct ion_custom_data __user *data; - int err; - - data32 = compat_ptr(arg); - data = compat_alloc_user_space(sizeof(*data)); - if (!data) - return -EFAULT; - - err = compat_get_ion_custom_data(data32, data); - if (err) - return err; - - return filp->f_op->unlocked_ioctl(filp, ION_IOC_CUSTOM, - (unsigned long)data); - } case ION_IOC_SHARE: - case ION_IOC_MAP: - case ION_IOC_IMPORT: - case ION_IOC_SYNC: return filp->f_op->unlocked_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); default: diff --git a/drivers/staging/android/ion/hisilicon/Kconfig b/drivers/staging/android/ion/hisilicon/Kconfig deleted file mode 100644 index 2b4bd07..0000000 --- a/drivers/staging/android/ion/hisilicon/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -config HI6220_ION - bool "Hi6220 ION Driver" - depends on ARCH_HISI && ION - help - Build the Hisilicon Hi6220 ion driver. diff --git a/drivers/staging/android/ion/hisilicon/Makefile b/drivers/staging/android/ion/hisilicon/Makefile deleted file mode 100644 index 2a89414..0000000 --- a/drivers/staging/android/ion/hisilicon/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_HI6220_ION) += hi6220_ion.o diff --git a/drivers/staging/android/ion/hisilicon/hi6220_ion.c b/drivers/staging/android/ion/hisilicon/hi6220_ion.c deleted file mode 100644 index 0de7897..0000000 --- a/drivers/staging/android/ion/hisilicon/hi6220_ion.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Hisilicon Hi6220 ION Driver - * - * Copyright (c) 2015 Hisilicon Limited. - * - * Author: Chen Feng <puck.chen@hisilicon.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define pr_fmt(fmt) "Ion: " fmt - -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/of.h> -#include <linux/mm.h> -#include "../ion_priv.h" -#include "../ion.h" -#include "../ion_of.h" - -struct hisi_ion_dev { - struct ion_heap **heaps; - struct ion_device *idev; - struct ion_platform_data *data; -}; - -static struct ion_of_heap hisi_heaps[] = { - PLATFORM_HEAP("hisilicon,sys_user", 0, - ION_HEAP_TYPE_SYSTEM, "sys_user"), - PLATFORM_HEAP("hisilicon,sys_contig", 1, - ION_HEAP_TYPE_SYSTEM_CONTIG, "sys_contig"), - PLATFORM_HEAP("hisilicon,cma", ION_HEAP_TYPE_DMA, ION_HEAP_TYPE_DMA, - "cma"), - {} -}; - -static int hi6220_ion_probe(struct platform_device *pdev) -{ - struct hisi_ion_dev *ipdev; - int i; - - ipdev = devm_kzalloc(&pdev->dev, sizeof(*ipdev), GFP_KERNEL); - if (!ipdev) - return -ENOMEM; - - platform_set_drvdata(pdev, ipdev); - - ipdev->idev = ion_device_create(NULL); - if (IS_ERR(ipdev->idev)) - return PTR_ERR(ipdev->idev); - - ipdev->data = ion_parse_dt(pdev, hisi_heaps); - if (IS_ERR(ipdev->data)) - return PTR_ERR(ipdev->data); - - ipdev->heaps = devm_kzalloc(&pdev->dev, - sizeof(struct ion_heap) * ipdev->data->nr, - GFP_KERNEL); - if (!ipdev->heaps) { - ion_destroy_platform_data(ipdev->data); - return -ENOMEM; - } - - for (i = 0; i < ipdev->data->nr; i++) { - ipdev->heaps[i] = ion_heap_create(&ipdev->data->heaps[i]); - if (!ipdev->heaps) { - ion_destroy_platform_data(ipdev->data); - return -ENOMEM; - } - ion_device_add_heap(ipdev->idev, ipdev->heaps[i]); - } - return 0; -} - -static int hi6220_ion_remove(struct platform_device *pdev) -{ - struct hisi_ion_dev *ipdev; - int i; - - ipdev = platform_get_drvdata(pdev); - - for (i = 0; i < ipdev->data->nr; i++) - ion_heap_destroy(ipdev->heaps[i]); - - ion_destroy_platform_data(ipdev->data); - ion_device_destroy(ipdev->idev); - - return 0; -} - -static const struct of_device_id hi6220_ion_match_table[] = { - {.compatible = "hisilicon,hi6220-ion"}, - {}, -}; - -static struct platform_driver hi6220_ion_driver = { - .probe = hi6220_ion_probe, - .remove = hi6220_ion_remove, - .driver = { - .name = "ion-hi6220", - .of_match_table = hi6220_ion_match_table, - }, -}; - -static int __init hi6220_ion_init(void) -{ - return platform_driver_register(&hi6220_ion_driver); -} - -subsys_initcall(hi6220_ion_init); diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index 9ff815a..a361724 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -26,7 +26,6 @@ union ion_ioctl_arg { struct ion_fd_data fd; struct ion_allocation_data allocation; struct ion_handle_data handle; - struct ion_custom_data custom; struct ion_heap_query query; }; @@ -51,9 +50,7 @@ static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg) static unsigned int ion_ioctl_dir(unsigned int cmd) { switch (cmd) { - case ION_IOC_SYNC: case ION_IOC_FREE: - case ION_IOC_CUSTOM: return _IOC_WRITE; default: return _IOC_DIR(cmd); @@ -63,7 +60,6 @@ static unsigned int ion_ioctl_dir(unsigned int cmd) long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct ion_client *client = filp->private_data; - struct ion_device *dev = client->dev; struct ion_handle *cleanup_handle = NULL; int ret = 0; unsigned int dir; @@ -95,7 +91,6 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct ion_handle *handle; handle = ion_alloc(client, data.allocation.len, - data.allocation.align, data.allocation.heap_id_mask, data.allocation.flags); if (IS_ERR(handle)) @@ -123,7 +118,6 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; } case ION_IOC_SHARE: - case ION_IOC_MAP: { struct ion_handle *handle; @@ -136,30 +130,6 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ret = data.fd.fd; break; } - case ION_IOC_IMPORT: - { - struct ion_handle *handle; - - handle = ion_import_dma_buf_fd(client, data.fd.fd); - if (IS_ERR(handle)) - ret = PTR_ERR(handle); - else - data.handle.handle = handle->id; - break; - } - case ION_IOC_SYNC: - { - ret = ion_sync_for_device(client, data.fd.fd); - break; - } - case ION_IOC_CUSTOM: - { - if (!dev->custom_ioctl) - return -ENOTTY; - ret = dev->custom_ioctl(client, data.custom.cmd, - data.custom.arg); - break; - } case ION_IOC_HEAP_QUERY: ret = ion_query_heaps(client, &data.query); break; diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index f45115f..3d979ef 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -42,37 +42,11 @@ #include "ion_priv.h" #include "compat_ion.h" -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); } -static inline struct page *ion_buffer_page(struct page *page) -{ - return (struct page *)((unsigned long)page & ~(1UL)); -} - -static inline bool ion_buffer_page_is_dirty(struct page *page) -{ - return !!((unsigned long)page & 1UL); -} - -static inline void ion_buffer_page_dirty(struct page **page) -{ - *page = (struct page *)((unsigned long)(*page) | 1UL); -} - -static inline void ion_buffer_page_clean(struct page **page) -{ - *page = (struct page *)((unsigned long)(*page) & ~(1UL)); -} - /* this function should only be called while dev->lock is held */ static void ion_buffer_add(struct ion_device *dev, struct ion_buffer *buffer) @@ -103,7 +77,6 @@ static void ion_buffer_add(struct ion_device *dev, 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; @@ -119,15 +92,14 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->flags = flags; kref_init(&buffer->ref); - ret = heap->ops->allocate(heap, buffer, len, align, flags); + ret = heap->ops->allocate(heap, buffer, len, flags); if (ret) { if (!(heap->flags & ION_HEAP_FLAG_DEFER_FREE)) goto err2; ion_heap_freelist_drain(heap, 0); - ret = heap->ops->allocate(heap, buffer, len, align, - flags); + ret = heap->ops->allocate(heap, buffer, len, flags); if (ret) goto err2; } @@ -142,28 +114,10 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->dev = dev; buffer->size = len; - if (ion_buffer_fault_user_mappings(buffer)) { - int num_pages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; - struct scatterlist *sg; - int i, j, k = 0; - - buffer->pages = vmalloc(sizeof(struct page *) * num_pages); - if (!buffer->pages) { - ret = -ENOMEM; - goto err1; - } - - for_each_sg(table->sgl, sg, table->nents, i) { - struct page *page = sg_page(sg); - - for (j = 0; j < sg->length / PAGE_SIZE; j++) - buffer->pages[k++] = page++; - } - } - buffer->dev = dev; buffer->size = len; INIT_LIST_HEAD(&buffer->vmas); + INIT_LIST_HEAD(&buffer->attachments); mutex_init(&buffer->lock); /* * this will set up dma addresses for the sglist -- it is not @@ -320,24 +274,6 @@ int ion_handle_put(struct ion_handle *handle) return ret; } -static struct ion_handle *ion_handle_lookup(struct ion_client *client, - struct ion_buffer *buffer) -{ - struct rb_node *n = client->handles.rb_node; - - while (n) { - struct ion_handle *entry = rb_entry(n, struct ion_handle, node); - - if (buffer < entry->buffer) - n = n->rb_left; - else if (buffer > entry->buffer) - n = n->rb_right; - else - return entry; - } - return ERR_PTR(-EINVAL); -} - struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, int id) { @@ -401,7 +337,7 @@ static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) } struct ion_handle *ion_alloc(struct ion_client *client, size_t len, - size_t align, unsigned int heap_id_mask, + unsigned int heap_id_mask, unsigned int flags) { struct ion_handle *handle; @@ -410,8 +346,8 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, struct ion_heap *heap; int ret; - pr_debug("%s: len %zu align %zu heap_id_mask %u flags %x\n", __func__, - len, align, heap_id_mask, flags); + pr_debug("%s: len %zu heap_id_mask %u flags %x\n", __func__, + len, heap_id_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 @@ -428,7 +364,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, /* if the caller didn't specify this heap id */ if (!((1 << heap->id) & heap_id_mask)) continue; - buffer = ion_buffer_create(heap, dev, len, align, flags); + buffer = ion_buffer_create(heap, dev, len, flags); if (!IS_ERR(buffer)) break; } @@ -798,136 +734,116 @@ void ion_client_destroy(struct ion_client *client) } EXPORT_SYMBOL(ion_client_destroy); -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) +static struct sg_table *dup_sg_table(struct sg_table *table) { - struct dma_buf *dmabuf = attachment->dmabuf; - struct ion_buffer *buffer = dmabuf->priv; + struct sg_table *new_table; + int ret, i; + struct scatterlist *sg, *new_sg; - ion_buffer_sync_for_device(buffer, attachment->dev, direction); - return buffer->sg_table; -} + new_table = kzalloc(sizeof(*new_table), GFP_KERNEL); + if (!new_table) + return ERR_PTR(-ENOMEM); -static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, - struct sg_table *table, - enum dma_data_direction direction) -{ + ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL); + if (ret) { + kfree(new_table); + return ERR_PTR(-ENOMEM); + } + + new_sg = new_table->sgl; + for_each_sg(table->sgl, sg, table->nents, i) { + memcpy(new_sg, sg, sizeof(*sg)); + sg->dma_address = 0; + new_sg = sg_next(new_sg); + } + + return new_table; } -void ion_pages_sync_for_device(struct device *dev, struct page *page, - size_t size, enum dma_data_direction dir) +static void free_duped_table(struct sg_table *table) { - struct scatterlist sg; - - sg_init_table(&sg, 1); - sg_set_page(&sg, page, size, 0); - /* - * This is not correct - sg_dma_address needs a dma_addr_t that is valid - * for the targeted device, but this works on the currently targeted - * hardware. - */ - sg_dma_address(&sg) = page_to_phys(page); - dma_sync_sg_for_device(dev, &sg, 1, dir); + sg_free_table(table); + kfree(table); } -struct ion_vma_list { +struct ion_dma_buf_attachment { + struct device *dev; + struct sg_table *table; 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) +static int ion_dma_buf_attach(struct dma_buf *dmabuf, struct device *dev, + struct dma_buf_attachment *attachment) { - struct ion_vma_list *vma_list; - int pages = PAGE_ALIGN(buffer->size) / PAGE_SIZE; - int i; - - 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 (i = 0; i < pages; i++) { - struct page *page = buffer->pages[i]; + struct ion_dma_buf_attachment *a; + struct sg_table *table; + struct ion_buffer *buffer = dmabuf->priv; - if (ion_buffer_page_is_dirty(page)) - ion_pages_sync_for_device(dev, ion_buffer_page(page), - PAGE_SIZE, dir); + a = kzalloc(sizeof(*a), GFP_KERNEL); + if (!a) + return -ENOMEM; - ion_buffer_page_clean(buffer->pages + i); + table = dup_sg_table(buffer->sg_table); + if (IS_ERR(table)) { + kfree(a); + return -ENOMEM; } - 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); - } - mutex_unlock(&buffer->lock); -} + a->table = table; + a->dev = dev; + INIT_LIST_HEAD(&a->list); -static int ion_vm_fault(struct vm_fault *vmf) -{ - struct ion_buffer *buffer = vmf->vma->vm_private_data; - unsigned long pfn; - int ret; + attachment->priv = a; mutex_lock(&buffer->lock); - ion_buffer_page_dirty(buffer->pages + vmf->pgoff); - BUG_ON(!buffer->pages || !buffer->pages[vmf->pgoff]); - - pfn = page_to_pfn(ion_buffer_page(buffer->pages[vmf->pgoff])); - ret = vm_insert_pfn(vmf->vma, vmf->address, pfn); + list_add(&a->list, &buffer->attachments); mutex_unlock(&buffer->lock); - if (ret) - return VM_FAULT_ERROR; - return VM_FAULT_NOPAGE; + return 0; } -static void ion_vm_open(struct vm_area_struct *vma) +static void ion_dma_buf_detatch(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) { - struct ion_buffer *buffer = vma->vm_private_data; - struct ion_vma_list *vma_list; + struct ion_dma_buf_attachment *a = attachment->priv; + struct ion_buffer *buffer = dmabuf->priv; - vma_list = kmalloc(sizeof(*vma_list), GFP_KERNEL); - if (!vma_list) - return; - vma_list->vma = vma; + free_duped_table(a->table); mutex_lock(&buffer->lock); - list_add(&vma_list->list, &buffer->vmas); + list_del(&a->list); mutex_unlock(&buffer->lock); - pr_debug("%s: adding %p\n", __func__, vma); + + kfree(a); } -static void ion_vm_close(struct vm_area_struct *vma) + +static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction direction) { - struct ion_buffer *buffer = vma->vm_private_data; - struct ion_vma_list *vma_list, *tmp; + struct ion_dma_buf_attachment *a = attachment->priv; + struct sg_table *table; + int ret; - 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; + table = a->table; + + if (!dma_map_sg(attachment->dev, table->sgl, table->nents, + direction)){ + ret = -ENOMEM; + goto err; } - mutex_unlock(&buffer->lock); + return table; + +err: + free_duped_table(table); + return ERR_PTR(ret); } -static const struct vm_operations_struct ion_vma_ops = { - .open = ion_vm_open, - .close = ion_vm_close, - .fault = ion_vm_fault, -}; +static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *table, + enum dma_data_direction direction) +{ + dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction); +} static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) { @@ -940,15 +856,6 @@ static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) return -EINVAL; } - if (ion_buffer_fault_user_mappings(buffer)) { - vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | - VM_DONTDUMP; - 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); @@ -988,26 +895,45 @@ static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, { struct ion_buffer *buffer = dmabuf->priv; void *vaddr; + struct ion_dma_buf_attachment *a; - if (!buffer->heap->ops->map_kernel) { - pr_err("%s: map kernel is not implemented by this heap.\n", - __func__); - return -ENODEV; + /* + * TODO: Move this elsewhere because we don't always need a vaddr + */ + if (buffer->heap->ops->map_kernel) { + mutex_lock(&buffer->lock); + vaddr = ion_buffer_kmap_get(buffer); + mutex_unlock(&buffer->lock); } + mutex_lock(&buffer->lock); - vaddr = ion_buffer_kmap_get(buffer); + list_for_each_entry(a, &buffer->attachments, list) { + dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents, + DMA_BIDIRECTIONAL); + } mutex_unlock(&buffer->lock); - return PTR_ERR_OR_ZERO(vaddr); + + return 0; } static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction direction) { struct ion_buffer *buffer = dmabuf->priv; + struct ion_dma_buf_attachment *a; + + if (buffer->heap->ops->map_kernel) { + mutex_lock(&buffer->lock); + ion_buffer_kmap_put(buffer); + mutex_unlock(&buffer->lock); + } mutex_lock(&buffer->lock); - ion_buffer_kmap_put(buffer); + list_for_each_entry(a, &buffer->attachments, list) { + dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents, + DMA_BIDIRECTIONAL); + } mutex_unlock(&buffer->lock); return 0; @@ -1018,6 +944,8 @@ static const struct dma_buf_ops dma_buf_ops = { .unmap_dma_buf = ion_unmap_dma_buf, .mmap = ion_mmap, .release = ion_dma_buf_release, + .attach = ion_dma_buf_attach, + .detach = ion_dma_buf_detatch, .begin_cpu_access = ion_dma_buf_begin_cpu_access, .end_cpu_access = ion_dma_buf_end_cpu_access, .kmap_atomic = ion_dma_buf_kmap, @@ -1077,88 +1005,6 @@ int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle) } EXPORT_SYMBOL(ion_share_dma_buf_fd); -struct ion_handle *ion_import_dma_buf(struct ion_client *client, - struct dma_buf *dmabuf) -{ - struct ion_buffer *buffer; - struct ion_handle *handle; - int ret; - - /* if this memory came from ion */ - - if (dmabuf->ops != &dma_buf_ops) { - pr_err("%s: can not import dmabuf from another exporter\n", - __func__); - 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(handle)) { - ion_handle_get(handle); - mutex_unlock(&client->lock); - goto end; - } - - handle = ion_handle_create(client, buffer); - if (IS_ERR(handle)) { - mutex_unlock(&client->lock); - goto end; - } - - ret = ion_handle_add(client, handle); - mutex_unlock(&client->lock); - if (ret) { - ion_handle_put(handle); - handle = ERR_PTR(ret); - } - -end: - return handle; -} -EXPORT_SYMBOL(ion_import_dma_buf); - -struct ion_handle *ion_import_dma_buf_fd(struct ion_client *client, int fd) -{ - struct dma_buf *dmabuf; - struct ion_handle *handle; - - dmabuf = dma_buf_get(fd); - if (IS_ERR(dmabuf)) - return ERR_CAST(dmabuf); - - handle = ion_import_dma_buf(client, dmabuf); - dma_buf_put(dmabuf); - return handle; -} -EXPORT_SYMBOL(ion_import_dma_buf_fd); - -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(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; -} - int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query) { struct ion_device *dev = client->dev; @@ -1425,10 +1271,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) } EXPORT_SYMBOL(ion_device_add_heap); -struct ion_device *ion_device_create(long (*custom_ioctl) - (struct ion_client *client, - unsigned int cmd, - unsigned long arg)) +struct ion_device *ion_device_create(void) { struct ion_device *idev; int ret; @@ -1465,7 +1308,6 @@ struct ion_device *ion_device_create(long (*custom_ioctl) debugfs_done: - idev->custom_ioctl = custom_ioctl; idev->buffers = RB_ROOT; mutex_init(&idev->buffer_lock); init_rwsem(&idev->lock); diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 93dafb4..3b4bff5 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -45,7 +45,6 @@ struct ion_buffer; * @name: used for debug purposes * @base: base address of heap in physical memory if applicable * @size: size of the heap in bytes if applicable - * @align: required alignment in physical memory if applicable * @priv: private info passed from the board file * * Provided by the board file. @@ -93,8 +92,6 @@ void ion_client_destroy(struct ion_client *client); * ion_alloc - allocate ion memory * @client: the client * @len: size of the allocation - * @align: requested allocation alignment, lots of hardware blocks - * have alignment requirements of some kind * @heap_id_mask: mask of heaps to allocate from, if multiple bits are set * heaps will be tried in order from highest to lowest * id @@ -106,7 +103,7 @@ void ion_client_destroy(struct ion_client *client); * an opaque handle to it. */ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, - size_t align, unsigned int heap_id_mask, + unsigned int heap_id_mask, unsigned int flags); /** diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index a8ea973..e0e360f 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -34,8 +34,7 @@ struct ion_carveout_heap { }; static ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, - unsigned long size, - unsigned long align) + unsigned long size) { struct ion_carveout_heap *carveout_heap = container_of(heap, struct ion_carveout_heap, heap); @@ -60,16 +59,13 @@ static void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, static int ion_carveout_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, - unsigned long size, unsigned long align, + unsigned long size, unsigned long flags) { struct sg_table *table; ion_phys_addr_t paddr; int ret; - if (align > PAGE_SIZE) - return -EINVAL; - table = kmalloc(sizeof(*table), GFP_KERNEL); if (!table) return -ENOMEM; @@ -77,7 +73,7 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, if (ret) goto err_free; - paddr = ion_carveout_allocate(heap, size, align); + paddr = ion_carveout_allocate(heap, size); if (paddr == ION_CARVEOUT_ALLOCATE_FAIL) { ret = -ENOMEM; goto err_free_table; @@ -104,10 +100,6 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer) ion_heap_buffer_zero(buffer); - if (ion_buffer_cached(buffer)) - dma_sync_sg_for_device(NULL, table->sgl, table->nents, - DMA_BIDIRECTIONAL); - ion_carveout_free(heap, paddr, buffer->size); sg_free_table(table); kfree(table); @@ -132,8 +124,6 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) page = pfn_to_page(PFN_DOWN(heap_data->base)); size = heap_data->size; - ion_pages_sync_for_device(NULL, page, size, DMA_BIDIRECTIONAL); - ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL)); if (ret) return ERR_PTR(ret); diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 70495dc..46e13f6 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -35,7 +35,7 @@ struct ion_chunk_heap { static int ion_chunk_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, - unsigned long size, unsigned long align, + unsigned long size, unsigned long flags) { struct ion_chunk_heap *chunk_heap = @@ -46,9 +46,6 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, unsigned long num_chunks; unsigned long allocated_size; - if (align > chunk_heap->chunk_size) - return -EINVAL; - allocated_size = ALIGN(size, chunk_heap->chunk_size); num_chunks = allocated_size / chunk_heap->chunk_size; @@ -104,10 +101,6 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) ion_heap_buffer_zero(buffer); - if (ion_buffer_cached(buffer)) - dma_sync_sg_for_device(NULL, table->sgl, table->nents, - DMA_BIDIRECTIONAL); - for_each_sg(table->sgl, sg, table->nents, i) { gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)), sg->length); @@ -135,8 +128,6 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) page = pfn_to_page(PFN_DOWN(heap_data->base)); size = heap_data->size; - ion_pages_sync_for_device(NULL, page, size, DMA_BIDIRECTIONAL); - ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL)); if (ret) return ERR_PTR(ret); @@ -160,8 +151,8 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; - pr_debug("%s: base %lu size %zu align %ld\n", __func__, - chunk_heap->base, heap_data->size, heap_data->align); + pr_debug("%s: base %lu size %zu \n", __func__, + chunk_heap->base, heap_data->size); return &chunk_heap->heap; diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 6c40685..d562fd7 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -40,7 +40,7 @@ struct ion_cma_buffer_info { /* ION CMA heap operations functions */ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, - unsigned long len, unsigned long align, + unsigned long len, unsigned long flags) { struct ion_cma_heap *cma_heap = to_cma_heap(heap); @@ -52,9 +52,6 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, if (buffer->flags & ION_FLAG_CACHED) return -EINVAL; - if (align > PAGE_SIZE) - return -EINVAL; - info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; diff --git a/drivers/staging/android/ion/ion_dummy_driver.c b/drivers/staging/android/ion/ion_dummy_driver.c deleted file mode 100644 index cf5c010..0000000 --- a/drivers/staging/android/ion/ion_dummy_driver.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * drivers/gpu/ion/ion_dummy_driver.c - * - * Copyright (C) 2013 Linaro, 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/platform_device.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/bootmem.h> -#include <linux/memblock.h> -#include <linux/sizes.h> -#include <linux/io.h> -#include "ion.h" -#include "ion_priv.h" - -static struct ion_device *idev; -static struct ion_heap **heaps; - -static void *carveout_ptr; -static void *chunk_ptr; - -static struct ion_platform_heap dummy_heaps[] = { - { - .id = ION_HEAP_TYPE_SYSTEM, - .type = ION_HEAP_TYPE_SYSTEM, - .name = "system", - }, - { - .id = ION_HEAP_TYPE_SYSTEM_CONTIG, - .type = ION_HEAP_TYPE_SYSTEM_CONTIG, - .name = "system contig", - }, - { - .id = ION_HEAP_TYPE_CARVEOUT, - .type = ION_HEAP_TYPE_CARVEOUT, - .name = "carveout", - .size = SZ_4M, - }, - { - .id = ION_HEAP_TYPE_CHUNK, - .type = ION_HEAP_TYPE_CHUNK, - .name = "chunk", - .size = SZ_4M, - .align = SZ_16K, - .priv = (void *)(SZ_16K), - }, -}; - -static const struct ion_platform_data dummy_ion_pdata = { - .nr = ARRAY_SIZE(dummy_heaps), - .heaps = dummy_heaps, -}; - -static int __init ion_dummy_init(void) -{ - int i, err; - - idev = ion_device_create(NULL); - if (IS_ERR(idev)) - return PTR_ERR(idev); - heaps = kcalloc(dummy_ion_pdata.nr, sizeof(struct ion_heap *), - GFP_KERNEL); - if (!heaps) - return -ENOMEM; - - - /* Allocate a dummy carveout heap */ - carveout_ptr = alloc_pages_exact( - dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size, - GFP_KERNEL); - if (carveout_ptr) - dummy_heaps[ION_HEAP_TYPE_CARVEOUT].base = - virt_to_phys(carveout_ptr); - else - pr_err("ion_dummy: Could not allocate carveout\n"); - - /* Allocate a dummy chunk heap */ - chunk_ptr = alloc_pages_exact( - dummy_heaps[ION_HEAP_TYPE_CHUNK].size, - GFP_KERNEL); - if (chunk_ptr) - dummy_heaps[ION_HEAP_TYPE_CHUNK].base = virt_to_phys(chunk_ptr); - else - pr_err("ion_dummy: Could not allocate chunk\n"); - - for (i = 0; i < dummy_ion_pdata.nr; i++) { - struct ion_platform_heap *heap_data = &dummy_ion_pdata.heaps[i]; - - if (heap_data->type == ION_HEAP_TYPE_CARVEOUT && - !heap_data->base) - continue; - - if (heap_data->type == ION_HEAP_TYPE_CHUNK && !heap_data->base) - continue; - - 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]); - } - return 0; -err: - for (i = 0; i < dummy_ion_pdata.nr; ++i) - ion_heap_destroy(heaps[i]); - kfree(heaps); - - if (carveout_ptr) { - free_pages_exact(carveout_ptr, - dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); - carveout_ptr = NULL; - } - if (chunk_ptr) { - free_pages_exact(chunk_ptr, - dummy_heaps[ION_HEAP_TYPE_CHUNK].size); - chunk_ptr = NULL; - } - return err; -} -device_initcall(ion_dummy_init); - -static void __exit ion_dummy_exit(void) -{ - int i; - - ion_device_destroy(idev); - - for (i = 0; i < dummy_ion_pdata.nr; i++) - ion_heap_destroy(heaps[i]); - kfree(heaps); - - if (carveout_ptr) { - free_pages_exact(carveout_ptr, - dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); - carveout_ptr = NULL; - } - if (chunk_ptr) { - free_pages_exact(chunk_ptr, - dummy_heaps[ION_HEAP_TYPE_CHUNK].size); - chunk_ptr = NULL; - } -} -__exitcall(ion_dummy_exit); diff --git a/drivers/staging/android/ion/ion_of.c b/drivers/staging/android/ion/ion_of.c deleted file mode 100644 index 7791c70..0000000 --- a/drivers/staging/android/ion/ion_of.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Based on work from: - * Andrew Andrianov <andrew@ncrmnt.org> - * Google - * The Linux Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_platform.h> -#include <linux/of_address.h> -#include <linux/clk.h> -#include <linux/dma-mapping.h> -#include <linux/cma.h> -#include <linux/dma-contiguous.h> -#include <linux/io.h> -#include <linux/of_reserved_mem.h> -#include "ion.h" -#include "ion_priv.h" -#include "ion_of.h" - -static int ion_parse_dt_heap_common(struct device_node *heap_node, - struct ion_platform_heap *heap, - struct ion_of_heap *compatible) -{ - int i; - - for (i = 0; compatible[i].name; i++) { - if (of_device_is_compatible(heap_node, compatible[i].compat)) - break; - } - - if (!compatible[i].name) - return -ENODEV; - - heap->id = compatible[i].heap_id; - heap->type = compatible[i].type; - heap->name = compatible[i].name; - heap->align = compatible[i].align; - - /* Some kind of callback function pointer? */ - - pr_info("%s: id %d type %d name %s align %lx\n", __func__, - heap->id, heap->type, heap->name, heap->align); - return 0; -} - -static int ion_setup_heap_common(struct platform_device *parent, - struct device_node *heap_node, - struct ion_platform_heap *heap) -{ - int ret = 0; - - switch (heap->type) { - case ION_HEAP_TYPE_CARVEOUT: - case ION_HEAP_TYPE_CHUNK: - if (heap->base && heap->size) - return 0; - - ret = of_reserved_mem_device_init(heap->priv); - break; - default: - break; - } - - return ret; -} - -struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, - struct ion_of_heap *compatible) -{ - int num_heaps, ret; - const struct device_node *dt_node = pdev->dev.of_node; - struct device_node *node; - struct ion_platform_heap *heaps; - struct ion_platform_data *data; - int i = 0; - - num_heaps = of_get_available_child_count(dt_node); - - if (!num_heaps) - return ERR_PTR(-EINVAL); - - heaps = devm_kzalloc(&pdev->dev, - sizeof(struct ion_platform_heap) * num_heaps, - GFP_KERNEL); - if (!heaps) - return ERR_PTR(-ENOMEM); - - data = devm_kzalloc(&pdev->dev, sizeof(struct ion_platform_data), - GFP_KERNEL); - if (!data) - return ERR_PTR(-ENOMEM); - - for_each_available_child_of_node(dt_node, node) { - struct platform_device *heap_pdev; - - ret = ion_parse_dt_heap_common(node, &heaps[i], compatible); - if (ret) - return ERR_PTR(ret); - - heap_pdev = of_platform_device_create(node, heaps[i].name, - &pdev->dev); - if (!heap_pdev) - return ERR_PTR(-ENOMEM); - heap_pdev->dev.platform_data = &heaps[i]; - - heaps[i].priv = &heap_pdev->dev; - - ret = ion_setup_heap_common(pdev, node, &heaps[i]); - if (ret) - goto out_err; - i++; - } - - data->heaps = heaps; - data->nr = num_heaps; - return data; - -out_err: - for ( ; i >= 0; i--) - if (heaps[i].priv) - of_device_unregister(to_platform_device(heaps[i].priv)); - - return ERR_PTR(ret); -} - -void ion_destroy_platform_data(struct ion_platform_data *data) -{ - int i; - - for (i = 0; i < data->nr; i++) - if (data->heaps[i].priv) - of_device_unregister(to_platform_device( - data->heaps[i].priv)); -} - -#ifdef CONFIG_OF_RESERVED_MEM -#include <linux/of.h> -#include <linux/of_fdt.h> -#include <linux/of_reserved_mem.h> - -static int rmem_ion_device_init(struct reserved_mem *rmem, struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct ion_platform_heap *heap = pdev->dev.platform_data; - - heap->base = rmem->base; - heap->base = rmem->size; - pr_debug("%s: heap %s base %pa size %pa dev %p\n", __func__, - heap->name, &rmem->base, &rmem->size, dev); - return 0; -} - -static void rmem_ion_device_release(struct reserved_mem *rmem, - struct device *dev) -{ -} - -static const struct reserved_mem_ops rmem_dma_ops = { - .device_init = rmem_ion_device_init, - .device_release = rmem_ion_device_release, -}; - -static int __init rmem_ion_setup(struct reserved_mem *rmem) -{ - phys_addr_t size = rmem->size; - - size = size / 1024; - - pr_info("Ion memory setup at %pa size %pa MiB\n", - &rmem->base, &size); - rmem->ops = &rmem_dma_ops; - return 0; -} - -RESERVEDMEM_OF_DECLARE(ion, "ion-region", rmem_ion_setup); -#endif diff --git a/drivers/staging/android/ion/ion_of.h b/drivers/staging/android/ion/ion_of.h deleted file mode 100644 index 8241a17..0000000 --- a/drivers/staging/android/ion/ion_of.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Based on work from: - * Andrew Andrianov <andrew@ncrmnt.org> - * Google - * The Linux Foundation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _ION_OF_H -#define _ION_OF_H - -struct ion_of_heap { - const char *compat; - int heap_id; - int type; - const char *name; - int align; -}; - -#define PLATFORM_HEAP(_compat, _id, _type, _name) \ -{ \ - .compat = _compat, \ - .heap_id = _id, \ - .type = _type, \ - .name = _name, \ - .align = PAGE_SIZE, \ -} - -struct ion_platform_data *ion_parse_dt(struct platform_device *pdev, - struct ion_of_heap *compatible); - -void ion_destroy_platform_data(struct ion_platform_data *data); - -#endif diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index aea89c1..532eda7 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -30,9 +30,6 @@ static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) if (!page) return NULL; - if (!pool->cached) - ion_pages_sync_for_device(NULL, page, PAGE_SIZE << pool->order, - DMA_BIDIRECTIONAL); return page; } diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 5b3059c7..a86866a 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -44,7 +44,6 @@ * @lock: protects the buffers cnt fields * @kmap_cnt: number of times the buffer is mapped to the kernel * @vaddr: the kernel 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 * @pages: flat array of pages in the buffer -- used by fault * handler and only valid for buffers that are faulted in @@ -70,10 +69,10 @@ struct ion_buffer { struct mutex lock; int kmap_cnt; void *vaddr; - int dmap_cnt; struct sg_table *sg_table; struct page **pages; struct list_head vmas; + struct list_head attachments; /* used to track orphaned buffers */ int handle_count; char task_comm[TASK_COMM_LEN]; @@ -96,8 +95,6 @@ struct ion_device { struct mutex buffer_lock; struct rw_semaphore lock; struct plist_head heaps; - long (*custom_ioctl)(struct ion_client *client, unsigned int cmd, - unsigned long arg); struct rb_root clients; struct dentry *debug_root; struct dentry *heaps_debug_root; @@ -174,7 +171,7 @@ struct ion_handle { struct ion_heap_ops { int (*allocate)(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len, - unsigned long align, unsigned long flags); + unsigned long flags); void (*free)(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); @@ -261,14 +258,10 @@ 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)); +struct ion_device *ion_device_create(void); /** * ion_device_destroy - free and device and it's resource @@ -441,21 +434,8 @@ void ion_page_pool_free(struct ion_page_pool *pool, struct page *page); int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, int nr_to_scan); -/** - * ion_pages_sync_for_device - cache flush pages for use with the specified - * device - * @dev: the device the pages will be used with - * @page: the first page to be flushed - * @size: size in bytes of region to be flushed - * @dir: direction of dma transfer - */ -void ion_pages_sync_for_device(struct device *dev, struct page *page, - size_t size, enum dma_data_direction dir); - long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -int ion_sync_for_device(struct ion_client *client, int fd); - struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, int id); diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 3ebbb75..a33331b 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -75,9 +75,6 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, page = ion_page_pool_alloc(pool); - if (cached) - ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order, - DMA_BIDIRECTIONAL); return page; } @@ -129,7 +126,7 @@ static struct page *alloc_largest_available(struct ion_system_heap *heap, static int ion_system_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, - unsigned long size, unsigned long align, + unsigned long size, unsigned long flags) { struct ion_system_heap *sys_heap = container_of(heap, @@ -143,9 +140,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, unsigned long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; - if (align > PAGE_SIZE) - return -EINVAL; - if (size / PAGE_SIZE > totalram_pages / 2) return -ENOMEM; @@ -372,7 +366,6 @@ void ion_system_heap_destroy(struct ion_heap *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) { int order = get_order(len); @@ -381,9 +374,6 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap, unsigned long i; int ret; - if (align > (PAGE_SIZE << order)) - return -EINVAL; - page = alloc_pages(low_order_gfp_flags, order); if (!page) return -ENOMEM; @@ -408,8 +398,6 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap, buffer->sg_table = table; - ion_pages_sync_for_device(NULL, page, len, DMA_BIDIRECTIONAL); - return 0; free_table: diff --git a/drivers/staging/android/ion/ion_test.c b/drivers/staging/android/ion/ion_test.c deleted file mode 100644 index 5abf8320..0000000 --- a/drivers/staging/android/ion/ion_test.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * - * Copyright (C) 2013 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. - * - */ - -#define pr_fmt(fmt) "ion-test: " fmt - -#include <linux/dma-buf.h> -#include <linux/dma-direction.h> -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/uaccess.h> -#include <linux/vmalloc.h> - -#include "ion.h" -#include "../uapi/ion_test.h" - -#define u64_to_uptr(x) ((void __user *)(unsigned long)(x)) - -struct ion_test_device { - struct miscdevice misc; -}; - -struct ion_test_data { - struct dma_buf *dma_buf; - struct device *dev; -}; - -static int ion_handle_test_dma(struct device *dev, struct dma_buf *dma_buf, - void __user *ptr, size_t offset, size_t size, - bool write) -{ - int ret = 0; - struct dma_buf_attachment *attach; - struct sg_table *table; - pgprot_t pgprot = pgprot_writecombine(PAGE_KERNEL); - enum dma_data_direction dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - struct sg_page_iter sg_iter; - unsigned long offset_page; - - attach = dma_buf_attach(dma_buf, dev); - if (IS_ERR(attach)) - return PTR_ERR(attach); - - table = dma_buf_map_attachment(attach, dir); - if (IS_ERR(table)) - return PTR_ERR(table); - - offset_page = offset >> PAGE_SHIFT; - offset %= PAGE_SIZE; - - for_each_sg_page(table->sgl, &sg_iter, table->nents, offset_page) { - struct page *page = sg_page_iter_page(&sg_iter); - void *vaddr = vmap(&page, 1, VM_MAP, pgprot); - size_t to_copy = PAGE_SIZE - offset; - - to_copy = min(to_copy, size); - if (!vaddr) { - ret = -ENOMEM; - goto err; - } - - if (write) - ret = copy_from_user(vaddr + offset, ptr, to_copy); - else - ret = copy_to_user(ptr, vaddr + offset, to_copy); - - vunmap(vaddr); - if (ret) { - ret = -EFAULT; - goto err; - } - size -= to_copy; - if (!size) - break; - ptr += to_copy; - offset = 0; - } - -err: - dma_buf_unmap_attachment(attach, table, dir); - dma_buf_detach(dma_buf, attach); - return ret; -} - -static int ion_handle_test_kernel(struct dma_buf *dma_buf, void __user *ptr, - size_t offset, size_t size, bool write) -{ - int ret; - unsigned long page_offset = offset >> PAGE_SHIFT; - size_t copy_offset = offset % PAGE_SIZE; - size_t copy_size = size; - enum dma_data_direction dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - - if (offset > dma_buf->size || size > dma_buf->size - offset) - return -EINVAL; - - ret = dma_buf_begin_cpu_access(dma_buf, dir); - if (ret) - return ret; - - while (copy_size > 0) { - size_t to_copy; - void *vaddr = dma_buf_kmap(dma_buf, page_offset); - - if (!vaddr) - goto err; - - to_copy = min_t(size_t, PAGE_SIZE - copy_offset, copy_size); - - if (write) - ret = copy_from_user(vaddr + copy_offset, ptr, to_copy); - else - ret = copy_to_user(ptr, vaddr + copy_offset, to_copy); - - dma_buf_kunmap(dma_buf, page_offset, vaddr); - if (ret) { - ret = -EFAULT; - goto err; - } - - copy_size -= to_copy; - ptr += to_copy; - page_offset++; - copy_offset = 0; - } -err: - dma_buf_end_cpu_access(dma_buf, dir); - return ret; -} - -static long ion_test_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct ion_test_data *test_data = filp->private_data; - int ret = 0; - - union { - struct ion_test_rw_data test_rw; - } data; - - if (_IOC_SIZE(cmd) > sizeof(data)) - return -EINVAL; - - if (_IOC_DIR(cmd) & _IOC_WRITE) - if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) - return -EFAULT; - - switch (cmd) { - case ION_IOC_TEST_SET_FD: - { - struct dma_buf *dma_buf = NULL; - int fd = arg; - - if (fd >= 0) { - dma_buf = dma_buf_get((int)arg); - if (IS_ERR(dma_buf)) - return PTR_ERR(dma_buf); - } - if (test_data->dma_buf) - dma_buf_put(test_data->dma_buf); - test_data->dma_buf = dma_buf; - break; - } - case ION_IOC_TEST_DMA_MAPPING: - { - ret = ion_handle_test_dma(test_data->dev, test_data->dma_buf, - u64_to_uptr(data.test_rw.ptr), - data.test_rw.offset, - data.test_rw.size, - data.test_rw.write); - break; - } - case ION_IOC_TEST_KERNEL_MAPPING: - { - ret = ion_handle_test_kernel(test_data->dma_buf, - u64_to_uptr(data.test_rw.ptr), - data.test_rw.offset, - data.test_rw.size, - data.test_rw.write); - break; - } - default: - return -ENOTTY; - } - - if (_IOC_DIR(cmd) & _IOC_READ) { - if (copy_to_user((void __user *)arg, &data, sizeof(data))) - return -EFAULT; - } - return ret; -} - -static int ion_test_open(struct inode *inode, struct file *file) -{ - struct ion_test_data *data; - struct miscdevice *miscdev = file->private_data; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->dev = miscdev->parent; - - file->private_data = data; - - return 0; -} - -static int ion_test_release(struct inode *inode, struct file *file) -{ - struct ion_test_data *data = file->private_data; - - kfree(data); - - return 0; -} - -static const struct file_operations ion_test_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = ion_test_ioctl, - .compat_ioctl = ion_test_ioctl, - .open = ion_test_open, - .release = ion_test_release, -}; - -static int __init ion_test_probe(struct platform_device *pdev) -{ - int ret; - struct ion_test_device *testdev; - - testdev = devm_kzalloc(&pdev->dev, sizeof(struct ion_test_device), - GFP_KERNEL); - if (!testdev) - return -ENOMEM; - - testdev->misc.minor = MISC_DYNAMIC_MINOR; - testdev->misc.name = "ion-test"; - testdev->misc.fops = &ion_test_fops; - testdev->misc.parent = &pdev->dev; - ret = misc_register(&testdev->misc); - if (ret) { - pr_err("failed to register misc device.\n"); - return ret; - } - - platform_set_drvdata(pdev, testdev); - - return 0; -} - -static int ion_test_remove(struct platform_device *pdev) -{ - struct ion_test_device *testdev; - - testdev = platform_get_drvdata(pdev); - if (!testdev) - return -ENODATA; - - misc_deregister(&testdev->misc); - return 0; -} - -static struct platform_device *ion_test_pdev; -static struct platform_driver ion_test_platform_driver = { - .remove = ion_test_remove, - .driver = { - .name = "ion-test", - }, -}; - -static int __init ion_test_init(void) -{ - ion_test_pdev = platform_device_register_simple("ion-test", - -1, NULL, 0); - if (IS_ERR(ion_test_pdev)) - return PTR_ERR(ion_test_pdev); - - return platform_driver_probe(&ion_test_platform_driver, ion_test_probe); -} - -static void __exit ion_test_exit(void) -{ - platform_driver_unregister(&ion_test_platform_driver); - platform_device_unregister(ion_test_pdev); -} - -module_init(ion_test_init); -module_exit(ion_test_exit); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/android/ion/tegra/Makefile b/drivers/staging/android/ion/tegra/Makefile deleted file mode 100644 index 808f1f5..0000000 --- a/drivers/staging/android/ion/tegra/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_ION_TEGRA) += tegra_ion.o diff --git a/drivers/staging/android/ion/tegra/tegra_ion.c b/drivers/staging/android/ion/tegra/tegra_ion.c deleted file mode 100644 index 49e55e5..0000000 --- a/drivers/staging/android/ion/tegra/tegra_ion.c +++ /dev/null @@ -1,80 +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/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include "../ion.h" -#include "../ion_priv.h" - -static struct ion_device *idev; -static int num_heaps; -static struct ion_heap **heaps; - -static 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 = devm_kcalloc(&pdev->dev, pdata->nr, - sizeof(struct ion_heap *), GFP_KERNEL); - - idev = ion_device_create(NULL); - if (IS_ERR(idev)) - 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) - ion_heap_destroy(heaps[i]); - return err; -} - -static 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]); - return 0; -} - -static struct platform_driver ion_driver = { - .probe = tegra_ion_probe, - .remove = tegra_ion_remove, - .driver = { .name = "ion-tegra" } -}; - -module_platform_driver(ion_driver); - |