diff options
Diffstat (limited to 'drivers/staging/android')
| -rw-r--r-- | drivers/staging/android/alarm-dev.c | 1 | ||||
| -rw-r--r-- | drivers/staging/android/binder.c | 59 | ||||
| -rw-r--r-- | drivers/staging/android/ion/ion.c | 14 | ||||
| -rw-r--r-- | drivers/staging/android/ion/ion_carveout_heap.c | 2 | ||||
| -rw-r--r-- | drivers/staging/android/ion/ion_chunk_heap.c | 2 | ||||
| -rw-r--r-- | drivers/staging/android/ion/ion_heap.c | 2 | ||||
| -rw-r--r-- | drivers/staging/android/ion/ion_page_pool.c | 49 | ||||
| -rw-r--r-- | drivers/staging/android/ion/ion_priv.h | 3 | ||||
| -rw-r--r-- | drivers/staging/android/ion/ion_system_heap.c | 68 | ||||
| -rw-r--r-- | drivers/staging/android/logger.c | 3 | ||||
| -rw-r--r-- | drivers/staging/android/ram_console.h | 22 | ||||
| -rw-r--r-- | drivers/staging/android/sw_sync.c | 2 | ||||
| -rw-r--r-- | drivers/staging/android/sync.c | 12 | ||||
| -rw-r--r-- | drivers/staging/android/timed_gpio.c | 5 | ||||
| -rw-r--r-- | drivers/staging/android/timed_output.c | 1 | ||||
| -rw-r--r-- | drivers/staging/android/uapi/ion.h | 12 |
16 files changed, 150 insertions, 107 deletions
diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index 2fc7cdd4c4e..f200e8a8432 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c @@ -329,6 +329,7 @@ static int alarm_release(struct inode *inode, struct file *file) if (file->private_data) { for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { uint32_t alarm_type_mask = 1U << i; + if (alarm_enabled & alarm_type_mask) { alarm_dbg(INFO, "%s: clear alarm, pending %d\n", diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index cfe4bc8f05c..a741da77828 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -118,6 +118,7 @@ static int binder_set_stop_on_user_error(const char *val, struct kernel_param *kp) { int ret; + ret = param_set_int(val, kp); if (binder_stop_on_user_error < 2) wake_up(&binder_user_error_wait); @@ -194,6 +195,7 @@ static struct binder_transaction_log_entry *binder_transaction_log_add( struct binder_transaction_log *log) { struct binder_transaction_log_entry *e; + e = &log->entry[log->next]; memset(e, 0, sizeof(*e)); log->next++; @@ -432,16 +434,17 @@ static inline void binder_unlock(const char *tag) static void binder_set_nice(long nice) { long min_nice; + if (can_nice(current, nice)) { set_user_nice(current, nice); return; } - min_nice = 20 - current->signal->rlim[RLIMIT_NICE].rlim_cur; + min_nice = rlimit_to_nice(current->signal->rlim[RLIMIT_NICE].rlim_cur); binder_debug(BINDER_DEBUG_PRIORITY_CAP, "%d: nice value %ld not allowed use %ld instead\n", current->pid, nice, min_nice); set_user_nice(current, min_nice); - if (min_nice < 20) + if (min_nice <= MAX_NICE) return; binder_user_error("%d RLIMIT_NICE not set\n", current->pid); } @@ -584,6 +587,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { int ret; struct page **page_array_ptr; + page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; BUG_ON(*page); @@ -726,6 +730,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, binder_insert_allocated_buffer(proc, buffer); if (buffer_size != size) { struct binder_buffer *new_buffer = (void *)buffer->data + size; + list_add(&new_buffer->entry, &buffer->entry); new_buffer->free = 1; binder_insert_free_buffer(proc, new_buffer); @@ -838,6 +843,7 @@ static void binder_free_buf(struct binder_proc *proc, if (!list_is_last(&buffer->entry, &proc->buffers)) { struct binder_buffer *next = list_entry(buffer->entry.next, struct binder_buffer, entry); + if (next->free) { rb_erase(&next->rb_node, &proc->free_buffers); binder_delete_free_buffer(proc, next); @@ -846,6 +852,7 @@ static void binder_free_buf(struct binder_proc *proc, if (proc->buffers.next != &buffer->entry) { struct binder_buffer *prev = list_entry(buffer->entry.prev, struct binder_buffer, entry); + if (prev->free) { binder_delete_free_buffer(proc, buffer); rb_erase(&prev->rb_node, &proc->free_buffers); @@ -1107,6 +1114,7 @@ static int binder_inc_ref(struct binder_ref *ref, int strong, struct list_head *target_list) { int ret; + if (strong) { if (ref->strong == 0) { ret = binder_inc_node(ref->node, 1, 1, target_list); @@ -1138,6 +1146,7 @@ static int binder_dec_ref(struct binder_ref *ref, int strong) ref->strong--; if (ref->strong == 0) { int ret; + ret = binder_dec_node(ref->node, strong, 1); if (ret) return ret; @@ -1177,6 +1186,7 @@ static void binder_send_failed_reply(struct binder_transaction *t, uint32_t error_code) { struct binder_thread *target_thread; + BUG_ON(t->flags & TF_ONE_WAY); while (1) { target_thread = t->from; @@ -1247,6 +1257,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, off_end = (void *)offp + buffer->offsets_size; for (; offp < off_end; offp++) { struct flat_binder_object *fp; + if (*offp > buffer->data_size - sizeof(*fp) || buffer->data_size < sizeof(*fp) || !IS_ALIGNED(*offp, sizeof(u32))) { @@ -1259,6 +1270,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_BINDER: case BINDER_TYPE_WEAK_BINDER: { struct binder_node *node = binder_get_node(proc, fp->binder); + if (node == NULL) { pr_err("transaction release %d bad node %016llx\n", debug_id, (u64)fp->binder); @@ -1272,6 +1284,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle); + if (ref == NULL) { pr_err("transaction release %d bad handle %d\n", debug_id, fp->handle); @@ -1363,6 +1376,7 @@ static void binder_transaction(struct binder_proc *proc, } else { if (tr->target.handle) { struct binder_ref *ref; + ref = binder_get_ref(proc, tr->target.handle); if (ref == NULL) { binder_user_error("%d:%d got transaction to invalid handle\n", @@ -1386,6 +1400,7 @@ static void binder_transaction(struct binder_proc *proc, } if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) { struct binder_transaction *tmp; + tmp = thread->transaction_stack; if (tmp->to_thread != thread) { binder_user_error("%d:%d got new transaction with bad transaction stack, transaction %d has target %d:%d\n", @@ -1452,7 +1467,7 @@ static void binder_transaction(struct binder_proc *proc, t->from = thread; else t->from = NULL; - t->sender_euid = proc->tsk->cred->euid; + t->sender_euid = task_euid(proc->tsk); t->to_proc = target_proc; t->to_thread = target_thread; t->code = tr->code; @@ -1501,6 +1516,7 @@ static void binder_transaction(struct binder_proc *proc, off_end = (void *)offp + tr->offsets_size; for (; offp < off_end; offp++) { struct flat_binder_object *fp; + if (*offp > t->buffer->data_size - sizeof(*fp) || t->buffer->data_size < sizeof(*fp) || !IS_ALIGNED(*offp, sizeof(u32))) { @@ -1515,6 +1531,7 @@ static void binder_transaction(struct binder_proc *proc, case BINDER_TYPE_WEAK_BINDER: { struct binder_ref *ref; struct binder_node *node = binder_get_node(proc, fp->binder); + if (node == NULL) { node = binder_new_node(proc, fp->binder, fp->cookie); if (node == NULL) { @@ -1529,6 +1546,7 @@ static void binder_transaction(struct binder_proc *proc, proc->pid, thread->pid, (u64)fp->binder, node->debug_id, (u64)fp->cookie, (u64)node->cookie); + return_error = BR_FAILED_REPLY; goto err_binder_get_ref_for_node_failed; } ref = binder_get_ref_for_node(target_proc, node); @@ -1553,6 +1571,7 @@ static void binder_transaction(struct binder_proc *proc, case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle); + if (ref == NULL) { binder_user_error("%d:%d got transaction with invalid handle, %d\n", proc->pid, @@ -1575,6 +1594,7 @@ static void binder_transaction(struct binder_proc *proc, (u64)ref->node->ptr); } else { struct binder_ref *new_ref; + new_ref = binder_get_ref_for_node(target_proc, ref->node); if (new_ref == NULL) { return_error = BR_FAILED_REPLY; @@ -1694,6 +1714,7 @@ err_no_context_mgr_node: { struct binder_transaction_log_entry *fe; + fe = binder_transaction_log_add(&binder_transaction_log_failed); *fe = *e; } @@ -2024,12 +2045,14 @@ static int binder_thread_write(struct binder_proc *proc, struct binder_work *w; binder_uintptr_t cookie; struct binder_ref_death *death = NULL; + if (get_user(cookie, (binder_uintptr_t __user *)ptr)) return -EFAULT; ptr += sizeof(void *); list_for_each_entry(w, &proc->delivered_death, entry) { struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work); + if (tmp_death->cookie == cookie) { death = tmp_death; break; @@ -2216,6 +2239,7 @@ retry: const char *cmd_name; int strong = node->internal_strong_refs || node->local_strong_refs; int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong; + if (weak && !node->has_weak_ref) { cmd = BR_INCREFS; cmd_name = "BR_INCREFS"; @@ -2322,6 +2346,7 @@ retry: BUG_ON(t->buffer == NULL); if (t->buffer->target_node) { struct binder_node *target_node = t->buffer->target_node; + tr.target.ptr = target_node->ptr; tr.cookie = target_node->cookie; t->saved_priority = task_nice(current); @@ -2343,6 +2368,7 @@ retry: if (t->from) { struct task_struct *sender = t->from->proc->tsk; + tr.sender_pid = task_tgid_nr_ns(sender, task_active_pid_ns(current)); } else { @@ -2413,6 +2439,7 @@ done: static void binder_release_work(struct list_head *list) { struct binder_work *w; + while (!list_empty(list)) { w = list_first_entry(list, struct binder_work, entry); list_del_init(&w->entry); @@ -2574,6 +2601,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct binder_thread *thread; unsigned int size = _IOC_SIZE(cmd); void __user *ubuf = (void __user *)arg; + kuid_t curr_euid = current_euid(); /*pr_info("binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/ @@ -2593,6 +2621,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) switch (cmd) { case BINDER_WRITE_READ: { struct binder_write_read bwr; + if (size != sizeof(struct binder_write_read)) { ret = -EINVAL; goto err; @@ -2658,15 +2687,16 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } if (uid_valid(binder_context_mgr_uid)) { - if (!uid_eq(binder_context_mgr_uid, current->cred->euid)) { + if (!uid_eq(binder_context_mgr_uid, curr_euid)) { pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n", - from_kuid(&init_user_ns, current->cred->euid), + from_kuid(&init_user_ns, curr_euid), from_kuid(&init_user_ns, binder_context_mgr_uid)); ret = -EPERM; goto err; } - } else - binder_context_mgr_uid = current->cred->euid; + } else { + binder_context_mgr_uid = curr_euid; + } binder_context_mgr_node = binder_new_node(proc, 0, 0); if (binder_context_mgr_node == NULL) { ret = -ENOMEM; @@ -2683,16 +2713,20 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) binder_free_thread(proc, thread); thread = NULL; break; - case BINDER_VERSION: + case BINDER_VERSION: { + struct binder_version __user *ver = ubuf; + if (size != sizeof(struct binder_version)) { ret = -EINVAL; goto err; } - if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) { + if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, + &ver->protocol_version)) { ret = -EINVAL; goto err; } break; + } default: ret = -EINVAL; goto err; @@ -2713,6 +2747,7 @@ err_unlocked: static void binder_vma_open(struct vm_area_struct *vma) { struct binder_proc *proc = vma->vm_private_data; + binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, @@ -2723,6 +2758,7 @@ static void binder_vma_open(struct vm_area_struct *vma) static void binder_vma_close(struct vm_area_struct *vma) { struct binder_proc *proc = vma->vm_private_data; + binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, @@ -2865,6 +2901,7 @@ static int binder_open(struct inode *nodp, struct file *filp) if (binder_debugfs_dir_entry_proc) { char strbuf[11]; + snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO, binder_debugfs_dir_entry_proc, proc, &binder_proc_fops); @@ -2886,8 +2923,10 @@ static void binder_deferred_flush(struct binder_proc *proc) { struct rb_node *n; int wake_count = 0; + for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) { struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); + thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN; if (thread->looper & BINDER_LOOPER_STATE_WAITING) { wake_up_interruptible(&thread->wait); @@ -2904,6 +2943,7 @@ static void binder_deferred_flush(struct binder_proc *proc) static int binder_release(struct inode *nodp, struct file *filp) { struct binder_proc *proc = filp->private_data; + debugfs_remove(proc->debugfs_entry); binder_defer_work(proc, BINDER_DEFERRED_RELEASE); @@ -3065,6 +3105,7 @@ static void binder_deferred_func(struct work_struct *work) struct files_struct *files; int defer; + do { binder_lock(__func__); mutex_lock(&binder_deferred_lock); diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 3d5bf147223..389b8f67a2e 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -408,6 +408,7 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client, while (n) { struct ion_handle *entry = rb_entry(n, struct ion_handle, node); + if (buffer < entry->buffer) n = n->rb_left; else if (buffer > entry->buffer) @@ -626,6 +627,10 @@ static void ion_handle_kmap_put(struct ion_handle *handle) { struct ion_buffer *buffer = handle->buffer; + if (!handle->kmap_cnt) { + WARN(1, "%s: Double unmap detected! bailing...\n", __func__); + return; + } handle->kmap_cnt--; if (!handle->kmap_cnt) ion_buffer_kmap_put(buffer); @@ -720,9 +725,11 @@ static int ion_get_client_serial(const struct rb_root *root, { 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); @@ -1035,12 +1042,14 @@ static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) static void ion_dma_buf_release(struct dma_buf *dmabuf) { struct ion_buffer *buffer = dmabuf->priv; + ion_buffer_put(buffer); } static void *ion_dma_buf_kmap(struct dma_buf *dmabuf, unsigned long offset) { struct ion_buffer *buffer = dmabuf->priv; + return buffer->vaddr + offset * PAGE_SIZE; } @@ -1292,6 +1301,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case ION_IOC_IMPORT: { struct ion_handle *handle; + handle = ion_import_dma_buf(client, data.fd.fd); if (IS_ERR(handle)) ret = PTR_ERR(handle); @@ -1393,6 +1403,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) struct ion_client *client = rb_entry(n, struct ion_client, node); size_t size = ion_debug_heap_total(client, heap->id); + if (!size) continue; if (client->task) { @@ -1516,6 +1527,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) 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); @@ -1531,6 +1543,7 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *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); @@ -1606,6 +1619,7 @@ void __init ion_reserve(struct ion_platform_data *data) if (data->heaps[i].base == 0) { phys_addr_t paddr; + paddr = memblock_alloc_base(data->heaps[i].size, data->heaps[i].align, MEMBLOCK_ALLOC_ANYWHERE); diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 3cb05b9b0e9..dcb6f2196c8 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -81,7 +81,7 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, if (align > PAGE_SIZE) return -EINVAL; - table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (!table) return -ENOMEM; ret = sg_alloc_table(table, 1, GFP_KERNEL); diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index d40f5f83180..3f2c12ba4d1 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -55,7 +55,7 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap, if (allocated_size > chunk_heap->size - chunk_heap->allocated) return -ENOMEM; - table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (!table) return -ENOMEM; ret = sg_alloc_table(table, num_chunks, GFP_KERNEL); diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index bdc6a28ba8c..4605e04712a 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -48,6 +48,7 @@ void *ion_heap_map_kernel(struct ion_heap *heap, for_each_sg(table->sgl, sg, table->nents, i) { 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++) *(tmp++) = page++; @@ -105,6 +106,7 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, 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); diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index ecb5fc34ec5..5864f3dfcbc 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -21,13 +21,9 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/swap.h> #include "ion_priv.h" -struct ion_page_pool_item { - struct page *page; - struct list_head list; -}; - static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) { struct page *page = alloc_pages(pool->gfp_mask, pool->order); @@ -47,19 +43,12 @@ static void ion_page_pool_free_pages(struct ion_page_pool *pool, static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page) { - struct ion_page_pool_item *item; - - item = kmalloc(sizeof(struct ion_page_pool_item), GFP_KERNEL); - if (!item) - return -ENOMEM; - mutex_lock(&pool->mutex); - item->page = page; if (PageHighMem(page)) { - list_add_tail(&item->list, &pool->high_items); + list_add_tail(&page->lru, &pool->high_items); pool->high_count++; } else { - list_add_tail(&item->list, &pool->low_items); + list_add_tail(&page->lru, &pool->low_items); pool->low_count++; } mutex_unlock(&pool->mutex); @@ -68,28 +57,23 @@ static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page) static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high) { - struct ion_page_pool_item *item; struct page *page; if (high) { BUG_ON(!pool->high_count); - item = list_first_entry(&pool->high_items, - struct ion_page_pool_item, list); + page = list_first_entry(&pool->high_items, struct page, lru); pool->high_count--; } else { BUG_ON(!pool->low_count); - item = list_first_entry(&pool->low_items, - struct ion_page_pool_item, list); + page = list_first_entry(&pool->low_items, struct page, lru); pool->low_count--; } - list_del(&item->list); - page = item->page; - kfree(item); + list_del(&page->lru); return page; } -void *ion_page_pool_alloc(struct ion_page_pool *pool) +struct page *ion_page_pool_alloc(struct ion_page_pool *pool) { struct page *page = NULL; @@ -112,6 +96,8 @@ void ion_page_pool_free(struct ion_page_pool *pool, struct page *page) { int ret; + BUG_ON(pool->order != compound_order(page)); + ret = ion_page_pool_add(pool, page); if (ret) ion_page_pool_free_pages(pool, page); @@ -119,12 +105,12 @@ void ion_page_pool_free(struct ion_page_pool *pool, struct page *page) static int ion_page_pool_total(struct ion_page_pool *pool, bool high) { - int total = 0; + int count = pool->low_count; + + if (high) + count += pool->high_count; - total += high ? (pool->high_count + pool->low_count) * - (1 << pool->order) : - pool->low_count * (1 << pool->order); - return total; + return count << pool->order; } int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, @@ -133,7 +119,10 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, int freed; bool high; - high = !!(gfp_mask & __GFP_HIGHMEM); + if (current_is_kswapd()) + high = 1; + else + high = !!(gfp_mask & __GFP_HIGHMEM); if (nr_to_scan == 0) return ion_page_pool_total(pool, high); @@ -167,7 +156,7 @@ struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) pool->low_count = 0; INIT_LIST_HEAD(&pool->low_items); INIT_LIST_HEAD(&pool->high_items); - pool->gfp_mask = gfp_mask; + pool->gfp_mask = gfp_mask | __GFP_COMP; pool->order = order; mutex_init(&pool->mutex); plist_node_init(&pool->list, order); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 1eba3f2076a..c8f01757abf 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -178,6 +178,7 @@ struct ion_heap { spinlock_t free_lock; wait_queue_head_t waitqueue; struct task_struct *task; + int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *); }; @@ -377,7 +378,7 @@ struct ion_page_pool { struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order); void ion_page_pool_destroy(struct ion_page_pool *); -void *ion_page_pool_alloc(struct ion_page_pool *); +struct page *ion_page_pool_alloc(struct ion_page_pool *); void ion_page_pool_free(struct ion_page_pool *, struct page *); /** ion_page_pool_shrink - shrinks the size of the memory cached in the pool diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index c92363356ae..cb7ae08a5e2 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -34,6 +34,7 @@ static const int num_orders = ARRAY_SIZE(orders); static int order_to_index(unsigned int order) { int i; + for (i = 0; i < num_orders; i++) if (order == orders[i]) return i; @@ -41,7 +42,7 @@ static int order_to_index(unsigned int order) return -1; } -static unsigned int order_to_size(int order) +static inline unsigned int order_to_size(int order) { return PAGE_SIZE << order; } @@ -72,14 +73,12 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, if (order > 4) gfp_flags = high_order_gfp_flags; - page = alloc_pages(gfp_flags, order); + page = alloc_pages(gfp_flags | __GFP_COMP, order); if (!page) return NULL; ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order, DMA_BIDIRECTIONAL); } - if (!page) - return NULL; return page; } @@ -92,6 +91,7 @@ static void free_buffer_page(struct ion_system_heap *heap, 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 { __free_pages(page, order); @@ -124,7 +124,6 @@ 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); @@ -142,7 +141,6 @@ static int ion_system_heap_allocate(struct ion_heap *heap, heap); struct sg_table *table; struct scatterlist *sg; - int ret; struct list_head pages; struct page_info *info, *tmp_info; int i = 0; @@ -160,24 +158,23 @@ static int ion_system_heap_allocate(struct ion_heap *heap, info = alloc_largest_available(sys_heap, buffer, size_remaining, max_order); if (!info) - goto err; + goto free_pages; list_add_tail(&info->list, &pages); - size_remaining -= (1 << info->order) * PAGE_SIZE; + size_remaining -= PAGE_SIZE << info->order; max_order = info->order; i++; } - table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (!table) - goto err; + goto free_pages; - ret = sg_alloc_table(table, i, GFP_KERNEL); - if (ret) - goto err1; + if (sg_alloc_table(table, i, GFP_KERNEL)) + goto free_table; sg = table->sgl; list_for_each_entry_safe(info, tmp_info, &pages, list) { struct page *page = info->page; - sg_set_page(sg, page, (1 << info->order) * PAGE_SIZE, 0); + sg_set_page(sg, page, PAGE_SIZE << info->order, 0); sg = sg_next(sg); list_del(&info->list); kfree(info); @@ -185,9 +182,10 @@ static int ion_system_heap_allocate(struct ion_heap *heap, buffer->priv_virt = table; return 0; -err1: + +free_table: kfree(table); -err: +free_pages: list_for_each_entry_safe(info, tmp_info, &pages, list) { free_buffer_page(sys_heap, buffer, info->page, info->order); kfree(info); @@ -197,14 +195,12 @@ err: 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, + struct ion_system_heap *sys_heap = container_of(buffer->heap, struct ion_system_heap, heap); struct sg_table *table = buffer->sg_table; bool cached = ion_buffer_cached(buffer); struct scatterlist *sg; - LIST_HEAD(pages); int i; /* uncached pages come from the page pools, zero them before returning @@ -242,6 +238,7 @@ static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, 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); } @@ -267,14 +264,16 @@ static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, struct ion_system_heap, heap); int i; + for (i = 0; i < num_orders; i++) { struct ion_page_pool *pool = sys_heap->pools[i]; + seq_printf(s, "%d order %u highmem pages in pool = %lu total\n", pool->high_count, pool->order, - (1 << pool->order) * PAGE_SIZE * pool->high_count); + (PAGE_SIZE << pool->order) * pool->high_count); seq_printf(s, "%d order %u lowmem pages in pool = %lu total\n", pool->low_count, pool->order, - (1 << pool->order) * PAGE_SIZE * pool->low_count); + (PAGE_SIZE << pool->order) * pool->low_count); } return 0; } @@ -293,7 +292,7 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) heap->pools = kzalloc(sizeof(struct ion_page_pool *) * num_orders, GFP_KERNEL); if (!heap->pools) - goto err_alloc_pools; + goto free_heap; for (i = 0; i < num_orders; i++) { struct ion_page_pool *pool; gfp_t gfp_flags = low_order_gfp_flags; @@ -302,18 +301,18 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) gfp_flags = high_order_gfp_flags; pool = ion_page_pool_create(gfp_flags, orders[i]); if (!pool) - goto err_create_pool; + goto destroy_pools; heap->pools[i] = pool; } heap->heap.debug_show = ion_system_heap_debug_show; return &heap->heap; -err_create_pool: - for (i = 0; i < num_orders; i++) - if (heap->pools[i]) - ion_page_pool_destroy(heap->pools[i]); + +destroy_pools: + while (i--) + ion_page_pool_destroy(heap->pools[i]); kfree(heap->pools); -err_alloc_pools: +free_heap: kfree(heap); return ERR_PTR(-ENOMEM); } @@ -356,15 +355,15 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap, for (i = len >> PAGE_SHIFT; i < (1 << order); i++) __free_page(page + i); - table = kzalloc(sizeof(struct sg_table), GFP_KERNEL); + table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (!table) { ret = -ENOMEM; - goto out; + goto free_pages; } ret = sg_alloc_table(table, 1, GFP_KERNEL); if (ret) - goto out; + goto free_table; sg_set_page(table->sgl, page, len, 0); @@ -374,10 +373,12 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap, return 0; -out: +free_table: + kfree(table); +free_pages: for (i = 0; i < len >> PAGE_SHIFT; i++) __free_page(page + i); - kfree(table); + return ret; } @@ -443,4 +444,3 @@ void ion_system_contig_heap_destroy(struct ion_heap *heap) { kfree(heap); } - diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index d42f5785f09..2772e01b37f 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -108,6 +108,7 @@ static inline struct logger_log *file_get_log(struct file *file) { if (file->f_mode & FMODE_READ) { struct logger_reader *reader = file->private_data; + return reader->log; } else return file->private_data; @@ -124,6 +125,7 @@ static struct logger_entry *get_entry_header(struct logger_log *log, size_t off, struct logger_entry *scratch) { size_t len = min(sizeof(struct logger_entry), log->size - off); + if (len != sizeof(struct logger_entry)) { memcpy(((void *) scratch), log->buffer + off, len); memcpy(((void *) scratch) + len, log->buffer, @@ -642,6 +644,7 @@ static unsigned int logger_poll(struct file *file, poll_table *wait) static long logger_set_version(struct logger_reader *reader, void __user *arg) { int version; + if (copy_from_user(&version, arg, sizeof(int))) return -EFAULT; diff --git a/drivers/staging/android/ram_console.h b/drivers/staging/android/ram_console.h deleted file mode 100644 index 9f1125c1106..00000000000 --- a/drivers/staging/android/ram_console.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2010 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 _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_ -#define _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_ - -struct ram_console_platform_data { - const char *bootinfo; -}; - -#endif /* _INCLUDE_LINUX_PLATFORM_DATA_RAM_CONSOLE_H_ */ diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index f24493ac65e..12a136ec1ce 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -97,6 +97,7 @@ static void sw_sync_pt_value_str(struct sync_pt *sync_pt, char *str, int size) { struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; + snprintf(str, size, "%d", pt->value); } @@ -156,6 +157,7 @@ static int sw_sync_open(struct inode *inode, struct file *file) static int sw_sync_release(struct inode *inode, struct file *file) { struct sw_sync_timeline *obj = file->private_data; + sync_timeline_destroy(&obj->obj); return 0; } diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 3d05f662110..18174f7c871 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -92,6 +92,10 @@ static void sync_timeline_free(struct kref *kref) void sync_timeline_destroy(struct sync_timeline *obj) { obj->destroyed = true; + /* + * Ensure timeline is marked as destroyed before + * changing timeline's fences status. + */ smp_wmb(); /* @@ -384,6 +388,7 @@ static void sync_fence_detach_pts(struct sync_fence *fence) list_for_each_safe(pos, n, &fence->pt_list_head) { struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list); + sync_timeline_remove_pt(pt); } } @@ -394,6 +399,7 @@ static void sync_fence_free_pts(struct sync_fence *fence) list_for_each_safe(pos, n, &fence->pt_list_head) { struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list); + sync_pt_free(pt); } } @@ -827,6 +833,7 @@ static long sync_fence_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct sync_fence *fence = file->private_data; + switch (cmd) { case SYNC_IOC_WAIT: return sync_fence_ioctl_wait(fence, arg); @@ -856,18 +863,21 @@ static const char *sync_status_str(int status) static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence) { int status = pt->status; + seq_printf(s, " %s%spt %s", fence ? pt->parent->name : "", fence ? "_" : "", sync_status_str(status)); if (pt->status) { struct timeval tv = ktime_to_timeval(pt->timestamp); + seq_printf(s, "@%ld.%06ld", tv.tv_sec, tv.tv_usec); } if (pt->parent->ops->timeline_value_str && pt->parent->ops->pt_value_str) { char value[64]; + pt->parent->ops->pt_value_str(pt, value, sizeof(value)); seq_printf(s, ": %s", value); if (fence) { @@ -892,6 +902,7 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) if (obj->ops->timeline_value_str) { char value[64]; + obj->ops->timeline_value_str(obj, value, sizeof(value)); seq_printf(s, ": %s", value); } else if (obj->ops->print_obj) { @@ -1001,6 +1012,7 @@ static void sync_dump(void) for (i = 0; i < s.count; i += DUMP_CHUNK) { if ((s.count - i) > DUMP_CHUNK) { char c = s.buf[i + DUMP_CHUNK]; + s.buf[i + DUMP_CHUNK] = 0; pr_cont("%s", s.buf + i); s.buf[i + DUMP_CHUNK] = c; diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c index 0c7fdc83b33..180c209a009 100644 --- a/drivers/staging/android/timed_gpio.c +++ b/drivers/staging/android/timed_gpio.c @@ -51,6 +51,7 @@ static int gpio_get_time(struct timed_output_dev *dev) if (hrtimer_active(&data->timer)) { ktime_t r = hrtimer_get_remaining(&data->timer); struct timeval t = ktime_to_timeval(r); + return t.tv_sec * 1000 + t.tv_usec / 1000; } else return 0; @@ -91,8 +92,8 @@ static int timed_gpio_probe(struct platform_device *pdev) return -EBUSY; gpio_data = devm_kzalloc(&pdev->dev, - sizeof(struct timed_gpio_data) * pdata->num_gpios, - GFP_KERNEL); + sizeof(struct timed_gpio_data) * pdata->num_gpios, + GFP_KERNEL); if (!gpio_data) return -ENOMEM; diff --git a/drivers/staging/android/timed_output.c b/drivers/staging/android/timed_output.c index 2c617834dc4..c341ac11c5a 100644 --- a/drivers/staging/android/timed_output.c +++ b/drivers/staging/android/timed_output.c @@ -97,7 +97,6 @@ void timed_output_dev_unregister(struct timed_output_dev *tdev) { tdev->enable(tdev, 0); device_destroy(timed_output_class, MKDEV(0, tdev->index)); - dev_set_drvdata(tdev->dev, NULL); } EXPORT_SYMBOL_GPL(timed_output_dev_unregister); diff --git a/drivers/staging/android/uapi/ion.h b/drivers/staging/android/uapi/ion.h index f09e7c154d6..6aa49567337 100644 --- a/drivers/staging/android/uapi/ion.h +++ b/drivers/staging/android/uapi/ion.h @@ -27,12 +27,12 @@ typedef int ion_user_handle_t; * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc * @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved - * carveout heap, allocations are physically - * contiguous + * carveout heap, allocations are physically + * contiguous * @ION_HEAP_TYPE_DMA: memory allocated via DMA API * @ION_NUM_HEAPS: helper for iterating over heaps, a bit mask - * is used to identify the heaps, so only 32 - * total heap types are supported + * is used to identify the heaps, so only 32 + * total heap types are supported */ enum ion_heap_type { ION_HEAP_TYPE_SYSTEM, @@ -50,7 +50,7 @@ enum ion_heap_type { #define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT) #define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA) -#define ION_NUM_HEAP_IDS sizeof(unsigned int) * 8 +#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8) /** * allocation flags - the lower 16 bits are used by core ion, the upper 16 @@ -78,7 +78,7 @@ enum ion_heap_type { * @align: required alignment of the allocation * @heap_id_mask: mask of heap ids to allocate from * @flags: flags passed to heap - * @handle: pointer that will be populated with a cookie to use to + * @handle: pointer that will be populated with a cookie to use to * refer to this allocation * * Provided by userspace as an argument to the ioctl |
