diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-24 12:47:33 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-24 12:47:33 -0800 |
commit | 693fed981eb9bf6e70bfda66bb872e2bb8155671 (patch) | |
tree | f37b03fde9901e75fa77d6943ee54b29f9064f53 /drivers/android | |
parent | 0601f25d1c4937c678db786961705ce56fbd6bb6 (diff) | |
parent | 6ec363fc6142226b9ab5a6528f65333d729d2b6b (diff) |
Merge tag 'char-misc-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc and other driver subsystem updates from Greg KH:
"Here is the large set of driver changes for char/misc drivers and
other smaller driver subsystems that flow through this git tree.
Included in here are:
- New IIO drivers and features and improvments in that subsystem
- New hwtracing drivers and additions to that subsystem
- lots of interconnect changes and new drivers as that subsystem
seems under very active development recently. This required also
merging in the icc subsystem changes through this tree.
- FPGA driver updates
- counter subsystem and driver updates
- MHI driver updates
- nvmem driver updates
- documentation updates
- Other smaller driver updates and fixes, full details in the
shortlog
All of these have been in linux-next for a while with no reported
problems"
* tag 'char-misc-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (223 commits)
scripts/tags.sh: fix incompatibility with PCRE2
firmware: coreboot: Remove GOOGLE_COREBOOT_TABLE_ACPI/OF Kconfig entries
mei: lower the log level for non-fatal failed messages
mei: bus: disallow driver match while dismantling device
misc: vmw_balloon: fix memory leak with using debugfs_lookup()
nvmem: stm32: fix OPTEE dependency
dt-bindings: nvmem: qfprom: add IPQ8074 compatible
nvmem: qcom-spmi-sdam: register at device init time
nvmem: rave-sp-eeprm: fix kernel-doc bad line warning
nvmem: stm32: detect bsec pta presence for STM32MP15x
nvmem: stm32: add OP-TEE support for STM32MP13x
nvmem: core: use nvmem_add_one_cell() in nvmem_add_cells_from_of()
nvmem: core: add nvmem_add_one_cell()
nvmem: core: drop the removal of the cells in nvmem_add_cells()
nvmem: core: move struct nvmem_cell_info to nvmem-provider.h
nvmem: core: add an index parameter to the cell
of: property: add #nvmem-cell-cells property
of: property: make #.*-cells optional for simple props
of: base: add of_parse_phandle_with_optional_args()
net: add helper eth_addr_add()
...
Diffstat (limited to 'drivers/android')
-rw-r--r-- | drivers/android/binder.c | 65 | ||||
-rw-r--r-- | drivers/android/binder_internal.h | 3 | ||||
-rw-r--r-- | drivers/android/binderfs.c | 4 |
3 files changed, 41 insertions, 31 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index cb08982b9666..fb56bfc45096 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -277,11 +277,11 @@ _binder_proc_lock(struct binder_proc *proc, int line) /** * binder_proc_unlock() - Release spinlock for given binder_proc - * @proc: struct binder_proc to acquire + * @proc: struct binder_proc to acquire * * Release lock acquired via binder_proc_lock() */ -#define binder_proc_unlock(_proc) _binder_proc_unlock(_proc, __LINE__) +#define binder_proc_unlock(proc) _binder_proc_unlock(proc, __LINE__) static void _binder_proc_unlock(struct binder_proc *proc, int line) __releases(&proc->outer_lock) @@ -378,7 +378,7 @@ _binder_node_inner_lock(struct binder_node *node, int line) } /** - * binder_node_unlock() - Release node and inner locks + * binder_node_inner_unlock() - Release node and inner locks * @node: struct binder_node to acquire * * Release lock acquired via binder_node_lock() @@ -1194,13 +1194,13 @@ static int binder_inc_ref_olocked(struct binder_ref *ref, int strong, } /** - * binder_dec_ref() - dec the ref for given handle + * binder_dec_ref_olocked() - dec the ref for given handle * @ref: ref to be decremented * @strong: if true, strong decrement, else weak * * Decrement the ref. * - * Return: true if ref is cleaned up and ready to be freed + * Return: %true if ref is cleaned up and ready to be freed. */ static bool binder_dec_ref_olocked(struct binder_ref *ref, int strong) { @@ -2728,7 +2728,10 @@ binder_find_outdated_transaction_ilocked(struct binder_transaction *t, * * Return: 0 if the transaction was successfully queued * BR_DEAD_REPLY if the target process or thread is dead - * BR_FROZEN_REPLY if the target process or thread is frozen + * BR_FROZEN_REPLY if the target process or thread is frozen and + * the sync transaction was rejected + * BR_TRANSACTION_PENDING_FROZEN if the target process is frozen + * and the async transaction was successfully queued */ static int binder_proc_transaction(struct binder_transaction *t, struct binder_proc *proc, @@ -2738,6 +2741,7 @@ static int binder_proc_transaction(struct binder_transaction *t, bool oneway = !!(t->flags & TF_ONE_WAY); bool pending_async = false; struct binder_transaction *t_outdated = NULL; + bool frozen = false; BUG_ON(!node); binder_node_lock(node); @@ -2751,15 +2755,16 @@ static int binder_proc_transaction(struct binder_transaction *t, binder_inner_proc_lock(proc); if (proc->is_frozen) { + frozen = true; proc->sync_recv |= !oneway; proc->async_recv |= oneway; } - if ((proc->is_frozen && !oneway) || proc->is_dead || + if ((frozen && !oneway) || proc->is_dead || (thread && thread->is_dead)) { binder_inner_proc_unlock(proc); binder_node_unlock(node); - return proc->is_frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY; + return frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY; } if (!thread && !pending_async) @@ -2770,7 +2775,7 @@ static int binder_proc_transaction(struct binder_transaction *t, } else if (!pending_async) { binder_enqueue_work_ilocked(&t->work, &proc->todo); } else { - if ((t->flags & TF_UPDATE_TXN) && proc->is_frozen) { + if ((t->flags & TF_UPDATE_TXN) && frozen) { t_outdated = binder_find_outdated_transaction_ilocked(t, &node->async_todo); if (t_outdated) { @@ -2807,14 +2812,17 @@ static int binder_proc_transaction(struct binder_transaction *t, binder_stats_deleted(BINDER_STAT_TRANSACTION); } + if (oneway && frozen) + return BR_TRANSACTION_PENDING_FROZEN; + return 0; } /** * binder_get_node_refs_for_txn() - Get required refs on node for txn * @node: struct binder_node for which to get refs - * @proc: returns @node->proc if valid - * @error: if no @proc then returns BR_DEAD_REPLY + * @procp: returns @node->proc if valid + * @error: if no @procp then returns BR_DEAD_REPLY * * User-space normally keeps the node alive when creating a transaction * since it has a reference to the target. The local strong ref keeps it @@ -2828,8 +2836,8 @@ static int binder_proc_transaction(struct binder_transaction *t, * constructing the transaction, so we take that here as well. * * Return: The target_node with refs taken or NULL if no @node->proc is NULL. - * Also sets @proc if valid. If the @node->proc is NULL indicating that the - * target proc has died, @error is set to BR_DEAD_REPLY + * Also sets @procp if valid. If the @node->proc is NULL indicating that the + * target proc has died, @error is set to BR_DEAD_REPLY. */ static struct binder_node *binder_get_node_refs_for_txn( struct binder_node *node, @@ -3607,9 +3615,17 @@ static void binder_transaction(struct binder_proc *proc, } else { BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); - binder_enqueue_thread_work(thread, tcomplete); return_error = binder_proc_transaction(t, target_proc, NULL); - if (return_error) + /* + * Let the caller know when async transaction reaches a frozen + * process and is put in a pending queue, waiting for the target + * process to be unfrozen. + */ + if (return_error == BR_TRANSACTION_PENDING_FROZEN) + tcomplete->type = BINDER_WORK_TRANSACTION_PENDING; + binder_enqueue_thread_work(thread, tcomplete); + if (return_error && + return_error != BR_TRANSACTION_PENDING_FROZEN) goto err_dead_proc_or_thread; } if (target_thread) @@ -4440,10 +4456,13 @@ retry: binder_stat_br(proc, thread, cmd); } break; case BINDER_WORK_TRANSACTION_COMPLETE: + case BINDER_WORK_TRANSACTION_PENDING: case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: { if (proc->oneway_spam_detection_enabled && w->type == BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT) cmd = BR_ONEWAY_SPAM_SUSPECT; + else if (w->type == BINDER_WORK_TRANSACTION_PENDING) + cmd = BR_TRANSACTION_PENDING_FROZEN; else cmd = BR_TRANSACTION_COMPLETE; binder_inner_proc_unlock(proc); @@ -5006,20 +5025,14 @@ static __poll_t binder_poll(struct file *filp, return 0; } -static int binder_ioctl_write_read(struct file *filp, - unsigned int cmd, unsigned long arg, +static int binder_ioctl_write_read(struct file *filp, unsigned long arg, struct binder_thread *thread) { int ret = 0; struct binder_proc *proc = filp->private_data; - unsigned int size = _IOC_SIZE(cmd); void __user *ubuf = (void __user *)arg; struct binder_write_read bwr; - if (size != sizeof(struct binder_write_read)) { - ret = -EINVAL; - goto out; - } if (copy_from_user(&bwr, ubuf, sizeof(bwr))) { ret = -EFAULT; goto out; @@ -5296,7 +5309,6 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) int ret; struct binder_proc *proc = filp->private_data; struct binder_thread *thread; - unsigned int size = _IOC_SIZE(cmd); void __user *ubuf = (void __user *)arg; /*pr_info("binder_ioctl: %d:%d %x %lx\n", @@ -5318,7 +5330,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) switch (cmd) { case BINDER_WRITE_READ: - ret = binder_ioctl_write_read(filp, cmd, arg, thread); + ret = binder_ioctl_write_read(filp, arg, thread); if (ret) goto err; break; @@ -5361,10 +5373,6 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 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, &ver->protocol_version)) { ret = -EINVAL; @@ -6169,6 +6177,7 @@ static const char * const binder_return_strings[] = { "BR_FAILED_REPLY", "BR_FROZEN_REPLY", "BR_ONEWAY_SPAM_SUSPECT", + "BR_TRANSACTION_PENDING_FROZEN" }; static const char * const binder_command_strings[] = { diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index abe19d88c6ec..28ef5b3704b1 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -133,7 +133,7 @@ enum binder_stat_types { }; struct binder_stats { - atomic_t br[_IOC_NR(BR_ONEWAY_SPAM_SUSPECT) + 1]; + atomic_t br[_IOC_NR(BR_TRANSACTION_PENDING_FROZEN) + 1]; atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1]; atomic_t obj_created[BINDER_STAT_COUNT]; atomic_t obj_deleted[BINDER_STAT_COUNT]; @@ -152,6 +152,7 @@ struct binder_work { enum binder_work_type { BINDER_WORK_TRANSACTION = 1, BINDER_WORK_TRANSACTION_COMPLETE, + BINDER_WORK_TRANSACTION_PENDING, BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT, BINDER_WORK_RETURN_ERROR, BINDER_WORK_NODE, diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c index 348d63d1e3d3..76e7d6676657 100644 --- a/drivers/android/binderfs.c +++ b/drivers/android/binderfs.c @@ -222,14 +222,14 @@ err: } /** - * binderfs_ctl_ioctl - handle binder device node allocation requests + * binder_ctl_ioctl - handle binder device node allocation requests * * The request handler for the binder-control device. All requests operate on * the binderfs mount the binder-control device resides in: * - BINDER_CTL_ADD * Allocate a new binder device. * - * Return: 0 on success, negative errno on failure + * Return: %0 on success, negative errno on failure. */ static long binder_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |