mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-14 08:36:12 -04:00
Merge 9ac5330952 on remote branch
Change-Id: I2bc2c0c1648f02c8ff789668d059648935202501
This commit is contained in:
commit
cda32b0480
97 changed files with 2684 additions and 1040 deletions
|
|
@ -1 +1 @@
|
|||
LTS_5.4.147_e785a25f5262
|
||||
LTS_5.4.147_983a7e7c981b
|
||||
|
|
|
|||
4
arch/arm/configs/vendor/sdxlemur.config
vendored
4
arch/arm/configs/vendor/sdxlemur.config
vendored
|
|
@ -208,10 +208,11 @@ CONFIG_USB_LINK_LAYER_TEST=y
|
|||
CONFIG_USB_GADGET_VBUS_DRAW=900
|
||||
CONFIG_SPMI=y
|
||||
CONFIG_HW_RANDOM_MSM_LEGACY=y
|
||||
CONFIG_CRYPTO_SHA512=y
|
||||
CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
|
||||
CONFIG_CRYPTO_DEV_QCRYPTO=y
|
||||
CONFIG_CRYPTO_DEV_QCEDEV=y
|
||||
CONIFG_CRYPTO_CTR=y
|
||||
CONFIG_CRYPTO_CTR=y
|
||||
CONFIG_MFD_I2C_PMIC=y
|
||||
CONFIG_MFD_SPMI_PMIC=y
|
||||
CONFIG_SPMI_MSM_PMIC_ARB=y
|
||||
|
|
@ -378,3 +379,4 @@ CONFIG_DRM=y
|
|||
CONFIG_GKI_HIDDEN_DRM_CONFIGS=y
|
||||
CONFIG_SDX_EXT_IPC=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_MACSEC=y
|
||||
|
|
|
|||
|
|
@ -198,12 +198,10 @@ CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
|
|||
# CONFIG_HID_APPLE is not set
|
||||
# CONFIG_HID_BELKIN is not set
|
||||
# CONFIG_HID_CHERRY is not set
|
||||
# CONFIG_HID_CHICONY is not set
|
||||
# CONFIG_HID_CYPRESS is not set
|
||||
# CONFIG_HID_EZKEY is not set
|
||||
# CONFIG_HID_ITE is not set
|
||||
# CONFIG_HID_KENSINGTON is not set
|
||||
# CONFIG_HID_LOGITECH is not set
|
||||
# CONFIG_HID_REDRAGON is not set
|
||||
# CONFIG_HID_MICROSOFT is not set
|
||||
# CONFIG_HID_MONTEREY is not set
|
||||
|
|
|
|||
|
|
@ -1644,6 +1644,12 @@ static void binder_free_transaction(struct binder_transaction *t)
|
|||
|
||||
if (target_proc) {
|
||||
binder_inner_proc_lock(target_proc);
|
||||
target_proc->outstanding_txns--;
|
||||
if (target_proc->outstanding_txns < 0)
|
||||
pr_warn("%s: Unexpected outstanding_txns %d\n",
|
||||
__func__, target_proc->outstanding_txns);
|
||||
if (!target_proc->outstanding_txns && target_proc->is_frozen)
|
||||
wake_up_interruptible_all(&target_proc->freeze_wait);
|
||||
if (t->buffer)
|
||||
t->buffer->transaction = NULL;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
|
|
@ -2185,7 +2191,8 @@ static int binder_translate_binder(struct flat_binder_object *fp,
|
|||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
|
||||
if (security_binder_transfer_binder(binder_get_cred(proc),
|
||||
binder_get_cred(target_proc))) {
|
||||
ret = -EPERM;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -2231,7 +2238,8 @@ static int binder_translate_handle(struct flat_binder_object *fp,
|
|||
proc->pid, thread->pid, fp->handle);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
|
||||
if (security_binder_transfer_binder(binder_get_cred(proc),
|
||||
binder_get_cred(target_proc))) {
|
||||
ret = -EPERM;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -2319,7 +2327,8 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
|
|||
ret = -EBADF;
|
||||
goto err_fget;
|
||||
}
|
||||
ret = security_binder_transfer_file(proc->tsk, target_proc->tsk, file);
|
||||
ret = security_binder_transfer_file(binder_get_cred(proc),
|
||||
binder_get_cred(target_proc), file);
|
||||
if (ret < 0) {
|
||||
ret = -EPERM;
|
||||
goto err_security;
|
||||
|
|
@ -2475,10 +2484,11 @@ static int binder_fixup_parent(struct binder_transaction *t,
|
|||
* If the @thread parameter is not NULL, the transaction is always queued
|
||||
* to the waitlist of that specific thread.
|
||||
*
|
||||
* Return: true if the transactions was successfully queued
|
||||
* false if the target process or thread is dead
|
||||
* 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
|
||||
*/
|
||||
static bool binder_proc_transaction(struct binder_transaction *t,
|
||||
static int binder_proc_transaction(struct binder_transaction *t,
|
||||
struct binder_proc *proc,
|
||||
struct binder_thread *thread)
|
||||
{
|
||||
|
|
@ -2502,11 +2512,16 @@ static bool binder_proc_transaction(struct binder_transaction *t,
|
|||
}
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
if (proc->is_frozen) {
|
||||
proc->sync_recv |= !oneway;
|
||||
proc->async_recv |= oneway;
|
||||
}
|
||||
|
||||
if (proc->is_dead || (thread && thread->is_dead)) {
|
||||
if ((proc->is_frozen && !oneway) || proc->is_dead ||
|
||||
(thread && thread->is_dead)) {
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_unlock(node);
|
||||
return false;
|
||||
return proc->is_frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY;
|
||||
}
|
||||
|
||||
if (!thread && !pending_async)
|
||||
|
|
@ -2525,10 +2540,11 @@ static bool binder_proc_transaction(struct binder_transaction *t,
|
|||
if (!pending_async)
|
||||
binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */);
|
||||
|
||||
proc->outstanding_txns++;
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_unlock(node);
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2718,8 +2734,8 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
goto err_dead_binder;
|
||||
}
|
||||
e->to_node = target_node->debug_id;
|
||||
if (security_binder_transaction(proc->tsk,
|
||||
target_proc->tsk) < 0) {
|
||||
if (security_binder_transaction(binder_get_cred(proc),
|
||||
binder_get_cred(target_proc)) < 0) {
|
||||
return_error = BR_FAILED_REPLY;
|
||||
return_error_param = -EPERM;
|
||||
return_error_line = __LINE__;
|
||||
|
|
@ -2854,7 +2870,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
u32 secid;
|
||||
size_t added_size;
|
||||
|
||||
security_task_getsecid(proc->tsk, &secid);
|
||||
security_cred_getsecid(binder_get_cred(proc), &secid);
|
||||
ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
|
||||
if (ret) {
|
||||
return_error = BR_FAILED_REPLY;
|
||||
|
|
@ -3168,12 +3184,14 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
binder_enqueue_thread_work(thread, tcomplete);
|
||||
binder_inner_proc_lock(target_proc);
|
||||
if (target_thread->is_dead) {
|
||||
return_error = BR_DEAD_REPLY;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
goto err_dead_proc_or_thread;
|
||||
}
|
||||
BUG_ON(t->buffer->async_transaction != 0);
|
||||
binder_pop_transaction_ilocked(target_thread, in_reply_to);
|
||||
binder_enqueue_thread_work_ilocked(target_thread, &t->work);
|
||||
target_proc->outstanding_txns++;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
wake_up_interruptible_sync(&target_thread->wait);
|
||||
trace_android_vh_binder_restore_priority(in_reply_to, current);
|
||||
|
|
@ -3194,7 +3212,9 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
t->from_parent = thread->transaction_stack;
|
||||
thread->transaction_stack = t;
|
||||
binder_inner_proc_unlock(proc);
|
||||
if (!binder_proc_transaction(t, target_proc, target_thread)) {
|
||||
return_error = binder_proc_transaction(t,
|
||||
target_proc, target_thread);
|
||||
if (return_error) {
|
||||
binder_inner_proc_lock(proc);
|
||||
binder_pop_transaction_ilocked(thread, t);
|
||||
binder_inner_proc_unlock(proc);
|
||||
|
|
@ -3204,7 +3224,8 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
BUG_ON(target_node == NULL);
|
||||
BUG_ON(t->buffer->async_transaction != 1);
|
||||
binder_enqueue_thread_work(thread, tcomplete);
|
||||
if (!binder_proc_transaction(t, target_proc, NULL))
|
||||
return_error = binder_proc_transaction(t, target_proc, NULL);
|
||||
if (return_error)
|
||||
goto err_dead_proc_or_thread;
|
||||
}
|
||||
if (target_thread)
|
||||
|
|
@ -3221,7 +3242,6 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
return;
|
||||
|
||||
err_dead_proc_or_thread:
|
||||
return_error = BR_DEAD_REPLY;
|
||||
return_error_line = __LINE__;
|
||||
binder_dequeue_work(proc, tcomplete);
|
||||
err_translate_failed:
|
||||
|
|
@ -3846,7 +3866,7 @@ static int binder_wait_for_work(struct binder_thread *thread,
|
|||
binder_inner_proc_lock(proc);
|
||||
list_del_init(&thread->waiting_thread_node);
|
||||
if (signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
ret = -EINTR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -4451,9 +4471,14 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc)
|
|||
static void binder_free_proc(struct binder_proc *proc)
|
||||
{
|
||||
struct binder_device *device;
|
||||
struct binder_proc_ext *eproc =
|
||||
container_of(proc, struct binder_proc_ext, proc);
|
||||
|
||||
BUG_ON(!list_empty(&proc->todo));
|
||||
BUG_ON(!list_empty(&proc->delivered_death));
|
||||
if (proc->outstanding_txns)
|
||||
pr_warn("%s: Unexpected outstanding_txns %d\n",
|
||||
__func__, proc->outstanding_txns);
|
||||
device = container_of(proc->context, struct binder_device, context);
|
||||
if (refcount_dec_and_test(&device->ref)) {
|
||||
kfree(proc->context->name);
|
||||
|
|
@ -4461,8 +4486,9 @@ static void binder_free_proc(struct binder_proc *proc)
|
|||
}
|
||||
binder_alloc_deferred_release(&proc->alloc);
|
||||
put_task_struct(proc->tsk);
|
||||
put_cred(eproc->cred);
|
||||
binder_stats_deleted(BINDER_STAT_PROC);
|
||||
kfree(proc);
|
||||
kfree(eproc);
|
||||
}
|
||||
|
||||
static void binder_free_thread(struct binder_thread *thread)
|
||||
|
|
@ -4516,6 +4542,7 @@ static int binder_thread_release(struct binder_proc *proc,
|
|||
(t->to_thread == thread) ? "in" : "out");
|
||||
|
||||
if (t->to_thread == thread) {
|
||||
thread->proc->outstanding_txns--;
|
||||
t->to_proc = NULL;
|
||||
t->to_thread = NULL;
|
||||
if (t->buffer) {
|
||||
|
|
@ -4538,23 +4565,20 @@ static int binder_thread_release(struct binder_proc *proc,
|
|||
__release(&t->lock);
|
||||
|
||||
/*
|
||||
* If this thread used poll, make sure we remove the waitqueue
|
||||
* from any epoll data structures holding it with POLLFREE.
|
||||
* waitqueue_active() is safe to use here because we're holding
|
||||
* the inner lock.
|
||||
* If this thread used poll, make sure we remove the waitqueue from any
|
||||
* poll data structures holding it.
|
||||
*/
|
||||
if ((thread->looper & BINDER_LOOPER_STATE_POLL) &&
|
||||
waitqueue_active(&thread->wait)) {
|
||||
wake_up_poll(&thread->wait, EPOLLHUP | POLLFREE);
|
||||
}
|
||||
if (thread->looper & BINDER_LOOPER_STATE_POLL)
|
||||
wake_up_pollfree(&thread->wait);
|
||||
|
||||
binder_inner_proc_unlock(thread->proc);
|
||||
|
||||
/*
|
||||
* This is needed to avoid races between wake_up_poll() above and
|
||||
* and ep_remove_waitqueue() called for other reasons (eg the epoll file
|
||||
* descriptor being closed); ep_remove_waitqueue() holds an RCU read
|
||||
* lock, so we can be sure it's done after calling synchronize_rcu().
|
||||
* This is needed to avoid races between wake_up_pollfree() above and
|
||||
* someone else removing the last entry from the queue for other reasons
|
||||
* (e.g. ep_remove_wait_queue() being called due to an epoll file
|
||||
* descriptor being closed). Such other users hold an RCU read lock, so
|
||||
* we can be sure they're done after we call synchronize_rcu().
|
||||
*/
|
||||
if (thread->looper & BINDER_LOOPER_STATE_POLL)
|
||||
synchronize_rcu();
|
||||
|
|
@ -4672,7 +4696,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp,
|
|||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
ret = security_binder_set_context_mgr(proc->tsk);
|
||||
ret = security_binder_set_context_mgr(binder_get_cred(proc));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (uid_valid(context->binder_context_mgr_uid)) {
|
||||
|
|
@ -4766,6 +4790,100 @@ static int binder_ioctl_get_node_debug_info(struct binder_proc *proc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool binder_txns_pending_ilocked(struct binder_proc *proc)
|
||||
{
|
||||
struct rb_node *n;
|
||||
struct binder_thread *thread;
|
||||
|
||||
if (proc->outstanding_txns > 0)
|
||||
return true;
|
||||
|
||||
for (n = rb_first(&proc->threads); n; n = rb_next(n)) {
|
||||
thread = rb_entry(n, struct binder_thread, rb_node);
|
||||
if (thread->transaction_stack)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
||||
struct binder_proc *target_proc)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!info->enable) {
|
||||
binder_inner_proc_lock(target_proc);
|
||||
target_proc->sync_recv = false;
|
||||
target_proc->async_recv = false;
|
||||
target_proc->is_frozen = false;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Freezing the target. Prevent new transactions by
|
||||
* setting frozen state. If timeout specified, wait
|
||||
* for transactions to drain.
|
||||
*/
|
||||
binder_inner_proc_lock(target_proc);
|
||||
target_proc->sync_recv = false;
|
||||
target_proc->async_recv = false;
|
||||
target_proc->is_frozen = true;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
|
||||
if (info->timeout_ms > 0)
|
||||
ret = wait_event_interruptible_timeout(
|
||||
target_proc->freeze_wait,
|
||||
(!target_proc->outstanding_txns),
|
||||
msecs_to_jiffies(info->timeout_ms));
|
||||
|
||||
/* Check pending transactions that wait for reply */
|
||||
if (ret >= 0) {
|
||||
binder_inner_proc_lock(target_proc);
|
||||
if (binder_txns_pending_ilocked(target_proc))
|
||||
ret = -EAGAIN;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
binder_inner_proc_lock(target_proc);
|
||||
target_proc->is_frozen = false;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int binder_ioctl_get_freezer_info(
|
||||
struct binder_frozen_status_info *info)
|
||||
{
|
||||
struct binder_proc *target_proc;
|
||||
bool found = false;
|
||||
__u32 txns_pending;
|
||||
|
||||
info->sync_recv = 0;
|
||||
info->async_recv = 0;
|
||||
|
||||
mutex_lock(&binder_procs_lock);
|
||||
hlist_for_each_entry(target_proc, &binder_procs, proc_node) {
|
||||
if (target_proc->pid == info->pid) {
|
||||
found = true;
|
||||
binder_inner_proc_lock(target_proc);
|
||||
txns_pending = binder_txns_pending_ilocked(target_proc);
|
||||
info->sync_recv |= target_proc->sync_recv |
|
||||
(txns_pending << 1);
|
||||
info->async_recv |= target_proc->async_recv;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
|
||||
if (!found)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -4884,6 +5002,84 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case BINDER_FREEZE: {
|
||||
struct binder_freeze_info info;
|
||||
struct binder_proc **target_procs = NULL, *target_proc;
|
||||
int target_procs_count = 0, i = 0;
|
||||
|
||||
ret = 0;
|
||||
|
||||
if (copy_from_user(&info, ubuf, sizeof(info))) {
|
||||
ret = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
mutex_lock(&binder_procs_lock);
|
||||
hlist_for_each_entry(target_proc, &binder_procs, proc_node) {
|
||||
if (target_proc->pid == info.pid)
|
||||
target_procs_count++;
|
||||
}
|
||||
|
||||
if (target_procs_count == 0) {
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
target_procs = kcalloc(target_procs_count,
|
||||
sizeof(struct binder_proc *),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!target_procs) {
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
hlist_for_each_entry(target_proc, &binder_procs, proc_node) {
|
||||
if (target_proc->pid != info.pid)
|
||||
continue;
|
||||
|
||||
binder_inner_proc_lock(target_proc);
|
||||
target_proc->tmp_ref++;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
|
||||
target_procs[i++] = target_proc;
|
||||
}
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
|
||||
for (i = 0; i < target_procs_count; i++) {
|
||||
if (ret >= 0)
|
||||
ret = binder_ioctl_freeze(&info,
|
||||
target_procs[i]);
|
||||
|
||||
binder_proc_dec_tmpref(target_procs[i]);
|
||||
}
|
||||
|
||||
kfree(target_procs);
|
||||
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
case BINDER_GET_FROZEN_INFO: {
|
||||
struct binder_frozen_status_info info;
|
||||
|
||||
if (copy_from_user(&info, ubuf, sizeof(info))) {
|
||||
ret = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = binder_ioctl_get_freezer_info(&info);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
if (copy_to_user(ubuf, &info, sizeof(info))) {
|
||||
ret = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
|
|
@ -4893,7 +5089,7 @@ err:
|
|||
if (thread)
|
||||
thread->looper_need_return = false;
|
||||
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
|
||||
if (ret && ret != -ERESTARTSYS)
|
||||
if (ret && ret != -EINTR)
|
||||
pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
|
||||
err_unlocked:
|
||||
trace_binder_ioctl_done(ret);
|
||||
|
|
@ -4974,6 +5170,7 @@ err_bad_arg:
|
|||
static int binder_open(struct inode *nodp, struct file *filp)
|
||||
{
|
||||
struct binder_proc *proc, *itr;
|
||||
struct binder_proc_ext *eproc;
|
||||
struct binder_device *binder_dev;
|
||||
struct binderfs_info *info;
|
||||
struct dentry *binder_binderfs_dir_entry_proc = NULL;
|
||||
|
|
@ -4982,14 +5179,17 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
|||
binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__,
|
||||
current->group_leader->pid, current->pid);
|
||||
|
||||
proc = kzalloc(sizeof(*proc), GFP_KERNEL);
|
||||
eproc = kzalloc(sizeof(*eproc), GFP_KERNEL);
|
||||
proc = &eproc->proc;
|
||||
if (proc == NULL)
|
||||
return -ENOMEM;
|
||||
spin_lock_init(&proc->inner_lock);
|
||||
spin_lock_init(&proc->outer_lock);
|
||||
get_task_struct(current->group_leader);
|
||||
proc->tsk = current->group_leader;
|
||||
eproc->cred = get_cred(filp->f_cred);
|
||||
INIT_LIST_HEAD(&proc->todo);
|
||||
init_waitqueue_head(&proc->freeze_wait);
|
||||
if (binder_supported_policy(current->policy)) {
|
||||
proc->default_priority.sched_policy = current->policy;
|
||||
proc->default_priority.prio = current->normal_prio;
|
||||
|
|
@ -5209,6 +5409,9 @@ static void binder_deferred_release(struct binder_proc *proc)
|
|||
proc->tmp_ref++;
|
||||
|
||||
proc->is_dead = true;
|
||||
proc->is_frozen = false;
|
||||
proc->sync_recv = false;
|
||||
proc->async_recv = false;
|
||||
threads = 0;
|
||||
active_transactions = 0;
|
||||
while ((n = rb_first(&proc->threads))) {
|
||||
|
|
|
|||
|
|
@ -388,9 +388,24 @@ struct binder_priority {
|
|||
* (protected by binder_deferred_lock)
|
||||
* @deferred_work: bitmap of deferred work to perform
|
||||
* (protected by binder_deferred_lock)
|
||||
* @outstanding_txns: number of transactions to be transmitted before
|
||||
* processes in freeze_wait are woken up
|
||||
* (protected by @inner_lock)
|
||||
* @is_dead: process is dead and awaiting free
|
||||
* when outstanding transactions are cleaned up
|
||||
* (protected by @inner_lock)
|
||||
* @is_frozen: process is frozen and unable to service
|
||||
* binder transactions
|
||||
* (protected by @inner_lock)
|
||||
* @sync_recv: process received sync transactions since last frozen
|
||||
* bit 0: received sync transaction after being frozen
|
||||
* bit 1: new pending sync transaction during freezing
|
||||
* (protected by @inner_lock)
|
||||
* @async_recv: process received async transactions since last frozen
|
||||
* (protected by @inner_lock)
|
||||
* @freeze_wait: waitqueue of processes waiting for all outstanding
|
||||
* transactions to be processed
|
||||
* (protected by @inner_lock)
|
||||
* @todo: list of work for this process
|
||||
* (protected by @inner_lock)
|
||||
* @stats: per-process binder statistics
|
||||
|
|
@ -431,7 +446,12 @@ struct binder_proc {
|
|||
struct task_struct *tsk;
|
||||
struct hlist_node deferred_work_node;
|
||||
int deferred_work;
|
||||
int outstanding_txns;
|
||||
bool is_dead;
|
||||
bool is_frozen;
|
||||
bool sync_recv;
|
||||
bool async_recv;
|
||||
wait_queue_head_t freeze_wait;
|
||||
|
||||
struct list_head todo;
|
||||
struct binder_stats stats;
|
||||
|
|
@ -449,6 +469,29 @@ struct binder_proc {
|
|||
struct dentry *binderfs_entry;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct binder_proc_ext - binder process bookkeeping
|
||||
* @proc: element for binder_procs list
|
||||
* @cred struct cred associated with the `struct file`
|
||||
* in binder_open()
|
||||
* (invariant after initialized)
|
||||
*
|
||||
* Extended binder_proc -- needed to add the "cred" field without
|
||||
* changing the KMI for binder_proc.
|
||||
*/
|
||||
struct binder_proc_ext {
|
||||
struct binder_proc proc;
|
||||
const struct cred *cred;
|
||||
};
|
||||
|
||||
static inline const struct cred *binder_get_cred(struct binder_proc *proc)
|
||||
{
|
||||
struct binder_proc_ext *eproc;
|
||||
|
||||
eproc = container_of(proc, struct binder_proc_ext, proc);
|
||||
return eproc->cred;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct binder_thread - binder thread bookkeeping
|
||||
* @proc: binder process for this thread
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/debugfs.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/btpower.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
|
@ -21,8 +22,13 @@
|
|||
#include "btfm_slim.h"
|
||||
#include "btfm_slim_slave.h"
|
||||
|
||||
#define BT_CMD_SLIM_TEST 0xbfac
|
||||
#define DELAY_FOR_PORT_OPEN_MS (200)
|
||||
|
||||
struct class *btfm_slim_class;
|
||||
static int btfm_slim_major;
|
||||
struct btfmslim *btfm_slim_drv_data;
|
||||
|
||||
static bool btfm_is_port_opening_delayed = true;
|
||||
|
||||
int btfm_slim_write(struct btfmslim *btfmslim,
|
||||
|
|
@ -612,6 +618,25 @@ static int btfm_slim_get_dt_info(struct btfmslim *btfmslim)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static long btfm_slim_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
BTFMSLIM_INFO("");
|
||||
switch (cmd) {
|
||||
case BT_CMD_SLIM_TEST:
|
||||
BTFMSLIM_INFO("cmd BT_CMD_SLIM_TEST, call btfm_slim_hw_init");
|
||||
ret = btfm_slim_hw_init(btfm_slim_drv_data);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations bt_dev_fops = {
|
||||
.unlocked_ioctl = btfm_slim_ioctl,
|
||||
.compat_ioctl = btfm_slim_ioctl,
|
||||
};
|
||||
|
||||
static int btfm_slim_probe(struct slim_device *slim)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -668,7 +693,36 @@ static int btfm_slim_probe(struct slim_device *slim)
|
|||
btfm_slim_unregister_codec(&slim->dev);
|
||||
goto free;
|
||||
}
|
||||
|
||||
btfm_slim_drv_data = btfm_slim;
|
||||
btfm_slim_major = register_chrdev(0, "btfm_slim", &bt_dev_fops);
|
||||
if (btfm_slim_major < 0) {
|
||||
BTFMSLIM_ERR("%s: failed to allocate char dev\n", __func__);
|
||||
ret = -1;
|
||||
goto register_err;
|
||||
}
|
||||
|
||||
btfm_slim_class = class_create(THIS_MODULE, "btfmslim-dev");
|
||||
if (IS_ERR(btfm_slim_class)) {
|
||||
BTFMSLIM_ERR("%s: coudn't create class\n", __func__);
|
||||
ret = -1;
|
||||
goto class_err;
|
||||
}
|
||||
|
||||
if (device_create(btfm_slim_class, NULL, MKDEV(btfm_slim_major, 0),
|
||||
NULL, "btfmslim") == NULL) {
|
||||
BTFMSLIM_ERR("%s: failed to allocate char dev\n", __func__);
|
||||
ret = -1;
|
||||
goto device_err;
|
||||
}
|
||||
return ret;
|
||||
|
||||
device_err:
|
||||
class_destroy(btfm_slim_class);
|
||||
class_err:
|
||||
unregister_chrdev(btfm_slim_major, "btfm_slim");
|
||||
register_err:
|
||||
btfm_slim_unregister_codec(&slim->dev);
|
||||
free:
|
||||
slim_remove_device(&btfm_slim->slim_ifd);
|
||||
dealloc:
|
||||
|
|
|
|||
|
|
@ -23,12 +23,10 @@
|
|||
|
||||
static DEFINE_VDD_REGULATORS(vdd_cx, VDD_HIGH_L1 + 1, 1, vdd_corner);
|
||||
static DEFINE_VDD_REGULATORS(vdd_mx, VDD_HIGH_L1 + 1, 1, vdd_corner);
|
||||
static DEFINE_VDD_REGULATORS(vdd_gx, VDD_HIGH_L1 + 1, 1, vdd_corner);
|
||||
static DEFINE_VDD_REGULATORS(vdd_gx, VDD_NUM, 2, vdd_gx_corner);
|
||||
|
||||
static struct clk_vdd_class *gpu_cc_blair_regulators[] = {
|
||||
&vdd_cx,
|
||||
&vdd_mx,
|
||||
&vdd_gx,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -468,6 +466,22 @@ static int gpu_cc_blair_probe(struct platform_device *pdev)
|
|||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
vdd_gx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_gx");
|
||||
if (IS_ERR(vdd_gx.regulator[0])) {
|
||||
if (!(PTR_ERR(vdd_gx.regulator[0]) == -EPROBE_DEFER))
|
||||
dev_err(&pdev->dev, "Unable to get vdd_gx regulator\n");
|
||||
return PTR_ERR(vdd_gx.regulator[0]);
|
||||
}
|
||||
|
||||
vdd_gx.regulator[1] = devm_regulator_get(&pdev->dev, "vdd_cx");
|
||||
if (IS_ERR(vdd_gx.regulator[1])) {
|
||||
if (!(PTR_ERR(vdd_gx.regulator[1]) == -EPROBE_DEFER))
|
||||
dev_err(&pdev->dev, "Unable to get vdd_cx regulator\n");
|
||||
return PTR_ERR(vdd_gx.regulator[1]);
|
||||
}
|
||||
|
||||
vdd_cx.regulator[0] = vdd_gx.regulator[1];
|
||||
|
||||
regmap = qcom_cc_map(pdev, &gpu_cc_blair_desc);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
|
|
|||
|
|
@ -32,4 +32,17 @@ static int vdd_corner[] = {
|
|||
[VDD_HIGH_L1] = RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR,
|
||||
};
|
||||
|
||||
|
||||
static int vdd_gx_corner[] = {
|
||||
0, 0,
|
||||
RPM_SMD_REGULATOR_LEVEL_MIN_SVS, RPM_SMD_REGULATOR_LEVEL_MIN_SVS,
|
||||
RPM_SMD_REGULATOR_LEVEL_LOW_SVS, RPM_SMD_REGULATOR_LEVEL_LOW_SVS,
|
||||
RPM_SMD_REGULATOR_LEVEL_SVS, RPM_SMD_REGULATOR_LEVEL_SVS,
|
||||
RPM_SMD_REGULATOR_LEVEL_SVS_PLUS, RPM_SMD_REGULATOR_LEVEL_SVS_PLUS,
|
||||
RPM_SMD_REGULATOR_LEVEL_NOM, RPM_SMD_REGULATOR_LEVEL_NOM,
|
||||
RPM_SMD_REGULATOR_LEVEL_NOM_PLUS, RPM_SMD_REGULATOR_LEVEL_NOM_PLUS,
|
||||
RPM_SMD_REGULATOR_LEVEL_TURBO, RPM_SMD_REGULATOR_LEVEL_TURBO,
|
||||
RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR, RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -206,14 +206,14 @@ config HID_CHERRY
|
|||
|
||||
config HID_CHICONY
|
||||
tristate "Chicony devices"
|
||||
depends on HID
|
||||
depends on USB_HID
|
||||
default !EXPERT
|
||||
---help---
|
||||
Support for Chicony Tactical pad and special keys on Chicony keyboards.
|
||||
|
||||
config HID_CORSAIR
|
||||
tristate "Corsair devices"
|
||||
depends on HID && USB && LEDS_CLASS
|
||||
depends on USB_HID && LEDS_CLASS
|
||||
---help---
|
||||
Support for Corsair devices that are not fully compliant with the
|
||||
HID standard.
|
||||
|
|
@ -244,7 +244,7 @@ config HID_MACALLY
|
|||
|
||||
config HID_PRODIKEYS
|
||||
tristate "Prodikeys PC-MIDI Keyboard support"
|
||||
depends on HID && SND
|
||||
depends on USB_HID && SND
|
||||
select SND_RAWMIDI
|
||||
---help---
|
||||
Support for Prodikeys PC-MIDI Keyboard device support.
|
||||
|
|
@ -524,7 +524,7 @@ config HID_LENOVO
|
|||
|
||||
config HID_LOGITECH
|
||||
tristate "Logitech devices"
|
||||
depends on HID
|
||||
depends on USB_HID
|
||||
default !EXPERT
|
||||
---help---
|
||||
Support for Logitech devices that are not fully compliant with HID standard.
|
||||
|
|
@ -900,7 +900,7 @@ config HID_SAITEK
|
|||
|
||||
config HID_SAMSUNG
|
||||
tristate "Samsung InfraRed remote control or keyboards"
|
||||
depends on HID
|
||||
depends on USB_HID
|
||||
---help---
|
||||
Support for Samsung InfraRed remote control or keyboards.
|
||||
|
||||
|
|
|
|||
|
|
@ -849,7 +849,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
if (drvdata->quirks & QUIRK_IS_MULTITOUCH)
|
||||
drvdata->tp = &asus_i2c_tp;
|
||||
|
||||
if (drvdata->quirks & QUIRK_T100_KEYBOARD) {
|
||||
if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && hid_is_usb(hdev)) {
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
|
||||
if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) {
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ static void bigben_worker(struct work_struct *work)
|
|||
struct bigben_device, worker);
|
||||
struct hid_field *report_field = bigben->report->field[0];
|
||||
|
||||
if (bigben->removed)
|
||||
if (bigben->removed || !report_field)
|
||||
return;
|
||||
|
||||
if (bigben->work_led) {
|
||||
|
|
|
|||
|
|
@ -58,8 +58,12 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
unsigned int *rsize)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
|
||||
struct usb_interface *intf;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return rdesc;
|
||||
|
||||
intf = to_usb_interface(hdev->dev.parent);
|
||||
if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
|
||||
/* Change usage maximum and logical maximum from 0x7fff to
|
||||
* 0x2fff, so they don't exceed HID_MAX_USAGES */
|
||||
|
|
|
|||
|
|
@ -553,7 +553,12 @@ static int corsair_probe(struct hid_device *dev, const struct hid_device_id *id)
|
|||
int ret;
|
||||
unsigned long quirks = id->driver_data;
|
||||
struct corsair_drvdata *drvdata;
|
||||
struct usb_interface *usbif = to_usb_interface(dev->dev.parent);
|
||||
struct usb_interface *usbif;
|
||||
|
||||
if (!hid_is_usb(dev))
|
||||
return -EINVAL;
|
||||
|
||||
usbif = to_usb_interface(dev->dev.parent);
|
||||
|
||||
drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata),
|
||||
GFP_KERNEL);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ struct elan_drvdata {
|
|||
|
||||
static int is_not_elan_touchpad(struct hid_device *hdev)
|
||||
{
|
||||
if (hdev->bus == BUS_USB) {
|
||||
if (hid_is_usb(hdev)) {
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
|
||||
return (intf->altsetting->desc.bInterfaceNumber !=
|
||||
|
|
|
|||
|
|
@ -229,6 +229,9 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
struct elo_priv *priv;
|
||||
int ret;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -140,12 +140,17 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type,
|
|||
static int holtek_kbd_probe(struct hid_device *hdev,
|
||||
const struct hid_device_id *id)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
int ret = hid_parse(hdev);
|
||||
struct usb_interface *intf;
|
||||
int ret;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (!ret)
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
|
||||
intf = to_usb_interface(hdev->dev.parent);
|
||||
if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) {
|
||||
struct hid_input *hidinput;
|
||||
list_for_each_entry(hidinput, &hdev->inputs, list) {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,14 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
return rdesc;
|
||||
}
|
||||
|
||||
static int holtek_mouse_probe(struct hid_device *hdev,
|
||||
const struct hid_device_id *id)
|
||||
{
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hid_device_id holtek_mouse_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
|
||||
USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
|
||||
|
|
@ -83,6 +91,7 @@ static struct hid_driver holtek_mouse_driver = {
|
|||
.name = "holtek_mouse",
|
||||
.id_table = holtek_mouse_devices,
|
||||
.report_fixup = holtek_mouse_report_fixup,
|
||||
.probe = holtek_mouse_probe,
|
||||
};
|
||||
|
||||
module_hid_driver(holtek_mouse_driver);
|
||||
|
|
|
|||
|
|
@ -769,12 +769,18 @@ static int lg_raw_event(struct hid_device *hdev, struct hid_report *report,
|
|||
|
||||
static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
|
||||
__u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
|
||||
struct usb_interface *iface;
|
||||
__u8 iface_num;
|
||||
unsigned int connect_mask = HID_CONNECT_DEFAULT;
|
||||
struct lg_drv_data *drv_data;
|
||||
int ret;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
iface = to_usb_interface(hdev->dev.parent);
|
||||
iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
|
||||
|
||||
/* G29 only work with the 1st interface */
|
||||
if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) &&
|
||||
(iface_num != 0)) {
|
||||
|
|
|
|||
|
|
@ -1686,7 +1686,7 @@ static int logi_dj_probe(struct hid_device *hdev,
|
|||
case recvr_type_27mhz: no_dj_interfaces = 2; break;
|
||||
case recvr_type_bluetooth: no_dj_interfaces = 2; break;
|
||||
}
|
||||
if (hid_is_using_ll_driver(hdev, &usb_hid_driver)) {
|
||||
if (hid_is_usb(hdev)) {
|
||||
intf = to_usb_interface(hdev->dev.parent);
|
||||
if (intf && intf->altsetting->desc.bInterfaceNumber >=
|
||||
no_dj_interfaces) {
|
||||
|
|
|
|||
|
|
@ -798,12 +798,18 @@ static int pk_raw_event(struct hid_device *hdev, struct hid_report *report,
|
|||
static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
|
||||
struct usb_interface *intf;
|
||||
unsigned short ifnum;
|
||||
unsigned long quirks = id->driver_data;
|
||||
struct pk_device *pk;
|
||||
struct pcmidi_snd *pm = NULL;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
intf = to_usb_interface(hdev->dev.parent);
|
||||
ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
|
||||
|
||||
pk = kzalloc(sizeof(*pk), GFP_KERNEL);
|
||||
if (pk == NULL) {
|
||||
hid_err(hdev, "can't alloc descriptor\n");
|
||||
|
|
|
|||
|
|
@ -344,6 +344,9 @@ static int arvo_probe(struct hid_device *hdev,
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
|
|
|
|||
|
|
@ -324,6 +324,9 @@ static int isku_probe(struct hid_device *hdev,
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
|
|
|
|||
|
|
@ -749,6 +749,9 @@ static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
|
|
|
|||
|
|
@ -431,6 +431,9 @@ static int koneplus_probe(struct hid_device *hdev,
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
|
|
|
|||
|
|
@ -133,6 +133,9 @@ static int konepure_probe(struct hid_device *hdev,
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
|
|
|
|||
|
|
@ -501,6 +501,9 @@ static int kovaplus_probe(struct hid_device *hdev,
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
|
|
|
|||
|
|
@ -160,6 +160,9 @@ static int lua_probe(struct hid_device *hdev,
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
|
|
|
|||
|
|
@ -449,6 +449,9 @@ static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
|
|
|
|||
|
|
@ -141,6 +141,9 @@ static int ryos_probe(struct hid_device *hdev,
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
|
|
|
|||
|
|
@ -113,6 +113,9 @@ static int savu_probe(struct hid_device *hdev,
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
retval = hid_parse(hdev);
|
||||
if (retval) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
|
|
|
|||
|
|
@ -152,6 +152,9 @@ static int samsung_probe(struct hid_device *hdev,
|
|||
int ret;
|
||||
unsigned int cmask = HID_CONNECT_DEFAULT;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
hid_err(hdev, "parse failed\n");
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ static int u2fzero_probe(struct hid_device *hdev,
|
|||
unsigned int minor;
|
||||
int ret;
|
||||
|
||||
if (!hid_is_using_ll_driver(hdev, &usb_hid_driver))
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);
|
||||
|
|
|
|||
|
|
@ -164,6 +164,9 @@ static int uclogic_probe(struct hid_device *hdev,
|
|||
struct uclogic_drvdata *drvdata = NULL;
|
||||
bool params_initialized = false;
|
||||
|
||||
if (!hid_is_usb(hdev))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* libinput requires the pad interface to be on a different node
|
||||
* than the pen, so use QUIRK_MULTI_INPUT for all tablets.
|
||||
|
|
|
|||
|
|
@ -841,8 +841,7 @@ int uclogic_params_init(struct uclogic_params *params,
|
|||
struct uclogic_params p = {0, };
|
||||
|
||||
/* Check arguments */
|
||||
if (params == NULL || hdev == NULL ||
|
||||
!hid_is_using_ll_driver(hdev, &usb_hid_driver)) {
|
||||
if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) {
|
||||
rc = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -726,7 +726,7 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev,
|
|||
* Skip the query for this type and modify defaults based on
|
||||
* interface number.
|
||||
*/
|
||||
if (features->type == WIRELESS) {
|
||||
if (features->type == WIRELESS && intf) {
|
||||
if (intf->cur_altsetting->desc.bInterfaceNumber == 0)
|
||||
features->device_type = WACOM_DEVICETYPE_WL_MONITOR;
|
||||
else
|
||||
|
|
@ -2217,7 +2217,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
|
|||
if ((features->type == HID_GENERIC) && !strcmp("Wacom HID", features->name)) {
|
||||
char *product_name = wacom->hdev->name;
|
||||
|
||||
if (hid_is_using_ll_driver(wacom->hdev, &usb_hid_driver)) {
|
||||
if (hid_is_usb(wacom->hdev)) {
|
||||
struct usb_interface *intf = to_usb_interface(wacom->hdev->dev.parent);
|
||||
struct usb_device *dev = interface_to_usbdev(intf);
|
||||
product_name = dev->product;
|
||||
|
|
@ -2448,6 +2448,9 @@ static void wacom_wireless_work(struct work_struct *work)
|
|||
|
||||
wacom_destroy_battery(wacom);
|
||||
|
||||
if (!usbdev)
|
||||
return;
|
||||
|
||||
/* Stylus interface */
|
||||
hdev1 = usb_get_intfdata(usbdev->config->interface[1]);
|
||||
wacom1 = hid_get_drvdata(hdev1);
|
||||
|
|
@ -2727,8 +2730,6 @@ static void wacom_mode_change_work(struct work_struct *work)
|
|||
static int wacom_probe(struct hid_device *hdev,
|
||||
const struct hid_device_id *id)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
struct usb_device *dev = interface_to_usbdev(intf);
|
||||
struct wacom *wacom;
|
||||
struct wacom_wac *wacom_wac;
|
||||
struct wacom_features *features;
|
||||
|
|
@ -2763,8 +2764,14 @@ static int wacom_probe(struct hid_device *hdev,
|
|||
wacom_wac->hid_data.inputmode = -1;
|
||||
wacom_wac->mode_report = -1;
|
||||
|
||||
wacom->usbdev = dev;
|
||||
wacom->intf = intf;
|
||||
if (hid_is_usb(hdev)) {
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
struct usb_device *dev = interface_to_usbdev(intf);
|
||||
|
||||
wacom->usbdev = dev;
|
||||
wacom->intf = intf;
|
||||
}
|
||||
|
||||
mutex_init(&wacom->lock);
|
||||
INIT_DELAYED_WORK(&wacom->init_work, wacom_init_work);
|
||||
INIT_WORK(&wacom->wireless_work, wacom_wireless_work);
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ struct geni_i2c_clk_fld {
|
|||
|
||||
static struct geni_i2c_clk_fld geni_i2c_clk_map[] = {
|
||||
{KHz(100), 7, 10, 11, 26},
|
||||
{KHz(400), 2, 5, 12, 24},
|
||||
{KHz(400), 2, 7, 10, 24},
|
||||
{KHz(1000), 1, 3, 9, 18},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
|
@ -511,6 +512,7 @@ struct haptics_chip {
|
|||
struct device_node *pbs_node;
|
||||
struct class hap_class;
|
||||
struct regulator *hpwr_vreg;
|
||||
struct hrtimer hbst_off_timer;
|
||||
int fifo_empty_irq;
|
||||
u32 hpwr_voltage_mv;
|
||||
u32 effects_count;
|
||||
|
|
@ -529,6 +531,7 @@ struct haptics_chip {
|
|||
bool clamp_at_5v;
|
||||
bool hpwr_vreg_enabled;
|
||||
bool is_hv_haptics;
|
||||
bool hboost_enabled;
|
||||
};
|
||||
|
||||
struct haptics_reg_info {
|
||||
|
|
@ -1292,6 +1295,9 @@ static int haptics_boost_vreg_enable(struct haptics_chip *chip, bool en)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (chip->hboost_enabled == en)
|
||||
return 0;
|
||||
|
||||
val = en ? HAP_VREG_ON_VAL : HAP_VREG_OFF_VAL;
|
||||
rc = nvmem_device_write(chip->hap_cfg_nvmem,
|
||||
PBS_ARG_REG, 1, &val);
|
||||
|
|
@ -1304,11 +1310,14 @@ static int haptics_boost_vreg_enable(struct haptics_chip *chip, bool en)
|
|||
val = PBS_TRIG_SET_VAL;
|
||||
rc = nvmem_device_write(chip->hap_cfg_nvmem,
|
||||
PBS_TRIG_SET_REG, 1, &val);
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Write SDAM %#x failed, rc=%d\n",
|
||||
PBS_TRIG_SET_REG, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
chip->hboost_enabled = en;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_swr_play_enabled(struct haptics_chip *chip)
|
||||
|
|
@ -1357,6 +1366,14 @@ static int haptics_wait_hboost_ready(struct haptics_chip *chip)
|
|||
|
||||
if (is_haptics_external_powered(chip))
|
||||
return 0;
|
||||
|
||||
if ((hrtimer_get_remaining(&chip->hbst_off_timer) > 0) ||
|
||||
hrtimer_active(&chip->hbst_off_timer)) {
|
||||
hrtimer_cancel(&chip->hbst_off_timer);
|
||||
dev_dbg(chip->dev, "hboost is still on, ignore\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait ~20ms until hBoost is ready, otherwise
|
||||
* bail out and return -EBUSY
|
||||
|
|
@ -1493,6 +1510,7 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en)
|
|||
return rc;
|
||||
}
|
||||
|
||||
#define BOOST_VREG_OFF_DELAY_SECONDS 2
|
||||
static int haptics_enable_play(struct haptics_chip *chip, bool en)
|
||||
{
|
||||
struct haptics_play_info *play = &chip->play;
|
||||
|
|
@ -1526,11 +1544,17 @@ static int haptics_enable_play(struct haptics_chip *chip, bool en)
|
|||
return rc;
|
||||
}
|
||||
|
||||
if (play->pattern_src == FIFO) {
|
||||
rc = haptics_boost_vreg_enable(chip, en);
|
||||
if (rc < 0)
|
||||
dev_err(chip->dev, "Notify vreg %s failed, rc=%d\n",
|
||||
en ? "enabling" : "disabling", rc);
|
||||
if (en) {
|
||||
rc = haptics_boost_vreg_enable(chip, true);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Keep boost vreg on failed, rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
hrtimer_start(&chip->hbst_off_timer,
|
||||
ktime_set(BOOST_VREG_OFF_DELAY_SECONDS, 0),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
|
@ -4582,6 +4606,21 @@ static bool is_swr_supported(struct haptics_chip *chip)
|
|||
return true;
|
||||
}
|
||||
|
||||
static enum hrtimer_restart haptics_disable_hbst_timer(struct hrtimer *timer)
|
||||
{
|
||||
struct haptics_chip *chip = container_of(timer,
|
||||
struct haptics_chip, hbst_off_timer);
|
||||
int rc;
|
||||
|
||||
rc = haptics_boost_vreg_enable(chip, false);
|
||||
if (rc < 0)
|
||||
dev_err(chip->dev, "disable boost vreg failed, rc=%d\n", rc);
|
||||
else
|
||||
dev_dbg(chip->dev, "boost vreg is disabled\n");
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static int haptics_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct haptics_chip *chip;
|
||||
|
|
@ -4646,6 +4685,8 @@ static int haptics_probe(struct platform_device *pdev)
|
|||
mutex_init(&chip->play.lock);
|
||||
disable_irq_nosync(chip->fifo_empty_irq);
|
||||
chip->fifo_empty_irq_en = false;
|
||||
hrtimer_init(&chip->hbst_off_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
chip->hbst_off_timer.function = haptics_disable_hbst_timer;
|
||||
|
||||
atomic_set(&chip->play.fifo_status.is_busy, 0);
|
||||
atomic_set(&chip->play.fifo_status.written_done, 0);
|
||||
|
|
@ -4755,6 +4796,12 @@ static int haptics_suspend(struct device *dev)
|
|||
}
|
||||
mutex_unlock(&play->lock);
|
||||
|
||||
/*
|
||||
* Cancel the hBoost turning off timer and disable
|
||||
* hBoost if it's still enabled
|
||||
*/
|
||||
hrtimer_cancel(&chip->hbst_off_timer);
|
||||
haptics_boost_vreg_enable(chip, false);
|
||||
rc = haptics_enable_hpwr_vreg(chip, false);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -243,18 +243,9 @@ struct npu_device {
|
|||
uint32_t hw_version;
|
||||
};
|
||||
|
||||
struct npu_kevent {
|
||||
struct list_head list;
|
||||
struct msm_npu_event evt;
|
||||
uint64_t reserved[4];
|
||||
};
|
||||
|
||||
struct npu_client {
|
||||
struct npu_device *npu_dev;
|
||||
wait_queue_head_t wait;
|
||||
|
||||
struct mutex list_lock;
|
||||
struct list_head evt_list;
|
||||
struct list_head mapped_buffer_list;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -27,14 +27,6 @@
|
|||
*/
|
||||
static int npu_debug_open(struct inode *inode, struct file *file);
|
||||
static int npu_debug_release(struct inode *inode, struct file *file);
|
||||
static int npu_debug_reg_open(struct inode *inode, struct file *file);
|
||||
static int npu_debug_reg_release(struct inode *inode, struct file *file);
|
||||
static ssize_t npu_debug_reg_read(struct file *file,
|
||||
char __user *user_buf, size_t count, loff_t *ppos);
|
||||
static ssize_t npu_debug_off_write(struct file *file,
|
||||
const char __user *user_buf, size_t count, loff_t *ppos);
|
||||
static ssize_t npu_debug_off_read(struct file *file,
|
||||
char __user *user_buf, size_t count, loff_t *ppos);
|
||||
static ssize_t npu_debug_log_read(struct file *file,
|
||||
char __user *user_buf, size_t count, loff_t *ppos);
|
||||
static ssize_t npu_debug_ctrl_write(struct file *file,
|
||||
|
|
@ -44,20 +36,7 @@ static ssize_t npu_debug_ctrl_write(struct file *file,
|
|||
* Variables
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
struct npu_device *g_npu_dev;
|
||||
|
||||
static const struct file_operations npu_reg_fops = {
|
||||
.open = npu_debug_reg_open,
|
||||
.release = npu_debug_reg_release,
|
||||
.read = npu_debug_reg_read,
|
||||
};
|
||||
|
||||
static const struct file_operations npu_off_fops = {
|
||||
.open = npu_debug_open,
|
||||
.release = npu_debug_release,
|
||||
.read = npu_debug_off_read,
|
||||
.write = npu_debug_off_write,
|
||||
};
|
||||
static struct npu_device *g_npu_dev;
|
||||
|
||||
static const struct file_operations npu_log_fops = {
|
||||
.open = npu_debug_open,
|
||||
|
|
@ -90,166 +69,6 @@ static int npu_debug_release(struct inode *inode, struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int npu_debug_reg_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct npu_debugfs_reg_ctx *reg_ctx;
|
||||
|
||||
reg_ctx = kzalloc(sizeof(*reg_ctx), GFP_KERNEL);
|
||||
if (!reg_ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
/* non-seekable */
|
||||
file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
|
||||
reg_ctx->npu_dev = inode->i_private;
|
||||
file->private_data = reg_ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int npu_debug_reg_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct npu_debugfs_reg_ctx *reg_ctx = file->private_data;
|
||||
|
||||
kfree(reg_ctx->buf);
|
||||
kfree(reg_ctx);
|
||||
file->private_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Function Implementations - Reg Read/Write
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
static ssize_t npu_debug_reg_read(struct file *file,
|
||||
char __user *user_buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct npu_debugfs_reg_ctx *reg_ctx = file->private_data;
|
||||
struct npu_device *npu_dev = reg_ctx->npu_dev;
|
||||
struct npu_debugfs_ctx *debugfs;
|
||||
size_t len;
|
||||
|
||||
debugfs = &npu_dev->debugfs_ctx;
|
||||
|
||||
if (debugfs->reg_cnt == 0)
|
||||
return 0;
|
||||
|
||||
if (!reg_ctx->buf) {
|
||||
char dump_buf[64];
|
||||
char *ptr;
|
||||
int cnt, tot, off;
|
||||
|
||||
reg_ctx->buf_len = sizeof(dump_buf) *
|
||||
DIV_ROUND_UP(debugfs->reg_cnt, ROW_BYTES);
|
||||
reg_ctx->buf = kzalloc(reg_ctx->buf_len, GFP_KERNEL);
|
||||
|
||||
if (!reg_ctx->buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ptr = npu_dev->core_io.base + debugfs->reg_off;
|
||||
tot = 0;
|
||||
off = (int)debugfs->reg_off;
|
||||
|
||||
if (npu_enable_core_power(npu_dev))
|
||||
return -EPERM;
|
||||
|
||||
for (cnt = debugfs->reg_cnt * 4; cnt > 0; cnt -= ROW_BYTES) {
|
||||
hex_dump_to_buffer(ptr, min(cnt, ROW_BYTES),
|
||||
ROW_BYTES, GROUP_BYTES, dump_buf,
|
||||
sizeof(dump_buf), false);
|
||||
len = scnprintf(reg_ctx->buf + tot,
|
||||
reg_ctx->buf_len - tot, "0x%08x: %s\n",
|
||||
((int) (unsigned long) ptr) -
|
||||
((int) (unsigned long) npu_dev->core_io.base),
|
||||
dump_buf);
|
||||
|
||||
ptr += ROW_BYTES;
|
||||
tot += len;
|
||||
if (tot >= reg_ctx->buf_len)
|
||||
break;
|
||||
}
|
||||
npu_disable_core_power(npu_dev);
|
||||
|
||||
reg_ctx->buf_len = tot;
|
||||
}
|
||||
|
||||
if (*ppos >= reg_ctx->buf_len)
|
||||
return 0; /* done reading */
|
||||
|
||||
len = min(count, reg_ctx->buf_len - (size_t) *ppos);
|
||||
pr_debug("read %zi %zi\n", count, reg_ctx->buf_len - (size_t) *ppos);
|
||||
if (copy_to_user(user_buf, reg_ctx->buf + *ppos, len)) {
|
||||
pr_err("failed to copy to user\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
*ppos += len; /* increase offset */
|
||||
return len;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Function Implementations - Offset Read/Write
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
static ssize_t npu_debug_off_write(struct file *file,
|
||||
const char __user *user_buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
size_t off = 0;
|
||||
uint32_t cnt, reg_cnt;
|
||||
char buf[24];
|
||||
struct npu_device *npu_dev = file->private_data;
|
||||
struct npu_debugfs_ctx *debugfs;
|
||||
|
||||
pr_debug("npu_dev %pK %pK\n", npu_dev, g_npu_dev);
|
||||
npu_dev = g_npu_dev;
|
||||
debugfs = &npu_dev->debugfs_ctx;
|
||||
|
||||
if (count >= sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(buf, user_buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
buf[count] = 0; /* end of string */
|
||||
|
||||
cnt = sscanf(buf, "%zx %x", &off, ®_cnt);
|
||||
if (cnt == 1)
|
||||
reg_cnt = DEFAULT_REG_DUMP_NUM;
|
||||
pr_debug("reg off = %zx, %d cnt=%d\n", off, reg_cnt, cnt);
|
||||
if (cnt >= 1) {
|
||||
debugfs->reg_off = off;
|
||||
debugfs->reg_cnt = reg_cnt;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t npu_debug_off_read(struct file *file,
|
||||
char __user *user_buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
size_t len;
|
||||
char buf[64];
|
||||
struct npu_device *npu_dev = file->private_data;
|
||||
struct npu_debugfs_ctx *debugfs;
|
||||
|
||||
pr_debug("npu_dev %pK %pK\n", npu_dev, g_npu_dev);
|
||||
npu_dev = g_npu_dev;
|
||||
debugfs = &npu_dev->debugfs_ctx;
|
||||
|
||||
if (*ppos)
|
||||
return 0; /* the end */
|
||||
|
||||
len = scnprintf(buf, sizeof(buf), "offset=0x%08x cnt=%d\n",
|
||||
debugfs->reg_off, debugfs->reg_cnt);
|
||||
len = min(len, count);
|
||||
|
||||
if (copy_to_user(user_buf, buf, len)) {
|
||||
pr_err("failed to copy to user\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
*ppos += len; /* increase offset */
|
||||
return len;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Function Implementations - DebugFS Log
|
||||
* -------------------------------------------------------------------------
|
||||
|
|
@ -374,18 +193,6 @@ int npu_debugfs_init(struct npu_device *npu_dev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!debugfs_create_file("reg", 0644, debugfs->root,
|
||||
npu_dev, &npu_reg_fops)) {
|
||||
pr_err("debugfs_create_file reg fail\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!debugfs_create_file("off", 0644, debugfs->root,
|
||||
npu_dev, &npu_off_fops)) {
|
||||
pr_err("debugfs_create_file off fail\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!debugfs_create_file("log", 0644, debugfs->root,
|
||||
npu_dev, &npu_log_fops)) {
|
||||
pr_err("debugfs_create_file log fail\n");
|
||||
|
|
|
|||
|
|
@ -102,8 +102,6 @@ static int npu_exec_network(struct npu_client *client,
|
|||
unsigned long arg);
|
||||
static int npu_exec_network_v2(struct npu_client *client,
|
||||
unsigned long arg);
|
||||
static int npu_receive_event(struct npu_client *client,
|
||||
unsigned long arg);
|
||||
static int npu_set_fw_state(struct npu_client *client, uint32_t enable);
|
||||
static int npu_set_property(struct npu_client *client,
|
||||
unsigned long arg);
|
||||
|
|
@ -111,7 +109,6 @@ static int npu_get_property(struct npu_client *client,
|
|||
unsigned long arg);
|
||||
static long npu_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
static unsigned int npu_poll(struct file *filp, struct poll_table_struct *p);
|
||||
static int npu_parse_dt_clock(struct npu_device *npu_dev);
|
||||
static int npu_parse_dt_regulator(struct npu_device *npu_dev);
|
||||
static int npu_of_parse_pwrlevels(struct npu_device *npu_dev,
|
||||
|
|
@ -223,7 +220,6 @@ static const struct file_operations npu_fops = {
|
|||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = npu_ioctl,
|
||||
#endif
|
||||
.poll = npu_poll,
|
||||
};
|
||||
|
||||
static const struct thermal_cooling_device_ops npu_cooling_ops = {
|
||||
|
|
@ -541,7 +537,7 @@ static int npu_set_cdsprm_corner_limit(enum cdsprm_npu_corner corner)
|
|||
return npu_set_power_level(g_npu_dev, false);
|
||||
}
|
||||
|
||||
const struct cdsprm_npu_limit_cbs cdsprm_npu_limit_cbs = {
|
||||
static const struct cdsprm_npu_limit_cbs cdsprm_npu_limit_cbs = {
|
||||
.set_corner_limit = npu_set_cdsprm_corner_limit,
|
||||
};
|
||||
|
||||
|
|
@ -573,7 +569,7 @@ static uint32_t npu_notify_cdsprm_cxlimit_corner(
|
|||
return pwr_lvl_to_set;
|
||||
}
|
||||
|
||||
int npu_cdsprm_cxlimit_init(struct npu_device *npu_dev)
|
||||
static int npu_cdsprm_cxlimit_init(struct npu_device *npu_dev)
|
||||
{
|
||||
bool enabled;
|
||||
int ret = 0;
|
||||
|
|
@ -597,7 +593,7 @@ int npu_cdsprm_cxlimit_init(struct npu_device *npu_dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int npu_cdsprm_cxlimit_deinit(struct npu_device *npu_dev)
|
||||
static int npu_cdsprm_cxlimit_deinit(struct npu_device *npu_dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
|
@ -1215,9 +1211,7 @@ static int npu_open(struct inode *inode, struct file *file)
|
|||
return -ENOMEM;
|
||||
|
||||
client->npu_dev = npu_dev;
|
||||
init_waitqueue_head(&client->wait);
|
||||
mutex_init(&client->list_lock);
|
||||
INIT_LIST_HEAD(&client->evt_list);
|
||||
INIT_LIST_HEAD(&(client->mapped_buffer_list));
|
||||
file->private_data = client;
|
||||
|
||||
|
|
@ -1227,17 +1221,8 @@ static int npu_open(struct inode *inode, struct file *file)
|
|||
static int npu_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct npu_client *client = file->private_data;
|
||||
struct npu_kevent *kevent;
|
||||
|
||||
npu_host_cleanup_networks(client);
|
||||
|
||||
while (!list_empty(&client->evt_list)) {
|
||||
kevent = list_first_entry(&client->evt_list,
|
||||
struct npu_kevent, list);
|
||||
list_del(&kevent->list);
|
||||
kfree(kevent);
|
||||
}
|
||||
|
||||
mutex_destroy(&client->list_lock);
|
||||
kfree(client);
|
||||
return 0;
|
||||
|
|
@ -1559,57 +1544,6 @@ static int npu_exec_network_v2(struct npu_client *client,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int npu_process_kevent(struct npu_kevent *kevt)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (kevt->evt.type) {
|
||||
case MSM_NPU_EVENT_TYPE_EXEC_V2_DONE:
|
||||
ret = copy_to_user((void __user *)kevt->reserved[1],
|
||||
(void *)kevt->reserved[0],
|
||||
kevt->evt.u.exec_v2_done.stats_buf_size);
|
||||
if (ret) {
|
||||
pr_err("fail to copy to user\n");
|
||||
kevt->evt.u.exec_v2_done.stats_buf_size = 0;
|
||||
ret = -EFAULT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int npu_receive_event(struct npu_client *client,
|
||||
unsigned long arg)
|
||||
{
|
||||
void __user *argp = (void __user *)arg;
|
||||
struct npu_kevent *kevt;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&client->list_lock);
|
||||
if (list_empty(&client->evt_list)) {
|
||||
pr_err("event list is empty\n");
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
kevt = list_first_entry(&client->evt_list,
|
||||
struct npu_kevent, list);
|
||||
list_del(&kevt->list);
|
||||
npu_process_kevent(kevt);
|
||||
ret = copy_to_user(argp, &kevt->evt,
|
||||
sizeof(struct msm_npu_event));
|
||||
if (ret) {
|
||||
pr_err("fail to copy to user\n");
|
||||
ret = -EFAULT;
|
||||
}
|
||||
kfree(kevt);
|
||||
}
|
||||
mutex_unlock(&client->list_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int npu_set_fw_state(struct npu_client *client, uint32_t enable)
|
||||
{
|
||||
struct npu_device *npu_dev = client->npu_dev;
|
||||
|
|
@ -1761,9 +1695,6 @@ static long npu_ioctl(struct file *file, unsigned int cmd,
|
|||
case MSM_NPU_EXEC_NETWORK_V2:
|
||||
ret = npu_exec_network_v2(client, arg);
|
||||
break;
|
||||
case MSM_NPU_RECEIVE_EVENT:
|
||||
ret = npu_receive_event(client, arg);
|
||||
break;
|
||||
case MSM_NPU_SET_PROP:
|
||||
ret = npu_set_property(client, arg);
|
||||
break;
|
||||
|
|
@ -1777,23 +1708,6 @@ static long npu_ioctl(struct file *file, unsigned int cmd,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int npu_poll(struct file *filp, struct poll_table_struct *p)
|
||||
{
|
||||
struct npu_client *client = filp->private_data;
|
||||
int rc = 0;
|
||||
|
||||
poll_wait(filp, &client->wait, p);
|
||||
|
||||
mutex_lock(&client->list_lock);
|
||||
if (!list_empty(&client->evt_list)) {
|
||||
pr_debug("poll cmd done\n");
|
||||
rc = POLLIN | POLLRDNORM;
|
||||
}
|
||||
mutex_unlock(&client->list_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Device Tree Parsing
|
||||
* -------------------------------------------------------------------------
|
||||
|
|
@ -2135,9 +2049,9 @@ static int npu_hw_info_init(struct npu_device *npu_dev)
|
|||
static int npu_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct resource *res = 0;
|
||||
struct npu_device *npu_dev = 0;
|
||||
struct thermal_cooling_device *tcdev = 0;
|
||||
struct resource *res = NULL;
|
||||
struct npu_device *npu_dev = NULL;
|
||||
struct thermal_cooling_device *tcdev = NULL;
|
||||
|
||||
npu_dev = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct npu_device), GFP_KERNEL);
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ static int npu_host_ipc_init_hfi(struct npu_device *npu_dev)
|
|||
struct hfi_queue_tbl_header *q_tbl_hdr = NULL;
|
||||
struct hfi_queue_header *q_hdr_arr = NULL;
|
||||
struct hfi_queue_header *q_hdr = NULL;
|
||||
void *q_tbl_addr = 0;
|
||||
void *q_tbl_addr = NULL;
|
||||
uint32_t reg_val = 0;
|
||||
uint32_t q_idx = 0;
|
||||
uint32_t q_tbl_size = sizeof(struct hfi_queue_tbl_header) +
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ void npu_mem_write(struct npu_device *npu_dev, void *dst, void *src,
|
|||
{
|
||||
size_t dst_off = (size_t)dst;
|
||||
uint32_t *src_ptr32 = (uint32_t *)src;
|
||||
uint8_t *src_ptr8 = 0;
|
||||
uint8_t *src_ptr8 = NULL;
|
||||
uint32_t i = 0;
|
||||
uint32_t num = 0;
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ int32_t npu_mem_read(struct npu_device *npu_dev, void *src, void *dst,
|
|||
{
|
||||
size_t src_off = (size_t)src;
|
||||
uint32_t *out32 = (uint32_t *)dst;
|
||||
uint8_t *out8 = 0;
|
||||
uint8_t *out8 = NULL;
|
||||
uint32_t i = 0;
|
||||
uint32_t num = 0;
|
||||
|
||||
|
|
@ -367,7 +367,7 @@ void npu_mem_invalidate(struct npu_client *client, int buf_hdl)
|
|||
|
||||
bool npu_mem_verify_addr(struct npu_client *client, uint64_t addr)
|
||||
{
|
||||
struct npu_ion_buf *ion_buf = 0;
|
||||
struct npu_ion_buf *ion_buf = NULL;
|
||||
struct list_head *pos = NULL;
|
||||
bool valid = false;
|
||||
|
||||
|
|
@ -387,7 +387,7 @@ bool npu_mem_verify_addr(struct npu_client *client, uint64_t addr)
|
|||
void npu_mem_unmap(struct npu_client *client, int buf_hdl, uint64_t addr)
|
||||
{
|
||||
struct npu_device *npu_dev = client->npu_dev;
|
||||
struct npu_ion_buf *ion_buf = 0;
|
||||
struct npu_ion_buf *ion_buf = NULL;
|
||||
|
||||
/* clear entry and retrieve the corresponding buffer */
|
||||
ion_buf = npu_get_npu_ion_buffer(client, buf_hdl);
|
||||
|
|
@ -466,7 +466,7 @@ void npu_process_log_message(struct npu_device *npu_dev, uint32_t *message,
|
|||
debugfs->log_buf_size) {
|
||||
/* Wrap around case */
|
||||
uint8_t *src_addr = (uint8_t *)message;
|
||||
uint8_t *dst_addr = 0;
|
||||
uint8_t *dst_addr = NULL;
|
||||
uint32_t remaining_to_end = debugfs->log_buf_size -
|
||||
debugfs->log_write_index + 1;
|
||||
dst_addr = debugfs->log_buf + debugfs->log_write_index;
|
||||
|
|
|
|||
|
|
@ -53,10 +53,9 @@ static void host_session_msg_hdlr(struct npu_device *npu_dev);
|
|||
static void host_session_log_hdlr(struct npu_device *npu_dev);
|
||||
static int host_error_hdlr(struct npu_device *npu_dev, bool force);
|
||||
static int npu_send_network_cmd(struct npu_device *npu_dev,
|
||||
struct npu_network *network, void *cmd_ptr, bool async);
|
||||
struct npu_network *network, void *cmd_ptr);
|
||||
static int npu_send_misc_cmd(struct npu_device *npu_dev, uint32_t q_idx,
|
||||
void *cmd_ptr);
|
||||
static int npu_queue_event(struct npu_client *client, struct npu_kevent *evt);
|
||||
static int npu_notify_dsp(struct npu_device *npu_dev, bool pwr_up);
|
||||
static int npu_notify_aop(struct npu_device *npu_dev, bool on);
|
||||
static int update_dcvs_activity(struct npu_device *npu_dev, uint32_t activity);
|
||||
|
|
@ -292,9 +291,8 @@ int npu_host_init(struct npu_device *npu_dev)
|
|||
struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
|
||||
|
||||
memset(host_ctx, 0, sizeof(*host_ctx));
|
||||
init_completion(&host_ctx->loopback_done);
|
||||
init_completion(&host_ctx->misc_done);
|
||||
init_completion(&host_ctx->fw_deinit_done);
|
||||
init_completion(&host_ctx->property_done);
|
||||
mutex_init(&host_ctx->lock);
|
||||
atomic_set(&host_ctx->ipc_trans_id, 1);
|
||||
host_ctx->npu_dev = npu_dev;
|
||||
|
|
@ -308,6 +306,8 @@ int npu_host_init(struct npu_device *npu_dev)
|
|||
if (!host_ctx->prop_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
host_ctx->misc_pending = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -348,7 +348,6 @@ static int host_error_hdlr(struct npu_device *npu_dev, bool force)
|
|||
{
|
||||
struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
|
||||
struct npu_network *network = NULL;
|
||||
struct npu_kevent kevt;
|
||||
int i;
|
||||
|
||||
if ((host_ctx->wdg_irq_sts == 0) && (host_ctx->err_irq_sts == 0)
|
||||
|
|
@ -368,21 +367,14 @@ static int host_error_hdlr(struct npu_device *npu_dev, bool force)
|
|||
network = &host_ctx->networks[i];
|
||||
if (network->is_valid && network->cmd_pending &&
|
||||
network->fw_error) {
|
||||
if (network->cmd_async) {
|
||||
pr_debug("async cmd, queue ssr event\n");
|
||||
kevt.evt.type = MSM_NPU_EVENT_TYPE_SSR;
|
||||
kevt.evt.u.ssr.network_hdl =
|
||||
network->network_hdl;
|
||||
if (npu_queue_event(network->client, &kevt))
|
||||
pr_err("queue npu event failed\n");
|
||||
} else {
|
||||
pr_debug("complete network %llx\n",
|
||||
network->id);
|
||||
complete(&network->cmd_done);
|
||||
}
|
||||
network->cmd_pending = false;
|
||||
pr_debug("complete network %llx\n",
|
||||
network->id);
|
||||
complete(&network->cmd_done);
|
||||
}
|
||||
}
|
||||
complete_all(&host_ctx->loopback_done);
|
||||
host_ctx->misc_pending = false;
|
||||
complete_all(&host_ctx->misc_done);
|
||||
mutex_unlock(&host_ctx->lock);
|
||||
|
||||
return 1;
|
||||
|
|
@ -699,31 +691,13 @@ static void free_network(struct npu_host_ctx *ctx, struct npu_client *client,
|
|||
* Function Definitions - IPC
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
static int npu_queue_event(struct npu_client *client, struct npu_kevent *evt)
|
||||
{
|
||||
struct npu_kevent *kevt = kmalloc(sizeof(*kevt), GFP_KERNEL);
|
||||
|
||||
if (!kevt)
|
||||
return -ENOMEM;
|
||||
|
||||
*kevt = *evt;
|
||||
INIT_LIST_HEAD(&kevt->list);
|
||||
mutex_lock(&client->list_lock);
|
||||
list_add_tail(&kevt->list, &client->evt_list);
|
||||
mutex_unlock(&client->list_lock);
|
||||
wake_up_interruptible(&client->wait);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
|
||||
{
|
||||
uint32_t msg_id;
|
||||
struct npu_network *network = NULL;
|
||||
struct npu_kevent kevt;
|
||||
struct npu_device *npu_dev = host_ctx->npu_dev;
|
||||
|
||||
memset(&kevt, 0, sizeof(kevt));
|
||||
msg_id = msg[1];
|
||||
switch (msg_id) {
|
||||
case NPU_IPC_MSG_EXECUTE_DONE:
|
||||
|
|
@ -762,18 +736,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
|
|||
network->cmd_pending = false;
|
||||
network->cmd_ret_status = exe_rsp_pkt->header.status;
|
||||
|
||||
if (!network->cmd_async) {
|
||||
complete(&network->cmd_done);
|
||||
} else {
|
||||
pr_debug("async cmd, queue event\n");
|
||||
kevt.evt.type = MSM_NPU_EVENT_TYPE_EXEC_DONE;
|
||||
kevt.evt.u.exec_done.network_hdl =
|
||||
exe_rsp_pkt->network_hdl;
|
||||
kevt.evt.u.exec_done.exec_result =
|
||||
exe_rsp_pkt->header.status;
|
||||
if (npu_queue_event(network->client, &kevt))
|
||||
pr_err("queue npu event failed\n");
|
||||
}
|
||||
complete(&network->cmd_done);
|
||||
network_put(network);
|
||||
|
||||
break;
|
||||
|
|
@ -817,22 +780,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
|
|||
network->stats_buf_size = stats_size;
|
||||
network->cmd_pending = false;
|
||||
network->cmd_ret_status = exe_rsp_pkt->header.status;
|
||||
|
||||
if (network->cmd_async) {
|
||||
pr_debug("async cmd, queue event\n");
|
||||
kevt.evt.type = MSM_NPU_EVENT_TYPE_EXEC_V2_DONE;
|
||||
kevt.evt.u.exec_v2_done.network_hdl =
|
||||
exe_rsp_pkt->network_hdl;
|
||||
kevt.evt.u.exec_v2_done.exec_result =
|
||||
exe_rsp_pkt->header.status;
|
||||
kevt.evt.u.exec_v2_done.stats_buf_size = stats_size;
|
||||
kevt.reserved[0] = (uint64_t)network->stats_buf;
|
||||
kevt.reserved[1] = (uint64_t)network->stats_buf_u;
|
||||
if (npu_queue_event(network->client, &kevt))
|
||||
pr_err("queue npu event failed\n");
|
||||
} else {
|
||||
complete(&network->cmd_done);
|
||||
}
|
||||
complete(&network->cmd_done);
|
||||
network_put(network);
|
||||
break;
|
||||
}
|
||||
|
|
@ -927,7 +875,9 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
|
|||
|
||||
pr_debug("NPU_IPC_MSG_LOOPBACK_DONE loopbackParams: 0x%x\n",
|
||||
lb_rsp_pkt->loopbackParams);
|
||||
complete_all(&host_ctx->loopback_done);
|
||||
host_ctx->misc_pending = false;
|
||||
|
||||
complete_all(&host_ctx->misc_done);
|
||||
break;
|
||||
}
|
||||
case NPU_IPC_MSG_SET_PROPERTY_DONE:
|
||||
|
|
@ -942,8 +892,9 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
|
|||
param[0]);
|
||||
|
||||
host_ctx->cmd_ret_status = prop_rsp_pkt->header.status;
|
||||
host_ctx->misc_pending = false;
|
||||
|
||||
complete_all(&host_ctx->property_done);
|
||||
complete_all(&host_ctx->misc_done);
|
||||
break;
|
||||
}
|
||||
case NPU_IPC_MSG_GET_PROPERTY_DONE:
|
||||
|
|
@ -968,8 +919,9 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
|
|||
sizeof(struct ipc_msg_header_pkt);
|
||||
memcpy(host_ctx->prop_buf, prop_data, prop_size);
|
||||
}
|
||||
host_ctx->misc_pending = false;
|
||||
|
||||
complete_all(&host_ctx->property_done);
|
||||
complete_all(&host_ctx->misc_done);
|
||||
break;
|
||||
}
|
||||
case NPU_IPC_MSG_GENERAL_NOTIFY:
|
||||
|
|
@ -1124,7 +1076,7 @@ int32_t npu_host_unmap_buf(struct npu_client *client,
|
|||
}
|
||||
|
||||
static int npu_send_network_cmd(struct npu_device *npu_dev,
|
||||
struct npu_network *network, void *cmd_ptr, bool async)
|
||||
struct npu_network *network, void *cmd_ptr)
|
||||
{
|
||||
struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
|
||||
int ret = 0;
|
||||
|
|
@ -1140,10 +1092,9 @@ static int npu_send_network_cmd(struct npu_device *npu_dev,
|
|||
pr_debug("Send cmd %d network id %lld\n",
|
||||
((struct ipc_cmd_header_pkt *)cmd_ptr)->cmd_type,
|
||||
network->id);
|
||||
network->cmd_async = async;
|
||||
network->cmd_ret_status = 0;
|
||||
network->cmd_pending = true;
|
||||
network->trans_id = atomic_read(&host_ctx->ipc_trans_id);
|
||||
network->trans_id = ((struct ipc_cmd_header_pkt *)cmd_ptr)->trans_id;
|
||||
ret = npu_host_ipc_send_cmd(npu_dev,
|
||||
IPC_QUEUE_APPS_EXEC, cmd_ptr);
|
||||
if (ret)
|
||||
|
|
@ -1163,11 +1114,18 @@ static int npu_send_misc_cmd(struct npu_device *npu_dev, uint32_t q_idx,
|
|||
if (host_ctx->fw_error || (host_ctx->fw_state == FW_DISABLED)) {
|
||||
pr_err("fw is in error state or disabled, can't send misc cmd\n");
|
||||
ret = -EIO;
|
||||
} else if (host_ctx->misc_pending) {
|
||||
pr_err("Another misc cmd is pending\n");
|
||||
ret = -EBUSY;
|
||||
} else {
|
||||
pr_debug("Send cmd %d\n",
|
||||
((struct ipc_cmd_header_pkt *)cmd_ptr)->cmd_type);
|
||||
host_ctx->cmd_ret_status = 0;
|
||||
reinit_completion(&host_ctx->misc_done);
|
||||
host_ctx->misc_pending = true;
|
||||
ret = npu_host_ipc_send_cmd(npu_dev, q_idx, cmd_ptr);
|
||||
if (ret)
|
||||
host_ctx->misc_pending = false;
|
||||
}
|
||||
mutex_unlock(&host_ctx->lock);
|
||||
|
||||
|
|
@ -1306,6 +1264,12 @@ int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
|
|||
goto set_prop_exit;
|
||||
}
|
||||
|
||||
ret = fw_init(npu_dev);
|
||||
if (ret) {
|
||||
pr_err("fw_init fail\n");
|
||||
goto set_prop_exit;
|
||||
}
|
||||
|
||||
prop_packet->header.cmd_type = NPU_IPC_CMD_SET_PROPERTY;
|
||||
prop_packet->header.size = pkt_size;
|
||||
prop_packet->header.trans_id =
|
||||
|
|
@ -1318,34 +1282,36 @@ int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
|
|||
for (i = 0; i < num_of_params; i++)
|
||||
prop_packet->prop_param[i] = property->prop_param[i];
|
||||
|
||||
reinit_completion(&host_ctx->property_done);
|
||||
ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_APPS_EXEC,
|
||||
prop_packet);
|
||||
|
||||
pr_debug("NPU_IPC_CMD_SET_PROPERTY sent status: %d\n", ret);
|
||||
|
||||
if (ret) {
|
||||
pr_err("NPU_IPC_CMD_SET_PROPERTY failed\n");
|
||||
goto set_prop_exit;
|
||||
goto deinit_fw;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_interruptible_timeout(
|
||||
&host_ctx->property_done,
|
||||
&host_ctx->misc_done,
|
||||
(host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ?
|
||||
NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT);
|
||||
|
||||
if (!ret) {
|
||||
pr_err_ratelimited("npu: NPU_IPC_CMD_SET_PROPERTY time out\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto set_prop_exit;
|
||||
goto deinit_fw;
|
||||
} else if (ret < 0) {
|
||||
pr_err("Wait for set_property done interrupted by signal\n");
|
||||
goto set_prop_exit;
|
||||
goto deinit_fw;
|
||||
}
|
||||
|
||||
ret = host_ctx->cmd_ret_status;
|
||||
if (ret)
|
||||
pr_err("set fw property failed %d\n", ret);
|
||||
|
||||
deinit_fw:
|
||||
fw_deinit(npu_dev, false, true);
|
||||
set_prop_exit:
|
||||
kfree(prop_packet);
|
||||
return ret;
|
||||
|
|
@ -1368,6 +1334,12 @@ int32_t npu_host_get_fw_property(struct npu_device *npu_dev,
|
|||
if (!prop_packet)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = fw_init(npu_dev);
|
||||
if (ret) {
|
||||
pr_err("fw_init fail\n");
|
||||
goto get_prop_exit;
|
||||
}
|
||||
|
||||
prop_packet->header.cmd_type = NPU_IPC_CMD_GET_PROPERTY;
|
||||
prop_packet->header.size = pkt_size;
|
||||
prop_packet->header.trans_id =
|
||||
|
|
@ -1380,28 +1352,27 @@ int32_t npu_host_get_fw_property(struct npu_device *npu_dev,
|
|||
for (i = 0; i < num_of_params; i++)
|
||||
prop_packet->prop_param[i] = property->prop_param[i];
|
||||
|
||||
reinit_completion(&host_ctx->property_done);
|
||||
ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_APPS_EXEC,
|
||||
prop_packet);
|
||||
pr_debug("NPU_IPC_CMD_GET_PROPERTY sent status: %d\n", ret);
|
||||
|
||||
if (ret) {
|
||||
pr_err("NPU_IPC_CMD_GET_PROPERTY failed\n");
|
||||
goto get_prop_exit;
|
||||
goto deinit_fw;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_interruptible_timeout(
|
||||
&host_ctx->property_done,
|
||||
&host_ctx->misc_done,
|
||||
(host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ?
|
||||
NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT);
|
||||
|
||||
if (!ret) {
|
||||
pr_err_ratelimited("npu: NPU_IPC_CMD_GET_PROPERTY time out\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto get_prop_exit;
|
||||
goto deinit_fw;
|
||||
} else if (ret < 0) {
|
||||
pr_err("Wait for get_property done interrupted by signal\n");
|
||||
goto get_prop_exit;
|
||||
goto deinit_fw;
|
||||
}
|
||||
|
||||
ret = host_ctx->cmd_ret_status;
|
||||
|
|
@ -1419,6 +1390,8 @@ int32_t npu_host_get_fw_property(struct npu_device *npu_dev,
|
|||
pr_err("get fw property failed %d\n", ret);
|
||||
}
|
||||
|
||||
deinit_fw:
|
||||
fw_deinit(npu_dev, false, true);
|
||||
get_prop_exit:
|
||||
kfree(prop_packet);
|
||||
return ret;
|
||||
|
|
@ -1475,7 +1448,7 @@ int32_t npu_host_load_network(struct npu_client *client,
|
|||
set_perf_mode(npu_dev);
|
||||
/* NPU_IPC_CMD_LOAD will go onto IPC_QUEUE_APPS_EXEC */
|
||||
reinit_completion(&network->cmd_done);
|
||||
ret = npu_send_network_cmd(npu_dev, network, &load_packet, false);
|
||||
ret = npu_send_network_cmd(npu_dev, network, &load_packet);
|
||||
if (ret) {
|
||||
pr_err("NPU_IPC_CMD_LOAD sent failed: %d\n", ret);
|
||||
goto error_free_network;
|
||||
|
|
@ -1593,7 +1566,7 @@ int32_t npu_host_load_network_v2(struct npu_client *client,
|
|||
set_perf_mode(npu_dev);
|
||||
/* NPU_IPC_CMD_LOAD_V2 will go onto IPC_QUEUE_APPS_EXEC */
|
||||
reinit_completion(&network->cmd_done);
|
||||
ret = npu_send_network_cmd(npu_dev, network, load_packet, false);
|
||||
ret = npu_send_network_cmd(npu_dev, network, load_packet);
|
||||
if (ret) {
|
||||
pr_debug("NPU_IPC_CMD_LOAD_V2 sent failed: %d\n", ret);
|
||||
goto error_free_network;
|
||||
|
|
@ -1609,7 +1582,7 @@ int32_t npu_host_load_network_v2(struct npu_client *client,
|
|||
mutex_lock(&host_ctx->lock);
|
||||
|
||||
if (!ret) {
|
||||
pr_err_ratelimited("npu: NPU_IPC_CMD_LOAD time out\n");
|
||||
pr_err_ratelimited("npu: NPU_IPC_CMD_LOAD_V2 time out\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto error_free_network;
|
||||
}
|
||||
|
|
@ -1685,7 +1658,7 @@ int32_t npu_host_unload_network(struct npu_client *client,
|
|||
retry:
|
||||
/* NPU_IPC_CMD_UNLOAD will go onto IPC_QUEUE_APPS_EXEC */
|
||||
reinit_completion(&network->cmd_done);
|
||||
ret = npu_send_network_cmd(npu_dev, network, &unload_packet, false);
|
||||
ret = npu_send_network_cmd(npu_dev, network, &unload_packet);
|
||||
|
||||
if (ret) {
|
||||
pr_err("NPU_IPC_CMD_UNLOAD sent failed: %d\n", ret);
|
||||
|
|
@ -1762,7 +1735,6 @@ int32_t npu_host_exec_network(struct npu_client *client,
|
|||
int32_t ret;
|
||||
struct npu_network *network;
|
||||
struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
|
||||
bool async_ioctl = !!exec_ioctl->async;
|
||||
|
||||
mutex_lock(&host_ctx->lock);
|
||||
network = get_network_by_hdl(host_ctx, client,
|
||||
|
|
@ -1826,18 +1798,13 @@ int32_t npu_host_exec_network(struct npu_client *client,
|
|||
|
||||
/* Send it on the high priority queue */
|
||||
reinit_completion(&network->cmd_done);
|
||||
ret = npu_send_network_cmd(npu_dev, network, &exec_packet, async_ioctl);
|
||||
ret = npu_send_network_cmd(npu_dev, network, &exec_packet);
|
||||
|
||||
if (ret) {
|
||||
pr_err("NPU_IPC_CMD_EXECUTE sent failed: %d\n", ret);
|
||||
goto exec_done;
|
||||
}
|
||||
|
||||
if (async_ioctl) {
|
||||
pr_debug("Async ioctl, return now\n");
|
||||
goto exec_done;
|
||||
}
|
||||
|
||||
mutex_unlock(&host_ctx->lock);
|
||||
|
||||
ret = wait_for_completion_timeout(
|
||||
|
|
@ -1892,7 +1859,6 @@ int32_t npu_host_exec_network_v2(struct npu_client *client,
|
|||
struct npu_network *network;
|
||||
struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
|
||||
uint32_t num_patch_params, pkt_size;
|
||||
bool async_ioctl = !!exec_ioctl->async;
|
||||
int i;
|
||||
|
||||
mutex_lock(&host_ctx->lock);
|
||||
|
|
@ -1965,18 +1931,13 @@ int32_t npu_host_exec_network_v2(struct npu_client *client,
|
|||
|
||||
/* Send it on the high priority queue */
|
||||
reinit_completion(&network->cmd_done);
|
||||
ret = npu_send_network_cmd(npu_dev, network, exec_packet, async_ioctl);
|
||||
ret = npu_send_network_cmd(npu_dev, network, exec_packet);
|
||||
|
||||
if (ret) {
|
||||
pr_err("NPU_IPC_CMD_EXECUTE_V2 sent failed: %d\n", ret);
|
||||
goto free_exec_packet;
|
||||
}
|
||||
|
||||
if (async_ioctl) {
|
||||
pr_debug("Async ioctl, return now\n");
|
||||
goto free_exec_packet;
|
||||
}
|
||||
|
||||
mutex_unlock(&host_ctx->lock);
|
||||
|
||||
ret = wait_for_completion_timeout(
|
||||
|
|
@ -2052,7 +2013,6 @@ int32_t npu_host_loopback_test(struct npu_device *npu_dev)
|
|||
loopback_packet.header.flags = 0;
|
||||
loopback_packet.loopbackParams = 15;
|
||||
|
||||
reinit_completion(&host_ctx->loopback_done);
|
||||
ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_APPS_EXEC, &loopback_packet);
|
||||
|
||||
if (ret) {
|
||||
|
|
@ -2061,7 +2021,7 @@ int32_t npu_host_loopback_test(struct npu_device *npu_dev)
|
|||
}
|
||||
|
||||
ret = wait_for_completion_interruptible_timeout(
|
||||
&host_ctx->loopback_done,
|
||||
&host_ctx->misc_done,
|
||||
(host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ?
|
||||
NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT);
|
||||
|
||||
|
|
|
|||
|
|
@ -77,9 +77,9 @@ struct npu_host_ctx {
|
|||
struct delayed_work fw_deinit_work;
|
||||
atomic_t fw_deinit_work_cnt;
|
||||
struct workqueue_struct *wq;
|
||||
struct completion loopback_done;
|
||||
struct completion misc_done;
|
||||
struct completion fw_deinit_done;
|
||||
struct completion property_done;
|
||||
bool misc_pending;
|
||||
void *prop_buf;
|
||||
int32_t network_num;
|
||||
struct npu_network networks[MAX_LOADED_NETWORK];
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#define pr_fmt(fmt) "synx: " fmt
|
||||
|
||||
|
|
@ -681,9 +681,9 @@ EXPORT_SYMBOL(synx_merge);
|
|||
int synx_release(struct synx_session session_id, s32 h_synx)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 idx;
|
||||
struct synx_client *client;
|
||||
struct synx_handle_coredata *synx_data;
|
||||
struct synx_coredata *synx_obj;
|
||||
|
||||
pr_debug("[sess: %u] Enter release from pid %d\n",
|
||||
session_id.client_id, current->pid);
|
||||
|
|
@ -692,21 +692,31 @@ int synx_release(struct synx_session session_id, s32 h_synx)
|
|||
if (!client)
|
||||
return -EINVAL;
|
||||
|
||||
synx_data = synx_util_acquire_handle(client, h_synx);
|
||||
synx_obj = synx_util_obtain_object(synx_data);
|
||||
/* no need to check for fence here */
|
||||
if (!synx_obj) {
|
||||
pr_err("%s: [sess: %u] invalid handle access %d\n",
|
||||
__func__, client->id, h_synx);
|
||||
rc = -EINVAL;
|
||||
goto fail;
|
||||
synx_data = NULL;
|
||||
idx = synx_util_handle_index(h_synx);
|
||||
|
||||
mutex_lock(&client->synx_table_lock[idx]);
|
||||
synx_data = &client->synx_table[idx];
|
||||
if (!synx_data->synx_obj) {
|
||||
pr_err("[sess: %u] invalid object handle %d\n",
|
||||
client->id, h_synx);
|
||||
} else if (synx_data->handle != h_synx) {
|
||||
pr_err("[sess: %u] stale object handle %d\n",
|
||||
client->id, h_synx);
|
||||
} else if (synx_data->rel_count == 0) {
|
||||
pr_err("[sess: %u] released object handle %d\n",
|
||||
client->id, h_synx);
|
||||
} else if (!kref_read(&synx_data->internal_refcount)) {
|
||||
pr_err("[sess: %u] destroyed object handle %d\n",
|
||||
client->id, h_synx);
|
||||
} else {
|
||||
synx_data->rel_count--;
|
||||
/* release the reference obtained at synx creation */
|
||||
kref_put(&synx_data->internal_refcount,
|
||||
synx_util_destroy_internal_handle);
|
||||
}
|
||||
mutex_unlock(&client->synx_table_lock[idx]);
|
||||
|
||||
/* release the reference obtained at synx creation */
|
||||
synx_util_release_handle(synx_data);
|
||||
|
||||
fail:
|
||||
synx_util_release_handle(synx_data);
|
||||
synx_put_client(client);
|
||||
pr_debug("[sess: %u] exit release with status %d\n",
|
||||
session_id.client_id, rc);
|
||||
|
|
@ -953,8 +963,10 @@ int synx_addrefcount(struct synx_session session_id, s32 h_synx, s32 count)
|
|||
idx = synx_util_handle_index(h_synx);
|
||||
mutex_lock(&client->synx_table_lock[idx]);
|
||||
/* acquire additional references to handle */
|
||||
while (count--)
|
||||
while (count--) {
|
||||
synx_data->rel_count++;
|
||||
kref_get(&synx_data->internal_refcount);
|
||||
}
|
||||
mutex_unlock(&client->synx_table_lock[idx]);
|
||||
|
||||
fail:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SYNX_PRIVATE_H__
|
||||
|
|
@ -181,6 +181,7 @@ struct synx_device;
|
|||
* @import_refcount : References for external clients for import
|
||||
* @id : Synx object handle for the client
|
||||
* @key : Key for import authentication
|
||||
* @rel_count : No of allowed release counts
|
||||
*/
|
||||
struct synx_handle_coredata {
|
||||
struct synx_client *client;
|
||||
|
|
@ -189,6 +190,7 @@ struct synx_handle_coredata {
|
|||
struct kref import_refcount;
|
||||
u32 handle;
|
||||
u16 key;
|
||||
u32 rel_count;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -231,6 +231,7 @@ int synx_util_init_handle(struct synx_client *client,
|
|||
synx_data->handle = h_synx;
|
||||
synx_data->synx_obj = synx_obj;
|
||||
kref_init(&synx_data->internal_refcount);
|
||||
synx_data->rel_count = 1;
|
||||
mutex_unlock(&client->synx_table_lock[idx]);
|
||||
|
||||
*new_synx = h_synx;
|
||||
|
|
@ -570,6 +571,9 @@ struct synx_handle_coredata *synx_util_acquire_handle(
|
|||
} else if (synx_data->handle != h_synx) {
|
||||
pr_err("[sess: %u] stale object handle %d\n",
|
||||
client->id, h_synx);
|
||||
} else if (synx_data->rel_count == 0) {
|
||||
pr_err("[sess: %u] released object handle %d\n",
|
||||
client->id, h_synx);
|
||||
} else if (!kref_read(&synx_data->internal_refcount)) {
|
||||
pr_err("[sess: %u] destroyed object handle %d\n",
|
||||
client->id, h_synx);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@
|
|||
|
||||
#define MAX_TUNING_LOOP 40
|
||||
|
||||
#if defined(CONFIG_SDC_QTI)
|
||||
#define SDHCI_DBG_DUMP_RS_INTERVAL (10 * HZ)
|
||||
#define SDHCI_DBG_DUMP_RS_BURST 2
|
||||
#endif
|
||||
|
||||
static unsigned int debug_quirks = 0;
|
||||
static unsigned int debug_quirks2;
|
||||
|
||||
|
|
@ -1486,6 +1491,10 @@ static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
|
|||
timeout += 10 * HZ;
|
||||
sdhci_mod_timer(host, cmd->mrq, timeout);
|
||||
|
||||
#if defined(CONFIG_SDC_QTI)
|
||||
if (cmd->data)
|
||||
host->data_start_time = ktime_get();
|
||||
#endif
|
||||
sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
|
||||
mmc_log_string(host->mmc,
|
||||
"updated ARGUMENT=0x%08x ARGUMENT_MODE=0x%08x COMMAND=0x%08x\n",
|
||||
|
|
@ -3127,6 +3136,10 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
|
|||
{
|
||||
u32 command;
|
||||
|
||||
#if defined(CONFIG_SDC_QTI)
|
||||
bool pr_msg = false;
|
||||
#endif
|
||||
|
||||
/* CMD19 generates _only_ Buffer Read Ready interrupt */
|
||||
if (intmask & SDHCI_INT_DATA_AVAIL) {
|
||||
command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
|
||||
|
|
@ -3217,9 +3230,41 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
|
|||
host->ops->adma_workaround(host, intmask);
|
||||
}
|
||||
|
||||
if (host->data->error)
|
||||
if (host->data->error) {
|
||||
#if defined(CONFIG_SDC_QTI)
|
||||
if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT
|
||||
| SDHCI_INT_DATA_END_BIT)) {
|
||||
command = SDHCI_GET_CMD(sdhci_readw(host,
|
||||
SDHCI_COMMAND));
|
||||
if ((command != MMC_SEND_TUNING_BLOCK_HS200) &&
|
||||
(command != MMC_SEND_TUNING_BLOCK))
|
||||
pr_msg = true;
|
||||
} else {
|
||||
pr_msg = true;
|
||||
}
|
||||
|
||||
if (host->mmc->ops->get_cd &&
|
||||
!host->mmc->ops->get_cd(host->mmc)) {
|
||||
pr_msg = false;
|
||||
pr_err("%s: Got data error(%d) during card removal\n",
|
||||
mmc_hostname(host->mmc), host->data->error);
|
||||
}
|
||||
|
||||
if (pr_msg && __ratelimit(&host->dbg_dump_rs)) {
|
||||
pr_err("%s: data txfr (0x%08x) error: %d after %lld ms\n",
|
||||
mmc_hostname(host->mmc), intmask,
|
||||
host->data->error, ktime_to_ms(ktime_sub(
|
||||
ktime_get(), host->data_start_time)));
|
||||
mmc_log_string(host->mmc,
|
||||
"data txfr (0x%08x) error: %d after %lld ms\n",
|
||||
intmask, host->data->error,
|
||||
ktime_to_ms(ktime_sub(ktime_get(),
|
||||
host->data_start_time)));
|
||||
sdhci_dumpregs(host);
|
||||
}
|
||||
#endif
|
||||
sdhci_finish_data(host);
|
||||
else {
|
||||
} else {
|
||||
if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
|
||||
sdhci_transfer_pio(host);
|
||||
|
||||
|
|
@ -3830,6 +3875,11 @@ struct sdhci_host *sdhci_alloc_host(struct device *dev,
|
|||
*/
|
||||
host->adma_table_cnt = SDHCI_MAX_SEGS * 2 + 1;
|
||||
|
||||
#if defined(CONFIG_SDC_QTI)
|
||||
ratelimit_state_init(&host->dbg_dump_rs, SDHCI_DBG_DUMP_RS_INTERVAL,
|
||||
SDHCI_DBG_DUMP_RS_BURST);
|
||||
#endif
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/mmc/host.h>
|
||||
|
||||
/*
|
||||
|
|
@ -616,6 +616,10 @@ struct sdhci_host {
|
|||
|
||||
u64 data_timeout;
|
||||
|
||||
#if defined(CONFIG_SDC_QTI)
|
||||
ktime_t data_start_time;
|
||||
struct ratelimit_state dbg_dump_rs;
|
||||
#endif
|
||||
unsigned long private[0] ____cacheline_aligned;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,36 +20,6 @@
|
|||
#define ONE_CODEWORD_SIZE 516
|
||||
|
||||
static struct device *dev_node;
|
||||
static int msm_nand_bam_panic_notifier(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct msm_nand_info *info = dev_get_drvdata(dev_node);
|
||||
|
||||
pr_info("Dumping APSS bam pipes register dumps\n");
|
||||
sps_get_bam_debug_info(info->sps.bam_handle, 93,
|
||||
(SPS_BAM_PIPE(0) |
|
||||
SPS_BAM_PIPE(1) |
|
||||
SPS_BAM_PIPE(2) |
|
||||
SPS_BAM_PIPE(3)),
|
||||
0, 2);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block msm_nand_bam_panic_blk = {
|
||||
.notifier_call = msm_nand_bam_panic_notifier,
|
||||
};
|
||||
|
||||
void msm_nand_bam_register_panic_handler(void)
|
||||
{
|
||||
atomic_notifier_chain_register(&panic_notifier_list,
|
||||
&msm_nand_bam_panic_blk);
|
||||
}
|
||||
|
||||
void msm_nand_bam_unregister_panic_handler(void)
|
||||
{
|
||||
atomic_notifier_chain_unregister(&panic_notifier_list,
|
||||
&msm_nand_bam_panic_blk);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the DMA memory for requested amount of size. It returns the pointer
|
||||
|
|
@ -4370,6 +4340,46 @@ out:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int msm_nand_bam_panic_notifier(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct msm_nand_info *info = dev_get_drvdata(dev_node);
|
||||
struct msm_nand_chip *chip = &info->nand_chip;
|
||||
int err;
|
||||
|
||||
err = msm_nand_get_device(chip->dev);
|
||||
if (err)
|
||||
goto out;
|
||||
pr_info("Dumping APSS bam pipes register dumps\n");
|
||||
sps_get_bam_debug_info(info->sps.bam_handle, 93,
|
||||
(SPS_BAM_PIPE(0) |
|
||||
SPS_BAM_PIPE(1) |
|
||||
SPS_BAM_PIPE(2) |
|
||||
SPS_BAM_PIPE(3)),
|
||||
0, 2);
|
||||
err = msm_nand_put_device(chip->dev);
|
||||
out:
|
||||
if (err)
|
||||
pr_err("Failed to get/put the device.\n");
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block msm_nand_bam_panic_blk = {
|
||||
.notifier_call = msm_nand_bam_panic_notifier,
|
||||
};
|
||||
|
||||
void msm_nand_bam_register_panic_handler(void)
|
||||
{
|
||||
atomic_notifier_chain_register(&panic_notifier_list,
|
||||
&msm_nand_bam_panic_blk);
|
||||
}
|
||||
|
||||
void msm_nand_bam_unregister_panic_handler(void)
|
||||
{
|
||||
atomic_notifier_chain_unregister(&panic_notifier_list,
|
||||
&msm_nand_bam_panic_blk);
|
||||
}
|
||||
|
||||
#define BOOT_DEV_MASK 0x1E
|
||||
#define BOOT_DEV_NAND 0x4
|
||||
|
||||
|
|
|
|||
1442
drivers/net/macsec.c
1442
drivers/net/macsec.c
File diff suppressed because it is too large
Load diff
|
|
@ -1918,7 +1918,7 @@ int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv)
|
|||
jiffies + msecs_to_jiffies(BOOT_DEBUG_TIMEOUT_MS));
|
||||
|
||||
ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_POWER_ON);
|
||||
del_timer(&pci_priv->boot_debug_timer);
|
||||
del_timer_sync(&pci_priv->boot_debug_timer);
|
||||
if (ret == 0)
|
||||
cnss_wlan_adsp_pc_enable(pci_priv, false);
|
||||
|
||||
|
|
|
|||
|
|
@ -5941,6 +5941,12 @@ static int msm_pcie_i2c_ctrl_init(struct msm_pcie_dev_t *pcie_dev)
|
|||
PCIE_DBG(pcie_dev, "PCIe: RC%d: No i2c phandle found\n",
|
||||
pcie_dev->rc_idx);
|
||||
return 0;
|
||||
} else {
|
||||
if (!i2c_ctrl->client) {
|
||||
PCIE_DBG(pcie_dev, "PCIe: RC%d: No i2c probe yet\n",
|
||||
pcie_dev->rc_idx);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_client_node = of_get_child_by_name(of_node, "pcie_i2c_ctrl");
|
||||
|
|
@ -6230,6 +6236,10 @@ static int msm_pcie_probe(struct platform_device *pdev)
|
|||
|
||||
dev_set_drvdata(&pdev->dev, pcie_dev);
|
||||
|
||||
ret = msm_pcie_i2c_ctrl_init(pcie_dev);
|
||||
if (ret)
|
||||
goto decrease_rc_num;
|
||||
|
||||
ret = msm_pcie_get_resources(pcie_dev, pcie_dev->pdev);
|
||||
if (ret)
|
||||
goto decrease_rc_num;
|
||||
|
|
@ -6244,6 +6254,7 @@ static int msm_pcie_probe(struct platform_device *pdev)
|
|||
else
|
||||
pcie_dev->use_pinctrl = true;
|
||||
|
||||
|
||||
if (pcie_dev->use_pinctrl) {
|
||||
pcie_dev->pins_default = pinctrl_lookup_state(pcie_dev->pinctrl,
|
||||
"default");
|
||||
|
|
@ -6296,8 +6307,6 @@ static int msm_pcie_probe(struct platform_device *pdev)
|
|||
pcie_dev->rc_idx, ret);
|
||||
}
|
||||
|
||||
msm_pcie_i2c_ctrl_init(pcie_dev);
|
||||
|
||||
msm_pcie_sysfs_init(pcie_dev);
|
||||
|
||||
pcie_dev->drv_ready = true;
|
||||
|
|
@ -7070,12 +7079,12 @@ static int pcie_i2c_ctrl_probe(struct i2c_client *client,
|
|||
|
||||
if (client_id == I2C_CLIENT_ID_NTN3) {
|
||||
i2c_ctrl = &msm_pcie_dev[rc_index].i2c_ctrl;
|
||||
i2c_ctrl->client = client;
|
||||
i2c_ctrl->client_i2c_read = ntn3_i2c_read;
|
||||
i2c_ctrl->client_i2c_write = ntn3_i2c_write;
|
||||
i2c_ctrl->client_i2c_reset = ntn3_ep_reset_ctrl;
|
||||
i2c_ctrl->client_i2c_dump_regs = ntn3_dump_regs;
|
||||
i2c_ctrl->client_i2c_de_emphasis_wa = ntn3_de_emphasis_wa;
|
||||
i2c_ctrl->client = client;
|
||||
} else {
|
||||
dev_err(&client->dev, "invalid client id %d\n", client_id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -695,7 +695,7 @@ static void mhi_dev_net_state_cb(struct mhi_dev_client_cb_data *cb_data)
|
|||
int mhi_dev_net_interface_init(void)
|
||||
{
|
||||
int ret_val = 0, index = 0;
|
||||
bool out_channel_started = false;
|
||||
uint32_t info_out_ch = 0;
|
||||
struct mhi_dev_net_client *mhi_net_client = NULL;
|
||||
|
||||
if (mhi_net_ctxt.client_handle) {
|
||||
|
|
@ -750,10 +750,7 @@ int mhi_dev_net_interface_init(void)
|
|||
}
|
||||
ret_val = mhi_register_state_cb(mhi_dev_net_state_cb,
|
||||
mhi_net_client, MHI_CLIENT_IP_SW_4_OUT);
|
||||
/* -EEXIST indicates success and channel is already open */
|
||||
if (ret_val == -EEXIST)
|
||||
out_channel_started = true;
|
||||
else if (ret_val < 0)
|
||||
if (ret_val < 0 && ret_val != -EEXIST)
|
||||
goto register_state_cb_fail;
|
||||
|
||||
ret_val = mhi_register_state_cb(mhi_dev_net_state_cb,
|
||||
|
|
@ -770,13 +767,16 @@ int mhi_dev_net_interface_init(void)
|
|||
* with mhi_dev_net_open_chan_create_netif().
|
||||
*/
|
||||
ret_val = 0;
|
||||
if (out_channel_started) {
|
||||
ret_val = mhi_dev_net_open_chan_create_netif
|
||||
(mhi_net_client);
|
||||
if (ret_val < 0) {
|
||||
mhi_dev_net_log(MHI_ERROR,
|
||||
"Failed to open channels\n");
|
||||
goto channel_open_fail;
|
||||
if (!mhi_ctrl_state_info(mhi_net_client->out_chan,
|
||||
&info_out_ch)) {
|
||||
if (info_out_ch == MHI_STATE_CONNECTED) {
|
||||
ret_val = mhi_dev_net_open_chan_create_netif
|
||||
(mhi_net_client);
|
||||
if (ret_val < 0) {
|
||||
mhi_dev_net_log(MHI_ERROR,
|
||||
"Failed to open channels\n");
|
||||
goto channel_open_fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ret_val < 0) {
|
||||
|
|
|
|||
|
|
@ -1338,6 +1338,17 @@ int mhi_dev_notify_sm_event(enum mhi_dev_event event)
|
|||
INIT_WORK(&state_change_event->work, mhi_sm_dev_event_manager);
|
||||
atomic_inc(&mhi_sm_ctx->pending_device_events);
|
||||
queue_work(mhi_sm_ctx->mhi_sm_wq, &state_change_event->work);
|
||||
|
||||
/*
|
||||
* Wait until M0 processing is completely done.
|
||||
* This ensures CHDB won't get processed while resume is in
|
||||
* progress thus avoids race between M0 and CHDB processing.
|
||||
*/
|
||||
if (event == MHI_DEV_EVENT_M0_STATE) {
|
||||
MHI_SM_DBG("Got M0, wait until resume is done\n");
|
||||
flush_workqueue(mhi_sm_ctx->mhi_sm_wq);
|
||||
}
|
||||
|
||||
res = 0;
|
||||
|
||||
exit:
|
||||
|
|
|
|||
|
|
@ -218,7 +218,6 @@ struct smb_dt_props {
|
|||
int term_current_src;
|
||||
int term_current_thresh_hi_ma;
|
||||
int term_current_thresh_lo_ma;
|
||||
int disable_suspend_on_collapse;
|
||||
};
|
||||
|
||||
struct smb5 {
|
||||
|
|
@ -556,7 +555,7 @@ static int smb5_parse_dt_misc(struct smb5 *chip, struct device_node *node)
|
|||
of_property_read_u32(node, "qcom,connector-internal-pull-kohm",
|
||||
&chg->connector_pull_up);
|
||||
|
||||
chip->dt.disable_suspend_on_collapse = of_property_read_bool(node,
|
||||
chg->disable_suspend_on_collapse = of_property_read_bool(node,
|
||||
"qcom,disable-suspend-on-collapse");
|
||||
chg->smb_pull_up = -EINVAL;
|
||||
of_property_read_u32(node, "qcom,smb-internal-pull-kohm",
|
||||
|
|
@ -2148,7 +2147,7 @@ static int smb5_init_hw(struct smb5 *chip)
|
|||
mask = USBIN_AICL_PERIODIC_RERUN_EN_BIT | USBIN_AICL_ADC_EN_BIT
|
||||
| USBIN_AICL_EN_BIT | SUSPEND_ON_COLLAPSE_USBIN_BIT;
|
||||
val = USBIN_AICL_PERIODIC_RERUN_EN_BIT | USBIN_AICL_EN_BIT;
|
||||
if (!chip->dt.disable_suspend_on_collapse)
|
||||
if (!chg->disable_suspend_on_collapse)
|
||||
val |= SUSPEND_ON_COLLAPSE_USBIN_BIT;
|
||||
if (chip->dt.adc_based_aicl)
|
||||
val |= USBIN_AICL_ADC_EN_BIT;
|
||||
|
|
|
|||
|
|
@ -1354,12 +1354,15 @@ static void smblib_uusb_removal(struct smb_charger *chg)
|
|||
smblib_err(chg, "Couldn't restore max pulses rc=%d\n",
|
||||
rc);
|
||||
|
||||
rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG,
|
||||
SUSPEND_ON_COLLAPSE_USBIN_BIT,
|
||||
SUSPEND_ON_COLLAPSE_USBIN_BIT);
|
||||
if (rc < 0)
|
||||
smblib_err(chg, "Couldn't turn on SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n",
|
||||
if (!chg->disable_suspend_on_collapse) {
|
||||
rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG,
|
||||
SUSPEND_ON_COLLAPSE_USBIN_BIT,
|
||||
SUSPEND_ON_COLLAPSE_USBIN_BIT);
|
||||
if (rc < 0)
|
||||
smblib_err(chg,
|
||||
"Couldn't turn on SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n",
|
||||
rc);
|
||||
}
|
||||
|
||||
chg->qc2_unsupported_voltage = QC2_COMPLIANT;
|
||||
}
|
||||
|
|
@ -6458,12 +6461,15 @@ static void typec_src_removal(struct smb_charger *chg)
|
|||
smblib_err(chg, "Couldn't restore max pulses rc=%d\n",
|
||||
rc);
|
||||
|
||||
rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG,
|
||||
SUSPEND_ON_COLLAPSE_USBIN_BIT,
|
||||
SUSPEND_ON_COLLAPSE_USBIN_BIT);
|
||||
if (rc < 0)
|
||||
smblib_err(chg, "Couldn't turn on SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n",
|
||||
if (!chg->disable_suspend_on_collapse) {
|
||||
rc = smblib_masked_write(chg, USBIN_AICL_OPTIONS_CFG_REG,
|
||||
SUSPEND_ON_COLLAPSE_USBIN_BIT,
|
||||
SUSPEND_ON_COLLAPSE_USBIN_BIT);
|
||||
if (rc < 0)
|
||||
smblib_err(chg,
|
||||
"Couldn't turn on SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n",
|
||||
rc);
|
||||
}
|
||||
|
||||
chg->qc2_unsupported_voltage = QC2_COMPLIANT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -594,6 +594,7 @@ struct smb_charger {
|
|||
bool apsd_ext_timeout;
|
||||
bool qc3p5_detected;
|
||||
int qc3p5_detected_mw;
|
||||
bool disable_suspend_on_collapse;
|
||||
|
||||
/* workaround flag */
|
||||
int real_charger_type;
|
||||
|
|
|
|||
|
|
@ -1307,7 +1307,8 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv,
|
|||
if (priv->force_err_fatal)
|
||||
ICNSS_ASSERT(0);
|
||||
|
||||
if (priv->device_id == WCN6750_DEVICE_ID) {
|
||||
if (priv->device_id == WCN6750_DEVICE_ID &&
|
||||
!IS_ERR(priv->smp2p_info.smem_state)) {
|
||||
priv->smp2p_info.seq = 0;
|
||||
if (qcom_smem_state_update_bits(
|
||||
priv->smp2p_info.smem_state,
|
||||
|
|
@ -3912,7 +3913,7 @@ static inline void icnss_get_smp2p_info(struct icnss_priv *priv)
|
|||
"wlan-smp2p-out",
|
||||
&priv->smp2p_info.smem_bit);
|
||||
if (IS_ERR(priv->smp2p_info.smem_state)) {
|
||||
icnss_pr_smp2p("Failed to get smem state %d",
|
||||
icnss_pr_err("Failed to get smem state %d",
|
||||
PTR_ERR(priv->smp2p_info.smem_state));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1081,7 +1081,6 @@ struct dwc3_scratchpad_array {
|
|||
* @link_state: link state
|
||||
* @speed: device speed (super, high, full, low)
|
||||
* @hwparams: copy of hwparams registers
|
||||
* @root: debugfs root folder pointer
|
||||
* @regset: debugfs pointer to regdump file
|
||||
* @dbg_lsp_select: current debug lsp mux register selection
|
||||
* @test_mode: true when we're entering a USB test mode
|
||||
|
|
@ -1307,7 +1306,6 @@ struct dwc3 {
|
|||
u8 num_eps;
|
||||
|
||||
struct dwc3_hwparams hwparams;
|
||||
struct dentry *root;
|
||||
struct debugfs_regset32 *regset;
|
||||
|
||||
u32 dbg_lsp_select;
|
||||
|
|
|
|||
|
|
@ -1023,8 +1023,10 @@ static void dwc3_debugfs_create_endpoint_files(struct dwc3_ep *dep,
|
|||
void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep)
|
||||
{
|
||||
struct dentry *dir;
|
||||
struct dentry *root;
|
||||
|
||||
dir = debugfs_create_dir(dep->name, dep->dwc->root);
|
||||
root = debugfs_lookup(dev_name(dep->dwc->dev), usb_debug_root);
|
||||
dir = debugfs_create_dir(dep->name, root);
|
||||
if (!dir) {
|
||||
pr_err("%s: failed to create dir %s\n", __func__, dep->name);
|
||||
return;
|
||||
|
|
@ -1278,8 +1280,6 @@ void dwc3_debugfs_init(struct dwc3 *dwc)
|
|||
return;
|
||||
}
|
||||
|
||||
dwc->root = root;
|
||||
|
||||
debugfs_create_file("regdump", 0444, root, dwc, &dwc3_regdump_fops);
|
||||
|
||||
debugfs_create_file("lsp_dump", S_IRUGO | S_IWUSR, root, dwc,
|
||||
|
|
@ -1310,6 +1310,6 @@ void dwc3_debugfs_init(struct dwc3 *dwc)
|
|||
|
||||
void dwc3_debugfs_exit(struct dwc3 *dwc)
|
||||
{
|
||||
debugfs_remove_recursive(dwc->root);
|
||||
debugfs_remove(debugfs_lookup(dev_name(dwc->dev), usb_debug_root));
|
||||
kfree(dwc->regset);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2324,6 +2324,10 @@ static void dwc3_restart_usb_work(struct work_struct *w)
|
|||
|
||||
dwc->err_evt_seen = false;
|
||||
flush_delayed_work(&mdwc->sm_work);
|
||||
|
||||
/* see comments in dwc3_msm_suspend */
|
||||
if (!mdwc->vbus_active)
|
||||
pm_relax(mdwc->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3375,6 +3379,12 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse,
|
|||
|
||||
dwc3_msm_update_bus_bw(mdwc, BUS_VOTE_NONE);
|
||||
|
||||
/*
|
||||
* If in_restart is marked as true from restart work do not release the wakeup
|
||||
* active source as it can lead the device to enter system suspend (if usb is
|
||||
* the last holding the wakeup active source). If actual cable disconnect happens
|
||||
* while in_restart is true wakeup active source will be released from restart work.
|
||||
*/
|
||||
if (!mdwc->in_restart) {
|
||||
/*
|
||||
* release wakeup source with timeout to defer system suspend to
|
||||
|
|
|
|||
|
|
@ -3144,7 +3144,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
|
|||
list_del(&dep->endpoint.ep_list);
|
||||
}
|
||||
|
||||
debugfs_remove_recursive(debugfs_lookup(dep->name, dwc->root));
|
||||
debugfs_remove_recursive(debugfs_lookup(dep->name,
|
||||
debugfs_lookup(dev_name(dep->dwc->dev),
|
||||
usb_debug_root)));
|
||||
kfree(dep);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1696,6 +1696,18 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|||
struct usb_function *f = NULL;
|
||||
u8 endp;
|
||||
|
||||
if (w_length > USB_COMP_EP0_BUFSIZ) {
|
||||
if (ctrl->bRequestType & USB_DIR_IN) {
|
||||
/* Cast away the const, we are going to overwrite on purpose. */
|
||||
__le16 *temp = (__le16 *)&ctrl->wLength;
|
||||
|
||||
*temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ);
|
||||
w_length = USB_COMP_EP0_BUFSIZ;
|
||||
} else {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* partial re-init of the response message; the function or the
|
||||
* gadget might need to intercept e.g. a control-OUT completion
|
||||
* when we delegate to it.
|
||||
|
|
@ -2229,7 +2241,7 @@ int composite_dev_prepare(struct usb_composite_driver *composite,
|
|||
if (!cdev->req)
|
||||
return -ENOMEM;
|
||||
|
||||
cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
|
||||
cdev->req->buf = kzalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
|
||||
if (!cdev->req->buf)
|
||||
goto fail;
|
||||
|
||||
|
|
|
|||
|
|
@ -601,8 +601,11 @@ fail:
|
|||
pr_err("acc_bind() could not allocate requests\n");
|
||||
while ((req = req_get(dev, &dev->tx_idle)))
|
||||
acc_request_free(req, dev->ep_in);
|
||||
for (i = 0; i < RX_REQ_MAX; i++)
|
||||
for (i = 0; i < RX_REQ_MAX; i++) {
|
||||
acc_request_free(dev->rx_req[i], dev->ep_out);
|
||||
dev->rx_req[i] = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -634,6 +637,12 @@ static ssize_t acc_read(struct file *fp, char __user *buf,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (!dev->rx_req[0]) {
|
||||
pr_warn("acc_read: USB request already handled/freed");
|
||||
r = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the data length by considering termination character.
|
||||
* Then compansite the difference of rounding up to
|
||||
|
|
@ -1100,8 +1109,10 @@ acc_function_unbind(struct usb_configuration *c, struct usb_function *f)
|
|||
|
||||
while ((req = req_get(dev, &dev->tx_idle)))
|
||||
acc_request_free(req, dev->ep_in);
|
||||
for (i = 0; i < RX_REQ_MAX; i++)
|
||||
for (i = 0; i < RX_REQ_MAX; i++) {
|
||||
acc_request_free(dev->rx_req[i], dev->ep_out);
|
||||
dev->rx_req[i] = NULL;
|
||||
}
|
||||
|
||||
acc_hid_unbind(dev);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -358,21 +358,28 @@ static inline struct f_cdev *cser_to_port(struct cserial *cser)
|
|||
return container_of(cser, struct f_cdev, port_usb);
|
||||
}
|
||||
|
||||
static unsigned int convert_uart_sigs_to_acm(unsigned int uart_sig)
|
||||
static unsigned int convert_uart_sigs_to_acm(struct cserial *cser, unsigned int uart_sig)
|
||||
{
|
||||
unsigned int acm_sig = 0;
|
||||
u16 state;
|
||||
|
||||
state = cser->serial_state;
|
||||
|
||||
/* Make sure that ACM bits from previous conversion are cleared */
|
||||
state &= ~(ACM_CTRL_RI | ACM_CTRL_DCD | ACM_CTRL_DSR | ACM_CTRL_BRK);
|
||||
|
||||
/* should this needs to be in calling functions ??? */
|
||||
uart_sig &= (TIOCM_RI | TIOCM_CD | TIOCM_DSR);
|
||||
uart_sig &= (TIOCM_RI | TIOCM_CD | TIOCM_DSR | TIOCM_CTS);
|
||||
|
||||
if (uart_sig & TIOCM_RI)
|
||||
acm_sig |= ACM_CTRL_RI;
|
||||
state |= ACM_CTRL_RI;
|
||||
if (uart_sig & TIOCM_CD)
|
||||
acm_sig |= ACM_CTRL_DCD;
|
||||
state |= ACM_CTRL_DCD;
|
||||
if (uart_sig & TIOCM_DSR)
|
||||
acm_sig |= ACM_CTRL_DSR;
|
||||
state |= ACM_CTRL_DSR;
|
||||
if (uart_sig & TIOCM_CTS)
|
||||
state |= ACM_CTRL_BRK;
|
||||
|
||||
return acm_sig;
|
||||
return state;
|
||||
}
|
||||
|
||||
static unsigned int convert_acm_sigs_to_uart(unsigned int acm_sig)
|
||||
|
|
@ -1660,7 +1667,7 @@ static void usb_cser_notify_modem(void *fport, int ctrl_bits)
|
|||
unsigned int cbits_to_laptop;
|
||||
|
||||
result = f_cdev_tiocmget(port);
|
||||
cbits_to_laptop = convert_uart_sigs_to_acm(result);
|
||||
cbits_to_laptop = convert_uart_sigs_to_acm(cser, result);
|
||||
if (cser->send_modem_ctrl_bits)
|
||||
cser->send_modem_ctrl_bits(cser, cbits_to_laptop);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2012,14 +2012,17 @@ static void ffs_data_clear(struct ffs_data *ffs)
|
|||
ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count);
|
||||
ffs->epfiles = NULL;
|
||||
}
|
||||
mutex_unlock(&ffs->mutex);
|
||||
|
||||
if (ffs->ffs_eventfd)
|
||||
eventfd_ctx_put(ffs->ffs_eventfd);
|
||||
|
||||
kfree(ffs->raw_descs_data);
|
||||
ffs->raw_descs_data = NULL;
|
||||
kfree(ffs->raw_strings);
|
||||
ffs->raw_strings = NULL;
|
||||
kfree(ffs->stringtabs);
|
||||
ffs->stringtabs = NULL;
|
||||
mutex_unlock(&ffs->mutex);
|
||||
}
|
||||
|
||||
static void ffs_data_reset(struct ffs_data *ffs)
|
||||
|
|
@ -2031,10 +2034,7 @@ static void ffs_data_reset(struct ffs_data *ffs)
|
|||
|
||||
ffs_data_clear(ffs);
|
||||
|
||||
ffs->raw_descs_data = NULL;
|
||||
ffs->raw_descs = NULL;
|
||||
ffs->raw_strings = NULL;
|
||||
ffs->stringtabs = NULL;
|
||||
|
||||
ffs->raw_descs_length = 0;
|
||||
ffs->fs_descs_count = 0;
|
||||
|
|
|
|||
|
|
@ -811,7 +811,6 @@ int usb_qdss_write(struct usb_qdss_ch *ch, struct qdss_request *d_req)
|
|||
req->length = d_req->length;
|
||||
req->sg = d_req->sg;
|
||||
req->num_sgs = d_req->num_sgs;
|
||||
req->num_mapped_sgs = d_req->num_mapped_sgs;
|
||||
reinit_completion(&qreq->write_done);
|
||||
if (req->sg)
|
||||
qdss_log("%s: req:%pK req->num_sgs:0x%x\n",
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ static int dbgp_enable_ep_req(struct usb_ep *ep)
|
|||
goto fail_1;
|
||||
}
|
||||
|
||||
req->buf = kmalloc(DBGP_REQ_LEN, GFP_KERNEL);
|
||||
req->buf = kzalloc(DBGP_REQ_LEN, GFP_KERNEL);
|
||||
if (!req->buf) {
|
||||
err = -ENOMEM;
|
||||
stp = 2;
|
||||
|
|
@ -345,6 +345,19 @@ static int dbgp_setup(struct usb_gadget *gadget,
|
|||
void *data = NULL;
|
||||
u16 len = 0;
|
||||
|
||||
if (length > DBGP_REQ_LEN) {
|
||||
if (ctrl->bRequestType & USB_DIR_IN) {
|
||||
/* Cast away the const, we are going to overwrite on purpose. */
|
||||
__le16 *temp = (__le16 *)&ctrl->wLength;
|
||||
|
||||
*temp = cpu_to_le16(DBGP_REQ_LEN);
|
||||
length = DBGP_REQ_LEN;
|
||||
} else {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (request == USB_REQ_GET_DESCRIPTOR) {
|
||||
switch (value>>8) {
|
||||
case USB_DT_DEVICE:
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ enum ep0_state {
|
|||
/* enough for the whole queue: most events invalidate others */
|
||||
#define N_EVENT 5
|
||||
|
||||
#define RBUF_SIZE 256
|
||||
|
||||
struct dev_data {
|
||||
spinlock_t lock;
|
||||
refcount_t count;
|
||||
|
|
@ -144,7 +146,7 @@ struct dev_data {
|
|||
struct dentry *dentry;
|
||||
|
||||
/* except this scratch i/o buffer for ep0 */
|
||||
u8 rbuf [256];
|
||||
u8 rbuf[RBUF_SIZE];
|
||||
};
|
||||
|
||||
static inline void get_dev (struct dev_data *data)
|
||||
|
|
@ -1333,6 +1335,18 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|||
u16 w_value = le16_to_cpu(ctrl->wValue);
|
||||
u16 w_length = le16_to_cpu(ctrl->wLength);
|
||||
|
||||
if (w_length > RBUF_SIZE) {
|
||||
if (ctrl->bRequestType & USB_DIR_IN) {
|
||||
/* Cast away the const, we are going to overwrite on purpose. */
|
||||
__le16 *temp = (__le16 *)&ctrl->wLength;
|
||||
|
||||
*temp = cpu_to_le16(RBUF_SIZE);
|
||||
w_length = RBUF_SIZE;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock (&dev->lock);
|
||||
dev->setup_abort = 0;
|
||||
if (dev->state == STATE_DEV_UNCONNECTED) {
|
||||
|
|
|
|||
|
|
@ -561,14 +561,14 @@ static int __init hh_msgq_init(void)
|
|||
spin_lock_init(&cap_table_entry->rx_lock);
|
||||
spin_lock_init(&cap_table_entry->cap_entry_lock);
|
||||
|
||||
cap_table_entry->tx_irq_name = kasprintf(GFP_KERNEL,
|
||||
cap_table_entry->tx_irq_name = kasprintf(GFP_ATOMIC,
|
||||
"hh_msgq_tx_%d", i);
|
||||
if (!cap_table_entry->tx_irq_name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
cap_table_entry->rx_irq_name = kasprintf(GFP_KERNEL,
|
||||
cap_table_entry->rx_irq_name = kasprintf(GFP_ATOMIC,
|
||||
"hh_msgq_rx_%d", i);
|
||||
if (!cap_table_entry->rx_irq_name) {
|
||||
ret = -ENOMEM;
|
||||
|
|
|
|||
184
fs/aio.c
184
fs/aio.c
|
|
@ -177,8 +177,9 @@ struct poll_iocb {
|
|||
struct file *file;
|
||||
struct wait_queue_head *head;
|
||||
__poll_t events;
|
||||
bool done;
|
||||
bool cancelled;
|
||||
bool work_scheduled;
|
||||
bool work_need_resched;
|
||||
struct wait_queue_entry wait;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
|
@ -1620,6 +1621,51 @@ static void aio_poll_put_work(struct work_struct *work)
|
|||
iocb_put(iocb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Safely lock the waitqueue which the request is on, synchronizing with the
|
||||
* case where the ->poll() provider decides to free its waitqueue early.
|
||||
*
|
||||
* Returns true on success, meaning that req->head->lock was locked, req->wait
|
||||
* is on req->head, and an RCU read lock was taken. Returns false if the
|
||||
* request was already removed from its waitqueue (which might no longer exist).
|
||||
*/
|
||||
static bool poll_iocb_lock_wq(struct poll_iocb *req)
|
||||
{
|
||||
wait_queue_head_t *head;
|
||||
|
||||
/*
|
||||
* While we hold the waitqueue lock and the waitqueue is nonempty,
|
||||
* wake_up_pollfree() will wait for us. However, taking the waitqueue
|
||||
* lock in the first place can race with the waitqueue being freed.
|
||||
*
|
||||
* We solve this as eventpoll does: by taking advantage of the fact that
|
||||
* all users of wake_up_pollfree() will RCU-delay the actual free. If
|
||||
* we enter rcu_read_lock() and see that the pointer to the queue is
|
||||
* non-NULL, we can then lock it without the memory being freed out from
|
||||
* under us, then check whether the request is still on the queue.
|
||||
*
|
||||
* Keep holding rcu_read_lock() as long as we hold the queue lock, in
|
||||
* case the caller deletes the entry from the queue, leaving it empty.
|
||||
* In that case, only RCU prevents the queue memory from being freed.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
head = smp_load_acquire(&req->head);
|
||||
if (head) {
|
||||
spin_lock(&head->lock);
|
||||
if (!list_empty(&req->wait.entry))
|
||||
return true;
|
||||
spin_unlock(&head->lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
static void poll_iocb_unlock_wq(struct poll_iocb *req)
|
||||
{
|
||||
spin_unlock(&req->head->lock);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void aio_poll_complete_work(struct work_struct *work)
|
||||
{
|
||||
struct poll_iocb *req = container_of(work, struct poll_iocb, work);
|
||||
|
|
@ -1639,14 +1685,27 @@ static void aio_poll_complete_work(struct work_struct *work)
|
|||
* avoid further branches in the fast path.
|
||||
*/
|
||||
spin_lock_irq(&ctx->ctx_lock);
|
||||
if (!mask && !READ_ONCE(req->cancelled)) {
|
||||
add_wait_queue(req->head, &req->wait);
|
||||
spin_unlock_irq(&ctx->ctx_lock);
|
||||
return;
|
||||
}
|
||||
if (poll_iocb_lock_wq(req)) {
|
||||
if (!mask && !READ_ONCE(req->cancelled)) {
|
||||
/*
|
||||
* The request isn't actually ready to be completed yet.
|
||||
* Reschedule completion if another wakeup came in.
|
||||
*/
|
||||
if (req->work_need_resched) {
|
||||
schedule_work(&req->work);
|
||||
req->work_need_resched = false;
|
||||
} else {
|
||||
req->work_scheduled = false;
|
||||
}
|
||||
poll_iocb_unlock_wq(req);
|
||||
spin_unlock_irq(&ctx->ctx_lock);
|
||||
return;
|
||||
}
|
||||
list_del_init(&req->wait.entry);
|
||||
poll_iocb_unlock_wq(req);
|
||||
} /* else, POLLFREE has freed the waitqueue, so we must complete */
|
||||
list_del_init(&iocb->ki_list);
|
||||
iocb->ki_res.res = mangle_poll(mask);
|
||||
req->done = true;
|
||||
spin_unlock_irq(&ctx->ctx_lock);
|
||||
|
||||
iocb_put(iocb);
|
||||
|
|
@ -1658,13 +1717,14 @@ static int aio_poll_cancel(struct kiocb *iocb)
|
|||
struct aio_kiocb *aiocb = container_of(iocb, struct aio_kiocb, rw);
|
||||
struct poll_iocb *req = &aiocb->poll;
|
||||
|
||||
spin_lock(&req->head->lock);
|
||||
WRITE_ONCE(req->cancelled, true);
|
||||
if (!list_empty(&req->wait.entry)) {
|
||||
list_del_init(&req->wait.entry);
|
||||
schedule_work(&aiocb->poll.work);
|
||||
}
|
||||
spin_unlock(&req->head->lock);
|
||||
if (poll_iocb_lock_wq(req)) {
|
||||
WRITE_ONCE(req->cancelled, true);
|
||||
if (!req->work_scheduled) {
|
||||
schedule_work(&aiocb->poll.work);
|
||||
req->work_scheduled = true;
|
||||
}
|
||||
poll_iocb_unlock_wq(req);
|
||||
} /* else, the request was force-cancelled by POLLFREE already */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1681,20 +1741,26 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
|
|||
if (mask && !(mask & req->events))
|
||||
return 0;
|
||||
|
||||
list_del_init(&req->wait.entry);
|
||||
|
||||
if (mask && spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) {
|
||||
/*
|
||||
* Complete the request inline if possible. This requires that three
|
||||
* conditions be met:
|
||||
* 1. An event mask must have been passed. If a plain wakeup was done
|
||||
* instead, then mask == 0 and we have to call vfs_poll() to get
|
||||
* the events, so inline completion isn't possible.
|
||||
* 2. The completion work must not have already been scheduled.
|
||||
* 3. ctx_lock must not be busy. We have to use trylock because we
|
||||
* already hold the waitqueue lock, so this inverts the normal
|
||||
* locking order. Use irqsave/irqrestore because not all
|
||||
* filesystems (e.g. fuse) call this function with IRQs disabled,
|
||||
* yet IRQs have to be disabled before ctx_lock is obtained.
|
||||
*/
|
||||
if (mask && !req->work_scheduled &&
|
||||
spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) {
|
||||
struct kioctx *ctx = iocb->ki_ctx;
|
||||
|
||||
/*
|
||||
* Try to complete the iocb inline if we can. Use
|
||||
* irqsave/irqrestore because not all filesystems (e.g. fuse)
|
||||
* call this function with IRQs disabled and because IRQs
|
||||
* have to be disabled before ctx_lock is obtained.
|
||||
*/
|
||||
list_del_init(&req->wait.entry);
|
||||
list_del(&iocb->ki_list);
|
||||
iocb->ki_res.res = mangle_poll(mask);
|
||||
req->done = true;
|
||||
if (iocb->ki_eventfd && eventfd_signal_count()) {
|
||||
iocb = NULL;
|
||||
INIT_WORK(&req->work, aio_poll_put_work);
|
||||
|
|
@ -1704,7 +1770,43 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
|
|||
if (iocb)
|
||||
iocb_put(iocb);
|
||||
} else {
|
||||
schedule_work(&req->work);
|
||||
/*
|
||||
* Schedule the completion work if needed. If it was already
|
||||
* scheduled, record that another wakeup came in.
|
||||
*
|
||||
* Don't remove the request from the waitqueue here, as it might
|
||||
* not actually be complete yet (we won't know until vfs_poll()
|
||||
* is called), and we must not miss any wakeups. POLLFREE is an
|
||||
* exception to this; see below.
|
||||
*/
|
||||
if (req->work_scheduled) {
|
||||
req->work_need_resched = true;
|
||||
} else {
|
||||
schedule_work(&req->work);
|
||||
req->work_scheduled = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the waitqueue is being freed early but we can't complete
|
||||
* the request inline, we have to tear down the request as best
|
||||
* we can. That means immediately removing the request from its
|
||||
* waitqueue and preventing all further accesses to the
|
||||
* waitqueue via the request. We also need to schedule the
|
||||
* completion work (done above). Also mark the request as
|
||||
* cancelled, to potentially skip an unneeded call to ->poll().
|
||||
*/
|
||||
if (mask & POLLFREE) {
|
||||
WRITE_ONCE(req->cancelled, true);
|
||||
list_del_init(&req->wait.entry);
|
||||
|
||||
/*
|
||||
* Careful: this *must* be the last step, since as soon
|
||||
* as req->head is NULL'ed out, the request can be
|
||||
* completed and freed, since aio_poll_complete_work()
|
||||
* will no longer need to take the waitqueue lock.
|
||||
*/
|
||||
smp_store_release(&req->head, NULL);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1712,6 +1814,7 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
|
|||
struct aio_poll_table {
|
||||
struct poll_table_struct pt;
|
||||
struct aio_kiocb *iocb;
|
||||
bool queued;
|
||||
int error;
|
||||
};
|
||||
|
||||
|
|
@ -1722,11 +1825,12 @@ aio_poll_queue_proc(struct file *file, struct wait_queue_head *head,
|
|||
struct aio_poll_table *pt = container_of(p, struct aio_poll_table, pt);
|
||||
|
||||
/* multiple wait queues per file are not supported */
|
||||
if (unlikely(pt->iocb->poll.head)) {
|
||||
if (unlikely(pt->queued)) {
|
||||
pt->error = -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
pt->queued = true;
|
||||
pt->error = 0;
|
||||
pt->iocb->poll.head = head;
|
||||
add_wait_queue(head, &pt->iocb->poll.wait);
|
||||
|
|
@ -1751,12 +1855,14 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb)
|
|||
req->events = demangle_poll(iocb->aio_buf) | EPOLLERR | EPOLLHUP;
|
||||
|
||||
req->head = NULL;
|
||||
req->done = false;
|
||||
req->cancelled = false;
|
||||
req->work_scheduled = false;
|
||||
req->work_need_resched = false;
|
||||
|
||||
apt.pt._qproc = aio_poll_queue_proc;
|
||||
apt.pt._key = req->events;
|
||||
apt.iocb = aiocb;
|
||||
apt.queued = false;
|
||||
apt.error = -EINVAL; /* same as no support for IOCB_CMD_POLL */
|
||||
|
||||
/* initialized the list so that we can do list_empty checks */
|
||||
|
|
@ -1765,23 +1871,35 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb)
|
|||
|
||||
mask = vfs_poll(req->file, &apt.pt) & req->events;
|
||||
spin_lock_irq(&ctx->ctx_lock);
|
||||
if (likely(req->head)) {
|
||||
spin_lock(&req->head->lock);
|
||||
if (unlikely(list_empty(&req->wait.entry))) {
|
||||
if (apt.error)
|
||||
if (likely(apt.queued)) {
|
||||
bool on_queue = poll_iocb_lock_wq(req);
|
||||
|
||||
if (!on_queue || req->work_scheduled) {
|
||||
/*
|
||||
* aio_poll_wake() already either scheduled the async
|
||||
* completion work, or completed the request inline.
|
||||
*/
|
||||
if (apt.error) /* unsupported case: multiple queues */
|
||||
cancel = true;
|
||||
apt.error = 0;
|
||||
mask = 0;
|
||||
}
|
||||
if (mask || apt.error) {
|
||||
/* Steal to complete synchronously. */
|
||||
list_del_init(&req->wait.entry);
|
||||
} else if (cancel) {
|
||||
/* Cancel if possible (may be too late though). */
|
||||
WRITE_ONCE(req->cancelled, true);
|
||||
} else if (!req->done) { /* actually waiting for an event */
|
||||
} else if (on_queue) {
|
||||
/*
|
||||
* Actually waiting for an event, so add the request to
|
||||
* active_reqs so that it can be cancelled if needed.
|
||||
*/
|
||||
list_add_tail(&aiocb->ki_list, &ctx->active_reqs);
|
||||
aiocb->ki_cancel = aio_poll_cancel;
|
||||
}
|
||||
spin_unlock(&req->head->lock);
|
||||
if (on_queue)
|
||||
poll_iocb_unlock_wq(req);
|
||||
}
|
||||
if (mask) { /* no async, we'd stolen it */
|
||||
aiocb->ki_res.res = mangle_poll(mask);
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ struct f2fs_mount_info {
|
|||
#define F2FS_FEATURE_SB_CHKSUM 0x0800
|
||||
#define F2FS_FEATURE_CASEFOLD 0x1000
|
||||
#define F2FS_FEATURE_COMPRESSION 0x2000
|
||||
#define F2FS_FEATURE_RO 0x4000
|
||||
|
||||
#define __F2FS_HAS_FEATURE(raw_super, mask) \
|
||||
((raw_super->feature & cpu_to_le32(mask)) != 0)
|
||||
|
|
@ -991,6 +992,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
|
|||
*/
|
||||
#define NR_CURSEG_DATA_TYPE (3)
|
||||
#define NR_CURSEG_NODE_TYPE (3)
|
||||
#define NR_CURSEG_RO_TYPE (2)
|
||||
#define NR_CURSEG_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
|
||||
|
||||
enum {
|
||||
|
|
@ -3968,6 +3970,7 @@ F2FS_FEATURE_FUNCS(verity, VERITY);
|
|||
F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM);
|
||||
F2FS_FEATURE_FUNCS(casefold, CASEFOLD);
|
||||
F2FS_FEATURE_FUNCS(compression, COMPRESSION);
|
||||
F2FS_FEATURE_FUNCS(readonly, RO);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi,
|
||||
|
|
|
|||
|
|
@ -68,6 +68,10 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
|
|||
goto err;
|
||||
}
|
||||
|
||||
err = f2fs_convert_inline_inode(inode);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
#ifdef CONFIG_F2FS_FS_COMPRESSION
|
||||
if (f2fs_compressed_file(inode)) {
|
||||
int ret = f2fs_is_compressed_cluster(inode, page->index);
|
||||
|
|
@ -515,7 +519,6 @@ static loff_t f2fs_llseek(struct file *file, loff_t offset, int whence)
|
|||
static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
int err;
|
||||
|
||||
if (unlikely(f2fs_cp_error(F2FS_I_SB(inode))))
|
||||
return -EIO;
|
||||
|
|
@ -523,11 +526,6 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
if (!f2fs_is_compress_backend_ready(inode))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* we don't need to use inline_data strictly */
|
||||
err = f2fs_convert_inline_inode(inode);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
file_accessed(file);
|
||||
vma->vm_ops = &f2fs_file_vm_ops;
|
||||
set_inode_flag(inode, FI_MMAP_FILE);
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
|
|||
int i;
|
||||
|
||||
ni->nid = nid;
|
||||
|
||||
retry:
|
||||
/* Check nat cache */
|
||||
down_read(&nm_i->nat_tree_lock);
|
||||
e = __lookup_nat_cache(nm_i, nid);
|
||||
|
|
@ -550,10 +550,19 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
|
|||
return 0;
|
||||
}
|
||||
|
||||
memset(&ne, 0, sizeof(struct f2fs_nat_entry));
|
||||
/*
|
||||
* Check current segment summary by trying to grab journal_rwsem first.
|
||||
* This sem is on the critical path on the checkpoint requiring the above
|
||||
* nat_tree_lock. Therefore, we should retry, if we failed to grab here
|
||||
* while not bothering checkpoint.
|
||||
*/
|
||||
if (!rwsem_is_locked(&sbi->cp_global_sem)) {
|
||||
down_read(&curseg->journal_rwsem);
|
||||
} else if (!down_read_trylock(&curseg->journal_rwsem)) {
|
||||
up_read(&nm_i->nat_tree_lock);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Check current segment summary */
|
||||
down_read(&curseg->journal_rwsem);
|
||||
i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0);
|
||||
if (i >= 0) {
|
||||
ne = nat_in_journal(journal, i);
|
||||
|
|
|
|||
|
|
@ -4373,6 +4373,10 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
|
|||
struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
|
||||
unsigned int blkofs = curseg->next_blkoff;
|
||||
|
||||
if (f2fs_sb_has_readonly(sbi) &&
|
||||
i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE)
|
||||
continue;
|
||||
|
||||
if (f2fs_test_bit(blkofs, se->cur_valid_map))
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#define DEF_MAX_RECLAIM_PREFREE_SEGMENTS 4096 /* 8GB in maximum */
|
||||
|
||||
#define F2FS_MIN_SEGMENTS 9 /* SB + 2 (CP + SIT + NAT) + SSA + MAIN */
|
||||
#define F2FS_MIN_META_SEGMENTS 8 /* SB + 2 (CP + SIT + NAT) + SSA */
|
||||
|
||||
/* L: Logical segment # in volume, R: Relative segment # in main area */
|
||||
#define GET_L2R_SEGNO(free_i, segno) ((segno) - (free_i)->start_segno)
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
|
|||
int ret;
|
||||
|
||||
if (!options)
|
||||
return 0;
|
||||
goto default_check;
|
||||
|
||||
while ((p = strsep(&options, ",")) != NULL) {
|
||||
int token;
|
||||
|
|
@ -932,6 +932,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
|
|||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
default_check:
|
||||
#ifdef CONFIG_QUOTA
|
||||
if (f2fs_check_quota_options(sbi))
|
||||
return -EINVAL;
|
||||
|
|
@ -993,6 +994,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
|
|||
*/
|
||||
if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
|
||||
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
|
||||
|
||||
if (f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) {
|
||||
f2fs_err(sbi, "Allow to mount readonly mode only");
|
||||
return -EROFS;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1629,7 +1635,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
|
|||
static void default_options(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
/* init some FS parameters */
|
||||
F2FS_OPTION(sbi).active_logs = NR_CURSEG_TYPE;
|
||||
if (f2fs_sb_has_readonly(sbi))
|
||||
F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
|
||||
else
|
||||
F2FS_OPTION(sbi).active_logs = NR_CURSEG_TYPE;
|
||||
|
||||
F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
|
||||
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
|
||||
F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
|
||||
|
|
@ -1808,6 +1818,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
|
|||
if (f2fs_readonly(sb) && (*flags & SB_RDONLY))
|
||||
goto skip;
|
||||
|
||||
if (f2fs_sb_has_readonly(sbi) && !(*flags & SB_RDONLY)) {
|
||||
err = -EROFS;
|
||||
goto restore_opts;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_QUOTA
|
||||
if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) {
|
||||
err = dquot_suspend(sb, -1);
|
||||
|
|
@ -2711,7 +2726,7 @@ static inline bool sanity_check_area_boundary(struct f2fs_sb_info *sbi,
|
|||
static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
|
||||
struct buffer_head *bh)
|
||||
{
|
||||
block_t segment_count, segs_per_sec, secs_per_zone;
|
||||
block_t segment_count, segs_per_sec, secs_per_zone, segment_count_main;
|
||||
block_t total_sections, blocks_per_seg;
|
||||
struct f2fs_super_block *raw_super = (struct f2fs_super_block *)
|
||||
(bh->b_data + F2FS_SUPER_OFFSET);
|
||||
|
|
@ -2781,6 +2796,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
|
|||
}
|
||||
|
||||
segment_count = le32_to_cpu(raw_super->segment_count);
|
||||
segment_count_main = le32_to_cpu(raw_super->segment_count_main);
|
||||
segs_per_sec = le32_to_cpu(raw_super->segs_per_sec);
|
||||
secs_per_zone = le32_to_cpu(raw_super->secs_per_zone);
|
||||
total_sections = le32_to_cpu(raw_super->section_count);
|
||||
|
|
@ -2794,8 +2810,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
|
|||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (total_sections > segment_count ||
|
||||
total_sections < F2FS_MIN_SEGMENTS ||
|
||||
if (total_sections > segment_count_main || total_sections < 1 ||
|
||||
segs_per_sec > segment_count || !segs_per_sec) {
|
||||
f2fs_info(sbi, "Invalid segment/section count (%u, %u x %u)",
|
||||
segment_count, total_sections, segs_per_sec);
|
||||
|
|
@ -2902,14 +2917,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
|
|||
ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
|
||||
reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
|
||||
|
||||
if (unlikely(fsmeta < F2FS_MIN_SEGMENTS ||
|
||||
if (!f2fs_sb_has_readonly(sbi) &&
|
||||
unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
|
||||
ovp_segments == 0 || reserved_segments == 0)) {
|
||||
f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
|
||||
return 1;
|
||||
}
|
||||
|
||||
user_block_count = le64_to_cpu(ckpt->user_block_count);
|
||||
segment_count_main = le32_to_cpu(raw_super->segment_count_main);
|
||||
segment_count_main = le32_to_cpu(raw_super->segment_count_main) +
|
||||
(f2fs_sb_has_readonly(sbi) ? 1 : 0);
|
||||
log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
|
||||
if (!user_block_count || user_block_count >=
|
||||
segment_count_main << log_blocks_per_seg) {
|
||||
|
|
@ -2940,6 +2956,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
|
|||
if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
|
||||
le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
|
||||
return 1;
|
||||
|
||||
if (f2fs_sb_has_readonly(sbi))
|
||||
goto check_data;
|
||||
|
||||
for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
|
||||
if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
|
||||
le32_to_cpu(ckpt->cur_node_segno[j])) {
|
||||
|
|
@ -2950,10 +2970,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
|
|||
}
|
||||
}
|
||||
}
|
||||
check_data:
|
||||
for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
|
||||
if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
|
||||
le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
|
||||
return 1;
|
||||
|
||||
if (f2fs_sb_has_readonly(sbi))
|
||||
goto skip_cross;
|
||||
|
||||
for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
|
||||
if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
|
||||
le32_to_cpu(ckpt->cur_data_segno[j])) {
|
||||
|
|
@ -2975,7 +3000,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
skip_cross:
|
||||
sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
|
||||
nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,9 @@ static ssize_t features_show(struct f2fs_attr *a,
|
|||
if (f2fs_sb_has_casefold(sbi))
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
|
||||
len ? ", " : "", "casefold");
|
||||
if (f2fs_sb_has_readonly(sbi))
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
|
||||
len ? ", " : "", "readonly");
|
||||
if (f2fs_sb_has_compression(sbi))
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
|
||||
len ? ", " : "", "compression");
|
||||
|
|
@ -457,6 +460,7 @@ enum feat_id {
|
|||
FEAT_SB_CHECKSUM,
|
||||
FEAT_CASEFOLD,
|
||||
FEAT_COMPRESSION,
|
||||
FEAT_RO,
|
||||
FEAT_TEST_DUMMY_ENCRYPTION_V2,
|
||||
FEAT_ENCRYPTED_CASEFOLD,
|
||||
};
|
||||
|
|
@ -479,6 +483,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a,
|
|||
case FEAT_SB_CHECKSUM:
|
||||
case FEAT_CASEFOLD:
|
||||
case FEAT_COMPRESSION:
|
||||
case FEAT_RO:
|
||||
case FEAT_TEST_DUMMY_ENCRYPTION_V2:
|
||||
case FEAT_ENCRYPTED_CASEFOLD:
|
||||
return sprintf(buf, "supported\n");
|
||||
|
|
@ -604,6 +609,7 @@ F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM);
|
|||
#ifdef CONFIG_UNICODE
|
||||
F2FS_FEATURE_RO_ATTR(casefold, FEAT_CASEFOLD);
|
||||
#endif
|
||||
F2FS_FEATURE_RO_ATTR(readonly, FEAT_RO);
|
||||
#ifdef CONFIG_F2FS_FS_COMPRESSION
|
||||
F2FS_FEATURE_RO_ATTR(compression, FEAT_COMPRESSION);
|
||||
#endif
|
||||
|
|
@ -697,6 +703,7 @@ static struct attribute *f2fs_feat_attrs[] = {
|
|||
#ifdef CONFIG_UNICODE
|
||||
ATTR_LIST(casefold),
|
||||
#endif
|
||||
ATTR_LIST(readonly),
|
||||
#ifdef CONFIG_F2FS_FS_COMPRESSION
|
||||
ATTR_LIST(compression),
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -35,17 +35,7 @@
|
|||
|
||||
void signalfd_cleanup(struct sighand_struct *sighand)
|
||||
{
|
||||
wait_queue_head_t *wqh = &sighand->signalfd_wqh;
|
||||
/*
|
||||
* The lockless check can race with remove_wait_queue() in progress,
|
||||
* but in this case its caller should run under rcu_read_lock() and
|
||||
* sighand_cachep is SLAB_TYPESAFE_BY_RCU, we can safely return.
|
||||
*/
|
||||
if (likely(!waitqueue_active(wqh)))
|
||||
return;
|
||||
|
||||
/* wait_queue_entry_t->func(POLLFREE) should do remove_wait_queue() */
|
||||
wake_up_poll(wqh, EPOLLHUP | POLLFREE);
|
||||
wake_up_pollfree(&sighand->signalfd_wqh);
|
||||
}
|
||||
|
||||
struct signalfd_ctx {
|
||||
|
|
|
|||
|
|
@ -837,6 +837,11 @@ static inline bool hid_is_using_ll_driver(struct hid_device *hdev,
|
|||
return hdev->ll_driver == driver;
|
||||
}
|
||||
|
||||
static inline bool hid_is_usb(struct hid_device *hdev)
|
||||
{
|
||||
return hid_is_using_ll_driver(hdev, &usb_hid_driver);
|
||||
}
|
||||
|
||||
#define PM_HINT_FULLON 1<<5
|
||||
#define PM_HINT_NORMAL 1<<1
|
||||
|
||||
|
|
|
|||
|
|
@ -1241,22 +1241,22 @@
|
|||
*
|
||||
* @binder_set_context_mgr:
|
||||
* Check whether @mgr is allowed to be the binder context manager.
|
||||
* @mgr contains the task_struct for the task being registered.
|
||||
* @mgr contains the struct cred for the current binder process.
|
||||
* Return 0 if permission is granted.
|
||||
* @binder_transaction:
|
||||
* Check whether @from is allowed to invoke a binder transaction call
|
||||
* to @to.
|
||||
* @from contains the task_struct for the sending task.
|
||||
* @to contains the task_struct for the receiving task.
|
||||
* @from contains the struct cred for the sending process.
|
||||
* @to contains the struct cred for the receiving process.
|
||||
* @binder_transfer_binder:
|
||||
* Check whether @from is allowed to transfer a binder reference to @to.
|
||||
* @from contains the task_struct for the sending task.
|
||||
* @to contains the task_struct for the receiving task.
|
||||
* @from contains the struct cred for the sending process.
|
||||
* @to contains the struct cred for the receiving process.
|
||||
* @binder_transfer_file:
|
||||
* Check whether @from is allowed to transfer @file to @to.
|
||||
* @from contains the task_struct for the sending task.
|
||||
* @from contains the struct cred for the sending process.
|
||||
* @file contains the struct file being transferred.
|
||||
* @to contains the task_struct for the receiving task.
|
||||
* @to contains the struct cred for the receiving process.
|
||||
*
|
||||
* @ptrace_access_check:
|
||||
* Check permission before allowing the current process to trace the
|
||||
|
|
@ -1456,13 +1456,13 @@
|
|||
* @what: kernel feature being accessed
|
||||
*/
|
||||
union security_list_options {
|
||||
int (*binder_set_context_mgr)(struct task_struct *mgr);
|
||||
int (*binder_transaction)(struct task_struct *from,
|
||||
struct task_struct *to);
|
||||
int (*binder_transfer_binder)(struct task_struct *from,
|
||||
struct task_struct *to);
|
||||
int (*binder_transfer_file)(struct task_struct *from,
|
||||
struct task_struct *to,
|
||||
int (*binder_set_context_mgr)(const struct cred *mgr);
|
||||
int (*binder_transaction)(const struct cred *from,
|
||||
const struct cred *to);
|
||||
int (*binder_transfer_binder)(const struct cred *from,
|
||||
const struct cred *to);
|
||||
int (*binder_transfer_file)(const struct cred *from,
|
||||
const struct cred *to,
|
||||
struct file *file);
|
||||
|
||||
int (*ptrace_access_check)(struct task_struct *child,
|
||||
|
|
|
|||
|
|
@ -326,6 +326,9 @@ struct phy_c45_device_ids {
|
|||
u32 device_ids[8];
|
||||
};
|
||||
|
||||
struct macsec_context;
|
||||
struct macsec_ops;
|
||||
|
||||
/* phy_device: An instance of a PHY
|
||||
*
|
||||
* drv: Pointer to the driver for this PHY instance
|
||||
|
|
@ -347,6 +350,7 @@ struct phy_c45_device_ids {
|
|||
* attached_dev: The attached enet driver's device instance ptr
|
||||
* adjust_link: Callback for the enet controller to respond to
|
||||
* changes in the link state.
|
||||
* macsec_ops: MACsec offloading ops.
|
||||
*
|
||||
* speed, duplex, pause, supported, advertising, lp_advertising,
|
||||
* and autoneg are used like in mii_if_info
|
||||
|
|
@ -448,6 +452,10 @@ struct phy_device {
|
|||
ANDROID_KABI_RESERVE(2);
|
||||
ANDROID_KABI_RESERVE(3);
|
||||
ANDROID_KABI_RESERVE(4);
|
||||
#if IS_ENABLED(CONFIG_MACSEC)
|
||||
/* MACsec management functions */
|
||||
const struct macsec_ops *macsec_ops;
|
||||
#endif
|
||||
};
|
||||
#define to_phy_device(d) container_of(to_mdio_device(d), \
|
||||
struct phy_device, mdio)
|
||||
|
|
|
|||
|
|
@ -249,13 +249,13 @@ extern int security_init(void);
|
|||
extern int early_security_init(void);
|
||||
|
||||
/* Security operations */
|
||||
int security_binder_set_context_mgr(struct task_struct *mgr);
|
||||
int security_binder_transaction(struct task_struct *from,
|
||||
struct task_struct *to);
|
||||
int security_binder_transfer_binder(struct task_struct *from,
|
||||
struct task_struct *to);
|
||||
int security_binder_transfer_file(struct task_struct *from,
|
||||
struct task_struct *to, struct file *file);
|
||||
int security_binder_set_context_mgr(const struct cred *mgr);
|
||||
int security_binder_transaction(const struct cred *from,
|
||||
const struct cred *to);
|
||||
int security_binder_transfer_binder(const struct cred *from,
|
||||
const struct cred *to);
|
||||
int security_binder_transfer_file(const struct cred *from,
|
||||
const struct cred *to, struct file *file);
|
||||
int security_ptrace_access_check(struct task_struct *child, unsigned int mode);
|
||||
int security_ptrace_traceme(struct task_struct *parent);
|
||||
int security_capget(struct task_struct *target,
|
||||
|
|
@ -481,25 +481,25 @@ static inline int early_security_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_binder_set_context_mgr(struct task_struct *mgr)
|
||||
static inline int security_binder_set_context_mgr(const struct cred *mgr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_binder_transaction(struct task_struct *from,
|
||||
struct task_struct *to)
|
||||
static inline int security_binder_transaction(const struct cred *from,
|
||||
const struct cred *to)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_binder_transfer_binder(struct task_struct *from,
|
||||
struct task_struct *to)
|
||||
static inline int security_binder_transfer_binder(const struct cred *from,
|
||||
const struct cred *to)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_binder_transfer_file(struct task_struct *from,
|
||||
struct task_struct *to,
|
||||
static inline int security_binder_transfer_file(const struct cred *from,
|
||||
const struct cred *to,
|
||||
struct file *file)
|
||||
{
|
||||
return 0;
|
||||
|
|
@ -985,6 +985,11 @@ static inline void security_transfer_creds(struct cred *new,
|
|||
{
|
||||
}
|
||||
|
||||
static inline void security_cred_getsecid(const struct cred *c, u32 *secid)
|
||||
{
|
||||
*secid = 0;
|
||||
}
|
||||
|
||||
static inline int security_kernel_act_as(struct cred *cred, u32 secid)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ struct qdss_request {
|
|||
void *context;
|
||||
struct scatterlist *sg;
|
||||
unsigned int num_sgs;
|
||||
unsigned int num_mapped_sgs;
|
||||
};
|
||||
|
||||
struct usb_qdss_ch {
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ void __wake_up_locked_key_bookmark(struct wait_queue_head *wq_head,
|
|||
void __wake_up_sync_key(struct wait_queue_head *wq_head, unsigned int mode, int nr, void *key);
|
||||
void __wake_up_locked(struct wait_queue_head *wq_head, unsigned int mode, int nr);
|
||||
void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode, int nr);
|
||||
void __wake_up_pollfree(struct wait_queue_head *wq_head);
|
||||
|
||||
#define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL)
|
||||
#define wake_up_nr(x, nr) __wake_up(x, TASK_NORMAL, nr, NULL)
|
||||
|
|
@ -231,6 +232,31 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode, int nr);
|
|||
#define wake_up_interruptible_sync_poll(x, m) \
|
||||
__wake_up_sync_key((x), TASK_INTERRUPTIBLE, 1, poll_to_key(m))
|
||||
|
||||
/**
|
||||
* wake_up_pollfree - signal that a polled waitqueue is going away
|
||||
* @wq_head: the wait queue head
|
||||
*
|
||||
* In the very rare cases where a ->poll() implementation uses a waitqueue whose
|
||||
* lifetime is tied to a task rather than to the 'struct file' being polled,
|
||||
* this function must be called before the waitqueue is freed so that
|
||||
* non-blocking polls (e.g. epoll) are notified that the queue is going away.
|
||||
*
|
||||
* The caller must also RCU-delay the freeing of the wait_queue_head, e.g. via
|
||||
* an explicit synchronize_rcu() or call_rcu(), or via SLAB_TYPESAFE_BY_RCU.
|
||||
*/
|
||||
static inline void wake_up_pollfree(struct wait_queue_head *wq_head)
|
||||
{
|
||||
/*
|
||||
* For performance reasons, we don't always take the queue lock here.
|
||||
* Therefore, we might race with someone removing the last entry from
|
||||
* the queue, and proceed while they still hold the queue lock.
|
||||
* However, rcu_read_lock() is required to be held in such cases, so we
|
||||
* can safely proceed with an RCU-delayed free.
|
||||
*/
|
||||
if (waitqueue_active(wq_head))
|
||||
__wake_up_pollfree(wq_head);
|
||||
}
|
||||
|
||||
#define ___wait_cond_timeout(condition) \
|
||||
({ \
|
||||
bool __cond = (condition); \
|
||||
|
|
|
|||
290
include/net/macsec.h
Normal file
290
include/net/macsec.h
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* MACsec netdev header, used for h/w accelerated implementations.
|
||||
*
|
||||
* Copyright (c) 2015 Sabrina Dubroca <sd@queasysnail.net>
|
||||
*/
|
||||
#ifndef _NET_MACSEC_H_
|
||||
#define _NET_MACSEC_H_
|
||||
|
||||
#include <linux/u64_stats_sync.h>
|
||||
#include <uapi/linux/if_link.h>
|
||||
#include <uapi/linux/if_macsec.h>
|
||||
|
||||
#define MACSEC_DEFAULT_PN_LEN 4
|
||||
#define MACSEC_XPN_PN_LEN 8
|
||||
|
||||
#define MACSEC_SALT_LEN 12
|
||||
#define MACSEC_NUM_AN 4 /* 2 bits for the association number */
|
||||
|
||||
typedef u64 __bitwise sci_t;
|
||||
typedef u32 __bitwise ssci_t;
|
||||
|
||||
typedef union salt {
|
||||
struct {
|
||||
u32 ssci;
|
||||
u64 pn;
|
||||
} __packed;
|
||||
u8 bytes[MACSEC_SALT_LEN];
|
||||
} __packed salt_t;
|
||||
|
||||
typedef union pn {
|
||||
struct {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
u32 lower;
|
||||
u32 upper;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
u32 upper;
|
||||
u32 lower;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
};
|
||||
u64 full64;
|
||||
} pn_t;
|
||||
|
||||
/**
|
||||
* struct macsec_key - SA key
|
||||
* @id: user-provided key identifier
|
||||
* @tfm: crypto struct, key storage
|
||||
* @salt: salt used to generate IV in XPN cipher suites
|
||||
*/
|
||||
struct macsec_key {
|
||||
u8 id[MACSEC_KEYID_LEN];
|
||||
struct crypto_aead *tfm;
|
||||
salt_t salt;
|
||||
};
|
||||
|
||||
struct macsec_rx_sc_stats {
|
||||
__u64 InOctetsValidated;
|
||||
__u64 InOctetsDecrypted;
|
||||
__u64 InPktsUnchecked;
|
||||
__u64 InPktsDelayed;
|
||||
__u64 InPktsOK;
|
||||
__u64 InPktsInvalid;
|
||||
__u64 InPktsLate;
|
||||
__u64 InPktsNotValid;
|
||||
__u64 InPktsNotUsingSA;
|
||||
__u64 InPktsUnusedSA;
|
||||
};
|
||||
|
||||
struct macsec_rx_sa_stats {
|
||||
__u32 InPktsOK;
|
||||
__u32 InPktsInvalid;
|
||||
__u32 InPktsNotValid;
|
||||
__u32 InPktsNotUsingSA;
|
||||
__u32 InPktsUnusedSA;
|
||||
};
|
||||
|
||||
struct macsec_tx_sa_stats {
|
||||
__u32 OutPktsProtected;
|
||||
__u32 OutPktsEncrypted;
|
||||
};
|
||||
|
||||
struct macsec_tx_sc_stats {
|
||||
__u64 OutPktsProtected;
|
||||
__u64 OutPktsEncrypted;
|
||||
__u64 OutOctetsProtected;
|
||||
__u64 OutOctetsEncrypted;
|
||||
};
|
||||
|
||||
struct macsec_dev_stats {
|
||||
__u64 OutPktsUntagged;
|
||||
__u64 InPktsUntagged;
|
||||
__u64 OutPktsTooLong;
|
||||
__u64 InPktsNoTag;
|
||||
__u64 InPktsBadTag;
|
||||
__u64 InPktsUnknownSCI;
|
||||
__u64 InPktsNoSCI;
|
||||
__u64 InPktsOverrun;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct macsec_rx_sa - receive secure association
|
||||
* @active:
|
||||
* @next_pn: packet number expected for the next packet
|
||||
* @lock: protects next_pn manipulations
|
||||
* @key: key structure
|
||||
* @ssci: short secure channel identifier
|
||||
* @stats: per-SA stats
|
||||
*/
|
||||
struct macsec_rx_sa {
|
||||
struct macsec_key key;
|
||||
ssci_t ssci;
|
||||
spinlock_t lock;
|
||||
union {
|
||||
pn_t next_pn_halves;
|
||||
u64 next_pn;
|
||||
};
|
||||
refcount_t refcnt;
|
||||
bool active;
|
||||
struct macsec_rx_sa_stats __percpu *stats;
|
||||
struct macsec_rx_sc *sc;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
struct pcpu_rx_sc_stats {
|
||||
struct macsec_rx_sc_stats stats;
|
||||
struct u64_stats_sync syncp;
|
||||
};
|
||||
|
||||
struct pcpu_tx_sc_stats {
|
||||
struct macsec_tx_sc_stats stats;
|
||||
struct u64_stats_sync syncp;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct macsec_rx_sc - receive secure channel
|
||||
* @sci: secure channel identifier for this SC
|
||||
* @active: channel is active
|
||||
* @sa: array of secure associations
|
||||
* @stats: per-SC stats
|
||||
*/
|
||||
struct macsec_rx_sc {
|
||||
struct macsec_rx_sc __rcu *next;
|
||||
sci_t sci;
|
||||
bool active;
|
||||
struct macsec_rx_sa __rcu *sa[MACSEC_NUM_AN];
|
||||
struct pcpu_rx_sc_stats __percpu *stats;
|
||||
refcount_t refcnt;
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct macsec_tx_sa - transmit secure association
|
||||
* @active:
|
||||
* @next_pn: packet number to use for the next packet
|
||||
* @lock: protects next_pn manipulations
|
||||
* @key: key structure
|
||||
* @ssci: short secure channel identifier
|
||||
* @stats: per-SA stats
|
||||
*/
|
||||
struct macsec_tx_sa {
|
||||
struct macsec_key key;
|
||||
ssci_t ssci;
|
||||
spinlock_t lock;
|
||||
union {
|
||||
pn_t next_pn_halves;
|
||||
u64 next_pn;
|
||||
};
|
||||
refcount_t refcnt;
|
||||
bool active;
|
||||
struct macsec_tx_sa_stats __percpu *stats;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct macsec_tx_sc - transmit secure channel
|
||||
* @active:
|
||||
* @encoding_sa: association number of the SA currently in use
|
||||
* @encrypt: encrypt packets on transmit, or authenticate only
|
||||
* @send_sci: always include the SCI in the SecTAG
|
||||
* @end_station:
|
||||
* @scb: single copy broadcast flag
|
||||
* @sa: array of secure associations
|
||||
* @stats: stats for this TXSC
|
||||
*/
|
||||
struct macsec_tx_sc {
|
||||
bool active;
|
||||
u8 encoding_sa;
|
||||
bool encrypt;
|
||||
bool send_sci;
|
||||
bool end_station;
|
||||
bool scb;
|
||||
struct macsec_tx_sa __rcu *sa[MACSEC_NUM_AN];
|
||||
struct pcpu_tx_sc_stats __percpu *stats;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct macsec_secy - MACsec Security Entity
|
||||
* @netdev: netdevice for this SecY
|
||||
* @n_rx_sc: number of receive secure channels configured on this SecY
|
||||
* @sci: secure channel identifier used for tx
|
||||
* @key_len: length of keys used by the cipher suite
|
||||
* @icv_len: length of ICV used by the cipher suite
|
||||
* @validate_frames: validation mode
|
||||
* @xpn: enable XPN for this SecY
|
||||
* @operational: MAC_Operational flag
|
||||
* @protect_frames: enable protection for this SecY
|
||||
* @replay_protect: enable packet number checks on receive
|
||||
* @replay_window: size of the replay window
|
||||
* @tx_sc: transmit secure channel
|
||||
* @rx_sc: linked list of receive secure channels
|
||||
*/
|
||||
struct macsec_secy {
|
||||
struct net_device *netdev;
|
||||
unsigned int n_rx_sc;
|
||||
sci_t sci;
|
||||
u16 key_len;
|
||||
u16 icv_len;
|
||||
enum macsec_validation_type validate_frames;
|
||||
bool xpn;
|
||||
bool operational;
|
||||
bool protect_frames;
|
||||
bool replay_protect;
|
||||
u32 replay_window;
|
||||
struct macsec_tx_sc tx_sc;
|
||||
struct macsec_rx_sc __rcu *rx_sc;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct macsec_context - MACsec context for hardware offloading
|
||||
*/
|
||||
struct macsec_context {
|
||||
struct phy_device *phydev;
|
||||
enum macsec_offload offload;
|
||||
|
||||
struct macsec_secy *secy;
|
||||
struct macsec_rx_sc *rx_sc;
|
||||
struct {
|
||||
unsigned char assoc_num;
|
||||
u8 key[MACSEC_KEYID_LEN];
|
||||
union {
|
||||
struct macsec_rx_sa *rx_sa;
|
||||
struct macsec_tx_sa *tx_sa;
|
||||
};
|
||||
} sa;
|
||||
union {
|
||||
struct macsec_tx_sc_stats *tx_sc_stats;
|
||||
struct macsec_tx_sa_stats *tx_sa_stats;
|
||||
struct macsec_rx_sc_stats *rx_sc_stats;
|
||||
struct macsec_rx_sa_stats *rx_sa_stats;
|
||||
struct macsec_dev_stats *dev_stats;
|
||||
} stats;
|
||||
|
||||
u8 prepare:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct macsec_ops - MACsec offloading operations
|
||||
*/
|
||||
struct macsec_ops {
|
||||
/* Device wide */
|
||||
int (*mdo_dev_open)(struct macsec_context *ctx);
|
||||
int (*mdo_dev_stop)(struct macsec_context *ctx);
|
||||
/* SecY */
|
||||
int (*mdo_add_secy)(struct macsec_context *ctx);
|
||||
int (*mdo_upd_secy)(struct macsec_context *ctx);
|
||||
int (*mdo_del_secy)(struct macsec_context *ctx);
|
||||
/* Security channels */
|
||||
int (*mdo_add_rxsc)(struct macsec_context *ctx);
|
||||
int (*mdo_upd_rxsc)(struct macsec_context *ctx);
|
||||
int (*mdo_del_rxsc)(struct macsec_context *ctx);
|
||||
/* Security associations */
|
||||
int (*mdo_add_rxsa)(struct macsec_context *ctx);
|
||||
int (*mdo_upd_rxsa)(struct macsec_context *ctx);
|
||||
int (*mdo_del_rxsa)(struct macsec_context *ctx);
|
||||
int (*mdo_add_txsa)(struct macsec_context *ctx);
|
||||
int (*mdo_upd_txsa)(struct macsec_context *ctx);
|
||||
int (*mdo_del_txsa)(struct macsec_context *ctx);
|
||||
/* Statistics */
|
||||
int (*mdo_get_dev_stats)(struct macsec_context *ctx);
|
||||
int (*mdo_get_tx_sc_stats)(struct macsec_context *ctx);
|
||||
int (*mdo_get_tx_sa_stats)(struct macsec_context *ctx);
|
||||
int (*mdo_get_rx_sc_stats)(struct macsec_context *ctx);
|
||||
int (*mdo_get_rx_sa_stats)(struct macsec_context *ctx);
|
||||
};
|
||||
|
||||
void macsec_pn_wrapped(struct macsec_secy *secy, struct macsec_tx_sa *tx_sa);
|
||||
|
||||
#endif /* _NET_MACSEC_H_ */
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
#define POLLRDHUP 0x2000
|
||||
#endif
|
||||
|
||||
#define POLLFREE (__force __poll_t)0x4000 /* currently only for epoll */
|
||||
#define POLLFREE (__force __poll_t)0x4000
|
||||
|
||||
#define POLL_BUSY_LOOP (__force __poll_t)0x8000
|
||||
|
||||
|
|
|
|||
|
|
@ -265,6 +265,25 @@ struct binder_node_info_for_ref {
|
|||
__u32 reserved3;
|
||||
};
|
||||
|
||||
struct binder_freeze_info {
|
||||
__u32 pid;
|
||||
__u32 enable;
|
||||
__u32 timeout_ms;
|
||||
};
|
||||
|
||||
struct binder_frozen_status_info {
|
||||
__u32 pid;
|
||||
|
||||
/* process received sync transactions since last frozen
|
||||
* bit 0: received sync transaction after being frozen
|
||||
* bit 1: new pending sync transaction during freezing
|
||||
*/
|
||||
__u32 sync_recv;
|
||||
|
||||
/* process received async transactions since last frozen */
|
||||
__u32 async_recv;
|
||||
};
|
||||
|
||||
#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
|
||||
#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64)
|
||||
#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32)
|
||||
|
|
@ -275,6 +294,8 @@ struct binder_node_info_for_ref {
|
|||
#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info)
|
||||
#define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref)
|
||||
#define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object)
|
||||
#define BINDER_FREEZE _IOW('b', 14, struct binder_freeze_info)
|
||||
#define BINDER_GET_FROZEN_INFO _IOWR('b', 15, struct binder_frozen_status_info)
|
||||
|
||||
/*
|
||||
* NOTE: Two special error codes you should check for when calling
|
||||
|
|
@ -456,6 +477,12 @@ enum binder_driver_return_protocol {
|
|||
* The the last transaction (either a bcTRANSACTION or
|
||||
* a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters.
|
||||
*/
|
||||
|
||||
BR_FROZEN_REPLY = _IO('r', 18),
|
||||
/*
|
||||
* The target of the last transaction (either a bcTRANSACTION or
|
||||
* a bcATTEMPT_ACQUIRE) is frozen. No parameters.
|
||||
*/
|
||||
};
|
||||
|
||||
enum binder_driver_command_protocol {
|
||||
|
|
|
|||
|
|
@ -460,6 +460,7 @@ enum {
|
|||
IFLA_MACSEC_REPLAY_PROTECT,
|
||||
IFLA_MACSEC_VALIDATION,
|
||||
IFLA_MACSEC_PAD,
|
||||
IFLA_MACSEC_OFFLOAD,
|
||||
__IFLA_MACSEC_MAX,
|
||||
};
|
||||
|
||||
|
|
@ -483,6 +484,13 @@ enum macsec_validation_type {
|
|||
MACSEC_VALIDATE_MAX = __MACSEC_VALIDATE_END - 1,
|
||||
};
|
||||
|
||||
enum macsec_offload {
|
||||
MACSEC_OFFLOAD_OFF = 0,
|
||||
MACSEC_OFFLOAD_PHY = 1,
|
||||
__MACSEC_OFFLOAD_END,
|
||||
MACSEC_OFFLOAD_MAX = __MACSEC_OFFLOAD_END - 1,
|
||||
};
|
||||
|
||||
/* IPVLAN section */
|
||||
enum {
|
||||
IFLA_IPVLAN_UNSPEC,
|
||||
|
|
|
|||
|
|
@ -22,9 +22,11 @@
|
|||
|
||||
#define MACSEC_KEYID_LEN 16
|
||||
|
||||
/* cipher IDs as per IEEE802.1AEbn-2011 */
|
||||
/* cipher IDs as per IEEE802.1AE-2018 (Table 14-1) */
|
||||
#define MACSEC_CIPHER_ID_GCM_AES_128 0x0080C20001000001ULL
|
||||
#define MACSEC_CIPHER_ID_GCM_AES_256 0x0080C20001000002ULL
|
||||
#define MACSEC_CIPHER_ID_GCM_AES_XPN_128 0x0080C20001000003ULL
|
||||
#define MACSEC_CIPHER_ID_GCM_AES_XPN_256 0x0080C20001000004ULL
|
||||
|
||||
/* deprecated cipher ID for GCM-AES-128 */
|
||||
#define MACSEC_DEFAULT_CIPHER_ID 0x0080020001000001ULL
|
||||
|
|
@ -45,6 +47,7 @@ enum macsec_attrs {
|
|||
MACSEC_ATTR_RXSC_LIST, /* dump, nested, macsec_rxsc_attrs for each RXSC */
|
||||
MACSEC_ATTR_TXSC_STATS, /* dump, nested, macsec_txsc_stats_attr */
|
||||
MACSEC_ATTR_SECY_STATS, /* dump, nested, macsec_secy_stats_attr */
|
||||
MACSEC_ATTR_OFFLOAD, /* config, nested, macsec_offload_attrs */
|
||||
__MACSEC_ATTR_END,
|
||||
NUM_MACSEC_ATTR = __MACSEC_ATTR_END,
|
||||
MACSEC_ATTR_MAX = __MACSEC_ATTR_END - 1,
|
||||
|
|
@ -87,16 +90,27 @@ enum macsec_sa_attrs {
|
|||
MACSEC_SA_ATTR_UNSPEC,
|
||||
MACSEC_SA_ATTR_AN, /* config/dump, u8 0..3 */
|
||||
MACSEC_SA_ATTR_ACTIVE, /* config/dump, u8 0..1 */
|
||||
MACSEC_SA_ATTR_PN, /* config/dump, u32 */
|
||||
MACSEC_SA_ATTR_PN, /* config/dump, u32/u64 (u64 if XPN) */
|
||||
MACSEC_SA_ATTR_KEY, /* config, data */
|
||||
MACSEC_SA_ATTR_KEYID, /* config/dump, 128-bit */
|
||||
MACSEC_SA_ATTR_STATS, /* dump, nested, macsec_sa_stats_attr */
|
||||
MACSEC_SA_ATTR_PAD,
|
||||
MACSEC_SA_ATTR_SSCI, /* config/dump, u32 - XPN only */
|
||||
MACSEC_SA_ATTR_SALT, /* config, 96-bit - XPN only */
|
||||
__MACSEC_SA_ATTR_END,
|
||||
NUM_MACSEC_SA_ATTR = __MACSEC_SA_ATTR_END,
|
||||
MACSEC_SA_ATTR_MAX = __MACSEC_SA_ATTR_END - 1,
|
||||
};
|
||||
|
||||
enum macsec_offload_attrs {
|
||||
MACSEC_OFFLOAD_ATTR_UNSPEC,
|
||||
MACSEC_OFFLOAD_ATTR_TYPE, /* config/dump, u8 0..2 */
|
||||
MACSEC_OFFLOAD_ATTR_PAD,
|
||||
__MACSEC_OFFLOAD_ATTR_END,
|
||||
NUM_MACSEC_OFFLOAD_ATTR = __MACSEC_OFFLOAD_ATTR_END,
|
||||
MACSEC_OFFLOAD_ATTR_MAX = __MACSEC_OFFLOAD_ATTR_END - 1,
|
||||
};
|
||||
|
||||
enum macsec_nl_commands {
|
||||
MACSEC_CMD_GET_TXSC,
|
||||
MACSEC_CMD_ADD_RXSC,
|
||||
|
|
@ -108,6 +122,7 @@ enum macsec_nl_commands {
|
|||
MACSEC_CMD_ADD_RXSA,
|
||||
MACSEC_CMD_DEL_RXSA,
|
||||
MACSEC_CMD_UPD_RXSA,
|
||||
MACSEC_CMD_UPD_OFFLOAD,
|
||||
};
|
||||
|
||||
/* u64 per-RXSC stats */
|
||||
|
|
|
|||
|
|
@ -385,6 +385,22 @@ struct ipa_init_modem_driver_req_msg_v01 {
|
|||
*/
|
||||
__u8 hw_fiter_stats_info_valid;
|
||||
struct ipa_filter_stats_info_type_v01 hw_filter_stats_info;
|
||||
|
||||
/* optional
|
||||
* Filter table smem info
|
||||
* Must be set to true if smem_info
|
||||
* is being passed(Currently not using it)
|
||||
*/
|
||||
__u8 smem_info_valid;
|
||||
struct ipa_modem_mem_info_type_v01 smem_info;
|
||||
|
||||
/* optional
|
||||
* IPA Peripheral stats info
|
||||
* Must be set to true if per_stats_info
|
||||
* is being passed
|
||||
*/
|
||||
__u8 per_stats_smem_info_valid;
|
||||
struct ipa_modem_mem_info_type_v01 per_stats_smem_info;
|
||||
}; /* Message */
|
||||
|
||||
/* Response Message; Requests the modem IPA driver about initialization */
|
||||
|
|
@ -2825,7 +2841,7 @@ struct ipa_move_nat_table_complt_ind_msg_v01 {
|
|||
#define QMI_IPA_MOVE_NAT_COMPLETE_IND_V01 0x0046
|
||||
|
||||
/* add for max length*/
|
||||
#define QMI_IPA_INIT_MODEM_DRIVER_REQ_MAX_MSG_LEN_V01 186
|
||||
#define QMI_IPA_INIT_MODEM_DRIVER_REQ_MAX_MSG_LEN_V01 210
|
||||
#define QMI_IPA_INIT_MODEM_DRIVER_RESP_MAX_MSG_LEN_V01 25
|
||||
#define QMI_IPA_INDICATION_REGISTER_REQ_MAX_MSG_LEN_V01 16
|
||||
#define QMI_IPA_INDICATION_REGISTER_RESP_MAX_MSG_LEN_V01 7
|
||||
|
|
|
|||
|
|
@ -206,6 +206,13 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode, int nr_e
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */
|
||||
|
||||
void __wake_up_pollfree(struct wait_queue_head *wq_head)
|
||||
{
|
||||
__wake_up(wq_head, TASK_NORMAL, 0, poll_to_key(EPOLLHUP | POLLFREE));
|
||||
/* POLLFREE must have cleared the queue. */
|
||||
WARN_ON_ONCE(waitqueue_active(wq_head));
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: we use "set_current_state()" _after_ the wait-queue add,
|
||||
* because we need a memory barrier there on SMP, so that any
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@ if test $# -gt 0; then
|
|||
kmi_generation=$1
|
||||
[ $(expr $kmi_generation : '^[0-9]\+$') -eq 0 ] && usage
|
||||
shift
|
||||
else
|
||||
usage
|
||||
fi
|
||||
fi
|
||||
if test $# -gt 0 -o ! -d "$srctree"; then
|
||||
|
|
@ -69,6 +67,8 @@ scm_version()
|
|||
|
||||
if [ -n "$android_release" ] && [ -n "$kmi_generation" ]; then
|
||||
printf '%s' "-$android_release-$kmi_generation"
|
||||
elif [ -n "$android_release" ]; then
|
||||
printf '%s' "-$android_release"
|
||||
fi
|
||||
|
||||
# If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
|
||||
|
|
|
|||
|
|
@ -670,25 +670,25 @@ static void __init lsm_early_task(struct task_struct *task)
|
|||
|
||||
/* Security operations */
|
||||
|
||||
int security_binder_set_context_mgr(struct task_struct *mgr)
|
||||
int security_binder_set_context_mgr(const struct cred *mgr)
|
||||
{
|
||||
return call_int_hook(binder_set_context_mgr, 0, mgr);
|
||||
}
|
||||
|
||||
int security_binder_transaction(struct task_struct *from,
|
||||
struct task_struct *to)
|
||||
int security_binder_transaction(const struct cred *from,
|
||||
const struct cred *to)
|
||||
{
|
||||
return call_int_hook(binder_transaction, 0, from, to);
|
||||
}
|
||||
|
||||
int security_binder_transfer_binder(struct task_struct *from,
|
||||
struct task_struct *to)
|
||||
int security_binder_transfer_binder(const struct cred *from,
|
||||
const struct cred *to)
|
||||
{
|
||||
return call_int_hook(binder_transfer_binder, 0, from, to);
|
||||
}
|
||||
|
||||
int security_binder_transfer_file(struct task_struct *from,
|
||||
struct task_struct *to, struct file *file)
|
||||
int security_binder_transfer_file(const struct cred *from,
|
||||
const struct cred *to, struct file *file)
|
||||
{
|
||||
return call_int_hook(binder_transfer_file, 0, from, to, file);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2059,22 +2059,19 @@ static inline u32 open_file_to_av(struct file *file)
|
|||
|
||||
/* Hook functions begin here. */
|
||||
|
||||
static int selinux_binder_set_context_mgr(struct task_struct *mgr)
|
||||
static int selinux_binder_set_context_mgr(const struct cred *mgr)
|
||||
{
|
||||
u32 mysid = current_sid();
|
||||
u32 mgrsid = task_sid(mgr);
|
||||
|
||||
return avc_has_perm(&selinux_state,
|
||||
mysid, mgrsid, SECCLASS_BINDER,
|
||||
current_sid(), cred_sid(mgr), SECCLASS_BINDER,
|
||||
BINDER__SET_CONTEXT_MGR, NULL);
|
||||
}
|
||||
|
||||
static int selinux_binder_transaction(struct task_struct *from,
|
||||
struct task_struct *to)
|
||||
static int selinux_binder_transaction(const struct cred *from,
|
||||
const struct cred *to)
|
||||
{
|
||||
u32 mysid = current_sid();
|
||||
u32 fromsid = task_sid(from);
|
||||
u32 tosid = task_sid(to);
|
||||
u32 fromsid = cred_sid(from);
|
||||
u32 tosid = cred_sid(to);
|
||||
int rc;
|
||||
|
||||
if (mysid != fromsid) {
|
||||
|
|
@ -2085,27 +2082,24 @@ static int selinux_binder_transaction(struct task_struct *from,
|
|||
return rc;
|
||||
}
|
||||
|
||||
return avc_has_perm(&selinux_state,
|
||||
fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
|
||||
NULL);
|
||||
return avc_has_perm(&selinux_state, fromsid, tosid,
|
||||
SECCLASS_BINDER, BINDER__CALL, NULL);
|
||||
}
|
||||
|
||||
static int selinux_binder_transfer_binder(struct task_struct *from,
|
||||
struct task_struct *to)
|
||||
static int selinux_binder_transfer_binder(const struct cred *from,
|
||||
const struct cred *to)
|
||||
{
|
||||
u32 fromsid = task_sid(from);
|
||||
u32 tosid = task_sid(to);
|
||||
|
||||
return avc_has_perm(&selinux_state,
|
||||
fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
|
||||
cred_sid(from), cred_sid(to),
|
||||
SECCLASS_BINDER, BINDER__TRANSFER,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static int selinux_binder_transfer_file(struct task_struct *from,
|
||||
struct task_struct *to,
|
||||
static int selinux_binder_transfer_file(const struct cred *from,
|
||||
const struct cred *to,
|
||||
struct file *file)
|
||||
{
|
||||
u32 sid = task_sid(to);
|
||||
u32 sid = cred_sid(to);
|
||||
struct file_security_struct *fsec = selinux_file(file);
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
struct inode_security_struct *isec;
|
||||
|
|
|
|||
|
|
@ -460,6 +460,7 @@ enum {
|
|||
IFLA_MACSEC_REPLAY_PROTECT,
|
||||
IFLA_MACSEC_VALIDATION,
|
||||
IFLA_MACSEC_PAD,
|
||||
IFLA_MACSEC_OFFLOAD,
|
||||
__IFLA_MACSEC_MAX,
|
||||
};
|
||||
|
||||
|
|
@ -483,6 +484,13 @@ enum macsec_validation_type {
|
|||
MACSEC_VALIDATE_MAX = __MACSEC_VALIDATE_END - 1,
|
||||
};
|
||||
|
||||
enum macsec_offload {
|
||||
MACSEC_OFFLOAD_OFF = 0,
|
||||
MACSEC_OFFLOAD_PHY = 1,
|
||||
__MACSEC_OFFLOAD_END,
|
||||
MACSEC_OFFLOAD_MAX = __MACSEC_OFFLOAD_END - 1,
|
||||
};
|
||||
|
||||
/* IPVLAN section */
|
||||
enum {
|
||||
IFLA_IPVLAN_UNSPEC,
|
||||
|
|
|
|||
Loading…
Reference in a new issue