From e89d9fc608d3c8a1cf21174a713d2ff7e88e7e00 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Fri, 22 Nov 2013 17:29:57 -0800 Subject: [PATCH 01/23] android: configs: require TCPMSS, remove SCHED_TRACER and TIMER_STATS TCPMSS is required for the Android Vpn service to correctly handle the MTU on tun/ppp devices. Bug: 11579326 We don't really need SCHED_TRACER and the TIMER_STATS. Change-Id: I10c5767a6324a496713752d4fe9eff361dc8e06a (cherry picked from commit 23f01e8e81f3c53985958fa291b39c84293ad047) --- android/configs/android-base.cfg | 1 + android/configs/android-recommended.cfg | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg index 25162024f889..a9597658ef14 100644 --- a/android/configs/android-base.cfg +++ b/android/configs/android-base.cfg @@ -85,6 +85,7 @@ CONFIG_NETFILTER_XT_TARGET_CONNMARK=y CONFIG_NETFILTER_XT_TARGET_MARK=y CONFIG_NETFILTER_XT_TARGET_NFLOG=y CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y CONFIG_NETFILTER_XT_TARGET_TPROXY=y CONFIG_NETFILTER_XT_TARGET_TRACE=y CONFIG_NET_CLS_ACT=y diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg index b0120f678cc4..1bd9f6f4b959 100644 --- a/android/configs/android-recommended.cfg +++ b/android/configs/android-recommended.cfg @@ -95,7 +95,6 @@ CONFIG_PM_RUNTIME=y CONFIG_PM_WAKELOCKS_LIMIT=0 CONFIG_POWER_SUPPLY=y CONFIG_SCHEDSTATS=y -CONFIG_SCHED_TRACER=y CONFIG_SMARTJOYPLUS_FF=y CONFIG_SND=y CONFIG_SOUND=y @@ -106,7 +105,6 @@ CONFIG_TABLET_USB_GTCO=y CONFIG_TABLET_USB_HANWANG=y CONFIG_TABLET_USB_KBTAB=y CONFIG_TABLET_USB_WACOM=y -CONFIG_TIMER_STATS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_UHID=y From a8694287f5cbd0585ac653924a4459d3f1aa5b29 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Fri, 13 Dec 2013 13:02:31 -0800 Subject: [PATCH 02/23] timerfd: support CLOCK_BOOTTIME clock Add CLOCK_BOOTTIME support to timerfd Change-Id: I14dee6d1104f15a05f463a632268ac4564753faf Signed-off-by: Greg Hackmann --- fs/timerfd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/timerfd.c b/fs/timerfd.c index 929312180dd0..0013142c0475 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -317,6 +317,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) (clockid != CLOCK_MONOTONIC && clockid != CLOCK_REALTIME && clockid != CLOCK_REALTIME_ALARM && + clockid != CLOCK_BOOTTIME && clockid != CLOCK_BOOTTIME_ALARM)) return -EINVAL; From f2b94c52648fa1bb7cba053ab0f4a85e066485a1 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Sat, 14 Dec 2013 12:06:45 -0800 Subject: [PATCH 03/23] ion: Don't allow building ION as a module. ION doesn't export the proper symbols for it to be a module. This causes build issues when ION is configured as a module. Since Andorid kernels rarely use modules (I think recent policy requires no modules?), go ahead and set the ION config to a bool from the tristate option. If folks decide ION as a module is important, we will have to go through and export the various needed symbols. Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index a342d96ee4f0..b95281eef2aa 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -1,5 +1,5 @@ menuconfig ION - tristate "Ion Memory Manager" + bool "Ion Memory Manager" select GENERIC_ALLOCATOR select DMA_SHARED_BUFFER ---help--- From 8d9bc1404990afcc1fa73f1412f2b653fc3ecd31 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 16 Dec 2013 16:33:00 -0800 Subject: [PATCH 04/23] ion: remove ion_user_handle_t from ion_test.h ion_test.h should not define ion_user_handle_t, and defining it causes a warning: In file included from drivers/staging/android/ion/ion_test.c:31: drivers/staging/android/ion/../uapi/ion_test.h:23: error: redefinition of typedef 'ion_user_handle_t' drivers/staging/android/ion/../uapi/ion.h:23: note: previous declaration of 'ion_user_handle_t' was here Change-Id: I541897745a5ff128790a7e51b23f3034f5d3d6d9 Reported-by: Andrew Morton Signed-off-by: Colin Cross --- drivers/staging/android/uapi/ion_test.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/android/uapi/ion_test.h b/drivers/staging/android/uapi/ion_test.h index 352379a02690..614d1e36f72c 100644 --- a/drivers/staging/android/uapi/ion_test.h +++ b/drivers/staging/android/uapi/ion_test.h @@ -20,8 +20,6 @@ #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 From e513299f8dc0a79e6e3f5ee79615426edaf086b9 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 12 Dec 2013 19:09:47 -0800 Subject: [PATCH 05/23] ion: Fix build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add #include to fix the following warning seen with gcc 4.7.3: In file included from drivers/staging/android/ion/ion_heap.c:26:0: drivers/staging/android/ion/ion_priv.h:358:21: warning: ‘struct device’ declared inside parameter list [enabled by default] drivers/staging/android/ion/ion_priv.h:358:21: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default] Change-Id: Icc249b32d877a5b76b1669c99bef2b05d9e322da Signed-off-by: John Stultz --- drivers/staging/android/ion/ion_priv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 19691c0d24c7..ac625b115057 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -17,6 +17,7 @@ #ifndef _ION_PRIV_H #define _ION_PRIV_H +#include #include #include #include From a1eabac6e216f8ecee7668ad4468990e465392ba Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Fri, 4 Oct 2013 10:59:57 -0700 Subject: [PATCH 06/23] gpiolib: safer implementation of desc_to_gpio() The current implementation of desc_to_gpio() relies on the chip pointer to be set to a valid value in order to compute the GPIO number. This was done in the hope that we can get rid of the gpio_desc global array, but this is not happening anytime soon. This patch reimplements desc_to_gpio() in a fashion similar to that of gpio_to_desc(). As a result, desc_to_gpio(gpio_to_desc(gpio)) == gpio is now always true. This allows to call desc_to_gpio() on non-initialized descriptors as some error-handling code currently does. Signed-off-by: Alexandre Courbot Reported-by: Dr. H. Nikolaus Schaller Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c2534d62911c..4aff349386d8 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -136,7 +136,7 @@ static struct gpio_desc *gpio_to_desc(unsigned gpio) */ static int desc_to_gpio(const struct gpio_desc *desc) { - return desc->chip->base + gpio_chip_hwgpio(desc); + return desc - &gpio_desc[0]; } From 39293584f8a423bcb4efba635cddacc3d4d0b85e Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 4 Dec 2013 15:23:41 -0800 Subject: [PATCH 07/23] android: configs: Add HIDRAW to recommended set The Logitech unifying driver depends on hidraw being available. Recommending one without the other will cause the Logitech driver to silently fail when connecting Logitech devices. Change-Id: I92ed2b6803537d9da6eed7fcada8f329cb4469a2 Signed-off-by: Michael Wright --- android/configs/android-recommended.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg index 1bd9f6f4b959..32596bc2e199 100644 --- a/android/configs/android-recommended.cfg +++ b/android/configs/android-recommended.cfg @@ -18,6 +18,7 @@ CONFIG_EXT4_FS=y CONFIG_EXT4_FS_SECURITY=y CONFIG_FUSE_FS=y CONFIG_GREENASIA_FF=y +CONFIG_HIDRAW=y CONFIG_HID_A4TECH=y CONFIG_HID_ACRUX=y CONFIG_HID_ACRUX_FF=y From d214ac7202b30062bf3164b61fc466793d359f7b Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Sun, 9 Jun 2013 11:08:32 +0800 Subject: [PATCH 08/23] gpiolib: remove warnning of allocations with IRQs disabled Move of_gpiochip_add outof spin_lock, since kzalloc inside of_gpiochip_add -> of_gpiochip_add_pin_range -> gpiochip_add_pin_range -> kzalloc WARNING: at kernel/lockdep.c:2740 lockdep_trace_alloc+0xf8/0xfc() DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags)) Signed-off-by: Zhangfei Gao Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 4aff349386d8..a35c5b932eba 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1214,15 +1214,14 @@ int gpiochip_add(struct gpio_chip *chip) } } + spin_unlock_irqrestore(&gpio_lock, flags); + #ifdef CONFIG_PINCTRL INIT_LIST_HEAD(&chip->pin_ranges); #endif of_gpiochip_add(chip); -unlock: - spin_unlock_irqrestore(&gpio_lock, flags); - if (status) goto fail; @@ -1235,6 +1234,9 @@ int gpiochip_add(struct gpio_chip *chip) chip->label ? : "generic"); return 0; + +unlock: + spin_unlock_irqrestore(&gpio_lock, flags); fail: /* failures here can mean systems won't boot... */ pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n", From 0a7dde3d881d173c9300bf1d46017cb593d3e52b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 17 Dec 2013 11:16:41 +0800 Subject: [PATCH 09/23] gpu: ion: use module_platform_driver to simplify the code module_platform_driver() makes the code simpler by eliminating boilerplate code. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/tegra/tegra_ion.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/staging/android/ion/tegra/tegra_ion.c b/drivers/staging/android/ion/tegra/tegra_ion.c index 0849600bcc00..4b3d93fbf9a5 100644 --- a/drivers/staging/android/ion/tegra/tegra_ion.c +++ b/drivers/staging/android/ion/tegra/tegra_ion.c @@ -81,16 +81,5 @@ static struct platform_driver ion_driver = { .driver = { .name = "ion-tegra" } }; -static int __init ion_init(void) -{ - return platform_driver_register(&ion_driver); -} - -static void __exit ion_exit(void) -{ - platform_driver_unregister(&ion_driver); -} - -module_init(ion_init); -module_exit(ion_exit); +module_platform_driver(ion_driver); From ddd0ec0672e38c79e815588bfd725d50bd15d657 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 17 Dec 2013 11:20:22 +0800 Subject: [PATCH 10/23] gpu: ion: fix sparse non static symbol warnings Fixes the following sparse warnings: drivers/staging/android/ion/tegra/tegra_ion.c:23:19: warning: symbol 'idev' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:24:19: warning: symbol 'tegra_user_mapper' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:25:5: warning: symbol 'num_heaps' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:26:17: warning: symbol 'heaps' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:28:5: warning: symbol 'tegra_ion_probe' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:66:5: warning: symbol 'tegra_ion_remove' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/tegra/tegra_ion.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/ion/tegra/tegra_ion.c b/drivers/staging/android/ion/tegra/tegra_ion.c index 4b3d93fbf9a5..3474c65f87fa 100644 --- a/drivers/staging/android/ion/tegra/tegra_ion.c +++ b/drivers/staging/android/ion/tegra/tegra_ion.c @@ -20,12 +20,11 @@ #include "../ion.h" #include "../ion_priv.h" -struct ion_device *idev; -struct ion_mapper *tegra_user_mapper; -int num_heaps; -struct ion_heap **heaps; +static struct ion_device *idev; +static int num_heaps; +static struct ion_heap **heaps; -int tegra_ion_probe(struct platform_device *pdev) +static int tegra_ion_probe(struct platform_device *pdev) { struct ion_platform_data *pdata = pdev->dev.platform_data; int err; @@ -63,7 +62,7 @@ int tegra_ion_probe(struct platform_device *pdev) return err; } -int tegra_ion_remove(struct platform_device *pdev) +static int tegra_ion_remove(struct platform_device *pdev) { struct ion_device *idev = platform_get_drvdata(pdev); int i; From d232ba2bea468a7d12d826d0fe62b3f8a9ba8d10 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Mon, 16 Dec 2013 21:07:51 -0800 Subject: [PATCH 11/23] staging: ion: Add HAVE_MEMBLOCK config dependency The kbuild test robot reported a build issue w/ ION on m68k: drivers/staging/android/ion/ion.c: In function 'ion_reserve': drivers/staging/android/ion/ion.c:1526:4: error: implicit declaration of function 'memblock_alloc_base' [-Werror=implicit-function-declaration] drivers/staging/android/ion/ion.c:1528:11: error: 'MEMBLOCK_ALLOC_ANYWHERE' undeclared (first use in this function) drivers/staging/android/ion/ion.c:1528:11: note: each undeclared identifier is reported only once for each function it appears in drivers/staging/android/ion/ion.c:1537:4: error: implicit declaration of function 'memblock_reserve' [-Werror=implicit-function-declaration] cc1: some warnings being treated as errors This is caused by ION using memblock functionality which m68k doesn't support. This patch adds a HAVE_MEMBLOCK dependency to the ION config. Acked-by: Colin Cross Cc: Android Kernel Team Reported-by: kbuild test robot Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index b95281eef2aa..a9a64ea2343f 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -1,5 +1,6 @@ menuconfig ION bool "Ion Memory Manager" + depends on HAVE_MEMBLOCK select GENERIC_ALLOCATOR select DMA_SHARED_BUFFER ---help--- From 60e11dfc002962181fe4f0db54b33c65fee02c52 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Mon, 16 Dec 2013 21:07:52 -0800 Subject: [PATCH 12/23] staging: ion: Fix possible null pointer dereference The kbuild test robot reported: drivers/staging/android/ion/ion_system_heap.c:122 alloc_largest_available() error: potential null dereference 'info'. (kmalloc returns null) Where the pointer returned from kmalloc goes unchecked for failure. This patch checks the return for NULL, and reworks the logic, as suggested by Colin, so we allocate the page_info structure first. Acked-by: Colin Cross Cc: Android Kernel Team Reported-by: kbuild test robot Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 05e9dc93980f..5bccf9e2c93c 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -108,6 +108,10 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap, struct page_info *info; int i; + info = kmalloc(sizeof(struct page_info), GFP_KERNEL); + if (!info) + return NULL; + for (i = 0; i < num_orders; i++) { if (size < order_to_size(orders[i])) continue; @@ -118,11 +122,12 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap, if (!page) continue; - info = kmalloc(sizeof(struct page_info), GFP_KERNEL); info->page = page; info->order = orders[i]; return info; } + kfree(info); + return NULL; } From c6448537fe9e8b684b214e89c6c68c3b209f549e Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 17 Dec 2013 17:04:29 -0800 Subject: [PATCH 13/23] staging: ion: Avoid using rt_mutexes directly RT_MUTEXES can be configured out of the kernel, causing compile problems with ION. To quote Colin: "rt_mutexes were added with the deferred freeing feature. Heaps need to return zeroed memory to userspace, but zeroing the memory on every allocation was causing performance issues. We added a SCHED_IDLE thread to zero memory in the background after freeing, but locking the heap from the SCHED_IDLE thread might block a high priority allocation thread for a long time. The lock is only used to protect the heap's free_list and free_list_size members, and is not held for any long or sleeping operations. Converting to a spinlock should prevent priority inversion without using the rt_mutex. I'd also rename it to free_lock to so it doesn't get used as a general heap lock." Thus this patch converts the rt_mutex usage to a spinlock and renames the lock free_lock to be more clear as to its use. I also had to change a bit of logic in ion_heap_freelist_drain() to safely avoid list corruption. Acked-by: Colin Cross Cc: Android Kernel Team Reported-by: Jim Davis Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_heap.c | 28 +++++++++++++++----------- drivers/staging/android/ion/ion_priv.h | 2 +- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 5b01e9e30a4f..96feebb6ad79 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -160,10 +160,10 @@ int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot) void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer) { - rt_mutex_lock(&heap->lock); + spin_lock(&heap->free_lock); list_add(&buffer->list, &heap->free_list); heap->free_list_size += buffer->size; - rt_mutex_unlock(&heap->lock); + spin_unlock(&heap->free_lock); wake_up(&heap->waitqueue); } @@ -171,34 +171,38 @@ size_t ion_heap_freelist_size(struct ion_heap *heap) { size_t size; - rt_mutex_lock(&heap->lock); + spin_lock(&heap->free_lock); size = heap->free_list_size; - rt_mutex_unlock(&heap->lock); + spin_unlock(&heap->free_lock); return size; } size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) { - struct ion_buffer *buffer, *tmp; + struct ion_buffer *buffer; size_t total_drained = 0; if (ion_heap_freelist_size(heap) == 0) return 0; - rt_mutex_lock(&heap->lock); + spin_lock(&heap->free_lock); if (size == 0) size = heap->free_list_size; - list_for_each_entry_safe(buffer, tmp, &heap->free_list, list) { + while (!list_empty(&heap->free_list)) { if (total_drained >= size) break; + buffer = list_first_entry(&heap->free_list, struct ion_buffer, + list); list_del(&buffer->list); heap->free_list_size -= buffer->size; total_drained += buffer->size; + spin_unlock(&heap->free_lock); ion_buffer_destroy(buffer); + spin_lock(&heap->free_lock); } - rt_mutex_unlock(&heap->lock); + spin_unlock(&heap->free_lock); return total_drained; } @@ -213,16 +217,16 @@ static int ion_heap_deferred_free(void *data) wait_event_freezable(heap->waitqueue, ion_heap_freelist_size(heap) > 0); - rt_mutex_lock(&heap->lock); + spin_lock(&heap->free_lock); if (list_empty(&heap->free_list)) { - rt_mutex_unlock(&heap->lock); + spin_unlock(&heap->free_lock); continue; } buffer = list_first_entry(&heap->free_list, struct ion_buffer, list); list_del(&buffer->list); heap->free_list_size -= buffer->size; - rt_mutex_unlock(&heap->lock); + spin_unlock(&heap->free_lock); ion_buffer_destroy(buffer); } @@ -235,7 +239,7 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) INIT_LIST_HEAD(&heap->free_list); heap->free_list_size = 0; - rt_mutex_init(&heap->lock); + spin_lock_init(&heap->free_lock); init_waitqueue_head(&heap->waitqueue); heap->task = kthread_run(ion_heap_deferred_free, heap, "%s", heap->name); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index ac625b115057..58e84cc81486 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -160,7 +160,7 @@ struct ion_heap { struct shrinker shrinker; struct list_head free_list; size_t free_list_size; - struct rt_mutex lock; + spinlock_t free_lock; wait_queue_head_t waitqueue; struct task_struct *task; int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *); From 892e1580141cde0f80180e43f6c8c3dc356ddaf2 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 19 Dec 2013 15:56:23 -0800 Subject: [PATCH 14/23] ion_test: Add compat_ioctl support (v2) Prior to subitting this, Colin reworked the compat_ioctl support for the ion_test driver, moving the structure to be the same size on both 32 and 64 bit architectures. Two small things were left out. The compat_ioctl ptr assignment, and the fact that despite having uniform sized types in the structure, the structure pads out to different sizes on different arches. This patch resolves this issue by adding a padding entry after the write flag, and adding the compat_ioctl ptr. Changes in v2: - Add a padding int rather then making write a u64 Cc: Colin Cross Cc: Greg KH Cc: Android Kernel Team Signed-off-by: John Stultz --- drivers/staging/android/ion/ion_test.c | 1 + drivers/staging/android/uapi/ion_test.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/staging/android/ion/ion_test.c b/drivers/staging/android/ion/ion_test.c index 3e20349baf7c..654acb5c8eba 100644 --- a/drivers/staging/android/ion/ion_test.c +++ b/drivers/staging/android/ion/ion_test.c @@ -231,6 +231,7 @@ static int ion_test_release(struct inode *inode, struct file *file) 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, }; diff --git a/drivers/staging/android/uapi/ion_test.h b/drivers/staging/android/uapi/ion_test.h index 614d1e36f72c..ffef06f63133 100644 --- a/drivers/staging/android/uapi/ion_test.h +++ b/drivers/staging/android/uapi/ion_test.h @@ -32,6 +32,7 @@ struct ion_test_rw_data { __u64 offset; __u64 size; int write; + int __padding; }; #define ION_IOC_MAGIC 'I' From f3ae9a8286d63f13715d2082965d6b8849af05a5 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 12 Dec 2013 17:50:35 -0800 Subject: [PATCH 15/23] ion: move shrinker out of heaps Every heap that uses deferred frees is going to need a shrinker to shrink the freelist under memory pressure. Rather than requiring each heap to implement a shrinker, automatically register a shrinker if the deferred free flag is set. The system heap also needs to shrink its page pools, so add a shrink function to the heap ops that will be called after shrinking the freelists. Change-Id: Icda722d683426fadb8ddd1c8e9499264ab682c57 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion.c | 3 + drivers/staging/android/ion/ion_heap.c | 38 +++++++++++ drivers/staging/android/ion/ion_page_pool.c | 7 +- drivers/staging/android/ion/ion_priv.h | 21 +++--- drivers/staging/android/ion/ion_system_heap.c | 66 +++++-------------- 5 files changed, 72 insertions(+), 63 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 7522b0be1749..1a85724ab22d 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1451,6 +1451,9 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) ion_heap_init_deferred_free(heap); + if ((heap->flags & ION_HEAP_FLAG_DEFER_FREE) || heap->ops->shrink) + ion_heap_init_shrinker(heap); + heap->dev = dev; down_write(&dev->lock); /* use negative heap->id to reverse the priority -- when traversing diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 96feebb6ad79..5c14bc2a1822 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -252,6 +252,44 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) return 0; } +static int ion_heap_shrink(struct shrinker *shrinker, struct shrink_control *sc) +{ + struct ion_heap *heap = container_of(shrinker, struct ion_heap, + shrinker); + int total = 0; + int freed = 0; + int to_scan = sc->nr_to_scan; + + if (to_scan == 0) + goto out; + + /* + * shrink the free list first, no point in zeroing the memory if we're + * just going to reclaim it + */ + if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) + freed = ion_heap_freelist_drain(heap, to_scan * PAGE_SIZE) / + PAGE_SIZE; + + to_scan -= freed; + if (to_scan < 0) + to_scan = 0; + +out: + total = ion_heap_freelist_size(heap) / PAGE_SIZE; + if (heap->ops->shrink) + total += heap->ops->shrink(heap, sc->gfp_mask, to_scan); + return total; +} + +void ion_heap_init_shrinker(struct ion_heap *heap) +{ + heap->shrinker.shrink = ion_heap_shrink; + heap->shrinker.seeks = DEFAULT_SEEKS; + heap->shrinker.batch = 0; + register_shrinker(&heap->shrinker); +} + struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) { struct ion_heap *heap = NULL; diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index f087a02770a8..0e20e62ec4bc 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -130,15 +130,11 @@ static int ion_page_pool_total(struct ion_page_pool *pool, bool high) int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, int nr_to_scan) { - int nr_freed = 0; int i; bool high; high = !!(gfp_mask & __GFP_HIGHMEM); - if (nr_to_scan == 0) - return ion_page_pool_total(pool, high); - for (i = 0; i < nr_to_scan; i++) { struct page *page; @@ -153,10 +149,9 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, } mutex_unlock(&pool->mutex); ion_page_pool_free_pages(pool, page); - nr_freed += (1 << pool->order); } - return nr_freed; + return ion_page_pool_total(pool, high); } struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 58e84cc81486..85866e6d2f92 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -114,6 +114,7 @@ struct ion_heap_ops { void (*unmap_kernel) (struct ion_heap *heap, struct ion_buffer *buffer); int (*map_user) (struct ion_heap *mapper, struct ion_buffer *buffer, struct vm_area_struct *vma); + int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan); }; /** @@ -132,10 +133,7 @@ struct ion_heap_ops { * allocating. These are specified by platform data and * MUST be unique * @name: used for debugging - * @shrinker: a shrinker for the heap, if the heap caches system - * memory, it must define a shrinker to return it on low - * memory conditions, this includes system memory cached - * in the deferred free lists for heaps that support it + * @shrinker: a shrinker for the heap * @free_list: free list head if deferred free is used * @free_list_size size of the deferred free list in bytes * @lock: protects the free list @@ -218,6 +216,16 @@ int ion_heap_map_user(struct ion_heap *, struct ion_buffer *, 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_shrinker + * @heap: the heap + * + * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag or defines the shrink op + * this function will be called to setup a shrinker to shrink the freelists + * and call the heap's shrink op. + */ +void ion_heap_init_shrinker(struct ion_heap *heap); + /** * ion_heap_init_deferred_free -- initialize deferred free functionality * @heap: the heap @@ -305,13 +313,8 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, * @low_count: number of lowmem items in the pool * @high_items: list of highmem items * @low_items: list of lowmem items - * @shrinker: a shrinker for the items * @mutex: lock protecting this struct and especially the count * item list - * @alloc: function to be used to allocate pageory when the pool - * is empty - * @free: function to be used to free pageory back to the system - * when the shrinker fires * @gfp_mask: gfp_mask to use from alloc * @order: order of pages in the pool * @list: plist node for list of pools diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 5bccf9e2c93c..4a87fcf53266 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -227,6 +227,23 @@ static void ion_system_heap_unmap_dma(struct ion_heap *heap, return; } +static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, + int nr_to_scan) +{ + struct ion_system_heap *sys_heap; + int nr_total = 0; + int i; + + sys_heap = container_of(heap, struct ion_system_heap, heap); + + for (i = 0; i < num_orders; i++) { + struct ion_page_pool *pool = sys_heap->pools[i]; + nr_total += ion_page_pool_shrink(pool, gfp_mask, nr_to_scan); + } + + return nr_total; +} + static struct ion_heap_ops system_heap_ops = { .allocate = ion_system_heap_allocate, .free = ion_system_heap_free, @@ -235,52 +252,9 @@ static struct ion_heap_ops system_heap_ops = { .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, .map_user = ion_heap_map_user, + .shrink = ion_system_heap_shrink, }; -static int ion_system_heap_shrink(struct shrinker *shrinker, - struct shrink_control *sc) { - - struct ion_heap *heap = container_of(shrinker, struct ion_heap, - shrinker); - struct ion_system_heap *sys_heap = container_of(heap, - struct ion_system_heap, - heap); - int nr_total = 0; - int nr_freed = 0; - int i; - - if (sc->nr_to_scan == 0) - goto end; - - /* shrink the free list first, no point in zeroing the memory if - we're just going to reclaim it */ - nr_freed += ion_heap_freelist_drain(heap, sc->nr_to_scan * PAGE_SIZE) / - PAGE_SIZE; - - if (nr_freed >= sc->nr_to_scan) - goto end; - - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool = sys_heap->pools[i]; - - nr_freed += ion_page_pool_shrink(pool, sc->gfp_mask, - sc->nr_to_scan); - if (nr_freed >= sc->nr_to_scan) - break; - } - -end: - /* total number of items is whatever the page pools are holding - plus whatever's in the freelist */ - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool = sys_heap->pools[i]; - nr_total += ion_page_pool_shrink(pool, sc->gfp_mask, 0); - } - nr_total += ion_heap_freelist_size(heap) / PAGE_SIZE; - return nr_total; - -} - static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, void *unused) { @@ -328,10 +302,6 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) heap->pools[i] = pool; } - heap->heap.shrinker.shrink = ion_system_heap_shrink; - heap->heap.shrinker.seeks = DEFAULT_SEEKS; - heap->heap.shrinker.batch = 0; - register_shrinker(&heap->heap.shrinker); heap->heap.debug_show = ion_system_heap_debug_show; return &heap->heap; err_create_pool: From 5ec06794e17b3c9ee1c59fa4ff6448a7f4384860 Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Thu, 29 Aug 2013 15:28:58 -0700 Subject: [PATCH 16/23] gpu: ion: create separate heap and client debugfs directories It can be slightly annoying to figure out which files under the ion debugfs directory are heap debug files and which ones are client debug files. Create separate subdirectories under ion to hold the different types of debug files. Change-Id: Ic773ab619ef94b9b4d0f3794def9d37645c7c212 Signed-off-by: Mitchel Humpherys --- drivers/staging/android/ion/ion.c | 57 ++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 1a85724ab22d..09a373f4afe9 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -59,6 +59,8 @@ struct ion_device { unsigned long arg); struct rb_root clients; struct dentry *debug_root; + struct dentry *heaps_debug_root; + struct dentry *clients_debug_root; }; /** @@ -763,8 +765,15 @@ struct ion_client *ion_client_create(struct ion_device *dev, snprintf(debug_name, 64, "%u", client->pid); client->debug_root = debugfs_create_file(debug_name, 0664, - dev->debug_root, client, - &debug_client_fops); + dev->clients_debug_root, + client, &debug_client_fops); + if (!client->debug_root) { + char buf[256], *path; + path = dentry_path(dev->clients_debug_root, buf, 256); + pr_err("Failed to create client debugfs at %s/%s\n", + path, debug_name); + } + up_write(&dev->lock); return client; @@ -1443,6 +1452,8 @@ DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) { + struct dentry *debug_file; + if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma || !heap->ops->unmap_dma) pr_err("%s: can not add heap with invalid ops struct.\n", @@ -1460,15 +1471,31 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) the list later attempt higher id numbers first */ plist_node_init(&heap->node, -heap->id); plist_add(&heap->node, &dev->heaps); - debugfs_create_file(heap->name, 0664, dev->debug_root, heap, - &debug_heap_fops); + debug_file = debugfs_create_file(heap->name, 0664, + dev->heaps_debug_root, heap, + &debug_heap_fops); + + if (!debug_file) { + char buf[256], *path; + path = dentry_path(dev->heaps_debug_root, buf, 256); + pr_err("Failed to create heap debugfs at %s/%s\n", + path, heap->name); + } + #ifdef DEBUG_HEAP_SHRINKER if (heap->shrinker.shrink) { char debug_name[64]; snprintf(debug_name, 64, "%s_shrink", heap->name); - debugfs_create_file(debug_name, 0644, dev->debug_root, heap, - &debug_shrink_fops); + debug_file = debugfs_create_file( + debug_name, 0644, dev->heaps_debug_root, heap, + &debug_shrink_fops); + if (!debug_file) { + char buf[256], *path; + path = dentry_path(dev->heaps_debug_root, buf, 256); + pr_err("Failed to create heap shrinker debugfs at %s/%s\n", + path, debug_name); + } } #endif up_write(&dev->lock); @@ -1497,8 +1524,21 @@ struct ion_device *ion_device_create(long (*custom_ioctl) } idev->debug_root = debugfs_create_dir("ion", NULL); - if (!idev->debug_root) - pr_err("ion: failed to create debug files.\n"); + if (!idev->debug_root) { + pr_err("ion: failed to create debugfs root directory.\n"); + goto debugfs_done; + } + idev->heaps_debug_root = debugfs_create_dir("heaps", idev->debug_root); + if (!idev->heaps_debug_root) { + pr_err("ion: failed to create debugfs heaps directory.\n"); + goto debugfs_done; + } + idev->clients_debug_root = debugfs_create_dir("clients", + idev->debug_root); + if (!idev->clients_debug_root) + pr_err("ion: failed to create debugfs clients directory.\n"); + +debugfs_done: idev->custom_ioctl = custom_ioctl; idev->buffers = RB_ROOT; @@ -1512,6 +1552,7 @@ struct ion_device *ion_device_create(long (*custom_ioctl) void ion_device_destroy(struct ion_device *dev) { misc_deregister(&dev->dev); + debugfs_remove_recursive(dev->debug_root); /* XXX need to free the heaps and clients ? */ kfree(dev); } From c95cd575f4ae04dbf59745f6f6f9e24f86571558 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Mon, 5 Dec 2011 15:32:36 -0800 Subject: [PATCH 17/23] gpu: ion: Fix debugfs handling of multiple kernel clients Currently, Ion registers all debugfs entries for clients via pid. If there are multiple kernel clients, this means the debugfs entry only gets created for the first one. Fix this by creating debugfs entries by name always. When creating user clients, specify the name via the pid. Change-Id: I00cbb284d1c53b3362bb7be9c0275620a9fac167 Signed-off-by: Laura Abbott Signed-off-by: Mitchel Humpherys --- drivers/staging/android/ion/ion.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 09a373f4afe9..ada4a02e1ef2 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -718,7 +718,6 @@ struct ion_client *ion_client_create(struct ion_device *dev, struct rb_node **p; struct rb_node *parent = NULL; struct ion_client *entry; - char debug_name[64]; pid_t pid; get_task_struct(current->group_leader); @@ -763,15 +762,14 @@ struct ion_client *ion_client_create(struct ion_device *dev, rb_link_node(&client->node, parent, p); rb_insert_color(&client->node, &dev->clients); - snprintf(debug_name, 64, "%u", client->pid); - client->debug_root = debugfs_create_file(debug_name, 0664, + client->debug_root = debugfs_create_file(name, 0664, dev->clients_debug_root, client, &debug_client_fops); if (!client->debug_root) { char buf[256], *path; path = dentry_path(dev->clients_debug_root, buf, 256); pr_err("Failed to create client debugfs at %s/%s\n", - path, debug_name); + path, name); } up_write(&dev->lock); @@ -1302,9 +1300,11 @@ static int ion_open(struct inode *inode, struct file *file) struct miscdevice *miscdev = file->private_data; struct ion_device *dev = container_of(miscdev, struct ion_device, dev); struct ion_client *client; + char debug_name[64]; pr_debug("%s: %d\n", __func__, __LINE__); - client = ion_client_create(dev, "user"); + snprintf(debug_name, 64, "%u", task_pid_nr(current->group_leader)); + client = ion_client_create(dev, debug_name); if (IS_ERR(client)) return PTR_ERR(client); file->private_data = client; From 0d8b5323f86e992177e9995a7e5e0ee163575ee9 Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Wed, 18 Dec 2013 22:10:07 -0800 Subject: [PATCH 18/23] ion: store a copy of the client name on client creation Currently, we copy the pointer passed in to ion_client_create without making a copy of the string itself. This approach is problematic since it relies on the client keeping the name string in working order. Change-Id: I62d79c7539b2c857a5a625339d49c9c892e8622d Signed-off-by: Mitchel Humpherys --- drivers/staging/android/ion/ion.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index ada4a02e1ef2..7627ffbc8360 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -734,19 +734,18 @@ struct ion_client *ion_client_create(struct ion_device *dev, task_unlock(current->group_leader); client = kzalloc(sizeof(struct ion_client), GFP_KERNEL); - if (!client) { - if (task) - put_task_struct(current->group_leader); - return ERR_PTR(-ENOMEM); - } + if (!client) + goto err_put_task_struct; client->dev = dev; client->handles = RB_ROOT; idr_init(&client->idr); mutex_init(&client->lock); - client->name = name; client->task = task; client->pid = pid; + client->name = kstrdup(name, GFP_KERNEL); + if (!client->name) + goto err_free_client; down_write(&dev->lock); p = &dev->clients.rb_node; @@ -775,6 +774,13 @@ struct ion_client *ion_client_create(struct ion_device *dev, up_write(&dev->lock); return client; + +err_free_client: + kfree(client); +err_put_task_struct: + if (task) + put_task_struct(current->group_leader); + return ERR_PTR(-ENOMEM); } EXPORT_SYMBOL(ion_client_create); @@ -799,6 +805,7 @@ void ion_client_destroy(struct ion_client *client) debugfs_remove_recursive(client->debug_root); up_write(&dev->lock); + kfree(client->name); kfree(client); } EXPORT_SYMBOL(ion_client_destroy); From 550640ca7aec7789cdd52742b4c1d9dd712a5dd8 Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Mon, 7 Oct 2013 09:24:29 -0700 Subject: [PATCH 19/23] gpu: ion: make sure all clients are exposed in debugfs Currently, if multiple Ion clients are created with the same name, only the first one shows up in debugfs. Rectify this by adding a monotonically-increasing serial number to the debug names of Ion clients. Change-Id: I000e45055d5029c7bccd88c36b238736929da3a5 Signed-off-by: Mitchel Humpherys --- drivers/staging/android/ion/ion.c | 38 +++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 7627ffbc8360..48774e3974aa 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -71,6 +71,8 @@ struct ion_device { * @idr: an idr space for allocating handle ids * @lock: lock protecting the tree of handles * @name: used for debugging + * @display_name: used for debugging (unique version of @name) + * @display_serial: used for debugging (to make display_name unique) * @task: used for debugging * * A client represents a list of buffers this client may access. @@ -84,6 +86,8 @@ struct ion_client { struct idr idr; struct mutex lock; const char *name; + char *display_name; + int display_serial; struct task_struct *task; pid_t pid; struct dentry *debug_root; @@ -710,6 +714,21 @@ static const struct file_operations debug_client_fops = { .release = single_release, }; +static int ion_get_client_serial(const struct rb_root *root, + const unsigned char *name) +{ + int serial = -1; + struct rb_node *node; + for (node = rb_first(root); node; node = rb_next(node)) { + struct ion_client *client = rb_entry(node, struct ion_client, + node); + if (strcmp(client->name, name)) + continue; + serial = max(serial, client->display_serial); + } + return serial + 1; +} + struct ion_client *ion_client_create(struct ion_device *dev, const char *name) { @@ -720,6 +739,11 @@ struct ion_client *ion_client_create(struct ion_device *dev, struct ion_client *entry; pid_t pid; + if (!name) { + pr_err("%s: Name cannot be null\n", __func__); + return ERR_PTR(-EINVAL); + } + get_task_struct(current->group_leader); task_lock(current->group_leader); pid = task_pid_nr(current->group_leader); @@ -748,6 +772,13 @@ struct ion_client *ion_client_create(struct ion_device *dev, goto err_free_client; down_write(&dev->lock); + client->display_serial = ion_get_client_serial(&dev->clients, name); + client->display_name = kasprintf( + GFP_KERNEL, "%s-%d", name, client->display_serial); + if (!client->display_name) { + up_write(&dev->lock); + goto err_free_client_name; + } p = &dev->clients.rb_node; while (*p) { parent = *p; @@ -761,20 +792,22 @@ struct ion_client *ion_client_create(struct ion_device *dev, rb_link_node(&client->node, parent, p); rb_insert_color(&client->node, &dev->clients); - client->debug_root = debugfs_create_file(name, 0664, + client->debug_root = debugfs_create_file(client->display_name, 0664, dev->clients_debug_root, client, &debug_client_fops); if (!client->debug_root) { char buf[256], *path; path = dentry_path(dev->clients_debug_root, buf, 256); pr_err("Failed to create client debugfs at %s/%s\n", - path, name); + path, client->display_name); } up_write(&dev->lock); return client; +err_free_client_name: + kfree(client->name); err_free_client: kfree(client); err_put_task_struct: @@ -805,6 +838,7 @@ void ion_client_destroy(struct ion_client *client) debugfs_remove_recursive(client->debug_root); up_write(&dev->lock); + kfree(client->display_name); kfree(client->name); kfree(client); } From 14f162cb64a8beca59f06cd94d5569bd550dc99d Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Tue, 6 Aug 2013 15:08:23 -0700 Subject: [PATCH 20/23] ion: Add private buffer flag to skip page pooling on free Currently, when we free a buffer it might actually just go back into a heap-specific page pool rather than going back to the system. This poses a problem because sometimes (like when we're running a shrinker in low memory conditions) we need to force the memory associated with the buffer to truly be relinquished to the system rather than just going back into a page pool. There isn't a use case for this flag by Ion clients, so make it a private flag. The main use case right now is to provide a mechanism for the deferred free code to force stale buffers to bypass page pooling. Change-Id: I724f89cc037083fe8576784363caa18a34e8705a Signed-off-by: Mitchel Humpherys --- drivers/staging/android/ion/ion_heap.c | 19 +++++++-- drivers/staging/android/ion/ion_priv.h | 42 ++++++++++++++++++- drivers/staging/android/ion/ion_system_heap.c | 4 +- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 5c14bc2a1822..750b76af0cf3 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -178,7 +178,8 @@ size_t ion_heap_freelist_size(struct ion_heap *heap) return size; } -size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) +static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size, + bool skip_pools) { struct ion_buffer *buffer; size_t total_drained = 0; @@ -197,6 +198,8 @@ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) list); list_del(&buffer->list); heap->free_list_size -= buffer->size; + if (skip_pools) + buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE; total_drained += buffer->size; spin_unlock(&heap->free_lock); ion_buffer_destroy(buffer); @@ -207,6 +210,16 @@ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) return total_drained; } +size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) +{ + return _ion_heap_freelist_drain(heap, size, false); +} + +size_t ion_heap_freelist_shrink(struct ion_heap *heap, size_t size) +{ + return _ion_heap_freelist_drain(heap, size, true); +} + static int ion_heap_deferred_free(void *data) { struct ion_heap *heap = data; @@ -265,10 +278,10 @@ static int ion_heap_shrink(struct shrinker *shrinker, struct shrink_control *sc) /* * shrink the free list first, no point in zeroing the memory if we're - * just going to reclaim it + * just going to reclaim it. Also, skip any possible page pooling. */ if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) - freed = ion_heap_freelist_drain(heap, to_scan * PAGE_SIZE) / + freed = ion_heap_freelist_shrink(heap, to_scan * PAGE_SIZE) / PAGE_SIZE; to_scan -= freed; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 85866e6d2f92..18ef365e7552 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -38,6 +38,7 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); * @dev: back pointer to the ion_device * @heap: back pointer to the heap the buffer came from * @flags: buffer specific flags + * @private_flags: internal buffer specific flags * @size: size of the buffer * @priv_virt: private data to the buffer representable as * a void * @@ -66,6 +67,7 @@ struct ion_buffer { struct ion_device *dev; struct ion_heap *heap; unsigned long flags; + unsigned long private_flags; size_t size; union { void *priv_virt; @@ -98,7 +100,11 @@ void ion_buffer_destroy(struct ion_buffer *buffer); * @map_user map memory to userspace * * allocate, phys, and map_user return 0 on success, -errno on error. - * map_dma and map_kernel return pointer on success, ERR_PTR on error. + * map_dma and map_kernel return pointer on success, ERR_PTR on + * error. @free will be called with ION_PRIV_FLAG_SHRINKER_FREE set in + * the buffer's private_flags when called from a shrinker. In that + * case, the pages being free'd must be truly free'd back to the + * system, not put in a page pool or otherwise cached. */ struct ion_heap_ops { int (*allocate) (struct ion_heap *heap, @@ -122,6 +128,17 @@ struct ion_heap_ops { */ #define ION_HEAP_FLAG_DEFER_FREE (1 << 0) +/** + * private flags - flags internal to ion + */ +/* + * Buffer is being freed from a shrinker function. Skip any possible + * heap-specific caching mechanism (e.g. page pools). Guarantees that + * any buffer storage that came from the system allocator will be + * returned to the system allocator. + */ +#define ION_PRIV_FLAG_SHRINKER_FREE (1 << 0) + /** * struct ion_heap - represents a heap in the system * @node: rb node to put the heap on the device's tree of heaps @@ -257,6 +274,29 @@ void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer); */ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size); +/** + * ion_heap_freelist_shrink - drain the deferred free + * list, skipping any heap-specific + * pooling or caching mechanisms + * + * @heap: the heap + * @size: amount of memory to drain in bytes + * + * Drains the indicated amount of memory from the deferred freelist immediately. + * Returns the total amount freed. The total freed may be higher depending + * on the size of the items in the list, or lower if there is insufficient + * total memory on the freelist. + * + * Unlike with @ion_heap_freelist_drain, don't put any pages back into + * page pools or otherwise cache the pages. Everything must be + * genuinely free'd back to the system. If you're free'ing from a + * shrinker you probably want to use this. Note that this relies on + * the heap.ops.free callback honoring the ION_PRIV_FLAG_SHRINKER_FREE + * flag. + */ +size_t ion_heap_freelist_shrink(struct ion_heap *heap, + size_t size); + /** * ion_heap_freelist_size - returns the size of the freelist in bytes * @heap: the heap diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 4a87fcf53266..a2c8968104f8 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -90,7 +90,7 @@ static void free_buffer_page(struct ion_system_heap *heap, { bool cached = ion_buffer_cached(buffer); - if (!cached) { + if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) { struct ion_page_pool *pool = heap->pools[order_to_index(order)]; ion_page_pool_free(pool, page); } else { @@ -205,7 +205,7 @@ static void ion_system_heap_free(struct ion_buffer *buffer) /* uncached pages come from the page pools, zero them before returning for security purposes (other allocations are zerod at alloc time */ - if (!cached) + if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) ion_heap_buffer_zero(buffer); for_each_sg(table->sgl, sg, table->nents, i) From c69de844c80884167bb42243b36498dde81eebf6 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 19 Dec 2013 18:37:49 -0800 Subject: [PATCH 21/23] ion: fix overflow and list bugs in system heap Fix a few bugs in ion_system_heap: Initialize the list node in the info block. Don't store size_remaining in a signed long, allocating >2GB could overflow, resulting in a call to sg_alloc_table with nents=0 which panics. alloc_largest_available will never return a block larger than size_remanining, so it can never go negative. Limit a single allocation to half of all memory. Prevents a large allocation from taking down the whole system. Change-Id: I7fcbd7e1d5b4d482d7612d80b6c9e8e24466f1d8 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_system_heap.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index a2c8968104f8..a052418d2efc 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -124,6 +124,7 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap, info->page = page; info->order = orders[i]; + INIT_LIST_HEAD(&info->list); return info; } kfree(info); @@ -145,12 +146,15 @@ static int ion_system_heap_allocate(struct ion_heap *heap, struct list_head pages; struct page_info *info, *tmp_info; int i = 0; - long size_remaining = PAGE_ALIGN(size); + 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; + INIT_LIST_HEAD(&pages); while (size_remaining > 0) { info = alloc_largest_available(sys_heap, buffer, size_remaining, From c5149b1e38ecd5c3f3d3add7fc118fb47b719929 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Fri, 27 Dec 2013 15:20:32 -0800 Subject: [PATCH 22/23] android: configs: add TIMER_STATS back, helps with sysrq t. Change-Id: I8fe033090e38523152225dcfb7a1828f530a0757 Signed-off-by: JP Abgrall (cherry picked from commit 7aee29d6482954ac9fecae3ce8a90b6759158107) --- android/configs/android-recommended.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg index 32596bc2e199..9caa089c5d19 100644 --- a/android/configs/android-recommended.cfg +++ b/android/configs/android-recommended.cfg @@ -106,6 +106,7 @@ CONFIG_TABLET_USB_GTCO=y CONFIG_TABLET_USB_HANWANG=y CONFIG_TABLET_USB_KBTAB=y CONFIG_TABLET_USB_WACOM=y +CONFIG_TIMER_STATS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_UHID=y From 0715d10b9e6c04327adb189e13ecd6a3c2df48ce Mon Sep 17 00:00:00 2001 From: Chih-Wei Huang Date: Tue, 24 Dec 2013 17:51:55 +0800 Subject: [PATCH 23/23] cpufreq: interactive: fix compiling warnings The gcc warns like: cpufreq_interactive.c:745:6: warning: operation on 'ret' may be undefined [-Wsequence-point] It was introduced by commit cf0fad49d17cb8273ce555dd5b7afab67d7923bf. Since sprintf(...) just return 1 (one character) in this case, ret should not changed. Just discarding the result of sprintf(...) leads to the result that the committer of cf0fad49d17cb8273ce555dd5b7afab67d7923bf wants. Change-Id: Ifed1cef6d6a31c3ed23dad03a567b3b9eddf3a57 Signed-off-by: Chih-Wei Huang --- drivers/cpufreq/cpufreq_interactive.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index d72e8c458f69..9f63bd1e4fee 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -752,7 +752,7 @@ static ssize_t show_target_loads( ret += sprintf(buf + ret, "%u%s", tunables->target_loads[i], i & 0x1 ? ":" : " "); - ret += sprintf(buf + --ret, "\n"); + sprintf(buf + ret - 1, "\n"); spin_unlock_irqrestore(&tunables->target_loads_lock, flags); return ret; } @@ -792,7 +792,7 @@ static ssize_t show_above_hispeed_delay( tunables->above_hispeed_delay[i], i & 0x1 ? ":" : " "); - ret += sprintf(buf + --ret, "\n"); + sprintf(buf + ret - 1, "\n"); spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags); return ret; }