From da3b36172d546200a851f165bf574d6090f4ff4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Mon, 24 Jun 2013 18:02:05 -0700 Subject: ARM: fiq_glue: Add custom fiq return handler api. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I5ff2764e85151ca0a88576542fda07c2d33dd065 Signed-off-by: Arve Hjønnevåg --- arch/arm/common/fiq_glue.S | 25 ++++++++++++------- arch/arm/common/fiq_glue_setup.c | 53 +++++++++++++++++++++++++++++++++++++--- arch/arm/include/asm/fiq_glue.h | 3 +++ 3 files changed, 69 insertions(+), 12 deletions(-) diff --git a/arch/arm/common/fiq_glue.S b/arch/arm/common/fiq_glue.S index 9e3455a09f8..24b42cec481 100644 --- a/arch/arm/common/fiq_glue.S +++ b/arch/arm/common/fiq_glue.S @@ -22,13 +22,14 @@ /* fiq stack: r0-r15,cpsr,spsr of interrupted mode */ ENTRY(fiq_glue) - /* store pc, cpsr from previous mode */ + /* store pc, cpsr from previous mode, reserve space for spsr */ mrs r12, spsr - sub r11, lr, #4 + sub lr, lr, #4 subs r10, #1 bne nested_fiq - stmfd sp!, {r11-r12, lr} + str r12, [sp, #-8]! + str lr, [sp, #-4]! /* store r8-r14 from previous mode */ sub sp, sp, #(7 * 4) @@ -85,12 +86,15 @@ fiq_from_usr_mode_exit: msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT) ldmfd sp!, {r0-r7} - add sp, sp, #(7 * 4) - ldmfd sp!, {r11-r12, lr} + ldr lr, [sp, #(4 * 7)] + ldr r12, [sp, #(4 * 8)] + add sp, sp, #(10 * 4) exit_fiq: msr spsr_cxsf, r12 add r10, #1 - movs pc, r11 + cmp r11, #0 + moveqs pc, lr + bx r11 /* jump to custom fiq return function */ nested_fiq: orr r12, r12, #(PSR_F_BIT) @@ -98,14 +102,17 @@ nested_fiq: fiq_glue_end: -ENTRY(fiq_glue_setup) /* func, data, sp */ - mrs r3, cpsr +ENTRY(fiq_glue_setup) /* func, data, sp, smc call number */ + stmfd sp!, {r4} + mrs r4, cpsr msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT) movs r8, r0 mov r9, r1 mov sp, r2 + mov r11, r3 moveq r10, #0 movne r10, #1 - msr cpsr_c, r3 + msr cpsr_c, r4 + ldmfd sp!, {r4} bx lr diff --git a/arch/arm/common/fiq_glue_setup.c b/arch/arm/common/fiq_glue_setup.c index 4044c7db95c..8cb1b611c6d 100644 --- a/arch/arm/common/fiq_glue_setup.c +++ b/arch/arm/common/fiq_glue_setup.c @@ -18,20 +18,23 @@ #include extern unsigned char fiq_glue, fiq_glue_end; -extern void fiq_glue_setup(void *func, void *data, void *sp); +extern void fiq_glue_setup(void *func, void *data, void *sp, + fiq_return_handler_t fiq_return_handler); static struct fiq_handler fiq_debbuger_fiq_handler = { .name = "fiq_glue", }; DEFINE_PER_CPU(void *, fiq_stack); static struct fiq_glue_handler *current_handler; +static fiq_return_handler_t fiq_return_handler; static DEFINE_MUTEX(fiq_glue_lock); static void fiq_glue_setup_helper(void *info) { struct fiq_glue_handler *handler = info; fiq_glue_setup(handler->fiq, handler, - __get_cpu_var(fiq_stack) + THREAD_START_SP); + __get_cpu_var(fiq_stack) + THREAD_START_SP, + fiq_return_handler); } int fiq_glue_register_handler(struct fiq_glue_handler *handler) @@ -80,6 +83,49 @@ err_busy: return ret; } +static void fiq_glue_update_return_handler(void (*fiq_return)(void)) +{ + fiq_return_handler = fiq_return; + if (current_handler) + on_each_cpu(fiq_glue_setup_helper, current_handler, true); +} + +int fiq_glue_set_return_handler(void (*fiq_return)(void)) +{ + int ret; + + mutex_lock(&fiq_glue_lock); + if (fiq_return_handler) { + ret = -EBUSY; + goto err_busy; + } + fiq_glue_update_return_handler(fiq_return); + ret = 0; +err_busy: + mutex_unlock(&fiq_glue_lock); + + return ret; +} +EXPORT_SYMBOL(fiq_glue_set_return_handler); + +int fiq_glue_clear_return_handler(void (*fiq_return)(void)) +{ + int ret; + + mutex_lock(&fiq_glue_lock); + if (WARN_ON(fiq_return_handler != fiq_return)) { + ret = -EINVAL; + goto err_inval; + } + fiq_glue_update_return_handler(NULL); + ret = 0; +err_inval: + mutex_unlock(&fiq_glue_lock); + + return ret; +} +EXPORT_SYMBOL(fiq_glue_clear_return_handler); + /** * fiq_glue_resume - Restore fiqs after suspend or low power idle states * @@ -93,7 +139,8 @@ void fiq_glue_resume(void) if (!current_handler) return; fiq_glue_setup(current_handler->fiq, current_handler, - __get_cpu_var(fiq_stack) + THREAD_START_SP); + __get_cpu_var(fiq_stack) + THREAD_START_SP, + fiq_return_handler); if (current_handler->resume) current_handler->resume(current_handler); } diff --git a/arch/arm/include/asm/fiq_glue.h b/arch/arm/include/asm/fiq_glue.h index d54c29db97a..a9e244f9f19 100644 --- a/arch/arm/include/asm/fiq_glue.h +++ b/arch/arm/include/asm/fiq_glue.h @@ -18,8 +18,11 @@ struct fiq_glue_handler { void (*fiq)(struct fiq_glue_handler *h, void *regs, void *svc_sp); void (*resume)(struct fiq_glue_handler *h); }; +typedef void (*fiq_return_handler_t)(void); int fiq_glue_register_handler(struct fiq_glue_handler *handler); +int fiq_glue_set_return_handler(fiq_return_handler_t fiq_return); +int fiq_glue_clear_return_handler(fiq_return_handler_t fiq_return); #ifdef CONFIG_FIQ_GLUE void fiq_glue_resume(void); -- cgit v1.2.3 From e8f7f42cdcbe3ae4c4bf719847369ddac44219a9 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 13 Nov 2013 14:46:06 -0800 Subject: ion: check invalid values in ion_system_heap ion_system_heap can only satisfy page alignment, and ion_system_contig_heap can only satisify alignment to the allocation size. Neither can support faulting user mappings because they use slab pages. Change-Id: I895c2d4184c672f647f83a17aeb862985dc92f2c Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_system_heap.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index ecae16f2109..4eb0ae8c675 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -150,6 +150,12 @@ static int ion_system_heap_allocate(struct ion_heap *heap, long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; + if (align > PAGE_SIZE) + return -EINVAL; + + if (ion_buffer_fault_user_mappings(buffer)) + return -EINVAL; + INIT_LIST_HEAD(&pages); while (size_remaining > 0) { info = alloc_largest_available(sys_heap, buffer, size_remaining, max_order); @@ -362,6 +368,14 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap, unsigned long align, unsigned long flags) { + int order = get_order(len); + + if (align > (PAGE_SIZE << order)) + return -EINVAL; + + if (ion_buffer_fault_user_mappings(buffer)) + return -EINVAL; + buffer->priv_virt = kzalloc(len, GFP_KERNEL); if (!buffer->priv_virt) return -ENOMEM; -- cgit v1.2.3 From 5c31b87cef4e03eea5b417a6e3f7c9b781aacf96 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 8 Nov 2013 16:32:47 -0800 Subject: ion: add test device for unit tests to interact with dma_bufs Add a /dev/ion-test device that will be created if CONFIG_ION_TEST is set. The device accepts a dma_buf fd and allows reading and writing to the backing memory using DMA-like apis or kernel mapping apis. Can be used to test the dma_buf mapping ops, including the ion implementations, from userspace. Change-Id: I30703ba69cd75bdfe7767ac642e5f0cacd8d0478 Signed-off-by: Colin Cross --- drivers/staging/android/ion/Kconfig | 7 + drivers/staging/android/ion/Makefile | 1 + drivers/staging/android/ion/ion_test.c | 281 ++++++++++++++++++++++++++++++++ drivers/staging/android/uapi/ion_test.h | 71 ++++++++ 4 files changed, 360 insertions(+) create mode 100644 drivers/staging/android/ion/ion_test.c create mode 100644 drivers/staging/android/uapi/ion_test.h diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index c62f2cbb9e8..6a5d8cfe793 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -6,6 +6,13 @@ menuconfig ION help Chose this option to enable the ION Memory Manager. +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_TEGRA tristate "Ion for Tegra" depends on ARCH_TEGRA && ION diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 9c956659124..75039b98eeb 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_ION) += ion.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 diff --git a/drivers/staging/android/ion/ion_test.c b/drivers/staging/android/ion/ion_test.c new file mode 100644 index 00000000000..3e20349baf7 --- /dev/null +++ b/drivers/staging/android/ion/ion_test.c @@ -0,0 +1,281 @@ +/* + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, offset, size, 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, offset, size, 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(struct ion_test_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, + .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 struct platform_driver ion_test_platform_driver = { + .driver = { + .name = "ion-test", + }, +}; + +static int __init ion_test_init(void) +{ + platform_device_register_simple("ion-test", -1, NULL, 0); + 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); +} + +module_init(ion_test_init); +module_exit(ion_test_exit); diff --git a/drivers/staging/android/uapi/ion_test.h b/drivers/staging/android/uapi/ion_test.h new file mode 100644 index 00000000000..352379a0269 --- /dev/null +++ b/drivers/staging/android/uapi/ion_test.h @@ -0,0 +1,71 @@ +/* + * drivers/staging/android/uapi/ion.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 _UAPI_LINUX_ION_TEST_H +#define _UAPI_LINUX_ION_TEST_H + +#include +#include + +typedef int ion_user_handle_t; + +/** + * struct ion_test_rw_data - metadata passed to the kernel to read handle + * @ptr: a pointer to an area at least as large as size + * @offset: offset into the ion buffer to start reading + * @size: size to read or write + * @write: 1 to write, 0 to read + */ +struct ion_test_rw_data { + __u64 ptr; + __u64 offset; + __u64 size; + int write; +}; + +#define ION_IOC_MAGIC 'I' + +/** + * DOC: ION_IOC_TEST_SET_DMA_BUF - attach a dma buf to the test driver + * + * Attaches a dma buf fd to the test driver. Passing a second fd or -1 will + * release the first fd. + */ +#define ION_IOC_TEST_SET_FD \ + _IO(ION_IOC_MAGIC, 0xf0) + +/** + * DOC: ION_IOC_TEST_DMA_MAPPING - read or write memory from a handle as DMA + * + * Reads or writes the memory from a handle using an uncached mapping. Can be + * used by unit tests to emulate a DMA engine as close as possible. Only + * expected to be used for debugging and testing, may not always be available. + */ +#define ION_IOC_TEST_DMA_MAPPING \ + _IOW(ION_IOC_MAGIC, 0xf1, struct ion_test_rw_data) + +/** + * DOC: ION_IOC_TEST_KERNEL_MAPPING - read or write memory from a handle + * + * Reads or writes the memory from a handle using a kernel mapping. Can be + * used by unit tests to test heap map_kernel functions. Only expected to be + * used for debugging and testing, may not always be available. + */ +#define ION_IOC_TEST_KERNEL_MAPPING \ + _IOW(ION_IOC_MAGIC, 0xf2, struct ion_test_rw_data) + + +#endif /* _UAPI_LINUX_ION_H */ -- cgit v1.2.3 From acd77fc7d05a80e7ae39e64e1a3948487e2255ff Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 19 Sep 2013 14:54:56 -0500 Subject: ion: update idr to avoid deprecated apis Use idr_alloc instead if idr_pre_get/idr_get_new_above, and remove idr_remove_all. Change-Id: I675b789879549bd3767ed3ef2016cf108eb622d2 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 4d19716cabd..80c79455c36 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -432,22 +432,16 @@ static bool ion_handle_validate(struct ion_client *client, struct ion_handle *ha static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) { - int rc; + int id; struct rb_node **p = &client->handles.rb_node; struct rb_node *parent = NULL; struct ion_handle *entry; - do { - int id; - rc = idr_pre_get(&client->idr, GFP_KERNEL); - if (!rc) - return -ENOMEM; - rc = idr_get_new_above(&client->idr, handle, 1, &id); - handle->id = id; - } while (rc == -EAGAIN); + id = idr_alloc(&client->idr, handle, 1, 0, GFP_KERNEL); + if (id < 0) + return id; - if (rc < 0) - return rc; + handle->id = id; while (*p) { parent = *p; @@ -786,7 +780,6 @@ void ion_client_destroy(struct ion_client *client) ion_handle_destroy(&handle->ref); } - idr_remove_all(&client->idr); idr_destroy(&client->idr); down_write(&dev->lock); -- cgit v1.2.3 From c7442a7605836527b6d8e6e7ed42608f35ae85ca Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 19 Sep 2013 10:12:05 -0500 Subject: ion: don't use __arm_ioremap to map pages ion_heap_map_kernel already implements mapping a scatterlist of pages into the kernel, and all heaps are required to have struct pages associated with them, so delete the functions that use __arm_ioremap and use ion_heap_map_kernel instead. Change-Id: Ia2dfd8d8c6e719d7d2f68dd4c458826fdb938260 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_carveout_heap.c | 42 ++----------------------- drivers/staging/android/ion/ion_chunk_heap.c | 2 -- 2 files changed, 3 insertions(+), 41 deletions(-) diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 4a94b17da67..f53e7008d6d 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -25,8 +25,6 @@ #include "ion.h" #include "ion_priv.h" -#include - struct ion_carveout_heap { struct ion_heap heap; struct gen_pool *pool; @@ -109,49 +107,15 @@ void ion_carveout_heap_unmap_dma(struct ion_heap *heap, sg_free_table(buffer->sg_table); } -void *ion_carveout_heap_map_kernel(struct ion_heap *heap, - struct ion_buffer *buffer) -{ - void *ret; - int mtype = MT_MEMORY_NONCACHED; - - if (buffer->flags & ION_FLAG_CACHED) - mtype = MT_MEMORY; - - ret = __arm_ioremap(buffer->priv_phys, buffer->size, - mtype); - if (ret == NULL) - return ERR_PTR(-ENOMEM); - - return ret; -} - -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, + .map_user = ion_heap_map_user, + .map_kernel = ion_heap_map_kernel, + .unmap_kernel = ion_heap_unmap_kernel, }; struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 19e13ecaa1c..3ca4b90424c 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -25,8 +25,6 @@ #include "ion.h" #include "ion_priv.h" -#include - struct ion_chunk_heap { struct ion_heap heap; struct gen_pool *pool; -- cgit v1.2.3 From f26a6f2aa0beea7eeb0a2f69d44a5975ef8c887e Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 19 Sep 2013 10:13:53 -0500 Subject: ion: don't use phys_to_page or __phys_to_pfn phys_to_page and __phys_to_pfn don't exist on all platforms. Use a combination of pfn_to_page, PFN_DOWN, page_to_pfn, and virt_to_page to get the same results. Change-Id: I53cef26059800bc8b7fb85ae458741574c97c257 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_carveout_heap.c | 4 ++-- drivers/staging/android/ion/ion_chunk_heap.c | 5 +++-- drivers/staging/android/ion/ion_system_heap.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index f53e7008d6d..ed2b7ae7096 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -96,8 +96,8 @@ struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, kfree(table); return ERR_PTR(ret); } - sg_set_page(table->sgl, phys_to_page(buffer->priv_phys), buffer->size, - 0); + sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(buffer->priv_phys)), + buffer->size, 0); return table; } diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 3ca4b90424c..e17b6016db5 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -71,7 +71,8 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, chunk_heap->chunk_size); if (!paddr) goto err; - sg_set_page(sg, phys_to_page(paddr), chunk_heap->chunk_size, 0); + sg_set_page(sg, pfn_to_page(PFN_DOWN(paddr)), + chunk_heap->chunk_size, 0); sg = sg_next(sg); } @@ -167,7 +168,7 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) goto error; } for (i = 0; i < chunk_heap->size; i += PAGE_SIZE) { - struct page *page = phys_to_page(chunk_heap->base + i); + struct page *page = pfn_to_page(PFN_DOWN(chunk_heap->base + i)); struct page **pages = &page; ret = map_vm_area(vm_struct, pgprot, &pages); diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 4eb0ae8c675..954eb56e715 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -426,7 +426,7 @@ 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)); + unsigned long pfn = page_to_pfn(virt_to_page(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); -- cgit v1.2.3 From 21e08b49ac311e3d1e9c7168de1bd42868176398 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 19 Sep 2013 09:20:23 -0500 Subject: ion: fix printk warnings Use %z for size_t and %pa for dma_addr_t to avoid warnings in printks. Change-Id: I2c72874acd0b69cb35fca691928783817deb9394 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion.c | 23 ++++++++++++----------- drivers/staging/android/ion/ion_chunk_heap.c | 2 +- drivers/staging/android/ion/ion_cma_heap.c | 4 ++-- drivers/staging/android/ion/ion_heap.c | 2 +- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 80c79455c36..371b04f80a2 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -471,7 +471,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, struct ion_heap *heap; int ret; - pr_debug("%s: len %d align %d heap_id_mask %u flags %x\n", __func__, + pr_debug("%s: len %zu align %zu heap_id_mask %u flags %x\n", __func__, len, align, heap_id_mask, flags); /* * traverse the list of heaps available in this system in priority @@ -688,7 +688,7 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) for (i = 0; i < ION_NUM_HEAP_IDS; i++) { if (!names[i]) continue; - seq_printf(s, "%16.16s: %16u\n", names[i], sizes[i]); + seq_printf(s, "%16.16s: %16zu\n", names[i], sizes[i]); } return 0; } @@ -1336,10 +1336,10 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) char task_comm[TASK_COMM_LEN]; get_task_comm(task_comm, client->task); - seq_printf(s, "%16.s %16u %16u\n", task_comm, + seq_printf(s, "%16.s %16u %16zu\n", task_comm, client->pid, size); } else { - seq_printf(s, "%16.s %16u %16u\n", client->name, + seq_printf(s, "%16.s %16u %16zu\n", client->name, client->pid, size); } } @@ -1354,19 +1354,20 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) 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, + seq_printf(s, "%16.s %16u %16zu %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", + seq_printf(s, "%16.s %16zu\n", "total orphaned", total_orphaned_size); - seq_printf(s, "%16.s %16u\n", "total ", total_size); + seq_printf(s, "%16.s %16zu\n", "total ", total_size); if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) - seq_printf(s, "%16.s %16u\n", "deferred free", + seq_printf(s, "%16.s %16zu\n", "deferred free", heap->free_list_size); seq_printf(s, "----------------------------------------------------\n"); @@ -1522,11 +1523,11 @@ void __init ion_reserve(struct ion_platform_data *data) int ret = memblock_reserve(data->heaps[i].base, data->heaps[i].size); if (ret) - pr_err("memblock reserve of %x@%lx failed\n", + pr_err("memblock reserve of %zx@%lx failed\n", data->heaps[i].size, data->heaps[i].base); } - pr_info("%s: %s reserved base %lx size %d\n", __func__, + pr_info("%s: %s reserved base %lx size %zu\n", __func__, data->heaps[i].name, data->heaps[i].base, data->heaps[i].size); diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index e17b6016db5..60952a8aa79 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -186,7 +186,7 @@ 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_info("%s: base %lu size %u align %ld\n", __func__, chunk_heap->base, + pr_info("%s: base %lu size %zu align %ld\n", __func__, chunk_heap->base, heap_data->size, heap_data->align); 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 55d6003f546..f8a8090bf89 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -128,8 +128,8 @@ static int ion_cma_phys(struct ion_heap *heap, struct ion_buffer *buffer, struct device *dev = cma_heap->dev; struct ion_cma_buffer_info *info = buffer->priv_virt; - dev_dbg(dev, "Return buffer %p physical address 0x%x\n", buffer, - info->handle); + dev_dbg(dev, "Return buffer %p physical address 0x%pa\n", buffer, + &info->handle); *addr = info->handle; *len = buffer->size; diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index f32f4e69765..5a93a0273fa 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -281,7 +281,7 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) } if (IS_ERR_OR_NULL(heap)) { - pr_err("%s: error creating heap %s type %d base %lu size %u\n", + pr_err("%s: error creating heap %s type %d base %lu size %zu\n", __func__, heap_data->name, heap_data->type, heap_data->base, heap_data->size); return ERR_PTR(-EINVAL); -- cgit v1.2.3 From 30b7bee7c585c7eb0b2797c38241fa9f5797982f Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 7 Nov 2013 12:18:57 -0800 Subject: gpu: ion: remove unnecessary function from system heap ion_system_contig_heap buffers have an sglist, just call ion_heap_map_user to map it. Change-Id: I6dea383955834613fa8833659b31533c957c2b0b Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_system_heap.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 954eb56e715..5b9c0e0da5e 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -422,17 +422,6 @@ void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, 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 = page_to_pfn(virt_to_page(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, @@ -441,7 +430,7 @@ static struct ion_heap_ops kmalloc_ops = { .unmap_dma = ion_system_contig_heap_unmap_dma, .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, - .map_user = ion_system_contig_heap_map_user, + .map_user = ion_heap_map_user, }; struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused) -- cgit v1.2.3 From b2ee33eb98bd8240787f6b3a6acffdbab40653dc Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 8 Nov 2013 16:55:35 -0800 Subject: ion: clean up ioctls Convert the ion ioctls to use _IOW instead of _IOWR where appropriate, and factor out the copy_from_user and copy_to_user based on the _IOC_DIR bits. For the existing incorrect ioctls, add a function to wrap _IOC_DIR to return the corrected value. Change-Id: I3cc34c84b9c52305bdbec27a9224447b102fadcd Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion.c | 110 ++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 371b04f80a2..fb345975937 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1157,41 +1157,65 @@ static int ion_sync_for_device(struct ion_client *client, int fd) return 0; } +/* fix up the cases where the ioctl direction bits are incorrect */ +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); + } +} + static 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; + + union { + struct ion_fd_data fd; + struct ion_allocation_data allocation; + struct ion_handle_data handle; + struct ion_custom_data custom; + } data; + + dir = ion_ioctl_dir(cmd); + + if (_IOC_SIZE(cmd) > sizeof(data)) + return -EINVAL; + + if (dir & _IOC_WRITE) + if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) + return -EFAULT; switch (cmd) { case ION_IOC_ALLOC: { - struct ion_allocation_data data; struct ion_handle *handle; - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) - return -EFAULT; - handle = ion_alloc(client, data.len, data.align, - data.heap_id_mask, data.flags); - + handle = ion_alloc(client, data.allocation.len, + data.allocation.align, + data.allocation.heap_id_mask, + data.allocation.flags); if (IS_ERR(handle)) return PTR_ERR(handle); - data.handle = handle->id; + data.allocation.handle = handle->id; - if (copy_to_user((void __user *)arg, &data, sizeof(data))) { - ion_free(client, handle); - return -EFAULT; - } + cleanup_handle = handle; break; } case ION_IOC_FREE: { - struct ion_handle_data data; struct ion_handle *handle; - if (copy_from_user(&data, (void __user *)arg, - sizeof(struct ion_handle_data))) - return -EFAULT; - handle = ion_handle_get_by_id(client, data.handle); + handle = ion_handle_get_by_id(client, data.handle.handle); if (IS_ERR(handle)) return PTR_ERR(handle); ion_free(client, handle); @@ -1201,68 +1225,52 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case ION_IOC_SHARE: case ION_IOC_MAP: { - struct ion_fd_data data; struct ion_handle *handle; - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) - return -EFAULT; - handle = ion_handle_get_by_id(client, data.handle); + handle = ion_handle_get_by_id(client, data.handle.handle); if (IS_ERR(handle)) return PTR_ERR(handle); - data.fd = ion_share_dma_buf_fd(client, handle); + data.fd.fd = ion_share_dma_buf_fd(client, handle); ion_handle_put(handle); - if (copy_to_user((void __user *)arg, &data, sizeof(data))) - return -EFAULT; - if (data.fd < 0) - return data.fd; + if (data.fd.fd < 0) + ret = data.fd.fd; break; } case ION_IOC_IMPORT: { - struct ion_fd_data data; struct ion_handle *handle; - int ret = 0; - if (copy_from_user(&data, (void __user *)arg, - sizeof(struct ion_fd_data))) - return -EFAULT; - handle = ion_import_dma_buf(client, data.fd); + handle = ion_import_dma_buf(client, data.fd.fd); if (IS_ERR(handle)) ret = PTR_ERR(handle); else - data.handle = handle->id; - - if (copy_to_user((void __user *)arg, &data, - sizeof(struct ion_fd_data))) - return -EFAULT; - if (ret < 0) - return ret; + data.handle.handle = handle->id; 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); + ret = ion_sync_for_device(client, data.fd.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); + ret = dev->custom_ioctl(client, data.custom.cmd, + data.custom.arg); + break; } default: return -ENOTTY; } - return 0; + + if (dir & _IOC_READ) { + if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { + if (cleanup_handle) + ion_free(client, cleanup_handle); + return -EFAULT; + } + } + return ret; } static int ion_release(struct inode *inode, struct file *file) -- cgit v1.2.3 From 9273153e861f3db897798ec0dc15f70d1aae9410 Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Tue, 6 Aug 2013 11:19:42 -0700 Subject: gpu: ion: fix use-after-free in ion_heap_freelist_drain The `buffer' variable is being used after being freed. Fix this. Change-Id: Iea3471fa7dc7535bbf0620c1639fea2008d7cf19 Signed-off-by: Mitchel Humpherys --- drivers/staging/android/ion/ion_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 5a93a0273fa..e061b266330 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -200,9 +200,9 @@ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) if (total_drained >= size) break; list_del(&buffer->list); - ion_buffer_destroy(buffer); heap->free_list_size -= buffer->size; total_drained += buffer->size; + ion_buffer_destroy(buffer); } rt_mutex_unlock(&heap->lock); -- cgit v1.2.3 From 818017a0caa6b7b3bb6e96697a2c35806e08f6a4 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 22 Nov 2013 15:36:27 -0800 Subject: ion: Fix two small issues in system_heap allocation In testing ion system heap allocations, I ran across two issues: 1) Not k*z*allocing the sg table. This can cause trouble if we end up trying call sg_alloc_table() with too many entries, then sg_alloc_table() internally fails and tries to free what it thinks is internal table structure, which causes bad pointer traversals. 2) The second list_for_each_entry probably should be _safe, since I was seeing strange lock warnings and oopses on occasion. This seems to resolve it, but could use some extra checking. Change-Id: I59d4c90104a8cf23dc4ae814d0b17348f1b68ac0 Signed-off-by: John Stultz --- drivers/staging/android/ion/ion_system_heap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 5b9c0e0da5e..5926be9d0fd 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -166,8 +166,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, max_order = info->order; i++; } - - table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); if (!table) goto err; @@ -189,7 +188,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, err1: kfree(table); err: - list_for_each_entry(info, &pages, list) { + list_for_each_entry_safe(info, tmp_info, &pages, list) { free_buffer_page(sys_heap, buffer, info->page, info->order); kfree(info); } -- cgit v1.2.3 From 8af13473b7ca01524862df8e8dae97892ea548ad Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 22 Nov 2013 22:48:42 -0800 Subject: ion: drop dependency on ARM Ion will compile and run on other platforms now, remove the dependency on ARM. Change-Id: I9da0ab686708bdab575a021031392b4402cce090 Signed-off-by: Colin Cross --- drivers/staging/android/ion/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 6a5d8cfe793..3215bd8fb45 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -1,6 +1,5 @@ menuconfig ION tristate "Ion Memory Manager" - depends on ARM select GENERIC_ALLOCATOR select DMA_SHARED_BUFFER help -- cgit v1.2.3 From 63ddadde39e91931890798084ef023ebab4b4a90 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 26 Nov 2013 13:43:29 -0800 Subject: ion: add alignment check to carveout heap Change-Id: I25c752b3eacb48cccea5be2df319634b3affd331 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_carveout_heap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index ed2b7ae7096..128ee115e60 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -70,6 +70,9 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, unsigned long size, unsigned long align, unsigned long flags) { + if (align > PAGE_SIZE) + return -EINVAL; + buffer->priv_phys = ion_carveout_allocate(heap, size, align); return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0; } -- cgit v1.2.3 From fc04e484c319b8df647886d4cf17f7c450453d1d Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 25 Nov 2013 13:32:51 -0800 Subject: ion: optimize ion_heap_buffer_zero ion_heap_buffer_zero can spend a long time in unmap_kernel_range if it has to broadcast a tlb flush to every cpu for every page. Modify it to batch pages into a larger region to clear using a single mapping. This may cause the mapping size to change if the buffer size is not a multiple of the mapping size, so switch to allocating the address space for each chunk. This allows us to use vm_map_ram to handle the allocation and mapping together. The number of pages to zero using a single mapping is set to 32 to hit the fastpath in vm_map_ram. Change-Id: I1accfe67b285cbc9e95e387bea4246864197827d Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_heap.c | 36 +++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index e061b266330..0d30f9f7eeb 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -100,40 +100,48 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, return 0; } +static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot) +{ + void *addr = vm_map_ram(pages, num, -1, pgprot); + if (!addr) + return -ENOMEM; + memset(addr, 0, PAGE_SIZE * num); + vm_unmap_ram(addr, num); + + return 0; +} + int ion_heap_buffer_zero(struct ion_buffer *buffer) { struct sg_table *table = buffer->sg_table; pgprot_t pgprot; struct scatterlist *sg; - struct vm_struct *vm_struct; int i, j, ret = 0; + struct page *pages[32]; + int k = 0; if (buffer->flags & ION_FLAG_CACHED) pgprot = PAGE_KERNEL; else pgprot = pgprot_writecombine(PAGE_KERNEL); - vm_struct = get_vm_area(PAGE_SIZE, VM_ALLOC); - if (!vm_struct) - return -ENOMEM; - for_each_sg(table->sgl, sg, table->nents, i) { struct page *page = sg_page(sg); unsigned long len = sg->length; for (j = 0; j < len / PAGE_SIZE; j++) { - struct page *sub_page = page + j; - struct page **pages = &sub_page; - ret = map_vm_area(vm_struct, pgprot, &pages); - if (ret) - goto end; - memset(vm_struct->addr, 0, PAGE_SIZE); - unmap_kernel_range((unsigned long)vm_struct->addr, - PAGE_SIZE); + pages[k++] = page + j; + if (k == ARRAY_SIZE(pages)) { + ret = ion_heap_clear_pages(pages, k, pgprot); + if (ret) + goto end; + k = 0; + } } + if (k) + ret = ion_heap_clear_pages(pages, k, pgprot); } end: - free_vm_area(vm_struct); return ret; } -- cgit v1.2.3 From b928ad649cd32b4ca5ba7429bfe897433d37dfea Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 21 Nov 2013 18:56:37 -0800 Subject: ion: free low memory from page pools first When the shrinkers are called with GFP_HIGH free low memory first, it is more important to have free than high memory. Change-Id: I7ad8a9c133830f04d429c3d87b781b3e862ccedb Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_page_pool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index b052ff6bf38..5a0e629c188 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -143,10 +143,10 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, struct page *page; mutex_lock(&pool->mutex); - if (high && pool->high_count) { - page = ion_page_pool_remove(pool, true); - } else if (pool->low_count) { + if (pool->low_count) { page = ion_page_pool_remove(pool, false); + } else if (high && pool->high_count) { + page = ion_page_pool_remove(pool, true); } else { mutex_unlock(&pool->mutex); break; -- cgit v1.2.3 From 3b8da00c6c5e42af7b532dbf51b2d5007095d844 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 26 Nov 2013 15:34:50 -0800 Subject: ion: check return value from remap_pfn_range Check the return value of remap_pfn_range and return an error if it fails. Change-Id: I206cf95a24607ebe1c80274e3ed15cc7c076d007 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_heap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 0d30f9f7eeb..403fdc7d745 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -76,6 +76,7 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long offset = vma->vm_pgoff * PAGE_SIZE; struct scatterlist *sg; int i; + int ret; for_each_sg(table->sgl, sg, table->nents, i) { struct page *page = sg_page(sg); @@ -91,8 +92,10 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, offset = 0; } len = min(len, remainder); - remap_pfn_range(vma, addr, page_to_pfn(page), len, + ret = remap_pfn_range(vma, addr, page_to_pfn(page), len, vma->vm_page_prot); + if (ret) + return ret; addr += len; if (addr >= vma->vm_end) return 0; -- cgit v1.2.3 From ed6cfafce575cc6baa099212c69b56c0132f598d Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 26 Nov 2013 15:05:46 -0800 Subject: ion: use vm_insert_pfn for faulted pages Most ion userspace mappings are created with remap_pfn_range. Use vm_insert_pfn instead of vm_insert_page to make faulted cached mappings look more like uncached mappings. Change-Id: I9ec5cad3fef54f3b80be8b306d7ff2f1fe3f0e66 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index fb345975937..4ccdda706f3 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -890,14 +890,15 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct ion_buffer *buffer = vma->vm_private_data; + unsigned long pfn; int ret; mutex_lock(&buffer->lock); ion_buffer_page_dirty(buffer->pages + vmf->pgoff); - BUG_ON(!buffer->pages || !buffer->pages[vmf->pgoff]); - ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, - ion_buffer_page(buffer->pages[vmf->pgoff])); + + pfn = page_to_pfn(ion_buffer_page(buffer->pages[vmf->pgoff])); + ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); mutex_unlock(&buffer->lock); if (ret) return VM_FAULT_ERROR; @@ -956,6 +957,8 @@ static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) } 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); -- cgit v1.2.3 From d671290eae60f4a77ab2aef79cfaed008ee0716d Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 26 Nov 2013 15:25:59 -0800 Subject: ion: remove ion_heap_alloc_pages Now that ion_vm_fault doesn't need a struct page with a nonzero refcount, there is no need allocate heap memory for cached pages using split_page. Remove the ion_heap_alloc_pages and ion_heap_free_pages helpers in favor of direct calls to alloc_pages and __free_pages, and remove the special handling in the system heap. Change-Id: I5966a798f48df2d56642e662a69c1495944f6509 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_heap.c | 27 --------------------------- drivers/staging/android/ion/ion_priv.h | 13 ------------- drivers/staging/android/ion/ion_system_heap.c | 7 +------ 3 files changed, 1 insertion(+), 46 deletions(-) diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 403fdc7d745..24d7e3284ae 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -148,33 +148,6 @@ end: return ret; } -struct page *ion_heap_alloc_pages(struct ion_buffer *buffer, gfp_t gfp_flags, - unsigned int order) -{ - struct page *page = alloc_pages(gfp_flags, order); - - if (!page) - return page; - - if (ion_buffer_fault_user_mappings(buffer)) - split_page(page, order); - - return page; -} - -void ion_heap_free_pages(struct ion_buffer *buffer, struct page *page, - unsigned int order) -{ - int i; - - if (!ion_buffer_fault_user_mappings(buffer)) { - __free_pages(page, order); - return; - } - for (i = 0; i < (1 << order); i++) - __free_page(page + i); -} - void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer * buffer) { rt_mutex_lock(&heap->lock); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index ea87b54987e..399ec692921 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -216,19 +216,6 @@ int ion_heap_map_user(struct ion_heap *, struct ion_buffer *, struct vm_area_struct *); int ion_heap_buffer_zero(struct ion_buffer *buffer); -/** - * ion_heap_alloc_pages - allocate pages from alloc_pages - * @buffer: the buffer to allocate for, used to extract the flags - * @gfp_flags: the gfp_t for the allocation - * @order: the order of the allocatoin - * - * This funciton allocations from alloc pages and also does any other - * necessary operations based on the buffer->flags. For buffers which - * will be faulted in the pages are split using split_page - */ -struct page *ion_heap_alloc_pages(struct ion_buffer *buffer, gfp_t gfp_flags, - unsigned int order); - /** * ion_heap_init_deferred_free -- initialize deferred free functionality * @heap: the heap diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 5926be9d0fd..e3aec597554 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -74,7 +74,7 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, if (order > 4) gfp_flags = high_order_gfp_flags; - page = ion_heap_alloc_pages(buffer, gfp_flags, order); + page = alloc_pages(gfp_flags, order); if (!page) return 0; ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order, @@ -91,15 +91,10 @@ static void free_buffer_page(struct ion_system_heap *heap, 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)]; 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); } -- cgit v1.2.3 From 1f67f7520303192e46e1621639097007ab076b90 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 26 Nov 2013 15:33:33 -0800 Subject: ion: allow cached mappings of chunk and system heap buffers Now that ion_vm_fault uses vm_insert_pfn instead of vm_insert_page cached buffers can be supported in any heap. Remove the checks in the chunk and system heaps. Change-Id: I371a44c400ed8a342c3b0eed90d0fb7060537697 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_chunk_heap.c | 3 --- drivers/staging/android/ion/ion_system_heap.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 60952a8aa79..03af672d1f3 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -47,9 +47,6 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, unsigned long num_chunks; unsigned long allocated_size; - if (ion_buffer_fault_user_mappings(buffer)) - return -ENOMEM; - allocated_size = ALIGN(size, chunk_heap->chunk_size); num_chunks = allocated_size / chunk_heap->chunk_size; diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index e3aec597554..2930eb1d9aa 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -148,9 +148,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, if (align > PAGE_SIZE) return -EINVAL; - if (ion_buffer_fault_user_mappings(buffer)) - return -EINVAL; - INIT_LIST_HEAD(&pages); while (size_remaining > 0) { info = alloc_largest_available(sys_heap, buffer, size_remaining, max_order); -- cgit v1.2.3 From 5d68d972728717ee85162bd50122901b7fe8cc6d Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 26 Nov 2013 15:35:29 -0800 Subject: ion: use alloc_pages in system contig heap There is no reason to use kzalloc, just call alloc_pages directly. Change the GFP from GFP_KERNEL to include __GFP_HIGH, to allow it to return contiguous pages from highmem. virt_to_* functions aren't valid on highmem pages, so store the struct page * in an sg_table in buffer->priv_virt like most other heaps, and replace virt_to_* with page_to_*. Change-Id: Ida78888b101f080883716e1fa5038dfc4dbabd16 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_system_heap.c | 71 ++++++++++++++++++--------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 2930eb1d9aa..d397aa023ae 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -360,29 +360,69 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap, unsigned long flags) { int order = get_order(len); + struct page *page; + struct sg_table *table; + unsigned long i; + int ret; if (align > (PAGE_SIZE << order)) return -EINVAL; - if (ion_buffer_fault_user_mappings(buffer)) - return -EINVAL; - - buffer->priv_virt = kzalloc(len, GFP_KERNEL); - if (!buffer->priv_virt) + page = alloc_pages(low_order_gfp_flags, order); + if (!page) return -ENOMEM; + + split_page(page, order); + + len = PAGE_ALIGN(len); + for (i = len >> PAGE_SHIFT; i < (1 << order); i++) + __free_page(page + i); + + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) { + ret = -ENOMEM; + goto out; + } + + ret = sg_alloc_table(table, 1, GFP_KERNEL); + if (ret) + goto out; + + sg_set_page(table->sgl, page, len, 0); + + buffer->priv_virt = table; + + ion_pages_sync_for_device(NULL, page, len, DMA_BIDIRECTIONAL); + return 0; + +out: + for (i = 0; i < len >> PAGE_SHIFT; i++) + __free_page(page + i); + kfree(table); + return ret; } void ion_system_contig_heap_free(struct ion_buffer *buffer) { - kfree(buffer->priv_virt); + struct sg_table *table = buffer->priv_virt; + struct page *page = sg_page(table->sgl); + unsigned long pages = PAGE_ALIGN(buffer->size) >> PAGE_SHIFT; + unsigned long i; + + for (i = 0; i < pages; i++) + __free_page(page + i); + sg_free_table(table); + kfree(table); } 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); + struct sg_table *table = buffer->priv_virt; + struct page *page = sg_page(table->sgl); + *addr = page_to_phys(page); *len = buffer->size; return 0; } @@ -390,27 +430,12 @@ static int ion_system_contig_heap_phys(struct ion_heap *heap, 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; + return buffer->priv_virt; } 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); } static struct ion_heap_ops kmalloc_ops = { -- cgit v1.2.3 From 6db8a1c0c9817d6ebd61c47110554aa34729e9a7 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 26 Nov 2013 21:25:47 -0800 Subject: ion: fix sparse warnings Fix sparse warnings in ion. Change-Id: Icbadf2ca53bea20914f608f619568629c178eae3 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion.c | 8 +++---- drivers/staging/android/ion/ion_carveout_heap.c | 8 +++---- drivers/staging/android/ion/ion_chunk_heap.c | 8 +++---- drivers/staging/android/ion/ion_cma_heap.c | 15 +++++++------ drivers/staging/android/ion/ion_heap.c | 4 ++-- drivers/staging/android/ion/ion_page_pool.c | 2 +- drivers/staging/android/ion/ion_system_heap.c | 30 ++++++++++++------------- 7 files changed, 37 insertions(+), 38 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 4ccdda706f3..426094c5ea3 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -669,7 +669,7 @@ 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_HEAP_IDS] = {0}; - const char *names[ION_NUM_HEAP_IDS] = {0}; + const char *names[ION_NUM_HEAP_IDS] = {NULL}; int i; mutex_lock(&client->lock); @@ -887,7 +887,7 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer, mutex_unlock(&buffer->lock); } -int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +static int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct ion_buffer *buffer = vma->vm_private_data; unsigned long pfn; @@ -939,7 +939,7 @@ static void ion_vm_close(struct vm_area_struct *vma) mutex_unlock(&buffer->lock); } -struct vm_operations_struct ion_vma_ops = { +static struct vm_operations_struct ion_vma_ops = { .open = ion_vm_open, .close = ion_vm_close, .fault = ion_vm_fault, @@ -1030,7 +1030,7 @@ static void ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start, mutex_unlock(&buffer->lock); } -struct dma_buf_ops dma_buf_ops = { +static struct dma_buf_ops dma_buf_ops = { .map_dma_buf = ion_map_dma_buf, .unmap_dma_buf = ion_unmap_dma_buf, .mmap = ion_mmap, diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 128ee115e60..bf53c2656e7 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -85,8 +85,8 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer) buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL; } -struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { struct sg_table *table; int ret; @@ -104,8 +104,8 @@ struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap, return table; } -void ion_carveout_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static void ion_carveout_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { sg_free_table(buffer->sg_table); } diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 03af672d1f3..9ca54586a51 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -115,14 +115,14 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer) kfree(table); } -struct sg_table *ion_chunk_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static struct sg_table *ion_chunk_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { return buffer->priv_virt; } -void ion_chunk_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static void ion_chunk_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { return; } diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index f8a8090bf89..58c497c197c 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -44,8 +44,8 @@ struct ion_cma_buffer_info { * This function could be replaced by dma_common_get_sgtable * as soon as it will avalaible. */ -int ion_cma_get_sgtable(struct device *dev, struct sg_table *sgt, - void *cpu_addr, dma_addr_t handle, size_t size) +static int ion_cma_get_sgtable(struct device *dev, struct sg_table *sgt, + void *cpu_addr, dma_addr_t handle, size_t size) { struct page *page = virt_to_page(cpu_addr); int ret; @@ -137,16 +137,16 @@ static int ion_cma_phys(struct ion_heap *heap, struct ion_buffer *buffer, return 0; } -struct sg_table *ion_cma_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static struct sg_table *ion_cma_heap_map_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { struct ion_cma_buffer_info *info = buffer->priv_virt; return info->table; } -void ion_cma_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static void ion_cma_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { return; } @@ -162,7 +162,8 @@ static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer, buffer->size); } -void *ion_cma_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) +static void *ion_cma_map_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) { struct ion_cma_buffer_info *info = buffer->priv_virt; /* kernel memory mapping has been done at allocation time */ diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 24d7e3284ae..4d69da55f89 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -38,7 +38,7 @@ void *ion_heap_map_kernel(struct ion_heap *heap, struct page **tmp = pages; if (!pages) - return 0; + return NULL; if (buffer->flags & ION_FLAG_CACHED) pgprot = PAGE_KERNEL; @@ -193,7 +193,7 @@ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) return total_drained; } -int ion_heap_deferred_free(void *data) +static int ion_heap_deferred_free(void *data) { struct ion_heap *heap = data; diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 5a0e629c188..50e68945b1b 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -134,7 +134,7 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, int i; bool high; - high = gfp_mask & __GFP_HIGHMEM; + high = !!(gfp_mask & __GFP_HIGHMEM); if (nr_to_scan == 0) return ion_page_pool_total(pool, high); diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index d397aa023ae..e824c0863bf 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -26,11 +26,9 @@ #include "ion.h" #include "ion_priv.h" -static unsigned int high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | - __GFP_NOWARN | __GFP_NORETRY) & - ~__GFP_WAIT; -static unsigned int low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | - __GFP_NOWARN); +static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN | + __GFP_NORETRY) & ~__GFP_WAIT; +static gfp_t 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) @@ -76,12 +74,12 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, gfp_flags = high_order_gfp_flags; page = alloc_pages(gfp_flags, order); if (!page) - return 0; + return NULL; ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order, DMA_BIDIRECTIONAL); } if (!page) - return 0; + return NULL; return page; } @@ -187,7 +185,7 @@ err: return -ENOMEM; } -void ion_system_heap_free(struct ion_buffer *buffer) +static void ion_system_heap_free(struct ion_buffer *buffer) { struct ion_heap *heap = buffer->heap; struct ion_system_heap *sys_heap = container_of(heap, @@ -211,14 +209,14 @@ void ion_system_heap_free(struct ion_buffer *buffer) kfree(table); } -struct sg_table *ion_system_heap_map_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static 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) +static void ion_system_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { return; } @@ -403,7 +401,7 @@ out: return ret; } -void ion_system_contig_heap_free(struct ion_buffer *buffer) +static void ion_system_contig_heap_free(struct ion_buffer *buffer) { struct sg_table *table = buffer->priv_virt; struct page *page = sg_page(table->sgl); @@ -427,14 +425,14 @@ static int ion_system_contig_heap_phys(struct ion_heap *heap, return 0; } -struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, +static struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap, struct ion_buffer *buffer) { return buffer->priv_virt; } -void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, - struct ion_buffer *buffer) +static void ion_system_contig_heap_unmap_dma(struct ion_heap *heap, + struct ion_buffer *buffer) { } -- cgit v1.2.3 From 1ebba641fb19e38541e30666de8f26b7971949dc Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 26 Nov 2013 21:36:54 -0800 Subject: ion: carveout heap: zero buffers on free, fix memory leak The carveout heap wasn't zeroing its buffers after use. Create the sg_table during allocate instead of map_dma, to allow using the sg_table during free, and call ion_heap_buffer_zero during free. Also fixes a missing kfree when destroying the table. Change-Id: I318a8493cce32580250884cae336dd2e2c28e73b Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_carveout_heap.c | 69 +++++++++++++++++-------- 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index bf53c2656e7..3f0e5a08fcf 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -14,7 +14,7 @@ * */ #include - +#include #include #include #include @@ -60,7 +60,11 @@ 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; + struct sg_table *table = buffer->priv_virt; + struct page *page = sg_page(table->sgl); + ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); + + *addr = paddr; *len = buffer->size; return 0; } @@ -70,44 +74,66 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, unsigned long size, unsigned long align, unsigned long flags) { + struct sg_table *table; + ion_phys_addr_t paddr; + int ret; + if (align > PAGE_SIZE) return -EINVAL; - buffer->priv_phys = ion_carveout_allocate(heap, size, align); - return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0; + table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!table) + return -ENOMEM; + ret = sg_alloc_table(table, 1, GFP_KERNEL); + if (ret) + goto err_free; + + paddr = ion_carveout_allocate(heap, size, align); + if (paddr == ION_CARVEOUT_ALLOCATE_FAIL) { + ret = -ENOMEM; + goto err_free_table; + } + + sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(paddr)), size, 0); + buffer->priv_virt = table; + + return 0; + +err_free_table: + sg_free_table(table); +err_free: + kfree(table); + return ret; } static void ion_carveout_heap_free(struct ion_buffer *buffer) { struct ion_heap *heap = buffer->heap; + struct sg_table *table = buffer->priv_virt; + struct page *page = sg_page(table->sgl); + ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); + + ion_heap_buffer_zero(buffer); - ion_carveout_free(heap, buffer->priv_phys, buffer->size); - buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL; + 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); } static 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, pfn_to_page(PFN_DOWN(buffer->priv_phys)), - buffer->size, 0); - return table; + return buffer->priv_virt; } static void ion_carveout_heap_unmap_dma(struct ion_heap *heap, struct ion_buffer *buffer) { - sg_free_table(buffer->sg_table); + return; } static struct ion_heap_ops carveout_heap_ops = { @@ -139,6 +165,7 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) -1); carveout_heap->heap.ops = &carveout_heap_ops; carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT; + carveout_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; return &carveout_heap->heap; } -- cgit v1.2.3 From 049ca90450f8de6bff6c326d6c20ba2959db2e00 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 27 Nov 2013 15:51:02 -0800 Subject: ion: add helper to zero contiguous region of pages Add ion_heap_pages_zero for ion heaps to use to zero pages during initialization or allocation, when a struct ion_buffer may not be available. Use it from the chunk heap and carveout heaps. Change-Id: Ic6c921943a8820cf9896da5164f2d9794d0fe91f Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_carveout_heap.c | 13 ++++++ drivers/staging/android/ion/ion_chunk_heap.c | 39 ++++++------------ drivers/staging/android/ion/ion_heap.c | 53 +++++++++++++++---------- drivers/staging/android/ion/ion_priv.h | 1 + 4 files changed, 58 insertions(+), 48 deletions(-) diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 3f0e5a08fcf..5165de2ce34 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -150,6 +150,19 @@ static struct ion_heap_ops carveout_heap_ops = { struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) { struct ion_carveout_heap *carveout_heap; + int ret; + + struct page *page; + size_t size; + + 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); carveout_heap = kzalloc(sizeof(struct ion_carveout_heap), GFP_KERNEL); if (!carveout_heap) diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 9ca54586a51..8671f12df13 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -140,9 +140,18 @@ static struct ion_heap_ops chunk_heap_ops = { struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) { struct ion_chunk_heap *chunk_heap; - struct vm_struct *vm_struct; - pgprot_t pgprot = pgprot_writecombine(PAGE_KERNEL); - int i, ret; + int ret; + struct page *page; + size_t size; + + 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); chunk_heap = kzalloc(sizeof(struct ion_chunk_heap), GFP_KERNEL); if (!chunk_heap) @@ -159,26 +168,6 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) chunk_heap->size = heap_data->size; chunk_heap->allocated = 0; - vm_struct = get_vm_area(PAGE_SIZE, VM_ALLOC); - if (!vm_struct) { - ret = -ENOMEM; - goto error; - } - for (i = 0; i < chunk_heap->size; i += PAGE_SIZE) { - struct page *page = pfn_to_page(PFN_DOWN(chunk_heap->base + i)); - struct page **pages = &page; - - ret = map_vm_area(vm_struct, pgprot, &pages); - if (ret) - goto error_map_vm_area; - memset(vm_struct->addr, 0, PAGE_SIZE); - unmap_kernel_range((unsigned long)vm_struct->addr, PAGE_SIZE); - } - free_vm_area(vm_struct); - - ion_pages_sync_for_device(NULL, pfn_to_page(PFN_DOWN(heap_data->base)), - heap_data->size, DMA_BIDIRECTIONAL); - gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1); chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; @@ -188,10 +177,6 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) return &chunk_heap->heap; -error_map_vm_area: - free_vm_area(vm_struct); -error: - gen_pool_destroy(chunk_heap->pool); error_gen_pool_create: kfree(chunk_heap); return ERR_PTR(ret); diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 4d69da55f89..6c0c089e03e 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -114,38 +114,49 @@ static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot) return 0; } +static int ion_heap_sglist_zero(struct scatterlist *sgl, unsigned int nents, + pgprot_t pgprot) +{ + int p = 0; + int ret = 0; + struct sg_page_iter piter; + struct page *pages[32]; + + for_each_sg_page(sgl, &piter, nents, 0) { + pages[p++] = sg_page_iter_page(&piter); + if (p == ARRAY_SIZE(pages)) { + ret = ion_heap_clear_pages(pages, p, pgprot); + if (ret) + return ret; + p = 0; + } + } + if (p) + ret = ion_heap_clear_pages(pages, p, pgprot); + + return ret; +} + int ion_heap_buffer_zero(struct ion_buffer *buffer) { struct sg_table *table = buffer->sg_table; pgprot_t pgprot; - struct scatterlist *sg; - int i, j, ret = 0; - struct page *pages[32]; - int k = 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) { - struct page *page = sg_page(sg); - unsigned long len = sg->length; + return ion_heap_sglist_zero(table->sgl, table->nents, pgprot); +} - for (j = 0; j < len / PAGE_SIZE; j++) { - pages[k++] = page + j; - if (k == ARRAY_SIZE(pages)) { - ret = ion_heap_clear_pages(pages, k, pgprot); - if (ret) - goto end; - k = 0; - } - } - if (k) - ret = ion_heap_clear_pages(pages, k, pgprot); - } -end: - return ret; +int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot) +{ + struct scatterlist sg; + + sg_init_table(&sg, 1); + sg_set_page(&sg, page, size, 0); + return ion_heap_sglist_zero(&sg, 1, pgprot); } void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer * buffer) diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 399ec692921..5b59f58f4b8 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -215,6 +215,7 @@ void ion_heap_unmap_kernel(struct ion_heap *, struct ion_buffer *); int ion_heap_map_user(struct ion_heap *, struct ion_buffer *, struct vm_area_struct *); int ion_heap_buffer_zero(struct ion_buffer *buffer); +int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot); /** * ion_heap_init_deferred_free -- initialize deferred free functionality -- cgit v1.2.3 From 1b1cbed2f4cd92b9ccfd28b985983e2d217ecd2e Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 27 Nov 2013 15:53:01 -0800 Subject: ion: add alignment check to chunk heap Change-Id: I4be12b9545a81f9b46339a905f00e1e64896b3ed Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_chunk_heap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 8671f12df13..9c0eb5431f8 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -47,6 +47,9 @@ 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; -- cgit v1.2.3 From 8069739d23200f68b59570f6c4c5a8ec66f38fab Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 27 Nov 2013 15:53:21 -0800 Subject: ion: fix bugs in cma heap Implement ion_cma_unmap_kernel, ion will call it unconditionally. Use correct gfp flags when calling dma_alloc_coherent so it doesn't try to use atomic DMA memory. Check for invalid alignment when allocating. Reject cached allocations - the cpu address returned by dma_alloc_coherent is always going to be an uncached mapping, so map_kernel will not see data written by a cached userspace mapping. Change-Id: I2ea03f28fae3749f6de0b89700b69da3845926ea Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_cma_heap.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 58c497c197c..4418bda7647 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -69,13 +69,20 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, dev_dbg(dev, "Request buffer allocation len %ld\n", len); + if (buffer->flags & ION_FLAG_CACHED) + return -EINVAL; + + if (align > PAGE_SIZE) + return -EINVAL; + info = kzalloc(sizeof(struct ion_cma_buffer_info), GFP_KERNEL); if (!info) { dev_err(dev, "Can't allocate buffer info\n"); return ION_CMA_ALLOCATE_FAILED; } - info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), 0); + info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), + GFP_HIGHUSER | __GFP_ZERO); if (!info->cpu_addr) { dev_err(dev, "Fail to allocate buffer\n"); @@ -170,6 +177,11 @@ static void *ion_cma_map_kernel(struct ion_heap *heap, return info->cpu_addr; } +static void ion_cma_unmap_kernel(struct ion_heap *heap, + struct ion_buffer *buffer) +{ +} + static struct ion_heap_ops ion_cma_ops = { .allocate = ion_cma_allocate, .free = ion_cma_free, @@ -178,6 +190,7 @@ static struct ion_heap_ops ion_cma_ops = { .phys = ion_cma_phys, .map_user = ion_cma_mmap, .map_kernel = ion_cma_map_kernel, + .unmap_kernel = ion_cma_unmap_kernel, }; struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data) -- cgit v1.2.3 From 191b477931f7a9b20caea9269f4f340ca76e5a2e Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Fri, 22 Nov 2013 14:07:03 -0800 Subject: android: configs: Reorder config fragments, update README Change-Id: I5ee4b794dcc00f74f26562e49a406ea292af63ee (cherry picked from commit 9ebedefd06142c9bc812bfa23401031525002a76) --- android/configs/README | 2 ++ android/configs/android-base.cfg | 1 + android/configs/android-recommended.cfg | 9 +++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/android/configs/README b/android/configs/README index 391dffa6f85..8798731f890 100644 --- a/android/configs/README +++ b/android/configs/README @@ -11,3 +11,5 @@ way to enable these options would be: This will generate a .config that can then be used to save a new defconfig or compile a new kernel with Android features enabled. +Because there is no tool to consistently generate these config fragments, +lets keep them alphabetically sorted instead of random. diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg index 2b98436550c..25162024f88 100644 --- a/android/configs/android-base.cfg +++ b/android/configs/android-base.cfg @@ -1,3 +1,4 @@ +# KEEP ALPHABETICALLY SORTED # CONFIG_INET_LRO is not set # CONFIG_MODULES is not set # CONFIG_OABI_COMPAT is not set diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg index 546c37f552b..b0120f678cc 100644 --- a/android/configs/android-recommended.cfg +++ b/android/configs/android-recommended.cfg @@ -1,7 +1,4 @@ -CONFIG_PANIC_TIMEOUT=5 -CONFIG_KALLSYMS_ALL=y -CONFIG_PERF_EVENTS=y -CONFIG_COMPACTION=y +# KEEP ALPHABETICALLY SORTED # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_LEGACY_PTYS is not set @@ -14,6 +11,7 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_COMPACTION=y CONFIG_DM_UEVENT=y CONFIG_DRAGONRISE_FF=y CONFIG_EXT4_FS=y @@ -81,6 +79,7 @@ CONFIG_ION=y CONFIG_JOYSTICK_XPAD=y CONFIG_JOYSTICK_XPAD_FF=y CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_KALLSYMS_ALL=y CONFIG_KSM=y CONFIG_LOGIG940_FF=y CONFIG_LOGIRUMBLEPAD2_FF=y @@ -88,7 +87,9 @@ CONFIG_LOGITECH_FF=y CONFIG_MD=y CONFIG_MEDIA_SUPPORT=y CONFIG_MSDOS_FS=y +CONFIG_PANIC_TIMEOUT=5 CONFIG_PANTHERLORD_FF=y +CONFIG_PERF_EVENTS=y CONFIG_PM_DEBUG=y CONFIG_PM_RUNTIME=y CONFIG_PM_WAKELOCKS_LIMIT=0 -- cgit v1.2.3 From 0f9ae3f7fc853efb3f36e44b1c24ca15490e54f0 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 7 Nov 2013 19:51:09 -0800 Subject: ion: Cleanup whitespace issues and other checkpatch problems Just some simple cleanups to address whitespace issues and other issues found w/ checkpatch. Change-Id: I181444505627894b8f3bbf59192703b0f65736ee Signed-off-by: John Stultz --- drivers/staging/android/ion/compat_ion.c | 4 +- drivers/staging/android/ion/ion.c | 53 ++++++++++++++------------- drivers/staging/android/ion/ion.h | 2 +- drivers/staging/android/ion/ion_chunk_heap.c | 1 - drivers/staging/android/ion/ion_heap.c | 5 +-- drivers/staging/android/ion/ion_page_pool.c | 2 +- drivers/staging/android/ion/ion_priv.h | 2 +- drivers/staging/android/ion/ion_system_heap.c | 3 +- 8 files changed, 37 insertions(+), 35 deletions(-) diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c index a89b067ec05..e9a8132cd56 100644 --- a/drivers/staging/android/ion/compat_ion.c +++ b/drivers/staging/android/ion/compat_ion.c @@ -91,8 +91,8 @@ 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; + compat_uint_t cmd; + compat_ulong_t arg; int err; err = get_user(cmd, &data32->cmd); diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 426094c5ea3..7522b0be174 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -110,8 +110,8 @@ struct ion_handle { bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer) { - return ((buffer->flags & ION_FLAG_CACHED) && - !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC)); + return (buffer->flags & ION_FLAG_CACHED) && + !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC); } bool ion_buffer_cached(struct ion_buffer *buffer) @@ -202,7 +202,8 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, buffer->size = len; table = heap->ops->map_dma(heap, buffer); - if (WARN_ONCE(table == NULL, "heap->ops->map_dma should return ERR_PTR on error")) + if (WARN_ONCE(table == NULL, + "heap->ops->map_dma should return ERR_PTR on error")) table = ERR_PTR(-EINVAL); if (IS_ERR(table)) { heap->ops->free(buffer); @@ -424,7 +425,8 @@ static struct ion_handle *ion_handle_get_by_id(struct ion_client *client, return handle ? handle : ERR_PTR(-EINVAL); } -static bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle) +static bool ion_handle_validate(struct ion_client *client, + struct ion_handle *handle) { WARN_ON(!mutex_is_locked(&client->lock)); return (idr_find(&client->idr, handle->id) == handle); @@ -578,7 +580,8 @@ static void *ion_buffer_kmap_get(struct ion_buffer *buffer) return buffer->vaddr; } vaddr = buffer->heap->ops->map_kernel(buffer->heap, buffer); - if (WARN_ONCE(vaddr == NULL, "heap->ops->map_kernel should return ERR_PTR on error")) + if (WARN_ONCE(vaddr == NULL, + "heap->ops->map_kernel should return ERR_PTR on error")) return ERR_PTR(-EINVAL); if (IS_ERR(vaddr)) return vaddr; @@ -1403,39 +1406,39 @@ static const struct file_operations debug_heap_fops = { #ifdef DEBUG_HEAP_SHRINKER static int debug_shrink_set(void *data, u64 val) { - struct ion_heap *heap = data; - struct shrink_control sc; - int objs; + struct ion_heap *heap = data; + struct shrink_control sc; + int objs; - sc.gfp_mask = -1; - sc.nr_to_scan = 0; + sc.gfp_mask = -1; + sc.nr_to_scan = 0; - if (!val) - return 0; + if (!val) + return 0; - objs = heap->shrinker.shrink(&heap->shrinker, &sc); - sc.nr_to_scan = objs; + objs = heap->shrinker.shrink(&heap->shrinker, &sc); + sc.nr_to_scan = objs; - heap->shrinker.shrink(&heap->shrinker, &sc); - return 0; + heap->shrinker.shrink(&heap->shrinker, &sc); + return 0; } static int debug_shrink_get(void *data, u64 *val) { - struct ion_heap *heap = data; - struct shrink_control sc; - int objs; + struct ion_heap *heap = data; + struct shrink_control sc; + int objs; - sc.gfp_mask = -1; - sc.nr_to_scan = 0; + sc.gfp_mask = -1; + sc.nr_to_scan = 0; - objs = heap->shrinker.shrink(&heap->shrinker, &sc); - *val = objs; - return 0; + objs = heap->shrinker.shrink(&heap->shrinker, &sc); + *val = objs; + return 0; } DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, - debug_shrink_set, "%llu\n"); + debug_shrink_set, "%llu\n"); #endif void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 962e1c58d36..dcd2a0cdb19 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -38,7 +38,7 @@ struct ion_buffer; * struct ion_platform_heap - defines a heap in the given platform * @type: type of the heap from ion_heap_type enum * @id: unique identifier for heap. When allocating higher numbers - * will be allocated from first. At allocation these are passed + * will be allocated from first. At allocation these are passed * as a bit mask and therefore can not exceed ION_NUM_HEAP_IDS. * @name: used for debug purposes * @base: base address of heap in physical memory if applicable diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 9c0eb5431f8..ca20d627960 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. * */ -//#include #include #include #include diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 6c0c089e03e..5b01e9e30a4 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -49,9 +49,8 @@ void *ion_heap_map_kernel(struct ion_heap *heap, int npages_this_entry = PAGE_ALIGN(sg->length) / PAGE_SIZE; struct page *page = sg_page(sg); BUG_ON(i >= npages); - for (j = 0; j < npages_this_entry; j++) { + for (j = 0; j < npages_this_entry; j++) *(tmp++) = page++; - } } vaddr = vmap(pages, npages, VM_MAP, pgprot); vfree(pages); @@ -159,7 +158,7 @@ int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot) return ion_heap_sglist_zero(&sg, 1, pgprot); } -void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer * buffer) +void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer) { rt_mutex_lock(&heap->lock); list_add(&buffer->list, &heap->free_list); diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 50e68945b1b..f087a02770a 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -108,7 +108,7 @@ void *ion_page_pool_alloc(struct ion_page_pool *pool) return page; } -void ion_page_pool_free(struct ion_page_pool *pool, struct page* page) +void ion_page_pool_free(struct ion_page_pool *pool, struct page *page) { int ret; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 5b59f58f4b8..19691c0d24c 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -230,7 +230,7 @@ int ion_heap_init_deferred_free(struct ion_heap *heap); /** * ion_heap_freelist_add - add a buffer to the deferred free list * @heap: the heap - * @buffer: the buffer + * @buffer: the buffer * * Adds an item to the deferred freelist. */ diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index e824c0863bf..05e9dc93980 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -148,7 +148,8 @@ static int ion_system_heap_allocate(struct ion_heap *heap, INIT_LIST_HEAD(&pages); while (size_remaining > 0) { - info = alloc_largest_available(sys_heap, buffer, size_remaining, max_order); + info = alloc_largest_available(sys_heap, buffer, size_remaining, + max_order); if (!info) goto err; list_add_tail(&info->list, &pages); -- cgit v1.2.3 From 8f1c42284159ebd6851e1e75507f2ad6fba87d0f Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 7 Nov 2013 19:58:41 -0800 Subject: ion: Improve ION config description Mostly just to quiet checkpatch warnings, be more verbose in describing the ION config option. Change-Id: I194235f1a68623dca15ae6e658fc99d00943a827 Signed-off-by: John Stultz --- drivers/staging/android/ion/Kconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index 3215bd8fb45..a342d96ee4f 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -2,8 +2,12 @@ menuconfig ION tristate "Ion Memory Manager" select GENERIC_ALLOCATOR select DMA_SHARED_BUFFER - help - Chose this option to enable the ION Memory Manager. + ---help--- + Chose this option to enable the ION Memory Manager, + used by Android to efficiently allocate buffers + from userspace that can be shared between drivers. + If you're not using Android its probably safe to + say N here. config ION_TEST tristate "Ion Test Device" -- cgit v1.2.3