diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 10 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_governor.c | 9 | ||||
-rw-r--r-- | drivers/staging/android/Kconfig | 8 | ||||
-rw-r--r-- | drivers/staging/android/binder.c | 1048 | ||||
-rw-r--r-- | drivers/staging/android/binder.h | 4 | ||||
-rw-r--r-- | drivers/staging/android/binder_trace.h | 14 | ||||
-rw-r--r-- | drivers/staging/android/uapi/binder.h | 169 | ||||
-rw-r--r-- | drivers/usb/gadget/f_accessory.c | 48 | ||||
-rw-r--r-- | drivers/usb/gadget/f_mtp.c | 16 | ||||
-rw-r--r-- | drivers/video/adf/adf_client.c | 7 | ||||
-rw-r--r-- | drivers/video/adf/adf_fops32.c | 4 | ||||
-rw-r--r-- | drivers/video/adf/adf_fops32.h | 8 |
12 files changed, 458 insertions, 887 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 2d53f47d1747..3faf62bdbad0 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -132,6 +132,16 @@ bool have_governor_per_policy(void) { return cpufreq_driver->have_governor_per_policy; } +EXPORT_SYMBOL_GPL(have_governor_per_policy); + +struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy) +{ + if (have_governor_per_policy()) + return &policy->kobj; + else + return cpufreq_global_kobject; +} +EXPORT_SYMBOL_GPL(get_governor_parent_kobj); static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) { diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index dc9b72e25c1a..1361bd432691 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -30,14 +30,6 @@ #include "cpufreq_governor.h" -static struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy) -{ - if (have_governor_per_policy()) - return &policy->kobj; - else - return cpufreq_global_kobject; -} - static struct attribute_group *get_sysfs_attr(struct dbs_data *dbs_data) { if (have_governor_per_policy()) @@ -404,6 +396,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, mutex_lock(&dbs_data->mutex); mutex_destroy(&cpu_cdbs->timer_mutex); + cpu_cdbs->cur_policy = NULL; mutex_unlock(&dbs_data->mutex); diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 6da535db2538..1e1b36ab1389 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -19,6 +19,14 @@ config ANDROID_BINDER_IPC Android process, using Binder to identify, invoke and pass arguments between said processes. +config ANDROID_BINDER_IPC_32BIT + bool + default y + depends on !64BIT && ANDROID_BINDER_IPC + ---help--- + Enable to support an old 32-bit Android user-space. Breaks the new + Android user-space. + config ASHMEM bool "Enable the Anonymous Shared Memory Subsystem" default n diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 65dd819d41aa..55195ea28de6 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -38,7 +38,6 @@ #include <linux/slab.h> #include <linux/pid_namespace.h> #include <linux/security.h> -#include <linux/compat.h> #include "binder.h" #include "binder_trace.h" @@ -142,87 +141,6 @@ module_param_call(stop_on_user_error, binder_set_stop_on_user_error, binder_stop_on_user_error = 2; \ } while (0) -#ifdef CONFIG_COMPAT -static inline void writeback_flat_binder_object(struct flat_binder_object *fp, - void __user *ptr) -{ - struct compat_flat_binder_object *tmp_fp; - - tmp_fp = (struct compat_flat_binder_object *) ptr; - tmp_fp->type = fp->type; - tmp_fp->flags = fp->flags; - tmp_fp->binder = ptr_to_compat(fp->binder); - tmp_fp->cookie = ptr_to_compat(fp->cookie); -} - -static inline struct flat_binder_object *copy_flat_binder_object(void __user *ptr) -{ - struct flat_binder_object *fp; - struct compat_flat_binder_object *tmp_fp; - - if (!is_compat_task()) - return (struct flat_binder_object *) ptr; - - fp = kzalloc(sizeof(*fp), GFP_KERNEL); - if (fp == NULL) - return NULL; - - tmp_fp = (struct compat_flat_binder_object *) ptr; - /* copy compat struct */ - fp->type = tmp_fp->type; - fp->flags = tmp_fp->flags; - fp->binder = compat_ptr(tmp_fp->binder); - fp->cookie = compat_ptr(tmp_fp->cookie); - - return fp; -} - -static inline uint32_t compat_change_size(uint32_t cmd, size_t size) -{ - uint32_t compat_cmd; - - compat_cmd = cmd & ~IOCSIZE_MASK; - compat_cmd = compat_cmd | ((size << _IOC_SIZESHIFT) & IOCSIZE_MASK); - return compat_cmd; -} - -#define align_helper(x) ( \ - is_compat_task() ? \ - ALIGN(x, sizeof(compat_uptr_t)) : \ - ALIGN(x, sizeof(void *)) \ - ) - -#define deref_helper(x) ( \ - is_compat_task() ? \ - (size_t) *(compat_size_t *)x : \ - *(size_t *)x \ - ) - -#define size_helper(x) ({ \ - size_t __size; \ - if (!is_compat_task()) \ - __size = sizeof(x); \ - else if (sizeof(x) == sizeof(struct flat_binder_object)) \ - __size = sizeof(struct compat_flat_binder_object); \ - else if (sizeof(x) == sizeof(struct binder_transaction_data)) \ - __size = sizeof(struct compat_binder_transaction_data); \ - else if (sizeof(x) == sizeof(size_t)) \ - __size = sizeof(compat_size_t); \ - else \ - BUG(); \ - __size; \ - }) -#else -#define align_helper(ptr) ALIGN(ptr, sizeof(void *)) -#define deref_helper(ptr) (*(typeof(size_t *))ptr) -#define size_helper(x) sizeof(x) - -static inline struct flat_binder_object *copy_flat_binder_object(void __user *ptr) -{ - return (struct flat_binder_object *)ptr; -} -#endif - enum binder_stat_types { BINDER_STAT_PROC, BINDER_STAT_THREAD, @@ -311,8 +229,8 @@ struct binder_node { int internal_strong_refs; int local_weak_refs; int local_strong_refs; - void __user *ptr; - void __user *cookie; + binder_uintptr_t ptr; + binder_uintptr_t cookie; unsigned has_strong_ref:1; unsigned pending_strong_ref:1; unsigned has_weak_ref:1; @@ -325,7 +243,7 @@ struct binder_node { struct binder_ref_death { struct binder_work work; - void __user *cookie; + binder_uintptr_t cookie; }; struct binder_ref { @@ -598,14 +516,14 @@ static void binder_insert_allocated_buffer(struct binder_proc *proc, } static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc, - void __user *user_ptr) + uintptr_t user_ptr) { struct rb_node *n = proc->allocated_buffers.rb_node; struct binder_buffer *buffer; struct binder_buffer *kern_ptr; - kern_ptr = user_ptr - proc->user_buffer_offset - - offsetof(struct binder_buffer, data); + kern_ptr = (struct binder_buffer *)(user_ptr - proc->user_buffer_offset + - offsetof(struct binder_buffer, data)); while (n) { buffer = rb_entry(n, struct binder_buffer, rb_node); @@ -939,7 +857,7 @@ static void binder_free_buf(struct binder_proc *proc, } static struct binder_node *binder_get_node(struct binder_proc *proc, - void __user *ptr) + binder_uintptr_t ptr) { struct rb_node *n = proc->nodes.rb_node; struct binder_node *node; @@ -958,8 +876,8 @@ static struct binder_node *binder_get_node(struct binder_proc *proc, } static struct binder_node *binder_new_node(struct binder_proc *proc, - void __user *ptr, - void __user *cookie) + binder_uintptr_t ptr, + binder_uintptr_t cookie) { struct rb_node **p = &proc->nodes.rb_node; struct rb_node *parent = NULL; @@ -991,9 +909,9 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, INIT_LIST_HEAD(&node->work.entry); INIT_LIST_HEAD(&node->async_todo); binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "%d:%d node %d u%p c%p created\n", + "%d:%d node %d u%016llx c%016llx created\n", proc->pid, current->pid, node->debug_id, - node->ptr, node->cookie); + (u64)node->ptr, (u64)node->cookie); return node; } @@ -1309,9 +1227,9 @@ static void binder_send_failed_reply(struct binder_transaction *t, static void binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer *buffer, - size_t *failed_at) + binder_size_t *failed_at) { - void *offp, *off_end; + binder_size_t *offp, *off_end; int debug_id = buffer->debug_id; binder_debug(BINDER_DEBUG_TRANSACTION, @@ -1322,33 +1240,34 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, if (buffer->target_node) binder_dec_node(buffer->target_node, 1, 0); - offp = (size_t *)(buffer->data + align_helper(buffer->data_size)); + offp = (binder_size_t *)(buffer->data + + ALIGN(buffer->data_size, sizeof(void *))); if (failed_at) off_end = failed_at; else off_end = (void *)offp + buffer->offsets_size; - for (; offp < off_end; offp += size_helper(size_t)) { - struct flat_binder_object *fp = NULL; - if (deref_helper(offp) > buffer->data_size - size_helper(*fp) || - buffer->data_size < size_helper(*fp) || - !IS_ALIGNED(deref_helper(offp), sizeof(u32))) { - pr_err("transaction release %d bad offset %zd, size %zd\n", - debug_id, deref_helper(offp), buffer->data_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))) { + pr_err("transaction release %d bad offset %lld, size %zd\n", + debug_id, (u64)*offp, buffer->data_size); continue; } - fp = copy_flat_binder_object(buffer->data + deref_helper(offp)); + fp = (struct flat_binder_object *)(buffer->data + *offp); switch (fp->type) { 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 %p\n", - debug_id, fp->binder); + pr_err("transaction release %d bad node %016llx\n", + debug_id, (u64)fp->binder); break; } binder_debug(BINDER_DEBUG_TRANSACTION, - " node %d u%p\n", - node->debug_id, node->ptr); + " node %d u%016llx\n", + node->debug_id, (u64)node->ptr); binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0); } break; case BINDER_TYPE_HANDLE: @@ -1377,8 +1296,6 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, debug_id, fp->type); break; } - if (is_compat_task()) - kfree(fp); } } @@ -1388,7 +1305,8 @@ static void binder_transaction(struct binder_proc *proc, { struct binder_transaction *t; struct binder_work *tcomplete; - void *offp, *off_end; + binder_size_t *offp, *off_end; + binder_size_t off_min; struct binder_proc *target_proc; struct binder_thread *target_thread = NULL; struct binder_node *target_node = NULL; @@ -1397,7 +1315,6 @@ static void binder_transaction(struct binder_proc *proc, struct binder_transaction *in_reply_to = NULL; struct binder_transaction_log_entry *e; uint32_t return_error; - struct flat_binder_object *fp = NULL; e = binder_transaction_log_add(&binder_transaction_log); e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY); @@ -1522,18 +1439,20 @@ static void binder_transaction(struct binder_proc *proc, if (reply) binder_debug(BINDER_DEBUG_TRANSACTION, - "%d:%d BC_REPLY %d -> %d:%d, data %p-%p size %zd-%zd\n", + "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld\n", proc->pid, thread->pid, t->debug_id, target_proc->pid, target_thread->pid, - tr->data.ptr.buffer, tr->data.ptr.offsets, - tr->data_size, tr->offsets_size); + (u64)tr->data.ptr.buffer, + (u64)tr->data.ptr.offsets, + (u64)tr->data_size, (u64)tr->offsets_size); else binder_debug(BINDER_DEBUG_TRANSACTION, - "%d:%d BC_TRANSACTION %d -> %d - node %d, data %p-%p size %zd-%zd\n", + "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld\n", proc->pid, thread->pid, t->debug_id, target_proc->pid, target_node->debug_id, - tr->data.ptr.buffer, tr->data.ptr.offsets, - tr->data_size, tr->offsets_size); + (u64)tr->data.ptr.buffer, + (u64)tr->data.ptr.offsets, + (u64)tr->data_size, (u64)tr->offsets_size); if (!reply && !(tr->flags & TF_ONE_WAY)) t->from = thread; @@ -1562,37 +1481,47 @@ static void binder_transaction(struct binder_proc *proc, if (target_node) binder_inc_node(target_node, 1, 0, NULL); - offp = (size_t *)(t->buffer->data + align_helper(tr->data_size)); + offp = (binder_size_t *)(t->buffer->data + + ALIGN(tr->data_size, sizeof(void *))); - if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) { + if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t) + tr->data.ptr.buffer, tr->data_size)) { binder_user_error("%d:%d got transaction with invalid data ptr\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; goto err_copy_data_failed; } - if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) { + if (copy_from_user(offp, (const void __user *)(uintptr_t) + tr->data.ptr.offsets, tr->offsets_size)) { binder_user_error("%d:%d got transaction with invalid offsets ptr\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; goto err_copy_data_failed; } - if (!IS_ALIGNED(tr->offsets_size, size_helper(size_t))) { - binder_user_error("%d:%d got transaction with invalid offsets size, %zd\n", - proc->pid, thread->pid, tr->offsets_size); + if (!IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))) { + binder_user_error("%d:%d got transaction with invalid offsets size, %lld\n", + proc->pid, thread->pid, (u64)tr->offsets_size); return_error = BR_FAILED_REPLY; goto err_bad_offset; } off_end = (void *)offp + tr->offsets_size; - for (; offp < off_end; offp += size_helper(size_t)) { - if (deref_helper(offp) > t->buffer->data_size - size_helper(*fp) || - t->buffer->data_size < size_helper(*fp) || - !IS_ALIGNED(deref_helper(offp), sizeof(u32))) { - binder_user_error("%d:%d got transaction with invalid offset, %zd\n", - proc->pid, thread->pid, deref_helper(offp)); + off_min = 0; + for (; offp < off_end; offp++) { + struct flat_binder_object *fp; + if (*offp > t->buffer->data_size - sizeof(*fp) || + *offp < off_min || + t->buffer->data_size < sizeof(*fp) || + !IS_ALIGNED(*offp, sizeof(u32))) { + binder_user_error("%d:%d got transaction with invalid offset, %lld (min %lld, max %lld)\n", + proc->pid, thread->pid, (u64)*offp, + (u64)off_min, + (u64)(t->buffer->data_size - + sizeof(*fp))); return_error = BR_FAILED_REPLY; goto err_bad_offset; } - fp = copy_flat_binder_object(t->buffer->data + deref_helper(offp)); + fp = (struct flat_binder_object *)(t->buffer->data + *offp); + off_min = *offp + sizeof(struct flat_binder_object); switch (fp->type) { case BINDER_TYPE_BINDER: case BINDER_TYPE_WEAK_BINDER: { @@ -1608,10 +1537,10 @@ static void binder_transaction(struct binder_proc *proc, node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS); } if (fp->cookie != node->cookie) { - binder_user_error("%d:%d sending u%p node %d, cookie mismatch %p != %p\n", + binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n", proc->pid, thread->pid, - fp->binder, node->debug_id, - fp->cookie, node->cookie); + (u64)fp->binder, node->debug_id, + (u64)fp->cookie, (u64)node->cookie); goto err_binder_get_ref_for_node_failed; } if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { @@ -1633,9 +1562,9 @@ static void binder_transaction(struct binder_proc *proc, trace_binder_transaction_node_to_ref(t, node, ref); binder_debug(BINDER_DEBUG_TRANSACTION, - " node %d u%p -> ref %d desc %d\n", - node->debug_id, node->ptr, ref->debug_id, - ref->desc); + " node %d u%016llx -> ref %d desc %d\n", + node->debug_id, (u64)node->ptr, + ref->debug_id, ref->desc); } break; case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { @@ -1661,9 +1590,9 @@ static void binder_transaction(struct binder_proc *proc, binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL); trace_binder_transaction_ref_to_node(t, ref); binder_debug(BINDER_DEBUG_TRANSACTION, - " ref %d desc %d -> node %d u%p\n", + " ref %d desc %d -> node %d u%016llx\n", ref->debug_id, ref->desc, ref->node->debug_id, - ref->node->ptr); + (u64)ref->node->ptr); } else { struct binder_ref *new_ref; new_ref = binder_get_ref_for_node(target_proc, ref->node); @@ -1732,12 +1661,6 @@ static void binder_transaction(struct binder_proc *proc, return_error = BR_FAILED_REPLY; goto err_bad_object_type; } -#ifdef CONFIG_COMPAT - if (is_compat_task()) { - writeback_flat_binder_object(fp, t->buffer->data + deref_helper(offp)); - kfree(fp); - } -#endif } if (reply) { BUG_ON(t->buffer->async_transaction != 0); @@ -1773,8 +1696,6 @@ err_binder_new_node_failed: err_bad_object_type: err_bad_offset: err_copy_data_failed: - if (is_compat_task()) - kfree(fp); trace_binder_transaction_failed_buffer_release(t->buffer); binder_transaction_buffer_release(target_proc, t->buffer, offp); t->buffer->transaction = NULL; @@ -1792,9 +1713,9 @@ err_dead_binder: err_invalid_target_handle: err_no_context_mgr_node: binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "%d:%d transaction failed %d, size %zd-%zd\n", + "%d:%d transaction failed %d, size %lld-%lld\n", proc->pid, thread->pid, return_error, - tr->data_size, tr->offsets_size); + (u64)tr->data_size, (u64)tr->offsets_size); { struct binder_transaction_log_entry *fe; @@ -1810,311 +1731,12 @@ err_no_context_mgr_node: thread->return_error = return_error; } -static void bc_increfs_done(struct binder_proc *proc, - struct binder_thread *thread, bool acquire, - void __user *node_ptr, void __user *cookie) -{ - struct binder_node *node; - - node = binder_get_node(proc, node_ptr); - if (node == NULL) { - binder_user_error("%d:%d %s u%p no match\n", - proc->pid, thread->pid, - acquire ? - "BC_ACQUIRE_DONE" : - "BC_INCREFS_DONE", - node_ptr); - return; - } - if (cookie != node->cookie) { - binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n", - proc->pid, thread->pid, - acquire ? - "BC_ACQUIRE_DONE" : "BC_INCREFS_DONE", - node_ptr, node->debug_id, - cookie, node->cookie); - return; - } - if (acquire) { - if (node->pending_strong_ref == 0) { - binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n", - proc->pid, thread->pid, - node->debug_id); - return; - } - node->pending_strong_ref = 0; - } else { - if (node->pending_weak_ref == 0) { - binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n", - proc->pid, thread->pid, - node->debug_id); - return; - } - node->pending_weak_ref = 0; - } - binder_dec_node(node, acquire, 0); - binder_debug(BINDER_DEBUG_USER_REFS, - "%d:%d %s node %d ls %d lw %d\n", - proc->pid, thread->pid, - acquire ? - "BC_ACQUIRE_DONE" : - "BC_INCREFS_DONE", - node->debug_id, node->local_strong_refs, - node->local_weak_refs); - return; -} - -static void bc_free_buffer(struct binder_proc *proc, - struct binder_thread *thread, void __user *data_ptr) -{ - struct binder_buffer *buffer; - - buffer = binder_buffer_lookup(proc, data_ptr); - if (buffer == NULL) { - binder_user_error("%d:%d BC_FREE_BUFFER u%p no match\n", - proc->pid, thread->pid, data_ptr); - return; - } - if (!buffer->allow_user_free) { - binder_user_error("%d:%d BC_FREE_BUFFER u%p matched unreturned buffer\n", - proc->pid, thread->pid, data_ptr); - return; - } - binder_debug(BINDER_DEBUG_FREE_BUFFER, - "%d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n", - proc->pid, thread->pid, data_ptr, buffer->debug_id, - buffer->transaction ? "active" : "finished"); - - if (buffer->transaction) { - buffer->transaction->buffer = NULL; - buffer->transaction = NULL; - } - if (buffer->async_transaction && buffer->target_node) { - BUG_ON(!buffer->target_node->has_async_transaction); - if (list_empty(&buffer->target_node->async_todo)) - buffer->target_node->has_async_transaction = 0; - else - list_move_tail(buffer->target_node->async_todo.next, &thread->todo); - } - trace_binder_transaction_buffer_release(buffer); - binder_transaction_buffer_release(proc, buffer, NULL); - binder_free_buf(proc, buffer); - return; -} - -static void bc_clear_death_notif(struct binder_proc *proc, - struct binder_thread *thread, bool request, - uint32_t target, void __user *cookie) -{ - struct binder_ref *ref; - struct binder_ref_death *death; - - ref = binder_get_ref(proc, target); - if (ref == NULL) { - binder_user_error("%d:%d %s invalid ref %d\n", - proc->pid, thread->pid, - request ? - "BC_REQUEST_DEATH_NOTIFICATION" : - "BC_CLEAR_DEATH_NOTIFICATION", - target); - return; - } - - binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, - "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n", - proc->pid, thread->pid, - request ? - "BC_REQUEST_DEATH_NOTIFICATION" : - "BC_CLEAR_DEATH_NOTIFICATION", - cookie, ref->debug_id, ref->desc, - ref->strong, ref->weak, ref->node->debug_id); - - if (request) { - if (ref->death) { - binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n", - proc->pid, thread->pid); - return; - } - death = kzalloc(sizeof(*death), GFP_KERNEL); - if (death == NULL) { - thread->return_error = BR_ERROR; - binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n", - proc->pid, thread->pid); - return; - } - binder_stats_created(BINDER_STAT_DEATH); - INIT_LIST_HEAD(&death->work.entry); - death->cookie = cookie; - ref->death = death; - if (ref->node->proc == NULL) { - ref->death->work.type = BINDER_WORK_DEAD_BINDER; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&ref->death->work.entry, &thread->todo); - } else { - list_add_tail(&ref->death->work.entry, &proc->todo); - wake_up_interruptible(&proc->wait); - } - } - } else { - if (ref->death == NULL) { - binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n", - proc->pid, thread->pid); - return; - } - death = ref->death; - if (death->cookie != cookie) { - binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n", - proc->pid, thread->pid, - death->cookie, cookie); - return; - } - ref->death = NULL; - if (list_empty(&death->work.entry)) { - death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&death->work.entry, &thread->todo); - } else { - list_add_tail(&death->work.entry, &proc->todo); - wake_up_interruptible(&proc->wait); - } - } else { - BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER); - death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR; - } - } - return; -} - -static void bc_dead_binder_done(struct binder_proc *proc, - struct binder_thread *thread, void __user *cookie) -{ - struct binder_work *w; - struct binder_ref_death *death = NULL; - - 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; - return; - } - } - binder_debug(BINDER_DEBUG_DEAD_BINDER, - "%d:%d BC_DEAD_BINDER_DONE %p found %p\n", - proc->pid, thread->pid, cookie, death); - if (death == NULL) { - binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n", - proc->pid, thread->pid, cookie); - return; - } - - list_del_init(&death->work.entry); - if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) { - death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&death->work.entry, &thread->todo); - } else { - list_add_tail(&death->work.entry, &proc->todo); - wake_up_interruptible(&proc->wait); - } - } - return; -} - -#ifdef CONFIG_COMPAT -static int compat_binder_thread_write(struct binder_proc *proc, - struct binder_thread *thread, uint32_t cmd, - void __user **ptr) -{ - BUG_ON(!is_compat_task()); - switch (cmd) { - case COMPAT_BC_INCREFS_DONE: - case COMPAT_BC_ACQUIRE_DONE: { - compat_uptr_t node_ptr; - compat_uptr_t cookie; - - if (get_user(node_ptr, (compat_uptr_t __user *)*ptr)) - return -EFAULT; - *ptr += sizeof(compat_uptr_t); - if (get_user(cookie, (compat_uptr_t __user *)*ptr)) - return -EFAULT; - *ptr += sizeof(compat_uptr_t); - bc_increfs_done(proc, thread, cmd == COMPAT_BC_ACQUIRE_DONE, - compat_ptr(node_ptr), compat_ptr(cookie)); - break; - } - - case COMPAT_BC_FREE_BUFFER: { - compat_uptr_t data_ptr; - - if (get_user(data_ptr, (compat_uptr_t __user *)*ptr)) - return -EFAULT; - *ptr += sizeof(compat_uptr_t); - bc_free_buffer(proc, thread, compat_ptr(data_ptr)); - break; - } - - case COMPAT_BC_TRANSACTION: - case COMPAT_BC_REPLY: { - struct binder_transaction_data tr; - struct compat_binder_transaction_data tmp_tr; - - if (copy_from_user(&tmp_tr, *ptr, sizeof(tmp_tr))) - return -EFAULT; - *ptr += sizeof(tmp_tr); - - memset(&tr, 0, sizeof(tr)); - /* copy from compat struct */ - tr.target.ptr = compat_ptr(tmp_tr.target.ptr); - tr.cookie = compat_ptr(tmp_tr.cookie); - tr.code = tmp_tr.code; - tr.flags = tmp_tr.flags; - tr.sender_pid = tmp_tr.sender_pid; - tr.sender_euid = tmp_tr.sender_euid; - tr.data_size = (size_t) tmp_tr.data_size; - tr.offsets_size = (size_t) tmp_tr.offsets_size; - tr.data.ptr.buffer = compat_ptr(tmp_tr.data.ptr.buffer); - tr.data.ptr.offsets = compat_ptr(tmp_tr.data.ptr.offsets); - - binder_transaction(proc, thread, &tr, cmd == COMPAT_BC_REPLY); - break; - } - case COMPAT_BC_REQUEST_DEATH_NOTIFICATION: - case COMPAT_BC_CLEAR_DEATH_NOTIFICATION: { - uint32_t target; - compat_uptr_t cookie; - - if (get_user(target, (uint32_t __user *)*ptr)) - return -EFAULT; - *ptr += sizeof(uint32_t); - if (get_user(cookie, (compat_uptr_t __user *)*ptr)) - return -EFAULT; - *ptr += sizeof(compat_uptr_t); - bc_clear_death_notif(proc, thread, cmd == COMPAT_BC_REQUEST_DEATH_NOTIFICATION, - target, compat_ptr(cookie)); - break; - } - case COMPAT_BC_DEAD_BINDER_DONE: { - compat_uptr_t cookie; - - if (get_user(cookie, (compat_uptr_t __user *)*ptr)) - return -EFAULT; - *ptr += sizeof(compat_uptr_t); - bc_dead_binder_done(proc, thread, compat_ptr(cookie)); - break; - } - default: - return -EINVAL; - } - return 0; -} -#endif - -static int binder_thread_write(struct binder_proc *proc, - struct binder_thread *thread, - void __user *buffer, size_t size, size_t *consumed) +int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, + binder_uintptr_t binder_buffer, size_t size, + binder_size_t *consumed) { uint32_t cmd; + void __user *buffer = (void __user *)(uintptr_t)binder_buffer; void __user *ptr = buffer + *consumed; void __user *end = buffer + size; @@ -2183,16 +1805,58 @@ static int binder_thread_write(struct binder_proc *proc, } case BC_INCREFS_DONE: case BC_ACQUIRE_DONE: { - void __user *node_ptr; - void __user *cookie; + binder_uintptr_t node_ptr; + binder_uintptr_t cookie; + struct binder_node *node; - if (get_user(node_ptr, (void * __user *)ptr)) + if (get_user(node_ptr, (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); - if (get_user(cookie, (void * __user *)ptr)) + ptr += sizeof(binder_uintptr_t); + if (get_user(cookie, (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); - bc_increfs_done(proc, thread, cmd == BC_ACQUIRE_DONE, node_ptr, cookie); + ptr += sizeof(binder_uintptr_t); + node = binder_get_node(proc, node_ptr); + if (node == NULL) { + binder_user_error("%d:%d %s u%016llx no match\n", + proc->pid, thread->pid, + cmd == BC_INCREFS_DONE ? + "BC_INCREFS_DONE" : + "BC_ACQUIRE_DONE", + (u64)node_ptr); + break; + } + if (cookie != node->cookie) { + binder_user_error("%d:%d %s u%016llx node %d cookie mismatch %016llx != %016llx\n", + proc->pid, thread->pid, + cmd == BC_INCREFS_DONE ? + "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", + (u64)node_ptr, node->debug_id, + (u64)cookie, (u64)node->cookie); + break; + } + if (cmd == BC_ACQUIRE_DONE) { + if (node->pending_strong_ref == 0) { + binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n", + proc->pid, thread->pid, + node->debug_id); + break; + } + node->pending_strong_ref = 0; + } else { + if (node->pending_weak_ref == 0) { + binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n", + proc->pid, thread->pid, + node->debug_id); + break; + } + node->pending_weak_ref = 0; + } + binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0); + binder_debug(BINDER_DEBUG_USER_REFS, + "%d:%d %s node %d ls %d lw %d\n", + proc->pid, thread->pid, + cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", + node->debug_id, node->local_strong_refs, node->local_weak_refs); break; } case BC_ATTEMPT_ACQUIRE: @@ -2203,12 +1867,43 @@ static int binder_thread_write(struct binder_proc *proc, return -EINVAL; case BC_FREE_BUFFER: { - void __user *data_ptr; + binder_uintptr_t data_ptr; + struct binder_buffer *buffer; - if (get_user(data_ptr, (void * __user *)ptr)) + if (get_user(data_ptr, (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); - bc_free_buffer(proc, thread, data_ptr); + ptr += sizeof(binder_uintptr_t); + + buffer = binder_buffer_lookup(proc, data_ptr); + if (buffer == NULL) { + binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n", + proc->pid, thread->pid, (u64)data_ptr); + break; + } + if (!buffer->allow_user_free) { + binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n", + proc->pid, thread->pid, (u64)data_ptr); + break; + } + binder_debug(BINDER_DEBUG_FREE_BUFFER, + "%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n", + proc->pid, thread->pid, (u64)data_ptr, buffer->debug_id, + buffer->transaction ? "active" : "finished"); + + if (buffer->transaction) { + buffer->transaction->buffer = NULL; + buffer->transaction = NULL; + } + if (buffer->async_transaction && buffer->target_node) { + BUG_ON(!buffer->target_node->has_async_transaction); + if (list_empty(&buffer->target_node->async_todo)) + buffer->target_node->has_async_transaction = 0; + else + list_move_tail(buffer->target_node->async_todo.next, &thread->todo); + } + trace_binder_transaction_buffer_release(buffer); + binder_transaction_buffer_release(proc, buffer, NULL); + binder_free_buf(proc, buffer); break; } @@ -2262,32 +1957,128 @@ static int binder_thread_write(struct binder_proc *proc, case BC_REQUEST_DEATH_NOTIFICATION: case BC_CLEAR_DEATH_NOTIFICATION: { uint32_t target; - void __user *cookie; + binder_uintptr_t cookie; + struct binder_ref *ref; + struct binder_ref_death *death; if (get_user(target, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); - if (get_user(cookie, (void __user * __user *)ptr)) + if (get_user(cookie, (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); - bc_clear_death_notif(proc, thread, cmd == BC_REQUEST_DEATH_NOTIFICATION, - target, cookie); - break; - } - case BC_DEAD_BINDER_DONE: { - void __user *cookie; + ptr += sizeof(binder_uintptr_t); + ref = binder_get_ref(proc, target); + if (ref == NULL) { + binder_user_error("%d:%d %s invalid ref %d\n", + proc->pid, thread->pid, + cmd == BC_REQUEST_DEATH_NOTIFICATION ? + "BC_REQUEST_DEATH_NOTIFICATION" : + "BC_CLEAR_DEATH_NOTIFICATION", + target); + break; + } - if (get_user(cookie, (void __user * __user *)ptr)) + binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, + "%d:%d %s %016llx ref %d desc %d s %d w %d for node %d\n", + proc->pid, thread->pid, + cmd == BC_REQUEST_DEATH_NOTIFICATION ? + "BC_REQUEST_DEATH_NOTIFICATION" : + "BC_CLEAR_DEATH_NOTIFICATION", + (u64)cookie, ref->debug_id, ref->desc, + ref->strong, ref->weak, ref->node->debug_id); + + if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { + if (ref->death) { + binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n", + proc->pid, thread->pid); + break; + } + death = kzalloc(sizeof(*death), GFP_KERNEL); + if (death == NULL) { + thread->return_error = BR_ERROR; + binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, + "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n", + proc->pid, thread->pid); + break; + } + binder_stats_created(BINDER_STAT_DEATH); + INIT_LIST_HEAD(&death->work.entry); + death->cookie = cookie; + ref->death = death; + if (ref->node->proc == NULL) { + ref->death->work.type = BINDER_WORK_DEAD_BINDER; + if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { + list_add_tail(&ref->death->work.entry, &thread->todo); + } else { + list_add_tail(&ref->death->work.entry, &proc->todo); + wake_up_interruptible(&proc->wait); + } + } + } else { + if (ref->death == NULL) { + binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n", + proc->pid, thread->pid); + break; + } + death = ref->death; + if (death->cookie != cookie) { + binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %016llx != %016llx\n", + proc->pid, thread->pid, + (u64)death->cookie, (u64)cookie); + break; + } + ref->death = NULL; + if (list_empty(&death->work.entry)) { + death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; + if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { + list_add_tail(&death->work.entry, &thread->todo); + } else { + list_add_tail(&death->work.entry, &proc->todo); + wake_up_interruptible(&proc->wait); + } + } else { + BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER); + death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR; + } + } + } break; + case BC_DEAD_BINDER_DONE: { + 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 *); - bc_dead_binder_done(proc, thread, cookie); - break; - } - default: -#ifdef CONFIG_COMPAT - if (is_compat_task() && (!compat_binder_thread_write(proc, thread, cmd, &ptr))) + 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; + } + } + binder_debug(BINDER_DEBUG_DEAD_BINDER, + "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n", + proc->pid, thread->pid, (u64)cookie, death); + if (death == NULL) { + binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n", + proc->pid, thread->pid, (u64)cookie); break; -#endif + } + + list_del_init(&death->work.entry); + if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) { + death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; + if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { + list_add_tail(&death->work.entry, &thread->todo); + } else { + list_add_tail(&death->work.entry, &proc->todo); + wake_up_interruptible(&proc->wait); + } + } + } break; + + default: pr_err("%d:%d unknown command %d\n", proc->pid, thread->pid, cmd); return -EINVAL; @@ -2321,121 +2112,12 @@ static int binder_has_thread_work(struct binder_thread *thread) (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); } -#ifdef CONFIG_COMPAT -static int binder_copy_to_user(uint32_t cmd, void *parcel, - void __user **ptr, size_t size) -{ - if (!is_compat_task()) { - if (put_user(cmd, (uint32_t __user *)*ptr)) - return -EFAULT; - *ptr += sizeof(uint32_t); - if (copy_to_user(*ptr, parcel, size)) - return -EFAULT; - *ptr += size; - return 0; - } - switch (cmd) { - case BR_INCREFS: - case BR_ACQUIRE: - case BR_RELEASE: - case BR_DECREFS: { - struct binder_ptr_cookie *fp; - struct compat_binder_ptr_cookie tmp; - - cmd = compat_change_size(cmd, sizeof(tmp)); - BUG_ON((cmd != COMPAT_BR_INCREFS) && - (cmd != COMPAT_BR_ACQUIRE) && - (cmd != COMPAT_BR_RELEASE) && - (cmd != COMPAT_BR_DECREFS)); - - fp = (struct binder_ptr_cookie *) parcel; - tmp.ptr = ptr_to_compat(fp->ptr); - tmp.cookie = ptr_to_compat(fp->cookie); - if (put_user(cmd, (uint32_t __user *)*ptr)) - return -EFAULT; - *ptr += sizeof(uint32_t); - if (copy_to_user(*ptr, &tmp, sizeof(tmp))) - return -EFAULT; - *ptr += sizeof(tmp); - - break; - } - case BR_DEAD_BINDER: - case BR_CLEAR_DEATH_NOTIFICATION_DONE: { - compat_uptr_t tmp; - - cmd = compat_change_size(cmd, sizeof(tmp)); - BUG_ON((cmd != COMPAT_BR_DEAD_BINDER) && - (cmd != COMPAT_BR_CLEAR_DEATH_NOTIFICATION_DONE)); - - tmp = ptr_to_compat((void *)*(uintptr_t *) parcel); - if (put_user(cmd, (uint32_t __user *)*ptr)) - return -EFAULT; - *ptr += sizeof(uint32_t); - if (copy_to_user(*ptr, &tmp, sizeof(tmp))) - return -EFAULT; - *ptr += sizeof(tmp); - - break; - } - case BR_REPLY: - case BR_TRANSACTION: { - struct binder_transaction_data *fp; - struct compat_binder_transaction_data tmp; - - memset(&tmp, 0, sizeof(tmp)); - cmd = compat_change_size(cmd, sizeof(tmp)); - BUG_ON((cmd != COMPAT_BR_REPLY) && - (cmd != COMPAT_BR_TRANSACTION)); - - fp = (struct binder_transaction_data *) parcel; - /* copy to compat struct */ - tmp.target.ptr = ptr_to_compat(fp->target.ptr); - tmp.cookie = ptr_to_compat(fp->cookie); - tmp.code = fp->code; - tmp.flags = fp->flags; - tmp.sender_pid = fp->sender_pid; - tmp.sender_euid = fp->sender_euid; - tmp.data_size = (compat_size_t) fp->data_size; - tmp.offsets_size = (compat_size_t) fp->offsets_size; - tmp.data.ptr.buffer = ptr_to_compat((void *)fp->data.ptr.buffer); - tmp.data.ptr.offsets = ptr_to_compat((void *)fp->data.ptr.offsets); - - if (put_user(cmd, (uint32_t __user *)*ptr)) - return -EFAULT; - *ptr += sizeof(uint32_t); - if (copy_to_user(*ptr, &tmp, sizeof(tmp))) - return -EFAULT; - *ptr += sizeof(tmp); - - break; - } - default: - pr_err("unexpected user copy, cmd %d, ptr %p\n", - cmd, (void *)*(uintptr_t *)ptr); - return -EFAULT; - } - return 0; -} -#else -static int binder_copy_to_user(uint32_t cmd, void *parcel, - void __user **ptr, size_t size) -{ - if (put_user(cmd, (uint32_t __user *)*ptr)) - return -EFAULT; - *ptr += sizeof(uint32_t); - if (copy_to_user(*ptr, parcel, size)) - return -EFAULT; - *ptr += size; - return 0; -} -#endif - static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, - void __user *buffer, size_t size, - size_t *consumed, int non_block) + binder_uintptr_t binder_buffer, size_t size, + binder_size_t *consumed, int non_block) { + void __user *buffer = (void __user *)(uintptr_t)binder_buffer; void __user *ptr = buffer + *consumed; void __user *end = buffer + size; @@ -2527,7 +2209,7 @@ retry: break; } - if (end - ptr < size_helper(tr) + 4) + if (end - ptr < sizeof(tr) + 4) break; switch (w->type) { @@ -2577,32 +2259,39 @@ retry: node->has_weak_ref = 0; } if (cmd != BR_NOOP) { - struct binder_ptr_cookie tmp; - - tmp.ptr = node->ptr; - tmp.cookie = node->cookie; - if (binder_copy_to_user(cmd, &tmp, &ptr, sizeof(struct binder_ptr_cookie))) + if (put_user(cmd, (uint32_t __user *)ptr)) + return -EFAULT; + ptr += sizeof(uint32_t); + if (put_user(node->ptr, + (binder_uintptr_t __user *)ptr)) return -EFAULT; + ptr += sizeof(binder_uintptr_t); + if (put_user(node->cookie, + (binder_uintptr_t __user *)ptr)) + return -EFAULT; + ptr += sizeof(binder_uintptr_t); binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_USER_REFS, - "%d:%d %s %d u%p c%p\n", - proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie); + "%d:%d %s %d u%016llx c%016llx\n", + proc->pid, thread->pid, cmd_name, + node->debug_id, + (u64)node->ptr, (u64)node->cookie); } else { list_del_init(&w->entry); if (!weak && !strong) { binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "%d:%d node %d u%p c%p deleted\n", + "%d:%d node %d u%016llx c%016llx deleted\n", proc->pid, thread->pid, node->debug_id, - node->ptr, node->cookie); + (u64)node->ptr, (u64)node->cookie); rb_erase(&node->rb_node, &proc->nodes); kfree(node); binder_stats_deleted(BINDER_STAT_NODE); } else { binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "%d:%d node %d u%p c%p state unchanged\n", - proc->pid, thread->pid, node->debug_id, node->ptr, - node->cookie); + "%d:%d node %d u%016llx c%016llx state unchanged\n", + proc->pid, thread->pid, node->debug_id, + (u64)node->ptr, (u64)node->cookie); } } } break; @@ -2617,18 +2306,21 @@ retry: cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE; else cmd = BR_DEAD_BINDER; - - if (binder_copy_to_user(cmd, &death->cookie, &ptr, sizeof(void *))) + if (put_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; - + ptr += sizeof(uint32_t); + if (put_user(death->cookie, + (binder_uintptr_t __user *)ptr)) + return -EFAULT; + ptr += sizeof(binder_uintptr_t); binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, - "%d:%d %s %p\n", + "%d:%d %s %016llx\n", proc->pid, thread->pid, cmd == BR_DEAD_BINDER ? "BR_DEAD_BINDER" : "BR_CLEAR_DEATH_NOTIFICATION_DONE", - death->cookie); + (u64)death->cookie); if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) { list_del(&w->entry); @@ -2658,8 +2350,8 @@ retry: binder_set_nice(target_node->min_priority); cmd = BR_TRANSACTION; } else { - tr.target.ptr = NULL; - tr.cookie = NULL; + tr.target.ptr = 0; + tr.cookie = 0; cmd = BR_REPLY; } tr.code = t->code; @@ -2676,25 +2368,31 @@ retry: tr.data_size = t->buffer->data_size; tr.offsets_size = t->buffer->offsets_size; - tr.data.ptr.buffer = (void *)t->buffer->data + - proc->user_buffer_offset; + tr.data.ptr.buffer = (binder_uintptr_t)( + (uintptr_t)t->buffer->data + + proc->user_buffer_offset); tr.data.ptr.offsets = tr.data.ptr.buffer + - align_helper(t->buffer->data_size); + ALIGN(t->buffer->data_size, + sizeof(void *)); - if (binder_copy_to_user(cmd, &tr, &ptr, sizeof(struct binder_transaction_data))) + if (put_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; + ptr += sizeof(uint32_t); + if (copy_to_user(ptr, &tr, sizeof(tr))) + return -EFAULT; + ptr += sizeof(tr); trace_binder_transaction_received(t); binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_TRANSACTION, - "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %p-%p\n", + "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n", proc->pid, thread->pid, (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" : "BR_REPLY", t->debug_id, t->from ? t->from->proc->pid : 0, t->from ? t->from->pid : 0, cmd, t->buffer->data_size, t->buffer->offsets_size, - tr.data.ptr.buffer, tr.data.ptr.offsets); + (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets); list_del(&t->work.entry); t->buffer->allow_user_free = 1; @@ -2764,8 +2462,8 @@ static void binder_release_work(struct list_head *list) death = container_of(w, struct binder_ref_death, work); binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, - "undelivered death notification, %p\n", - death->cookie); + "undelivered death notification, %016llx\n", + (u64)death->cookie); kfree(death); binder_stats_deleted(BINDER_STAT_DEATH); } break; @@ -2921,12 +2619,13 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d write %zd at %016lx, read %zd at %016lx\n", - proc->pid, thread->pid, bwr.write_size, - bwr.write_buffer, bwr.read_size, bwr.read_buffer); + "%d:%d write %lld at %016llx, read %lld at %016llx\n", + proc->pid, thread->pid, + (u64)bwr.write_size, (u64)bwr.write_buffer, + (u64)bwr.read_size, (u64)bwr.read_buffer); if (bwr.write_size > 0) { - ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed); + ret = binder_thread_write(proc, thread, bwr.write_buffer, bwr.write_size, &bwr.write_consumed); trace_binder_write_done(ret); if (ret < 0) { bwr.read_consumed = 0; @@ -2936,7 +2635,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } if (bwr.read_size > 0) { - ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); + ret = binder_thread_read(proc, thread, bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); trace_binder_read_done(ret); if (!list_empty(&proc->todo)) wake_up_interruptible(&proc->wait); @@ -2947,9 +2646,10 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d wrote %zd of %zd, read return %zd of %zd\n", - proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, - bwr.read_consumed, bwr.read_size); + "%d:%d wrote %lld of %lld, read return %lld of %lld\n", + proc->pid, thread->pid, + (u64)bwr.write_consumed, (u64)bwr.write_size, + (u64)bwr.read_consumed, (u64)bwr.read_size); if (copy_to_user(ubuf, &bwr, sizeof(bwr))) { ret = -EFAULT; goto err; @@ -2981,7 +2681,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } else binder_context_mgr_uid = current->cred->euid; - binder_context_mgr_node = binder_new_node(proc, NULL, NULL); + binder_context_mgr_node = binder_new_node(proc, 0, 0); if (binder_context_mgr_node == NULL) { ret = -ENOMEM; goto err; @@ -3024,80 +2724,6 @@ err_unlocked: return ret; } -/* TODO: add tracepoint */ -#ifdef CONFIG_COMPAT -static long compat_binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - int ret = 0; - struct binder_thread *thread; - struct compat_binder_write_read bwr; - struct binder_proc *proc = filp->private_data; - void __user *ubuf = compat_ptr(arg); - - /* pr_info("compat_binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg); */ - - if (cmd != COMPAT_BINDER_WRITE_READ) - return binder_ioctl(filp, cmd, arg); - - BUG_ON(!is_compat_task()); - binder_lock(__func__); - thread = binder_get_thread(proc); - if (thread == NULL) { - ret = -ENOMEM; - goto err; - } - - /* COMPAT_BINDER_WRITE_READ */ - if (copy_from_user(&bwr, ubuf, sizeof(bwr))) { - ret = -EFAULT; - goto err; - } - binder_debug(BINDER_DEBUG_READ_WRITE, - "compat: %d:%d write %d at %016x, read %d at %016x\n", - proc->pid, thread->pid, bwr.write_size, - bwr.write_buffer, bwr.read_size, bwr.read_buffer); - - if (bwr.write_size > 0) { - size_t tmp_write_consumed = (size_t)bwr.write_consumed; - ret = binder_thread_write(proc, thread, compat_ptr(bwr.write_buffer), (size_t)bwr.write_size, &tmp_write_consumed); - bwr.write_consumed = (compat_size_t)tmp_write_consumed; - if (ret < 0) { - bwr.read_consumed = 0; - if (copy_to_user(ubuf, &bwr, sizeof(bwr))) - ret = -EFAULT; - goto err; - } - } - - if (bwr.read_size > 0) { - size_t tmp_read_consumed = (size_t)bwr.read_consumed; - ret = binder_thread_read(proc, thread, compat_ptr(bwr.read_buffer), (size_t)bwr.read_size, &tmp_read_consumed, filp->f_flags & O_NONBLOCK); - bwr.read_consumed = (compat_size_t)tmp_read_consumed; - if (!list_empty(&proc->todo)) - wake_up_interruptible(&proc->wait); - if (ret < 0) { - if (copy_to_user(ubuf, &bwr, sizeof(bwr))) - ret = -EFAULT; - goto err; - } - } - binder_debug(BINDER_DEBUG_READ_WRITE, - "compat: %d:%d wrote %d of %d, read return %d of %d\n", - proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, - bwr.read_consumed, bwr.read_size); - if (copy_to_user(ubuf, &bwr, sizeof(bwr))) - ret = -EFAULT; - -err: - if (thread) - thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN; - binder_unlock(__func__); - if (ret && ret != -ERESTARTSYS) - pr_info("%d:%d compat ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); - return ret; -} -#endif - static void binder_vma_open(struct vm_area_struct *vma) { struct binder_proc *proc = vma->vm_private_data; @@ -3322,7 +2948,7 @@ static int binder_node_release(struct binder_node *node, int refs) refs++; if (!ref->death) - goto out; + continue; death++; @@ -3335,7 +2961,6 @@ static int binder_node_release(struct binder_node *node, int refs) BUG(); } -out: binder_debug(BINDER_DEBUG_DEAD_BINDER, "node %d now dead, refs %d, death %d\n", node->debug_id, refs, death); @@ -3551,8 +3176,9 @@ static void print_binder_work(struct seq_file *m, const char *prefix, break; case BINDER_WORK_NODE: node = container_of(w, struct binder_node, work); - seq_printf(m, "%snode work %d: u%p c%p\n", - prefix, node->debug_id, node->ptr, node->cookie); + seq_printf(m, "%snode work %d: u%016llx c%016llx\n", + prefix, node->debug_id, + (u64)node->ptr, (u64)node->cookie); break; case BINDER_WORK_DEAD_BINDER: seq_printf(m, "%shas dead binder\n", prefix); @@ -3612,8 +3238,8 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node) hlist_for_each_entry(ref, &node->refs, node_entry) count++; - seq_printf(m, " node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d", - node->debug_id, node->ptr, node->cookie, + seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d", + node->debug_id, (u64)node->ptr, (u64)node->cookie, node->has_strong_ref, node->has_weak_ref, node->local_strong_refs, node->local_weak_refs, node->internal_strong_refs, count); @@ -3915,9 +3541,7 @@ static const struct file_operations binder_fops = { .owner = THIS_MODULE, .poll = binder_poll, .unlocked_ioctl = binder_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = compat_binder_ioctl, -#endif + .compat_ioctl = binder_ioctl, .mmap = binder_mmap, .open = binder_open, .flush = binder_flush, diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h index d4101a671718..eb0834656dfe 100644 --- a/drivers/staging/android/binder.h +++ b/drivers/staging/android/binder.h @@ -20,6 +20,10 @@ #ifndef _LINUX_BINDER_H #define _LINUX_BINDER_H +#ifdef CONFIG_ANDROID_BINDER_IPC_32BIT +#define BINDER_IPC_32BIT 1 +#endif + #include "uapi/binder.h" #endif /* _LINUX_BINDER_H */ diff --git a/drivers/staging/android/binder_trace.h b/drivers/staging/android/binder_trace.h index c661e376398f..02add80b62a0 100644 --- a/drivers/staging/android/binder_trace.h +++ b/drivers/staging/android/binder_trace.h @@ -152,7 +152,7 @@ TRACE_EVENT(binder_transaction_node_to_ref, TP_STRUCT__entry( __field(int, debug_id) __field(int, node_debug_id) - __field(void __user *, node_ptr) + __field(binder_uintptr_t, node_ptr) __field(int, ref_debug_id) __field(uint32_t, ref_desc) ), @@ -163,8 +163,9 @@ TRACE_EVENT(binder_transaction_node_to_ref, __entry->ref_debug_id = ref->debug_id; __entry->ref_desc = ref->desc; ), - TP_printk("transaction=%d node=%d src_ptr=0x%p ==> dest_ref=%d dest_desc=%d", - __entry->debug_id, __entry->node_debug_id, __entry->node_ptr, + TP_printk("transaction=%d node=%d src_ptr=0x%016llx ==> dest_ref=%d dest_desc=%d", + __entry->debug_id, __entry->node_debug_id, + (u64)__entry->node_ptr, __entry->ref_debug_id, __entry->ref_desc) ); @@ -177,7 +178,7 @@ TRACE_EVENT(binder_transaction_ref_to_node, __field(int, ref_debug_id) __field(uint32_t, ref_desc) __field(int, node_debug_id) - __field(void __user *, node_ptr) + __field(binder_uintptr_t, node_ptr) ), TP_fast_assign( __entry->debug_id = t->debug_id; @@ -186,9 +187,10 @@ TRACE_EVENT(binder_transaction_ref_to_node, __entry->node_debug_id = ref->node->debug_id; __entry->node_ptr = (void __user *)ref->node->ptr; ), - TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%p", + TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%016llx", __entry->debug_id, __entry->node_debug_id, - __entry->ref_debug_id, __entry->ref_desc, __entry->node_ptr) + __entry->ref_debug_id, __entry->ref_desc, + (u64)__entry->node_ptr) ); TRACE_EVENT(binder_transaction_ref_to_ref, diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index 384658ac1bb4..4098c502fc36 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -21,9 +21,6 @@ #define _UAPI_LINUX_BINDER_H #include <linux/ioctl.h> -#ifdef CONFIG_COMPAT -#include <linux/compat.h> -#endif #define B_PACK_CHARS(c1, c2, c3, c4) \ ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4)) @@ -42,6 +39,14 @@ enum { FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, }; +#ifdef BINDER_IPC_32BIT +typedef __u32 binder_size_t; +typedef __u32 binder_uintptr_t; +#else +typedef __u64 binder_size_t; +typedef __u64 binder_uintptr_t; +#endif + /* * This is the flattened representation of a Binder object for transfer * between processes. The 'offsets' supplied as part of a binder transaction @@ -56,12 +61,12 @@ struct flat_binder_object { /* 8 bytes of data. */ union { - void __user *binder; /* local object */ - __u32 handle; /* remote object */ + binder_uintptr_t binder; /* local object */ + __u32 handle; /* remote object */ }; /* extra data associated with local object */ - void __user *cookie; + binder_uintptr_t cookie; }; /* @@ -70,12 +75,12 @@ struct flat_binder_object { */ struct binder_write_read { - size_t write_size; /* bytes to write */ - size_t write_consumed; /* bytes consumed by driver */ - unsigned long write_buffer; - size_t read_size; /* bytes to read */ - size_t read_consumed; /* bytes consumed by driver */ - unsigned long read_buffer; + binder_size_t write_size; /* bytes to write */ + binder_size_t write_consumed; /* bytes consumed by driver */ + binder_uintptr_t write_buffer; + binder_size_t read_size; /* bytes to read */ + binder_size_t read_consumed; /* bytes consumed by driver */ + binder_uintptr_t read_buffer; }; /* Use with BINDER_VERSION, driver fills in fields. */ @@ -85,7 +90,11 @@ struct binder_version { }; /* This is the current protocol version. */ +#ifdef BINDER_IPC_32BIT #define BINDER_CURRENT_PROTOCOL_VERSION 7 +#else +#define BINDER_CURRENT_PROTOCOL_VERSION 8 +#endif #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) @@ -123,17 +132,17 @@ struct binder_transaction_data { */ union { __u32 handle; /* target descriptor of command transaction */ - void *ptr; /* target descriptor of return transaction */ + binder_uintptr_t ptr; /* target descriptor of return transaction */ } target; - void *cookie; /* target object cookie */ + binder_uintptr_t cookie; /* target object cookie */ __u32 code; /* transaction command */ /* General information about the transaction. */ __u32 flags; pid_t sender_pid; uid_t sender_euid; - size_t data_size; /* number of bytes of data */ - size_t offsets_size; /* number of bytes of offsets */ + binder_size_t data_size; /* number of bytes of data */ + binder_size_t offsets_size; /* number of bytes of offsets */ /* If this transaction is inline, the data immediately * follows here; otherwise, it ends with a pointer to @@ -142,22 +151,22 @@ struct binder_transaction_data { union { struct { /* transaction data */ - const void __user *buffer; + binder_uintptr_t buffer; /* offsets from buffer to flat_binder_object structs */ - const void __user *offsets; + binder_uintptr_t offsets; } ptr; __u8 buf[8]; } data; }; struct binder_ptr_cookie { - void *ptr; - void *cookie; + binder_uintptr_t ptr; + binder_uintptr_t cookie; }; struct binder_handle_cookie { __u32 handle; - void *cookie; + binder_uintptr_t cookie; } __attribute__((packed)); struct binder_pri_desc { @@ -167,8 +176,8 @@ struct binder_pri_desc { struct binder_pri_ptr_cookie { __s32 priority; - void *ptr; - void *cookie; + binder_uintptr_t ptr; + binder_uintptr_t cookie; }; enum binder_driver_return_protocol { @@ -243,11 +252,11 @@ enum binder_driver_return_protocol { * stop threadpool thread */ - BR_DEAD_BINDER = _IOR('r', 15, void *), + BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t), /* * void *: cookie */ - BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *), + BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t), /* * void *: cookie */ @@ -273,7 +282,7 @@ enum binder_driver_command_protocol { * Else you have acquired a primary reference on the object. */ - BC_FREE_BUFFER = _IOW('c', 3, void *), + BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t), /* * void *: ptr to transaction data received on a read */ @@ -328,117 +337,11 @@ enum binder_driver_command_protocol { * void *: cookie */ - BC_DEAD_BINDER_DONE = _IOW('c', 16, void *), + BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t), /* * void *: cookie */ }; -/* Support for 32bit userspace on a 64bit system */ -#ifdef CONFIG_COMPAT -struct compat_flat_binder_object { - /* 8 bytes for large_flat_header. */ - __u32 type; - __u32 flags; - - /* 8 bytes of data. */ - union { - compat_uptr_t binder; /* local object */ - __u32 handle; /* remote object */ - }; - - /* extra data associated with local object */ - compat_uptr_t cookie; -}; - -struct compat_binder_write_read { - compat_size_t write_size; /* bytes to write */ - compat_size_t write_consumed; /* bytes consumed by driver */ - compat_ulong_t write_buffer; - compat_size_t read_size; /* bytes to read */ - compat_size_t read_consumed; /* bytes consumed by driver */ - compat_ulong_t read_buffer; -}; - -#define COMPAT_BINDER_WRITE_READ _IOWR('b', 1, struct compat_binder_write_read) - -struct compat_binder_transaction_data { - /* The first two are only used for bcTRANSACTION and brTRANSACTION, - * identifying the target and contents of the transaction. - */ - union { - __u32 handle; /* target descriptor of command transaction */ - compat_uptr_t ptr; /* target descriptor of return transaction */ - } target; - compat_uptr_t cookie; /* target object cookie */ - __u32 code; /* transaction command */ - - /* General information about the transaction. */ - __u32 flags; - pid_t sender_pid; - uid_t sender_euid; - compat_size_t data_size; /* number of bytes of data */ - compat_size_t offsets_size; /* number of bytes of offsets */ - - /* If this transaction is inline, the data immediately - * follows here; otherwise, it ends with a pointer to - * the data buffer. - */ - union { - struct { - /* transaction data */ - compat_uptr_t buffer; - /* offsets from buffer to flat_binder_object structs */ - compat_uptr_t offsets; - } ptr; - __u8 buf[8]; - } data; -}; - -struct compat_binder_ptr_cookie { - compat_uptr_t ptr; - compat_uptr_t cookie; -}; - -/* legacy - not used anymore */ -struct compat_binder_pri_ptr_cookie { - __s32 priority; - compat_uptr_t ptr; - compat_uptr_t cookie; -}; - -enum compat_binder_driver_return_protocol { - COMPAT_BR_TRANSACTION = _IOR('r', 2, struct compat_binder_transaction_data), - COMPAT_BR_REPLY = _IOR('r', 3, struct compat_binder_transaction_data), - - COMPAT_BR_INCREFS = _IOR('r', 7, struct compat_binder_ptr_cookie), - COMPAT_BR_ACQUIRE = _IOR('r', 8, struct compat_binder_ptr_cookie), - COMPAT_BR_RELEASE = _IOR('r', 9, struct compat_binder_ptr_cookie), - COMPAT_BR_DECREFS = _IOR('r', 10, struct compat_binder_ptr_cookie), - - /* legacy - not used anymore */ - COMPAT_BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct compat_binder_pri_ptr_cookie), - - COMPAT_BR_DEAD_BINDER = _IOR('r', 15, compat_uptr_t), - COMPAT_BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, compat_uptr_t), -}; - -enum compat_binder_driver_command_protocol { - COMPAT_BC_TRANSACTION = _IOW('c', 0, struct compat_binder_transaction_data), - COMPAT_BC_REPLY = _IOW('c', 1, struct compat_binder_transaction_data), - - COMPAT_BC_FREE_BUFFER = _IOW('c', 3, compat_uptr_t), - - COMPAT_BC_INCREFS_DONE = _IOW('c', 8, struct compat_binder_ptr_cookie), - COMPAT_BC_ACQUIRE_DONE = _IOW('c', 9, struct compat_binder_ptr_cookie), - - COMPAT_BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct compat_binder_ptr_cookie), - COMPAT_BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct compat_binder_ptr_cookie), - - COMPAT_BC_DEAD_BINDER_DONE = _IOW('c', 16, compat_uptr_t), -}; -#endif /* CONFIG_COMPAT */ - - #endif /* _UAPI_LINUX_BINDER_H */ diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c index 092964c2b506..53e50b5e8612 100644 --- a/drivers/usb/gadget/f_accessory.c +++ b/drivers/usb/gadget/f_accessory.c @@ -261,8 +261,10 @@ static void acc_complete_in(struct usb_ep *ep, struct usb_request *req) { struct acc_dev *dev = _acc_dev; - if (req->status != 0) + if (req->status == -ESHUTDOWN) { + pr_debug("acc_complete_in set disconnected"); acc_set_disconnected(dev); + } req_put(dev, &dev->tx_idle, req); @@ -274,8 +276,10 @@ static void acc_complete_out(struct usb_ep *ep, struct usb_request *req) struct acc_dev *dev = _acc_dev; dev->rx_done = 1; - if (req->status != 0) + if (req->status == -ESHUTDOWN) { + pr_debug("acc_complete_out set disconnected"); acc_set_disconnected(dev); + } wake_up(&dev->read_wq); } @@ -552,13 +556,16 @@ static ssize_t acc_read(struct file *fp, char __user *buf, { struct acc_dev *dev = fp->private_data; struct usb_request *req; - int r = count, xfer; + ssize_t r = count; + unsigned xfer; int ret = 0; - pr_debug("acc_read(%d)\n", count); + pr_debug("acc_read(%zu)\n", count); - if (dev->disconnected) + if (dev->disconnected) { + pr_debug("acc_read disconnected"); return -ENODEV; + } if (count > BULK_BUFFER_SIZE) count = BULK_BUFFER_SIZE; @@ -571,6 +578,12 @@ static ssize_t acc_read(struct file *fp, char __user *buf, goto done; } + if (dev->rx_done) { + // last req cancelled. try to get it. + req = dev->rx_req[0]; + goto copy_data; + } + requeue_req: /* queue a request */ req = dev->rx_req[0]; @@ -588,15 +601,23 @@ requeue_req: ret = wait_event_interruptible(dev->read_wq, dev->rx_done); if (ret < 0) { r = ret; - usb_ep_dequeue(dev->ep_out, req); + ret = usb_ep_dequeue(dev->ep_out, req); + if (ret != 0) { + // cancel failed. There can be a data already received. + // it will be retrieved in the next read. + pr_debug("acc_read: cancelling failed %d", ret); + } goto done; } + +copy_data: + dev->rx_done = 0; if (dev->online) { /* If we got a 0-len packet, throw it back and try again. */ if (req->actual == 0) goto requeue_req; - pr_debug("rx %p %d\n", req, req->actual); + pr_debug("rx %p %u\n", req, req->actual); xfer = (req->actual < count) ? req->actual : count; r = xfer; if (copy_to_user(buf, req->buf, xfer)) @@ -605,7 +626,7 @@ requeue_req: r = -EIO; done: - pr_debug("acc_read returning %d\n", r); + pr_debug("acc_read returning %zd\n", r); return r; } @@ -614,13 +635,16 @@ static ssize_t acc_write(struct file *fp, const char __user *buf, { struct acc_dev *dev = fp->private_data; struct usb_request *req = 0; - int r = count, xfer; + ssize_t r = count; + unsigned xfer; int ret; - pr_debug("acc_write(%d)\n", count); + pr_debug("acc_write(%zu)\n", count); - if (!dev->online || dev->disconnected) + if (!dev->online || dev->disconnected) { + pr_debug("acc_write disconnected or not online"); return -ENODEV; + } while (count > 0) { if (!dev->online) { @@ -665,7 +689,7 @@ static ssize_t acc_write(struct file *fp, const char __user *buf, if (req) req_put(dev, &dev->tx_idle, req); - pr_debug("acc_write returning %d\n", r); + pr_debug("acc_write returning %zd\n", r); return r; } diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c index 960d64fbd40b..620aeaaf2d72 100644 --- a/drivers/usb/gadget/f_mtp.c +++ b/drivers/usb/gadget/f_mtp.c @@ -466,10 +466,11 @@ static ssize_t mtp_read(struct file *fp, char __user *buf, struct mtp_dev *dev = fp->private_data; struct usb_composite_dev *cdev = dev->cdev; struct usb_request *req; - int r = count, xfer; + ssize_t r = count; + unsigned xfer; int ret = 0; - DBG(cdev, "mtp_read(%d)\n", count); + DBG(cdev, "mtp_read(%zu)\n", count); if (count > MTP_BULK_BUFFER_SIZE) return -EINVAL; @@ -533,7 +534,7 @@ done: dev->state = STATE_READY; spin_unlock_irq(&dev->lock); - DBG(cdev, "mtp_read returning %d\n", r); + DBG(cdev, "mtp_read returning %zd\n", r); return r; } @@ -543,11 +544,12 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf, struct mtp_dev *dev = fp->private_data; struct usb_composite_dev *cdev = dev->cdev; struct usb_request *req = 0; - int r = count, xfer; + ssize_t r = count; + unsigned xfer; int sendZLP = 0; int ret; - DBG(cdev, "mtp_write(%d)\n", count); + DBG(cdev, "mtp_write(%zu)\n", count); spin_lock_irq(&dev->lock); if (dev->state == STATE_CANCELED) { @@ -624,7 +626,7 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf, dev->state = STATE_READY; spin_unlock_irq(&dev->lock); - DBG(cdev, "mtp_write returning %d\n", r); + DBG(cdev, "mtp_write returning %zd\n", r); return r; } @@ -823,7 +825,7 @@ static int mtp_send_event(struct mtp_dev *dev, struct mtp_event *event) int ret; int length = event->length; - DBG(dev->cdev, "mtp_send_event(%d)\n", event->length); + DBG(dev->cdev, "mtp_send_event(%zu)\n", event->length); if (length < 0 || length > INTR_BUFFER_SIZE) return -EINVAL; diff --git a/drivers/video/adf/adf_client.c b/drivers/video/adf/adf_client.c index bba873d34bbb..8061d8e6b9fb 100644 --- a/drivers/video/adf/adf_client.c +++ b/drivers/video/adf/adf_client.c @@ -283,7 +283,7 @@ static int adf_buffer_map(struct adf_device *dev, struct adf_buffer *buf, attachment = dma_buf_attach(buf->dma_bufs[i], dev->dev); if (IS_ERR(attachment)) { ret = PTR_ERR(attachment); - dev_err(&dev->base.dev, "attaching plane %u failed: %d\n", + dev_err(&dev->base.dev, "attaching plane %zu failed: %d\n", i, ret); goto done; } @@ -292,12 +292,13 @@ static int adf_buffer_map(struct adf_device *dev, struct adf_buffer *buf, sg_table = dma_buf_map_attachment(attachment, DMA_TO_DEVICE); if (IS_ERR(sg_table)) { ret = PTR_ERR(sg_table); - dev_err(&dev->base.dev, "mapping plane %u failed: %d", + dev_err(&dev->base.dev, "mapping plane %zu failed: %d", i, ret); goto done; } else if (!sg_table) { ret = -ENOMEM; - dev_err(&dev->base.dev, "mapping plane %u failed\n", i); + dev_err(&dev->base.dev, "mapping plane %zu failed\n", + i); goto done; } mapping->sg_tables[i] = sg_table; diff --git a/drivers/video/adf/adf_fops32.c b/drivers/video/adf/adf_fops32.c index 60a47cf5a781..d299a8161491 100644 --- a/drivers/video/adf/adf_fops32.c +++ b/drivers/video/adf/adf_fops32.c @@ -81,7 +81,7 @@ long adf_compat_get_device_data(struct file *file, &data->custom_data)) return -EFAULT; - ret = adf_file_ioctl(file, ADF_GET_DEVICE_DATA32, (unsigned long)data); + ret = adf_file_ioctl(file, ADF_GET_DEVICE_DATA, (unsigned long)data); if (ret < 0) return ret; @@ -122,7 +122,7 @@ long adf_compat_get_interface_data(struct file *file, &data->custom_data)) return -EFAULT; - ret = adf_file_ioctl(file, ADF_GET_DEVICE_DATA32, (unsigned long)data); + ret = adf_file_ioctl(file, ADF_GET_INTERFACE_DATA, (unsigned long)data); if (ret < 0) return ret; diff --git a/drivers/video/adf/adf_fops32.h b/drivers/video/adf/adf_fops32.h index 18c673dc5e2e..53d43f010208 100644 --- a/drivers/video/adf/adf_fops32.h +++ b/drivers/video/adf/adf_fops32.h @@ -7,13 +7,13 @@ #include <video/adf.h> #define ADF_POST_CONFIG32 \ - _IOW('D', 2, struct adf_post_config32) + _IOW(ADF_IOCTL_TYPE, 2, struct adf_post_config32) #define ADF_GET_DEVICE_DATA32 \ - _IOR('D', 4, struct adf_device_data32) + _IOR(ADF_IOCTL_TYPE, 4, struct adf_device_data32) #define ADF_GET_INTERFACE_DATA32 \ - _IOR('D', 5, struct adf_interface_data32) + _IOR(ADF_IOCTL_TYPE, 5, struct adf_interface_data32) #define ADF_GET_OVERLAY_ENGINE_DATA32 \ - _IOR('D', 6, struct adf_overlay_engine_data32) + _IOR(ADF_IOCTL_TYPE, 6, struct adf_overlay_engine_data32) struct adf_post_config32 { compat_size_t n_interfaces; |