diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index bf65e24225a0..975f617613b8 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -949,12 +949,14 @@ icmp_ratelimit - INTEGER icmp_msgs_per_sec - INTEGER Limit maximal number of ICMP packets sent per second from this host. Only messages whose type matches icmp_ratemask (see below) are - controlled by this limit. + controlled by this limit. For security reasons, the precise count + of messages per second is randomized. Default: 1000 icmp_msgs_burst - INTEGER icmp_msgs_per_sec controls number of ICMP packets sent per second, while icmp_msgs_burst controls the burst size of these packets. + For security reasons, the precise burst size is randomized. Default: 50 icmp_ratemask - INTEGER diff --git a/arch/arm64/configs/vendor/f2q_kor_singlex_defconfig b/arch/arm64/configs/vendor/f2q_kor_singlex_defconfig index 98d500956eaf..72053c7375e4 100644 --- a/arch/arm64/configs/vendor/f2q_kor_singlex_defconfig +++ b/arch/arm64/configs/vendor/f2q_kor_singlex_defconfig @@ -6101,7 +6101,7 @@ CONFIG_FIVE_TEE_DRIVER=y # CONFIG_FIVE_USE_EMULATOR is not set CONFIG_FIVE_USE_QSEE=y # CONFIG_TEE_DRIVER_DEBUG is not set -CONFIG_FIVE_EARLY_LOAD_TRUSTED_APP=y +# CONFIG_FIVE_EARLY_LOAD_TRUSTED_APP is not set CONFIG_FIVE_SIGN_TA=n CONFIG_FIVE_SIGNCLIENT_PATH="/home/dpi/qb5_8815/workspace/P4_1716/buildscript/tools/signclient.jar" CONFIG_FIVE_PILSPLITTER_PATH="/home/dpi/qb5_8815/workspace/P4_1716/buildscript/tools/pil_splitter.py" @@ -6425,7 +6425,7 @@ CONFIG_INTEGRITY_AUDIT=y CONFIG_SECURITY_DEFEX=y # CONFIG_DEFEX_KERNEL_ONLY is not set CONFIG_SECURITY_DSMS=y -CONFIG_FIVE=n +CONFIG_FIVE=y # CONFIG_FIVE_DEBUG is not set CONFIG_FIVE_CERT_USER="x509_five_user.der" CONFIG_FIVE_DEFAULT_HASH_SHA1=y diff --git a/drivers/battery_v2/sec_battery.c b/drivers/battery_v2/sec_battery.c index 50a8263da576..769ff7bfe7ed 100644 --- a/drivers/battery_v2/sec_battery.c +++ b/drivers/battery_v2/sec_battery.c @@ -1598,10 +1598,7 @@ int sec_bat_set_charging_current(struct sec_battery_info *battery) #if defined(CONFIG_DUAL_BATTERY) sec_bat_divide_charging_current(battery, charging_current); -#endif - -#if defined(CONFIG_DUAL_BATTERY) - if (battery->charging_current < charging_current) + if (battery->charging_current <= charging_current) sec_bat_set_divide_charging_current(battery); #endif diff --git a/drivers/battery_v2/sec_step_charging.c b/drivers/battery_v2/sec_step_charging.c index 3b666cd747f7..f63ed8a5fc27 100644 --- a/drivers/battery_v2/sec_step_charging.c +++ b/drivers/battery_v2/sec_step_charging.c @@ -446,6 +446,9 @@ bool sec_bat_check_dc_step_charging(struct sec_battery_info *battery) val.intval = battery->pdata->dc_step_chg_val_iout[battery->pdata->age_step][step] / 2; psy_do_property(battery->pdata->charger_name, set, POWER_SUPPLY_EXT_PROP_DIRECT_CURRENT_MAX, val); + + /* updated charging current */ + battery->charging_current = battery->pdata->dc_step_chg_val_iout[battery->pdata->age_step][step]; } battery->step_charging_status = step; @@ -775,7 +778,8 @@ void sec_bat_set_aging_info_step_charging(struct sec_battery_info *battery) if (battery->pdata->dc_step_chg_val_vfloat[battery->pdata->age_step][i] > battery->pdata->chg_float_voltage) battery->pdata->dc_step_chg_val_vfloat[battery->pdata->age_step][i] = battery->pdata->chg_float_voltage; if (battery->dc_step_chg_type & STEP_CHARGING_CONDITION_VOLTAGE) - battery->pdata->dc_step_chg_cond_vol[i] = battery->pdata->dc_step_chg_val_vfloat[battery->pdata->age_step][i]; + if (battery->pdata->dc_step_chg_cond_vol[i] > battery->pdata->chg_float_voltage) + battery->pdata->dc_step_chg_cond_vol[i] = battery->pdata->chg_float_voltage; if ((battery->dc_step_chg_type & STEP_CHARGING_CONDITION_INPUT_CURRENT) && (i < battery->dc_step_chg_step - 1)) battery->pdata->dc_step_chg_cond_iin[i] = battery->pdata->dc_step_chg_val_iout[battery->pdata->age_step][i+1] / 2; } diff --git a/drivers/bus/mhi/core/mhi_pm.c b/drivers/bus/mhi/core/mhi_pm.c index 6816ac1ae477..6e3998688b58 100644 --- a/drivers/bus/mhi/core/mhi_pm.c +++ b/drivers/bus/mhi/core/mhi_pm.c @@ -631,8 +631,7 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, /* trigger MHI RESET so device will not access host ddr */ if (MHI_REG_ACCESS_VALID(prev_state)) { - /* MHI_RESET always timed-out, give 1000 msec for graceful reset */ - unsigned long timeout = msecs_to_jiffies(1000); + unsigned long timeout = msecs_to_jiffies(mhi_cntrl->timeout_ms); if (system_state == SYSTEM_POWER_OFF) { MHI_ERR("Do not Trigger device MHI_RESET, late shutdown\n"); diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 584b0cbd8df5..2efaf5b0e6c7 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -3284,13 +3284,15 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl, mutex_unlock(&fl->map_mutex); if (err) goto bail; - VERIFY(err, !fastrpc_munmap_on_dsp(fl, map->raddr, - map->phys, map->size, map->flags)); - if (err) - goto bail; - mutex_lock(&fl->map_mutex); - fastrpc_mmap_free(map, 0); - mutex_unlock(&fl->map_mutex); + if (map) { + VERIFY(err, !fastrpc_munmap_on_dsp(fl, map->raddr, + map->phys, map->size, map->flags)); + if (err) + goto bail; + mutex_lock(&fl->map_mutex); + fastrpc_mmap_free(map, 0); + mutex_unlock(&fl->map_mutex); + } bail: if (err && map) { mutex_lock(&fl->map_mutex); diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c index eb729b87f936..d67945724643 100644 --- a/drivers/gpu/msm/adreno_debugfs.c +++ b/drivers/gpu/msm/adreno_debugfs.c @@ -291,7 +291,7 @@ static int ctx_print(struct seq_file *s, void *unused) ctx_type_str(drawctxt->type), drawctxt->base.priority, drawctxt->base.proc_priv->comm, - drawctxt->base.proc_priv->pid, + pid_nr(drawctxt->base.proc_priv->pid), drawctxt->base.tid); seq_puts(s, "flags: "); diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 076ca9c0bae1..9f89df40dbd3 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -1670,7 +1670,7 @@ static inline const char *_kgsl_context_comm(struct kgsl_context *context) #define pr_fault(_d, _c, fmt, args...) \ dev_err((_d)->dev, "%s[%d]: " fmt, \ _kgsl_context_comm((_c)->context), \ - (_c)->context->proc_priv->pid, ##args) + pid_nr((_c)->context->proc_priv->pid), ##args) static void adreno_fault_header(struct kgsl_device *device, diff --git a/drivers/gpu/msm/adreno_profile.c b/drivers/gpu/msm/adreno_profile.c index 9e3740d6a9a9..b1b26fee8745 100644 --- a/drivers/gpu/msm/adreno_profile.c +++ b/drivers/gpu/msm/adreno_profile.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. */ #include @@ -131,7 +131,7 @@ static int _build_pre_ib_cmds(struct adreno_device *adreno_dev, ibcmds += _ib_cmd_mem_write(adreno_dev, ibcmds, gpuaddr + data_offset, drawctxt->base.id, &data_offset); ibcmds += _ib_cmd_mem_write(adreno_dev, ibcmds, gpuaddr + data_offset, - drawctxt->base.proc_priv->pid, &data_offset); + pid_nr(drawctxt->base.proc_priv->pid), &data_offset); ibcmds += _ib_cmd_mem_write(adreno_dev, ibcmds, gpuaddr + data_offset, drawctxt->base.tid, &data_offset); ibcmds += _ib_cmd_mem_write(adreno_dev, ibcmds, gpuaddr + data_offset, diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 9fd5b9f2b5d2..3a8752c5d897 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2008-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2008-2021, The Linux Foundation. All rights reserved. */ #include @@ -235,6 +235,7 @@ static struct kgsl_mem_entry *kgsl_mem_entry_create(void) kref_get(&entry->refcount); } + atomic_set(&entry->map_count, 0); return entry; } @@ -502,9 +503,6 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) idr_remove(&entry->priv->mem_idr, entry->id); entry->id = 0; - atomic_long_sub(atomic_long_read(&entry->memdesc.mapsize), - &entry->priv->gpumem_mapped); - spin_unlock(&entry->priv->mem_lock); kgsl_mmu_put_gpuaddr(&entry->memdesc); @@ -589,7 +587,7 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv, if (atomic_read(&proc_priv->ctxt_count) > KGSL_MAX_CONTEXTS_PER_PROC) { dev_err(device->dev, "Per process context limit reached for pid %u\n", - dev_priv->process_priv->pid); + pid_nr(dev_priv->process_priv->pid)); spin_unlock(&proc_priv->ctxt_count_lock); return -ENOSPC; } @@ -907,6 +905,7 @@ static void kgsl_destroy_process_private(struct kref *kref) struct kgsl_process_private *private = container_of(kref, struct kgsl_process_private, refcount); + put_pid(private->pid); idr_destroy(&private->mem_idr); idr_destroy(&private->syncsource_idr); @@ -936,7 +935,7 @@ struct kgsl_process_private *kgsl_process_private_find(pid_t pid) spin_lock(&kgsl_driver.proclist_lock); list_for_each_entry(p, &kgsl_driver.process_list, list) { - if (p->pid == pid) { + if (pid_nr(p->pid) == pid) { if (kgsl_process_private_get(p)) private = p; break; @@ -1016,17 +1015,9 @@ static void kgsl_svm_addr_log_print(struct kgsl_process_private *private) m = &entry->memdesc; kgsl_get_memory_usage(usage, sizeof(usage), m->flags); - if (m->useraddr) { - pr_err("%s : %p %p %16llu %5d %16s\n", __func__, - (uint64_t *)(uintptr_t) m->gpuaddr, - (unsigned long *) m->useraddr, - m->size, entry->id, usage); - } else { - pr_err("%s : %p %pK %16llu %5d %16s\n", __func__, - (uint64_t *)(uintptr_t) m->gpuaddr, - (unsigned long *) m->useraddr, - m->size, entry->id, usage); - } + pr_err("%s : %p %p %16llu %5d %16s\n", __func__, + (uint64_t *)(uintptr_t) m->gpuaddr, 0, + m->size, entry->id, usage); } spin_unlock(&private->mem_lock); @@ -1126,7 +1117,7 @@ static struct kgsl_process_private *kgsl_process_private_new( struct kgsl_device *device) { struct kgsl_process_private *private; - pid_t tgid = task_tgid_nr(current); + struct pid *cur_pid = get_task_pid(current->group_leader, PIDTYPE_PID); /* * Flush mem_workqueue to make sure that any lingering @@ -1137,21 +1128,30 @@ static struct kgsl_process_private *kgsl_process_private_new( /* Search in the process list */ list_for_each_entry(private, &kgsl_driver.process_list, list) { - if (private->pid == tgid) { - if (!kgsl_process_private_get(private)) + if (private->pid == cur_pid) { + if (!kgsl_process_private_get(private)) { private = ERR_PTR(-EINVAL); + } + /* + * We need to hold only one reference to the PID for + * each process struct to avoid overflowing the + * reference counter which can lead to use-after-free. + */ + put_pid(cur_pid); return private; } } /* Create a new object */ private = kzalloc(sizeof(struct kgsl_process_private), GFP_KERNEL); - if (private == NULL) + if (private == NULL) { + put_pid(cur_pid); return ERR_PTR(-ENOMEM); + } kref_init(&private->refcount); - private->pid = tgid; + private->pid = cur_pid; get_task_comm(private->comm, current->group_leader); spin_lock_init(&private->mem_lock); @@ -1164,12 +1164,14 @@ static struct kgsl_process_private *kgsl_process_private_new( kgsl_reclaim_proc_private_init(private); /* Allocate a pagetable for the new process object */ - private->pagetable = kgsl_mmu_getpagetable(&device->mmu, tgid); + private->pagetable = kgsl_mmu_getpagetable(&device->mmu, + pid_nr(cur_pid)); if (IS_ERR(private->pagetable)) { int err = PTR_ERR(private->pagetable); idr_destroy(&private->mem_idr); idr_destroy(&private->syncsource_idr); + put_pid(private->pid); kfree(private); private = ERR_PTR(err); @@ -2348,7 +2350,7 @@ long gpumem_free_entry(struct kgsl_mem_entry *entry) return -EBUSY; trace_kgsl_mem_free(entry); - kgsl_memfree_add(entry->priv->pid, + kgsl_memfree_add(pid_nr(entry->priv->pid), entry->memdesc.pagetable ? entry->memdesc.pagetable->name : 0, entry->memdesc.gpuaddr, entry->memdesc.size, @@ -2371,7 +2373,7 @@ static void gpumem_free_func(struct kgsl_device *device, /* Free the memory for all event types */ trace_kgsl_mem_timestamp_free(device, entry, KGSL_CONTEXT_ID(context), timestamp, 0); - kgsl_memfree_add(entry->priv->pid, + kgsl_memfree_add(pid_nr(entry->priv->pid), entry->memdesc.pagetable ? entry->memdesc.pagetable->name : 0, entry->memdesc.gpuaddr, entry->memdesc.size, @@ -2471,7 +2473,7 @@ static bool gpuobj_free_fence_func(void *priv) struct kgsl_mem_entry *entry = priv; trace_kgsl_mem_free(entry); - kgsl_memfree_add(entry->priv->pid, + kgsl_memfree_add(pid_nr(entry->priv->pid), entry->memdesc.pagetable ? entry->memdesc.pagetable->name : 0, entry->memdesc.gpuaddr, entry->memdesc.size, @@ -2578,14 +2580,6 @@ long kgsl_ioctl_cmdstream_freememontimestamp_ctxtid( return ret; } -static inline int _check_region(unsigned long start, unsigned long size, - uint64_t len) -{ - uint64_t end = ((uint64_t) start) + size; - - return (end > len); -} - static int check_vma_flags(struct vm_area_struct *vma, unsigned int flags) { @@ -2600,23 +2594,27 @@ static int check_vma_flags(struct vm_area_struct *vma, return -EFAULT; } -static int check_vma(struct vm_area_struct *vma, struct file *vmfile, - struct kgsl_memdesc *memdesc) +static int check_vma(unsigned long hostptr, u64 size) { - if (vma == NULL || vma->vm_file != vmfile) - return -EINVAL; + struct vm_area_struct *vma; + unsigned long cur = hostptr; - /* userspace may not know the size, in which case use the whole vma */ - if (memdesc->size == 0) - memdesc->size = vma->vm_end - vma->vm_start; - /* range checking */ - if (vma->vm_start != memdesc->useraddr || - (memdesc->useraddr + memdesc->size) != vma->vm_end) - return -EINVAL; - return check_vma_flags(vma, memdesc->flags); + while (cur < (hostptr + size)) { + vma = find_vma(current->mm, cur); + if (!vma) + return false; + + /* Don't remap memory that we already own */ + if (vma->vm_file && vma->vm_file->f_op == &kgsl_fops) + return false; + + cur = vma->vm_end; } -static int memdesc_sg_virt(struct kgsl_memdesc *memdesc, struct file *vmfile) + return true; +} + +static int memdesc_sg_virt(struct kgsl_memdesc *memdesc, unsigned long useraddr) { int ret = 0; long npages = 0, i; @@ -2639,18 +2637,16 @@ static int memdesc_sg_virt(struct kgsl_memdesc *memdesc, struct file *vmfile) } down_read(¤t->mm->mmap_sem); - /* If we have vmfile, make sure we map the correct vma and map it all */ - if (vmfile != NULL) - ret = check_vma(find_vma(current->mm, memdesc->useraddr), - vmfile, memdesc); - - if (ret == 0) { - npages = get_user_pages(memdesc->useraddr, - sglen, write, pages, NULL); - ret = (npages < 0) ? (int)npages : 0; + if (!check_vma(useraddr, memdesc->size)) { + up_read(¤t->mm->mmap_sem); + ret = -EFAULT; + goto out; } + + npages = get_user_pages(useraddr, sglen, write, pages, NULL); up_read(¤t->mm->mmap_sem); + ret = (npages < 0) ? (int)npages : 0; if (ret) goto out; @@ -2678,6 +2674,7 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, size_t offset, size_t size) { /* Map an anonymous memory chunk */ + int ret; if (size == 0 || offset != 0 || !IS_ALIGNED(size, PAGE_SIZE)) @@ -2685,23 +2682,25 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, entry->memdesc.pagetable = pagetable; entry->memdesc.size = (uint64_t) size; - entry->memdesc.useraddr = hostptr; entry->memdesc.flags |= (uint64_t)KGSL_MEMFLAGS_USERMEM_ADDR; if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { - int ret; - /* Register the address in the database */ ret = kgsl_mmu_set_svm_region(pagetable, - (uint64_t) entry->memdesc.useraddr, (uint64_t) size); + (uint64_t) hostptr, (uint64_t) size); if (ret) return ret; - entry->memdesc.gpuaddr = (uint64_t) entry->memdesc.useraddr; + entry->memdesc.gpuaddr = (uint64_t) hostptr; } - return memdesc_sg_virt(&entry->memdesc, NULL); + ret = memdesc_sg_virt(&entry->memdesc, hostptr); + + if (ret && kgsl_memdesc_use_cpu_map(&entry->memdesc)) + kgsl_mmu_put_gpuaddr(&entry->memdesc); + + return ret; } #ifdef CONFIG_DMA_SHARED_BUFFER @@ -2786,8 +2785,7 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device, return ret; } - /* Setup the user addr/cache mode for cache operations */ - entry->memdesc.useraddr = hostptr; + /* Setup the cache mode for cache operations */ _setup_cache_mode(entry, vma); up_read(¤t->mm->mmap_sem); return 0; @@ -3832,7 +3830,12 @@ long kgsl_ioctl_gpumem_get_info(struct kgsl_device_private *dev_priv, param->flags = (unsigned int) entry->memdesc.flags; param->size = (size_t) entry->memdesc.size; param->mmapsize = (size_t) kgsl_memdesc_footprint(&entry->memdesc); - param->useraddr = entry->memdesc.useraddr; + /* + * Entries can have multiple user mappings so thre isn't any one address + * we can report. Plus, the user should already know their mappings, so + * there isn't any value in reporting it back to them. + */ + param->useraddr = 0; kgsl_mem_entry_put(entry); return result; @@ -4305,9 +4308,6 @@ static int _sparse_bind(struct kgsl_process_private *process, if (memdesc->gpuaddr) return -EINVAL; - if (memdesc->useraddr != 0) - return -EINVAL; - pagetable = memdesc->pagetable; /* Clear out any mappings */ @@ -4588,7 +4588,12 @@ long kgsl_ioctl_gpuobj_info(struct kgsl_device_private *dev_priv, param->flags = entry->memdesc.flags; param->size = entry->memdesc.size; param->va_len = kgsl_memdesc_footprint(&entry->memdesc); - param->va_addr = (uint64_t) entry->memdesc.useraddr; + /* + * Entries can have multiple user mappings so thre isn't any one address + * we can report. Plus, the user should already know their mappings, so + * there isn't any value in reporting it back to them. + */ + param->va_addr = 0; kgsl_mem_entry_put(entry); return 0; @@ -4696,24 +4701,21 @@ static void kgsl_gpumem_vm_open(struct vm_area_struct *vma) if (kgsl_mem_entry_get(entry) == 0) vma->vm_private_data = NULL; + + atomic_inc(&entry->map_count); } static int kgsl_gpumem_vm_fault(struct vm_fault *vmf) { struct kgsl_mem_entry *entry = vmf->vma->vm_private_data; - int ret; if (!entry) return VM_FAULT_SIGBUS; if (!entry->memdesc.ops || !entry->memdesc.ops->vmfault) return VM_FAULT_SIGBUS; - ret = entry->memdesc.ops->vmfault(&entry->memdesc, vmf->vma, vmf); - if ((ret == 0) || (ret == VM_FAULT_NOPAGE)) - atomic_long_add(PAGE_SIZE, &entry->priv->gpumem_mapped); - - return ret; + return entry->memdesc.ops->vmfault(&entry->memdesc, vmf->vma, vmf); } static void @@ -4724,7 +4726,14 @@ kgsl_gpumem_vm_close(struct vm_area_struct *vma) if (!entry) return; - entry->memdesc.useraddr = 0; + /* + * Remove the memdesc from the mapped stat once all the mappings have + * gone away + */ + if (!atomic_dec_return(&entry->map_count)) + atomic_long_sub(entry->memdesc.size, + &entry->priv->gpumem_mapped); + kgsl_mem_entry_put_deferred(entry); } @@ -4763,7 +4772,8 @@ get_mmap_entry(struct kgsl_process_private *private, } } - if (entry->memdesc.useraddr != 0) { + /* Don't allow ourselves to remap user memory */ + if (entry->memdesc.flags & KGSL_MEMFLAGS_USERMEM_ADDR) { ret = -EBUSY; goto err_put; } @@ -4796,19 +4806,34 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private, { int ret; + /* + * Protect access to the gpuaddr here to prevent multiple vmas from + * trying to map a SVM region at the same time + */ + spin_lock(&entry->memdesc.gpuaddr_lock); + + if (entry->memdesc.gpuaddr) { + spin_unlock(&entry->memdesc.gpuaddr_lock); + return (unsigned long) -EBUSY; + } + ret = kgsl_mmu_set_svm_region(private->pagetable, (uint64_t) addr, (uint64_t) size); - if (ret != 0) - return ret; + if (ret != 0) { + spin_unlock(&entry->memdesc.gpuaddr_lock); + return (unsigned long) ret; + } entry->memdesc.gpuaddr = (uint64_t) addr; + spin_unlock(&entry->memdesc.gpuaddr_lock); + entry->memdesc.pagetable = private->pagetable; ret = kgsl_mmu_map(private->pagetable, &entry->memdesc); if (ret) { kgsl_mmu_put_gpuaddr(&entry->memdesc); - return ret; + return (unsigned long) ret; } kgsl_memfree_purge(private->pagetable, entry->memdesc.gpuaddr, @@ -4872,6 +4897,14 @@ static unsigned long _search_range(struct kgsl_process_private *private, result = _gpu_set_svm_region(private, entry, cpu, len); if (!IS_ERR_VALUE(result)) break; + /* + * _gpu_set_svm_region will return -EBUSY if we tried to set up + * SVM on an object that already has a GPU address. If + * that happens don't bother walking the rest of the + * region + */ + if ((long) result == -EBUSY) + return -EBUSY; trace_kgsl_mem_unmapped_area_collision(entry, cpu, len); @@ -5012,21 +5045,21 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr, if (IS_ERR_VALUE(val)) dev_err_ratelimited(device->dev, "get_unmapped_area: pid %d addr %lx pgoff %lx len %ld failed error %d\n", - private->pid, addr, pgoff, len, - (int) val); + pid_nr(private->pid), addr, + pgoff, len, (int) val); } else { val = _get_svm_area(private, entry, addr, len, flags); if (IS_ERR_VALUE(val)) dev_err_ratelimited(device->dev, "_get_svm_area: pid %d mmap_base %lx addr %lx pgoff %lx len %ld failed error %d\n", - private->pid, + pid_nr(private->pid), current->mm->mmap_base, addr, pgoff, len, (int) val); #if defined(CONFIG_DISPLAY_SAMSUNG) if (IS_ERR_VALUE(val)) { - kgsl_svm_addr_mapping_log(device, private->pid); - kgsl_svm_addr_hole_log(device, private->pid, entry->memdesc.flags); + kgsl_svm_addr_mapping_log(device, pid_nr(private->pid)); + kgsl_svm_addr_hole_log(device, pid_nr(private->pid), entry->memdesc.flags); } #endif } @@ -5100,14 +5133,11 @@ static int kgsl_mmap(struct file *file, struct vm_area_struct *vma) vm_insert_page(vma, addr, page); addr += PAGE_SIZE; } - atomic_long_add(m->size, &m->mapsize); - atomic_long_add(m->size, &entry->priv->gpumem_mapped); } vma->vm_file = file; entry->memdesc.vma = vma; - entry->memdesc.useraddr = vma->vm_start; /* * kgsl gets the entry id or the gpu address through vm_pgoff. @@ -5118,7 +5148,11 @@ static int kgsl_mmap(struct file *file, struct vm_area_struct *vma) */ vma->vm_pgoff = 0; - trace_kgsl_mem_mmap(entry); + if (atomic_inc_return(&entry->map_count) == 1) + atomic_long_add(entry->memdesc.size, + &entry->priv->gpumem_mapped); + + trace_kgsl_mem_mmap(entry, vma->vm_start); return 0; } diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 39c0b60e9224..157dd3b75b3c 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -196,11 +196,9 @@ struct kgsl_memdesc_ops { * @pagetable: Pointer to the pagetable that the object is mapped in * @hostptr: Kernel virtual address * @hostptr_count: Number of threads using hostptr - * @useraddr: User virtual address (if applicable) * @gpuaddr: GPU virtual address * @physaddr: Physical address of the memory object * @size: Size of the memory object - * @mapsize: Size of memory mapped in userspace * @priv: Internal flags and settings * @sgt: Scatter gather table for allocated pages * @ops: Function hooks for the memdesc memory type @@ -216,11 +214,9 @@ struct kgsl_memdesc { struct kgsl_pagetable *pagetable; void *hostptr; unsigned int hostptr_count; - unsigned long useraddr; uint64_t gpuaddr; phys_addr_t physaddr; uint64_t size; - atomic_long_t mapsize; unsigned int priv; struct sg_table *sgt; struct kgsl_memdesc_ops *ops; @@ -243,6 +239,11 @@ struct kgsl_memdesc { * @reclaimed_page_count: Total number of pages reclaimed */ int reclaimed_page_count; + /* + * @gpuaddr_lock: Spinlock to protect the gpuaddr from being accessed by + * multiple entities trying to map the same SVM region at once + */ + spinlock_t gpuaddr_lock; }; /* @@ -291,6 +292,11 @@ struct kgsl_mem_entry { struct work_struct work; spinlock_t bind_lock; struct rb_root bind_tree; + /** + * @map_count: Count how many vmas this object is mapped in - used for + * debugfs accounting + */ + atomic_t map_count; }; struct kgsl_device_private; diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c index 1e7c272fd0d4..8a5fb7a350a6 100644 --- a/drivers/gpu/msm/kgsl_debugfs.c +++ b/drivers/gpu/msm/kgsl_debugfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2002,2008-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2008-2020, The Linux Foundation. All rights reserved. */ #include @@ -147,7 +147,11 @@ static int print_mem_entry(void *data, void *ptr) flags[3] = get_alignflag(m); flags[4] = get_cacheflag(m); flags[5] = kgsl_memdesc_use_cpu_map(m) ? 'p' : '-'; - flags[6] = (m->useraddr) ? 'Y' : 'N'; + /* + * Show Y if at least one vma has this entry + * mapped (could be multiple) + */ + flags[6] = atomic_read(&entry->map_count) ? 'Y' : 'N'; flags[7] = kgsl_memdesc_is_secured(m) ? 's' : '-'; flags[8] = m->flags & KGSL_MEMFLAGS_SPARSE_PHYS ? 'P' : '-'; flags[9] = '\0'; @@ -158,26 +162,17 @@ static int print_mem_entry(void *data, void *ptr) kgsl_get_egl_counts(entry, &egl_surface_count, &egl_image_count); -#if defined(CONFIG_DISPLAY_SAMSUNG) && !defined(CONFIG_SAMSUNG_PRODUCT_SHIP) - seq_printf(s, m->useraddr ? "%p %p %16llu %5d %9s %10s %16s %5d %16ld %6d %6d" : - "%p %pK %16llu %5d %9s %10s %16s %5d %16ld %6d %6d", - (uint64_t *)(uintptr_t) m->gpuaddr, - (unsigned long *) m->useraddr, - m->size, entry->id, flags, - memtype_str(usermem_type), - usage, (m->sgt ? m->sgt->nents : 0), - atomic_long_read(&m->mapsize), - egl_surface_count, egl_image_count); -#else - seq_printf(s, "%pK %pK %16llu %5d %9s %10s %16s %5d %16ld %6d %6d", + seq_printf(s, "%pK %pK %16llu %5d %9s %10s %16s %5d %16d %6d %6d", (uint64_t *)(uintptr_t) m->gpuaddr, - (unsigned long *) m->useraddr, - m->size, entry->id, flags, + /* + * Show zero for the useraddr - we can't reliably track + * that value for multiple vmas anyway + */ + 0, m->size, entry->id, flags, memtype_str(usermem_type), usage, (m->sgt ? m->sgt->nents : 0), - atomic_long_read(&m->mapsize), + atomic_read(&entry->map_count), egl_surface_count, egl_image_count); -#endif if (entry->metadata[0] != 0) seq_printf(s, " %s", entry->metadata); @@ -247,7 +242,7 @@ static int process_mem_seq_show(struct seq_file *s, void *ptr) if (ptr == SEQ_START_TOKEN) { seq_printf(s, "%16s %16s %16s %5s %9s %10s %16s %5s %16s %6s %6s\n", "gpuaddr", "useraddr", "size", "id", "flags", "type", - "usage", "sglen", "mapsize", "eglsrf", "eglimg"); + "usage", "sglen", "mapcount", "eglsrf", "eglimg"); return 0; } else return print_mem_entry(s, ptr); @@ -405,7 +400,7 @@ void kgsl_process_init_debugfs(struct kgsl_process_private *private) unsigned char name[16]; struct dentry *dentry; - snprintf(name, sizeof(name), "%d", private->pid); + snprintf(name, sizeof(name), "%d", pid_nr(private->pid)); private->debug_root = debugfs_create_dir(name, proc_d_debugfs); @@ -425,14 +420,15 @@ void kgsl_process_init_debugfs(struct kgsl_process_private *private) } dentry = debugfs_create_file("mem", 0444, private->debug_root, - (void *) ((unsigned long) private->pid), &process_mem_fops); + (void *) ((unsigned long) pid_nr(private->pid)), + &process_mem_fops); if (IS_ERR_OR_NULL(dentry)) WARN((dentry == NULL), "Unable to create 'mem' file for %s\n", name); dentry = debugfs_create_file("sparse_mem", 0444, private->debug_root, - (void *) ((unsigned long) private->pid), + (void *) ((unsigned long) pid_nr(private->pid)), &process_sparse_mem_fops); if (IS_ERR_OR_NULL(dentry)) diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 6c30cfee2b7f..70d2d8065bbd 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -419,13 +419,13 @@ struct kgsl_context { #define pr_context(_d, _c, fmt, args...) \ dev_err((_d)->dev, "%s[%d]: " fmt, \ _context_comm((_c)), \ - (_c)->proc_priv->pid, ##args) + pid_nr((_c)->proc_priv->pid), ##args) /** * struct kgsl_process_private - Private structure for a KGSL process (across * all devices) * @priv: Internal flags, use KGSL_PROCESS_* values - * @pid: ID for the task owner of the process + * @pid: Identification structure for the task owner of the process * @comm: task name of the process * @mem_lock: Spinlock to protect the process memory lists * @refcount: kref object for reference counting the process @@ -443,7 +443,7 @@ struct kgsl_context { */ struct kgsl_process_private { unsigned long priv; - pid_t pid; + struct pid *pid; pid_t tid; char comm[TASK_COMM_LEN]; spinlock_t mem_lock; @@ -587,7 +587,7 @@ static inline void kgsl_process_sub_stats(struct kgsl_process_private *priv, struct mm_struct *mm; atomic_long_sub(size, &priv->stats[type].cur); - pid_struct = find_get_pid(priv->pid); + pid_struct = find_get_pid(pid_nr(priv->pid)); if (pid_struct) { task = get_pid_task(pid_struct, PIDTYPE_PID); if (task) { diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index cda276653add..c8ef21ba3308 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -655,7 +655,7 @@ static void _get_entries(struct kgsl_process_private *private, prev->flags = p->memdesc.flags; prev->priv = p->memdesc.priv; prev->pending_free = p->pending_free; - prev->pid = private->pid; + prev->pid = pid_nr(private->pid); __kgsl_get_memory_usage(prev); } @@ -665,7 +665,7 @@ static void _get_entries(struct kgsl_process_private *private, next->flags = n->memdesc.flags; next->priv = n->memdesc.priv; next->pending_free = n->pending_free; - next->pid = private->pid; + next->pid = pid_nr(private->pid); __kgsl_get_memory_usage(next); } } @@ -795,7 +795,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, private = kgsl_iommu_get_process(ptbase); if (private) { - pid = private->pid; + pid = pid_nr(private->pid); tid = private->tid; comm = private->comm; #if defined(CONFIG_DISPLAY_SAMSUNG) @@ -2536,6 +2536,11 @@ static int get_gpuaddr(struct kgsl_pagetable *pagetable, return -ENOMEM; } + /* + * This path is only called in a non-SVM path with locks so we can be + * sure we aren't racing with anybody so we don't need to worry about + * taking the lock + */ ret = _insert_gpuaddr(pagetable, addr, size); spin_unlock(&pagetable->lock); diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index eedd9e83ba91..707ac7bb7fa6 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved. */ #include @@ -448,7 +448,8 @@ void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc) return; if (!kgsl_memdesc_is_global(memdesc) && - !kgsl_memdesc_is_reclaimed(memdesc)) + !kgsl_memdesc_is_reclaimed(memdesc) && + (KGSL_MEMDESC_MAPPED & memdesc->priv)) unmap_fail = kgsl_mmu_unmap(pagetable, memdesc); /* @@ -459,10 +460,17 @@ void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc) if (PT_OP_VALID(pagetable, put_gpuaddr) && (unmap_fail == 0)) pagetable->pt_ops->put_gpuaddr(memdesc); + memdesc->pagetable = NULL; + + /* + * If SVM tries to take a GPU address it will lose the race until the + * gpuaddr returns to zero so we shouldn't need to worry about taking a + * lock here + */ + if (!kgsl_memdesc_is_global(memdesc)) memdesc->gpuaddr = 0; - memdesc->pagetable = NULL; } EXPORT_SYMBOL(kgsl_mmu_put_gpuaddr); diff --git a/drivers/gpu/msm/kgsl_reclaim.c b/drivers/gpu/msm/kgsl_reclaim.c index 5f9b6169f836..84ca92d30668 100644 --- a/drivers/gpu/msm/kgsl_reclaim.c +++ b/drivers/gpu/msm/kgsl_reclaim.c @@ -200,7 +200,6 @@ static int kgsl_reclaim_callback(struct notifier_block *nb, struct kgsl_mem_entry *entry; struct kgsl_memdesc *memdesc; int valid_entry, next = 0, ret; - u64 mapsize; process = kgsl_process_private_find(pid); if (!process) @@ -276,9 +275,6 @@ static int kgsl_reclaim_callback(struct notifier_block *nb, memdesc->reclaimed_page_count += memdesc->page_count; atomic_add(memdesc->page_count, &process->reclaimed_page_count); - mapsize = atomic_long_read(&memdesc->mapsize); - atomic_long_sub(mapsize, &memdesc->mapsize); - atomic_long_sub(mapsize, &process->gpumem_mapped); } kgsl_mem_entry_put(entry); diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index e0b3859aa620..3a347af8edf0 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -305,9 +305,9 @@ void kgsl_process_init_sysfs(struct kgsl_device *device, kgsl_process_private_get(private); if (kobject_init_and_add(&private->kobj, &process_ktype, - kgsl_driver.prockobj, "%d", private->pid)) { + kgsl_driver.prockobj, "%d", pid_nr(private->pid))) { dev_err(device->dev, "Unable to add sysfs for process %d\n", - private->pid); + pid_nr(private->pid)); return; } @@ -322,7 +322,7 @@ void kgsl_process_init_sysfs(struct kgsl_device *device, if (ret) dev_err(device->dev, "Unable to create sysfs files for process %d\n", - private->pid); + pid_nr(private->pid)); } for (i = 0; i < ARRAY_SIZE(debug_memstats); i++) { @@ -511,8 +511,6 @@ static int kgsl_page_alloc_vmfault(struct kgsl_memdesc *memdesc, vmf->page = page; - atomic_long_add(PAGE_SIZE, &memdesc->mapsize); - return 0; } @@ -685,8 +683,6 @@ static int kgsl_contiguous_vmfault(struct kgsl_memdesc *memdesc, else if (ret == -EFAULT) return VM_FAULT_SIGBUS; - atomic_long_add(PAGE_SIZE, &memdesc->mapsize); - return VM_FAULT_NOPAGE; } @@ -928,6 +924,7 @@ void kgsl_memdesc_init(struct kgsl_device *device, ilog2(PAGE_SIZE)); kgsl_memdesc_set_align(memdesc, align); spin_lock_init(&memdesc->lock); + spin_lock_init(&memdesc->gpuaddr_lock); } static int kgsl_shmem_alloc_page(struct page **pages, diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h index 3106e88579bf..501d97eb0e3a 100644 --- a/drivers/gpu/msm/kgsl_trace.h +++ b/drivers/gpu/msm/kgsl_trace.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020, The Linux Foundation. All rights reserved. */ #if !defined(_KGSL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) @@ -409,7 +409,7 @@ TRACE_EVENT(kgsl_mem_alloc, TP_fast_assign( __entry->gpuaddr = mem_entry->memdesc.gpuaddr; __entry->size = mem_entry->memdesc.size; - __entry->tgid = mem_entry->priv->pid; + __entry->tgid = pid_nr(mem_entry->priv->pid); kgsl_get_memory_usage(__entry->usage, sizeof(__entry->usage), mem_entry->memdesc.flags); __entry->id = mem_entry->id; @@ -425,9 +425,9 @@ TRACE_EVENT(kgsl_mem_alloc, TRACE_EVENT(kgsl_mem_mmap, - TP_PROTO(struct kgsl_mem_entry *mem_entry), + TP_PROTO(struct kgsl_mem_entry *mem_entry, unsigned long useraddr), - TP_ARGS(mem_entry), + TP_ARGS(mem_entry, useraddr), TP_STRUCT__entry( __field(unsigned long, useraddr) @@ -439,7 +439,7 @@ TRACE_EVENT(kgsl_mem_mmap, ), TP_fast_assign( - __entry->useraddr = mem_entry->memdesc.useraddr; + __entry->useraddr = useraddr; __entry->gpuaddr = mem_entry->memdesc.gpuaddr; __entry->size = mem_entry->memdesc.size; kgsl_get_memory_usage(__entry->usage, sizeof(__entry->usage), @@ -502,7 +502,7 @@ TRACE_EVENT(kgsl_mem_map, __entry->size = mem_entry->memdesc.size; __entry->fd = fd; __entry->type = kgsl_memdesc_usermem_type(&mem_entry->memdesc); - __entry->tgid = mem_entry->priv->pid; + __entry->tgid = pid_nr(mem_entry->priv->pid); kgsl_get_memory_usage(__entry->usage, sizeof(__entry->usage), mem_entry->memdesc.flags); __entry->id = mem_entry->id; @@ -537,7 +537,7 @@ TRACE_EVENT(kgsl_mem_free, __entry->gpuaddr = mem_entry->memdesc.gpuaddr; __entry->size = mem_entry->memdesc.size; __entry->type = kgsl_memdesc_usermem_type(&mem_entry->memdesc); - __entry->tgid = mem_entry->priv->pid; + __entry->tgid = pid_nr(mem_entry->priv->pid); kgsl_get_memory_usage(__entry->usage, sizeof(__entry->usage), mem_entry->memdesc.flags); __entry->id = mem_entry->id; @@ -572,7 +572,7 @@ TRACE_EVENT(kgsl_mem_sync_cache, __entry->gpuaddr = mem_entry->memdesc.gpuaddr; kgsl_get_memory_usage(__entry->usage, sizeof(__entry->usage), mem_entry->memdesc.flags); - __entry->tgid = mem_entry->priv->pid; + __entry->tgid = pid_nr(mem_entry->priv->pid); __entry->id = mem_entry->id; __entry->op = op; __entry->offset = offset; diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index ca0c20cb857e..ef6148c0355e 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -501,6 +501,19 @@ static int qseecom_reboot_notifier(struct notifier_block *nb, static struct notifier_block qseecom_reboot_nb = { .notifier_call = qseecom_reboot_notifier, }; + +static ssize_t qseecom_sysfs_shutdown(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + schedule_delayed_work(&listener_exit_work, 15 * HZ); + pr_warn("mark listener exit after timeout\n"); + + return count; +} + +static struct kobj_attribute qseecom_sysfs_attribute = + __ATTR(shutdown, 0660, NULL, qseecom_sysfs_shutdown); #endif #ifdef CONFIG_QSEECOM_DEBUG @@ -9725,6 +9738,10 @@ static int qseecom_probe(struct platform_device *pdev) { int rc; +#ifdef CONFIG_HANDLE_LISTENER_EXIT + struct kobject *qseecom_kobj; +#endif + rc = qseecom_init_dev(pdev); if (rc) return rc; @@ -9765,6 +9782,15 @@ static int qseecom_probe(struct platform_device *pdev) rc = register_reboot_notifier(&qseecom_reboot_nb); if (rc) pr_err("failed to register reboot notifier(%d)\n", rc); + + qseecom_kobj = kobject_create_and_add("shutdown_qseecom", kernel_kobj); + if (!qseecom_kobj) { + pr_err("Unable to create kernel object"); + } else { + rc = sysfs_create_file(qseecom_kobj, &qseecom_sysfs_attribute.attr); + if (rc) + pr_err("Unable to create qseecom sysfs file"); + } #endif atomic_set(&qseecom.qseecom_state, QSEECOM_STATE_READY); diff --git a/drivers/motor/cs40l2x-private.h b/drivers/motor/cs40l2x-private.h index d194b8a166d8..2c836677f4e0 100644 --- a/drivers/motor/cs40l2x-private.h +++ b/drivers/motor/cs40l2x-private.h @@ -602,6 +602,9 @@ #define CS40L2X_TRIG_HIBER_MASK 0x00000001 #define CS40L2X_TRIG_HIBER_SHIFT 0 +#define CS40L2X_UPDT_WKCTL_MASK 0x00000100 +#define CS40L2X_UPDT_WKCTL_SHIFT 8 + #define CS40L2X_WKSRC_POL_MASK 0x0000000F #define CS40L2X_WKSRC_POL_SHIFT 0 #define CS40L2X_WKSRC_POL_GPIO1 1 @@ -616,6 +619,9 @@ #define CS40L2X_WKSRC_EN_GPIO4 4 #define CS40L2X_WKSRC_EN_SDA 8 +#define CS40L2X_WR_PEND_STS_MASK 0x2 +#define CS40L2X_WR_PEND_STS_SHIFT 1 + #define CS40L2X_PLL_REFCLK_EN_MASK 0x00000010 #define CS40L2X_PLL_REFCLK_EN_SHIFT 4 diff --git a/drivers/motor/cs40l2x.c b/drivers/motor/cs40l2x.c index e52c963b9626..7e29d5660467 100644 --- a/drivers/motor/cs40l2x.c +++ b/drivers/motor/cs40l2x.c @@ -140,6 +140,8 @@ struct cs40l2x_private { #else struct led_classdev led_dev; #endif /* CONFIG_ANDROID_TIMED_OUTPUT */ + int vibe_start_count; + int vibe_done_count; }; static const char * const cs40l2x_supplies[] = { @@ -1111,99 +1113,144 @@ static ssize_t cs40l2x_cp_trigger_q_sub_show(struct device *dev, return ret; } -static int cs40l2x_hiber_cmd_send(struct cs40l2x_private *cs40l2x, - unsigned int hiber_cmd) +static int cs40l2x_wait_for_pwrmgt_sts(struct cs40l2x_private *cs40l2x) { - struct regmap *regmap = cs40l2x->regmap; + unsigned int sts; + int i, ret; + + for (i = 0; i < CS40L2X_STATUS_RETRIES; i++) { + ret = regmap_read(cs40l2x->regmap, CS40L2X_PWRMGT_STS, &sts); + if (ret) + dev_err(cs40l2x->dev, + "Failed to read PWRMGT_STS: %d\n", ret); + else if (!(sts & CS40L2X_WR_PEND_STS_MASK)) + return 0; + } + + dev_err(cs40l2x->dev, "Timed out reading PWRMGT_STS\n"); + return -ETIMEDOUT; +} + +static int cs40l2x_apply_hibernate_errata(struct cs40l2x_private *cs40l2x) +{ + int ret; + + dev_warn(cs40l2x->dev, "Retry hibernate\n"); + + cs40l2x_wait_for_pwrmgt_sts(cs40l2x); + + ret = regmap_write(cs40l2x->regmap, CS40L2X_WAKESRC_CTL, + (CS40L2X_WKSRC_EN_SDA << CS40L2X_WKSRC_EN_SHIFT) | + (CS40L2X_WKSRC_POL_SDA << CS40L2X_WKSRC_POL_SHIFT)); + if (ret) + dev_err(cs40l2x->dev, "Failed to set WAKESRC: %d\n", ret); + + cs40l2x_wait_for_pwrmgt_sts(cs40l2x); + + ret = regmap_write(cs40l2x->regmap, CS40L2X_WAKESRC_CTL, + CS40L2X_UPDT_WKCTL_MASK | + (CS40L2X_WKSRC_EN_SDA << CS40L2X_WKSRC_EN_SHIFT) | + (CS40L2X_WKSRC_POL_SDA << CS40L2X_WKSRC_POL_SHIFT)); + if (ret) + dev_err(cs40l2x->dev, "Failed to enable WAKESRC: %d\n", ret); + + cs40l2x_wait_for_pwrmgt_sts(cs40l2x); + + /* + * This write may force the device into hibernation before the ACK is + * returned, so ignore the return value. + */ + regmap_write(cs40l2x->regmap, CS40L2X_PWRMGT_CTL, + (1 << CS40L2X_MEM_RDY_SHIFT) | + (1 << CS40L2X_TRIG_HIBER_SHIFT)); + + return 0; +} + +static int cs40l2x_wake_from_hibernate(struct cs40l2x_private *cs40l2x) +{ + unsigned int pwr_reg = cs40l2x_dsp_reg(cs40l2x, "POWERSTATE", + CS40L2X_XM_UNPACKED_TYPE, + cs40l2x->fw_desc->id); unsigned int val; - int ret, i, j; + int ret, i; - switch (hiber_cmd) { - case CS40L2X_POWERCONTROL_NONE: - case CS40L2X_POWERCONTROL_FRC_STDBY: - return cs40l2x_ack_write(cs40l2x, - CS40L2X_MBOX_POWERCONTROL, hiber_cmd, + dev_dbg(cs40l2x->dev, "Attempt wake from hibernate\n"); + + ret = cs40l2x_ack_write(cs40l2x, CS40L2X_MBOX_POWERCONTROL, + CS40L2X_POWERCONTROL_WAKEUP, CS40L2X_POWERCONTROL_NONE); + if (ret) { + if (ret == -ETIME) + cs40l2x_apply_hibernate_errata(cs40l2x); - case CS40L2X_POWERCONTROL_HIBERNATE: - /* - * control port is unavailable immediately after - * this write, so don't poll for acknowledgment - */ - return regmap_write(regmap, - CS40L2X_MBOX_POWERCONTROL, hiber_cmd); + return ret; + } - case CS40L2X_POWERCONTROL_WAKEUP: - for (i = 0; i < CS40L2X_WAKEUP_RETRIES; i++) { - /* - * the first several transactions are expected to be - * NAK'd, so retry multiple times in rapid succession - */ - ret = regmap_write(regmap, - CS40L2X_MBOX_POWERCONTROL, hiber_cmd); - if (ret) { - usleep_range(1000, 1100); - continue; - } + for (i = 0; i < CS40L2X_STATUS_RETRIES; i++) { + ret = regmap_read(cs40l2x->regmap, pwr_reg, &val); + if (ret) { + dev_err(cs40l2x->dev, "Failed to read POWERSTATE: %d\n", + ret); + return ret; + } - /* - * verify the previous firmware ID remains intact and - * brute-force a dummy hibernation cycle if otherwise - */ - for (j = 0; j < CS40L2X_STATUS_RETRIES; j++) { - usleep_range(5000, 5100); + dev_dbg(cs40l2x->dev, "Read POWERSTATE: %d\n", val); - ret = regmap_read(regmap, - CS40L2X_XM_FW_ID, &val); - if (ret) - return ret; + switch (val) { + case CS40L2X_POWERSTATE_ACTIVE: + case CS40L2X_POWERSTATE_STANDBY: + dev_dbg(cs40l2x->dev, "Woke from hibernate\n"); + return 0; + case CS40L2X_POWERSTATE_HIBERNATE: + break; + default: + dev_err(cs40l2x->dev, "Invalid POWERSTATE: %x\n", val); + break; + } - if (val == cs40l2x->fw_desc->id) - break; - } - if (j < CS40L2X_STATUS_RETRIES) - break; + usleep_range(5000, 5100); + } - dev_warn(cs40l2x->dev, - "Unexpected firmware ID: 0x%06X\n", - val); + dev_err(cs40l2x->dev, "Timed out waiting for POWERSTATE: %d\n", val); - /* - * this write may force the device into hibernation - * before the ACK is returned, so ignore the return - * value - */ - regmap_write(regmap, CS40L2X_PWRMGT_CTL, - (1 << CS40L2X_MEM_RDY_SHIFT) | - (1 << CS40L2X_TRIG_HIBER_SHIFT)); + cs40l2x_apply_hibernate_errata(cs40l2x); - usleep_range(1000, 1100); - } - if (i == CS40L2X_WAKEUP_RETRIES) - return -EIO; + return -ETIMEDOUT; +} - for (i = 0; i < CS40L2X_STATUS_RETRIES; i++) { - ret = regmap_read(regmap, - cs40l2x_dsp_reg(cs40l2x, "POWERSTATE", - CS40L2X_XM_UNPACKED_TYPE, - cs40l2x->fw_desc->id), - &val); - if (ret) - return ret; +static int cs40l2x_hiber_cmd_send(struct cs40l2x_private *cs40l2x, + unsigned int hiber_cmd) +{ + int i; - switch (val) { - case CS40L2X_POWERSTATE_ACTIVE: - case CS40L2X_POWERSTATE_STANDBY: + switch (hiber_cmd) { + case CS40L2X_POWERCONTROL_NONE: + case CS40L2X_POWERCONTROL_FRC_STDBY: + return cs40l2x_ack_write(cs40l2x, CS40L2X_MBOX_POWERCONTROL, + hiber_cmd, CS40L2X_POWERCONTROL_NONE); + + case CS40L2X_POWERCONTROL_HIBERNATE: + /* + * The control port is unavailable immediately after this write, + * so don't poll for acknowledgment. + */ + return regmap_write(cs40l2x->regmap, CS40L2X_MBOX_POWERCONTROL, + hiber_cmd); + + case CS40L2X_POWERCONTROL_WAKEUP: + /* + * The first several transactions are expected to be NAK'd, so + * retry multiple times in rapid succession. + */ + for (i = 0; i < CS40L2X_WAKEUP_RETRIES; i++) { + if (!cs40l2x_wake_from_hibernate(cs40l2x)) return 0; - case CS40L2X_POWERSTATE_HIBERNATE: - break; - default: - return -EINVAL; - } - usleep_range(5000, 5100); + usleep_range(1000, 1100); } - return -ETIME; + + return -ETIMEDOUT; default: return -EINVAL; @@ -4619,15 +4666,8 @@ static void cs40l2x_vibe_mode_worker(struct work_struct *work) unsigned int val; int ret; - if (cs40l2x->devid != CS40L2X_DEVID_L25A) - return; - mutex_lock(&cs40l2x->lock); - if (cs40l2x->vibe_mode == CS40L2X_VIBE_MODE_HAPTIC - && cs40l2x->asp_enable == CS40L2X_ASP_DISABLED) - goto err_mutex; - ret = regmap_read(regmap, cs40l2x_dsp_reg(cs40l2x, "STATUS", CS40L2X_XM_UNPACKED_TYPE, CS40L2X_ALGO_ID_VIBE), &val); if (ret) { @@ -4694,28 +4734,37 @@ static void cs40l2x_vibe_mode_worker(struct work_struct *work) } cs40l2x->vibe_mode = CS40L2X_VIBE_MODE_HAPTIC; - if (cs40l2x->vibe_state != CS40L2X_VIBE_STATE_RUNNING) - cs40l2x_wl_relax(cs40l2x); - } else if (cs40l2x->vibe_mode == CS40L2X_VIBE_MODE_HAPTIC && - cs40l2x->a2h_enable) { - ret = regmap_update_bits(regmap, CS40L2X_PWR_CTRL3, - CS40L2X_CLASSH_EN_MASK, - 1 << CS40L2X_CLASSH_EN_SHIFT); - if (ret) + if (cs40l2x->pbq_state != CS40L2X_PBQ_STATE_IDLE) goto err_mutex; - ret = regmap_write(regmap, CS40L2X_DSP_VIRT1_MBOX_5, - CS40L2X_A2H_I2S_START); - if (ret) + cs40l2x->vibe_state = CS40L2X_VIBE_STATE_STOPPED; + cs40l2x_wl_relax(cs40l2x); + } else { + /* haptic-mode teardown */ + if (cs40l2x->vibe_state == CS40L2X_VIBE_STATE_STOPPED + || cs40l2x->pbq_state != CS40L2X_PBQ_STATE_IDLE) goto err_mutex; + + if (cs40l2x->amp_gnd_stby) { + ret = regmap_write(regmap, + CS40L2X_SPK_FORCE_TST_1, + CS40L2X_FORCE_SPK_GND); + if (ret) { + dev_err(dev, + "Failed to ground amplifier outputs\n"); + goto err_mutex; + } + } + + cs40l2x->vibe_state = CS40L2X_VIBE_STATE_STOPPED; + cs40l2x_wl_relax(cs40l2x); } ret = cs40l2x_enable_classh(cs40l2x); if (ret) goto err_mutex; - err_mutex: mutex_unlock(&cs40l2x->lock); } @@ -4885,6 +4934,8 @@ static int cs40l2x_pbq_pair_launch(struct cs40l2x_private *cs40l2x) if (ret) return ret; + cs40l2x->vibe_start_count++; + cs40l2x->pbq_state = CS40L2X_PBQ_STATE_PLAYING; cs40l2x->pbq_index++; @@ -4914,36 +4965,6 @@ static void cs40l2x_vibe_pbq_worker(struct work_struct *work) switch (cs40l2x->pbq_state) { case CS40L2X_PBQ_STATE_IDLE: - if (cs40l2x->vibe_state == CS40L2X_VIBE_STATE_STOPPED) - goto err_mutex; - - ret = regmap_read(regmap, - cs40l2x_dsp_reg(cs40l2x, "STATUS", - CS40L2X_XM_UNPACKED_TYPE, - CS40L2X_ALGO_ID_VIBE), - &val); - if (ret) { - dev_err(dev, "Failed to capture playback status\n"); - goto err_mutex; - } - - if (val != CS40L2X_STATUS_IDLE) - goto err_mutex; - - if (cs40l2x->amp_gnd_stby) { - ret = regmap_write(regmap, - CS40L2X_SPK_FORCE_TST_1, - CS40L2X_FORCE_SPK_GND); - if (ret) { - dev_err(dev, - "Failed to ground amplifier outputs\n"); - goto err_mutex; - } - } - - cs40l2x->vibe_state = CS40L2X_VIBE_STATE_STOPPED; - if (cs40l2x->vibe_mode != CS40L2X_VIBE_MODE_AUDIO) - cs40l2x_wl_relax(cs40l2x); goto err_mutex; case CS40L2X_PBQ_STATE_PLAYING: @@ -5522,6 +5543,8 @@ static void cs40l2x_vibe_start_worker(struct work_struct *work) if (ret) break; + cs40l2x->vibe_start_count++; + msleep(CS40L2X_PEAK_DELAY_MS); ret = regmap_write(regmap, @@ -5577,6 +5600,8 @@ static void cs40l2x_vibe_start_worker(struct work_struct *work) ret = cs40l2x_ack_write(cs40l2x, CS40L2X_MBOX_TRIGGER_MS, cs40l2x->cp_trailer_index & CS40L2X_INDEX_MASK, CS40L2X_MBOX_TRIGGERRESET); + + cs40l2x->vibe_start_count++; break; case CS40L2X_INDEX_CLICK_MIN ... CS40L2X_INDEX_CLICK_MAX: @@ -5592,6 +5617,8 @@ static void cs40l2x_vibe_start_worker(struct work_struct *work) ret = cs40l2x_ack_write(cs40l2x, CS40L2X_MBOX_TRIGGERINDEX, cs40l2x->cp_trailer_index, CS40L2X_MBOX_TRIGGERRESET); + + cs40l2x->vibe_start_count++; break; case CS40L2X_INDEX_PBQ: @@ -9098,6 +9125,9 @@ static irqreturn_t cs40l2x_irq(int irq, void *data) #endif /* intentionally fall through */ case CS40L2X_EVENT_CTRL_GPIO_STOP: + cs40l2x->vibe_done_count++; + dev_err(cs40l2x->dev, "Vibration Done: %d, %d\n", + cs40l2x->vibe_start_count, cs40l2x->vibe_done_count); if (asp_timeout > 0) hrtimer_start(&cs40l2x->asp_timer, ktime_set(asp_timeout / 1000, diff --git a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/inc/cdp_txrx_ops.h b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/inc/cdp_txrx_ops.h index 9a1cc3311aed..ad56a054555e 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/inc/cdp_txrx_ops.h +++ b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/inc/cdp_txrx_ops.h @@ -1320,6 +1320,8 @@ struct cdp_peer_ops { uint8_t *peer_mac, bool val); void (*set_peer_as_tdls_peer)(struct cdp_soc_t *soc, uint8_t vdev_id, uint8_t *peer_mac, bool val); + void (*peer_flush_frags)(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, uint8_t *peer_mac); }; /** diff --git a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/inc/cdp_txrx_peer_ops.h b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/inc/cdp_txrx_peer_ops.h index 9a11a5a58863..2a394392029b 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/inc/cdp_txrx_peer_ops.h +++ b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/inc/cdp_txrx_peer_ops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -569,4 +569,24 @@ cdp_peer_set_tdls_offchan_enabled(ol_txrx_soc_handle soc, uint8_t vdev_id, peer_mac, val); } +/** + * cdp_peer_flush_frags() - Flush frags on peer + * @soc - data path soc handle + * @vdev_id - virtual interface id + * @peer_mac - peer mac addr + * + * Return: None + */ +static inline void +cdp_peer_flush_frags(ol_txrx_soc_handle soc, uint8_t vdev_id, uint8_t *peer_mac) +{ + if (!soc || !soc->ops || !soc->ops->peer_ops) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL, + "%s invalid instance", __func__); + return; + } + + if (soc->ops->peer_ops->peer_flush_frags) + soc->ops->peer_ops->peer_flush_frags(soc, vdev_id, peer_mac); +} #endif /* _CDP_TXRX_PEER_H_ */ diff --git a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_internal.h b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_internal.h index 66f0a1fcc485..56be267ee8f0 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_internal.h +++ b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_internal.h @@ -2182,4 +2182,15 @@ void dp_desc_multi_pages_mem_free(struct dp_soc *soc, #endif +/** + * dp_peer_flush_frags() - Flush all fragments for a particular + * peer + * @soc_hdl - data path soc handle + * @vdev_id - vdev id + * @peer_addr - peer mac address + * + * Return: None + */ +void dp_peer_flush_frags(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_mac); #endif /* #ifndef _DP_INTERNAL_H_ */ diff --git a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_main.c b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_main.c index 400fbd7fdfbf..f98a53800a6e 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_main.c +++ b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_main.c @@ -11048,6 +11048,7 @@ static struct cdp_peer_ops dp_ops_peer = { .get_vdev_by_peer_addr = dp_get_vdev_by_peer_addr, .peer_get_peer_mac_addr = dp_peer_get_peer_mac_addr, .get_peer_state = dp_get_peer_state, + .peer_flush_frags = dp_peer_flush_frags, }; #endif diff --git a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.c b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.c index 8b11cc678ecd..20226c7d32cb 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.c +++ b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.c @@ -3488,6 +3488,8 @@ QDF_STATUS dp_peer_state_update(struct cdp_soc_t *soc_hdl, uint8_t *peer_mac, } peer->state = state; + peer->authorize = (state == OL_TXRX_PEER_STATE_AUTH) ? 1 : 0; + dp_info("peer %pK state %d", peer, peer->state); /* ref_cnt is incremented inside dp_peer_find_hash_find(). * Decrement it here. @@ -3841,3 +3843,30 @@ bool dp_peer_find_by_id_valid(struct dp_soc *soc, uint16_t peer_id) return false; } + +void dp_peer_flush_frags(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_mac) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_peer *peer = dp_peer_find_hash_find(soc, peer_mac, 0, + vdev_id); + struct dp_rx_tid *rx_tid; + uint8_t tid; + + if (!peer) + return; + + dp_info("Flushing fragments for peer " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(peer->mac_addr.raw)); + + for (tid = 0; tid < DP_MAX_TIDS; tid++) { + rx_tid = &peer->rx_tid[tid]; + + qdf_spin_lock_bh(&rx_tid->tid_lock); + dp_rx_defrag_waitlist_remove(peer, tid); + dp_rx_reorder_flush_frag(peer, tid); + qdf_spin_unlock_bh(&rx_tid->tid_lock); + } + + dp_peer_unref_delete(peer); +} diff --git a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.c b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.c index de8cb4ed24e1..97b749b57ed9 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.c +++ b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_rx.c @@ -1928,6 +1928,42 @@ dp_rx_ring_record_entry(struct dp_soc *soc, uint8_t ring_num, hal_ring_desc_t ri } #endif +#ifdef DISABLE_EAPOL_INTRABSS_FWD +/* + * dp_rx_intrabss_fwd_wrapper() - Wrapper API for intrabss fwd. For EAPOL + * pkt with DA not equal to vdev mac addr, fwd is not allowed. + * @soc: core txrx main context + * @ta_peer: source peer entry + * @rx_tlv_hdr: start address of rx tlvs + * @nbuf: nbuf that has to be intrabss forwarded + * @msdu_metadata: msdu metadata + * + * Return: true if it is forwarded else false + */ +static inline +bool dp_rx_intrabss_fwd_wrapper(struct dp_soc *soc, struct dp_peer *ta_peer, + uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf, + struct hal_rx_msdu_metadata msdu_metadata) +{ + if (qdf_unlikely(qdf_nbuf_is_ipv4_eapol_pkt(nbuf) && + qdf_mem_cmp(qdf_nbuf_data(nbuf) + + QDF_NBUF_DEST_MAC_OFFSET, + ta_peer->vdev->mac_addr.raw, + QDF_MAC_ADDR_SIZE))) + return false; + + return dp_rx_intrabss_fwd(soc, ta_peer, rx_tlv_hdr, nbuf, + msdu_metadata); + +} +#define DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata) \ + dp_rx_intrabss_fwd_wrapper(soc, peer, rx_tlv_hdr, nbuf, \ + msdu_metadata) +#else +#define DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata) \ + dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata) +#endif + /** * dp_rx_process() - Brain of the Rx processing functionality * Called from the bottom half (tasklet/NET_RX_SOFTIRQ) @@ -2461,6 +2497,23 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl, continue; } + /* + * Drop non-EAPOL frames from unauthorized peer. + */ + if (qdf_likely(peer) && qdf_unlikely(!peer->authorize)) { + bool is_eapol = qdf_nbuf_is_ipv4_eapol_pkt(nbuf) || + qdf_nbuf_is_ipv4_wapi_pkt(nbuf); + + if (!is_eapol) { + DP_STATS_INC(soc, + rx.err.peer_unauth_rx_pkt_drop, + 1); + qdf_nbuf_free(nbuf); + nbuf = next; + continue; + } + } + if (soc->process_rx_status) dp_rx_cksum_offload(vdev->pdev, nbuf, rx_tlv_hdr); @@ -2524,7 +2577,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl, /* Intrabss-fwd */ if (dp_rx_check_ap_bridge(vdev)) - if (dp_rx_intrabss_fwd(soc, + if (DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, nbuf, diff --git a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.c b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.c index 981f0ebe1066..05dec419292a 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.c +++ b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -853,9 +853,9 @@ static int dp_rx_defrag_pn_check(qdf_nbuf_t msdu, ((uint64_t)rx_mpdu_info_details->pn_127_96 << 32); if (cur_pn128[1] == prev_pn128[1]) - out_of_order = (cur_pn128[0] <= prev_pn128[0]); + out_of_order = (cur_pn128[0] - prev_pn128[0] != 1); else - out_of_order = (cur_pn128[1] < prev_pn128[1]); + out_of_order = (cur_pn128[1] - prev_pn128[1] != 1); return out_of_order; } @@ -906,6 +906,17 @@ dp_rx_construct_fraglist(struct dp_peer *peer, int tid, qdf_nbuf_t head, prev_pn128[0] = cur_pn128[0]; prev_pn128[1] = cur_pn128[1]; + /* + * Broadcast and multicast frames should never be fragmented. + * Iterating through all msdus and dropping fragments if even + * one of them has mcast/bcast destination address. + */ + if (hal_rx_msdu_is_wlan_mcast(msdu)) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "Dropping multicast/broadcast fragments"); + return QDF_STATUS_E_FAILURE; + } + dp_rx_frag_pull_hdr(msdu, hdrsize); len += qdf_nbuf_len(msdu); msdu = qdf_nbuf_next(msdu); diff --git a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_stats.c b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_stats.c index cb93c8781d4e..676d996fef14 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_stats.c +++ b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_stats.c @@ -6040,6 +6040,8 @@ dp_print_soc_rx_stats(struct dp_soc *soc) soc->stats.rx.err.defrag_peer_uninit); DP_PRINT_STATS("Pkts delivered no peer = %d", soc->stats.rx.err.pkt_delivered_no_peer); + DP_PRINT_STATS("Pkts drop due to no peer auth :%d", + soc->stats.rx.err.peer_unauth_rx_pkt_drop); DP_PRINT_STATS("Invalid Pdev = %d", soc->stats.rx.err.invalid_pdev); DP_PRINT_STATS("Invalid Peer = %d", diff --git a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_types.h b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_types.h index 0746816f3e35..f62ea069c7ce 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_types.h +++ b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/dp/wifi3.0/dp_types.h @@ -853,6 +853,8 @@ struct dp_soc_stats { uint32_t nbuf_sanity_fail; /* Duplicate link desc refilled */ uint32_t dup_refill_link_desc; + /* Non Eapol pkt drop cnt due to peer not authorized */ + uint32_t peer_unauth_rx_pkt_drop; } err; /* packet count per core - per ring */ diff --git a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/qdf/inc/qdf_lock.h b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/qdf/inc/qdf_lock.h index 14b68b965efc..91f8948f723f 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/qdf/inc/qdf_lock.h +++ b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/qdf/inc/qdf_lock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -90,13 +90,13 @@ do { \ uint64_t BEFORE_LOCK_time; \ uint64_t AFTER_LOCK_time; \ bool BEFORE_LOCK_is_locked = was_locked; \ - BEFORE_LOCK_time = qdf_get_log_timestamp(); \ + BEFORE_LOCK_time = qdf_get_log_timestamp_lightweight(); \ do {} while (0) #define AFTER_LOCK(lock, func) \ lock->stats.acquired_by = func; \ - AFTER_LOCK_time = qdf_get_log_timestamp(); \ + AFTER_LOCK_time = qdf_get_log_timestamp_lightweight(); \ lock->stats.acquired++; \ lock->stats.last_acquired = AFTER_LOCK_time; \ if (BEFORE_LOCK_is_locked) { \ @@ -121,11 +121,11 @@ do { \ do { \ uint64_t BEFORE_LOCK_time; \ uint64_t AFTER_LOCK_time; \ - BEFORE_LOCK_time = qdf_get_log_timestamp(); \ + BEFORE_LOCK_time = qdf_get_log_timestamp_lightweight(); \ do {} while (0) #define AFTER_TRYLOCK(lock, trylock_return, func) \ - AFTER_LOCK_time = qdf_get_log_timestamp(); \ + AFTER_LOCK_time = qdf_get_log_timestamp_lightweight(); \ if (trylock_return) { \ lock->stats.acquired++; \ lock->stats.last_acquired = AFTER_LOCK_time; \ @@ -138,8 +138,15 @@ do { \ /* max_hold_time in US */ #define BEFORE_UNLOCK(lock, max_hold_time) \ do {\ - uint64_t held_time = qdf_get_log_timestamp() - \ - lock->stats.last_acquired; \ + uint64_t BEFORE_UNLOCK_time; \ + uint64_t held_time; \ + BEFORE_UNLOCK_time = qdf_get_log_timestamp_lightweight(); \ +\ + if (unlikely(BEFORE_UNLOCK_time < lock->stats.last_acquired)) \ + held_time = 0; \ + else \ + held_time = BEFORE_UNLOCK_time - lock->stats.last_acquired; \ +\ lock->stats.held_time += held_time; \ \ if (held_time > lock->stats.max_held_time) \ diff --git a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/qdf/inc/qdf_time.h b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/qdf/inc/qdf_time.h index 32cfeba0068e..575e851bd410 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/qdf/inc/qdf_time.h +++ b/drivers/net/wireless/qualcomm/qca6390/qca-wifi-host-cmn/qdf/inc/qdf_time.h @@ -270,6 +270,21 @@ static inline uint64_t qdf_log_timestamp_to_usecs(uint64_t time) return time; } + +/** + * qdf_get_log_timestamp_lightweight - get time stamp for logging + * For adrastea this API returns QTIMER tick which is needed to synchronize + * host and fw log timestamps + * For ROME and other discrete solution this API returns system boot time stamp + * + * Return: + * QTIMER ticks(19.2MHz) for adrastea + * System tick for rome and other 3rd party platform solutions + */ +static inline uint64_t qdf_get_log_timestamp_lightweight(void) +{ + return __qdf_get_log_timestamp(); +} #else #define QDF_LOG_TIMESTAMP_UNIT KERNEL_LOG #define QDF_LOG_TIMESTAMP_CYCLES_PER_10_US 10 @@ -279,6 +294,22 @@ static inline uint64_t qdf_log_timestamp_to_usecs(uint64_t time) /* timestamps are already in micro seconds */ return time; } + +static inline uint64_t qdf_get_log_timestamp_lightweight(void) +{ + uint64_t timestamp_us; + + /* explicitly change to uint64_t, otherwise it will assign + * uint32_t to timestamp_us, which lose high 32bits. + * on 64bit platform, it will only use low 32bits jiffies in + * jiffies_to_msecs. + * eg: HZ=250, it will overflow every (0xffff ffff<<2==0x3fff ffff) + * ticks. it is 1193 hours. + */ + timestamp_us = + (uint64_t)__qdf_system_ticks_to_msecs(qdf_system_ticks()) * 1000; + return timestamp_us; +} #endif /* end of MSM_PLATFORM */ static inline void qdf_log_timestamp_to_secs(uint64_t time, uint64_t *secs, diff --git a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/Kbuild b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/Kbuild index f42095cadc1a..d06d8f2a127d 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/Kbuild +++ b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/Kbuild @@ -2907,6 +2907,7 @@ cppflags-y += -DENABLE_HAL_SOC_STATS cppflags-y += -DENABLE_HAL_REG_WR_HISTORY cppflags-y += -DDP_RX_DESC_COOKIE_INVALIDATE cppflags-y += -DPCI_LINK_STATUS_SANITY +cppflags-y += -DDISABLE_EAPOL_INTRABSS_FWD endif cppflags-$(CONFIG_WLAN_CLD_PM_QOS) += -DCLD_PM_QOS diff --git a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/components/ipa/core/inc/wlan_ipa_priv.h b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/components/ipa/core/inc/wlan_ipa_priv.h index 066ce70f1055..25bcdc2743b8 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/components/ipa/core/inc/wlan_ipa_priv.h +++ b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/components/ipa/core/inc/wlan_ipa_priv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -320,6 +320,7 @@ struct wlan_ipa_priv; * @interface_lock: Interface lock * @ifa_address: Interface address * @stats: Interface stats + * @bssid: BSSID. valid only for sta iface ctx; */ struct wlan_ipa_iface_context { struct wlan_ipa_priv *ipa_ctx; @@ -334,6 +335,7 @@ struct wlan_ipa_iface_context { qdf_spinlock_t interface_lock; uint32_t ifa_address; struct wlan_ipa_iface_stats stats; + struct qdf_mac_addr bssid; }; /** @@ -636,6 +638,7 @@ struct wlan_ipa_priv { uint32_t curr_cons_bw; uint8_t activated_fw_pipe; + uint8_t num_sap_connected; uint8_t sap_num_connected_sta; uint8_t sta_connected; uint32_t tx_pipe_handle; diff --git a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/components/ipa/core/src/wlan_ipa_core.c b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/components/ipa/core/src/wlan_ipa_core.c index 5d9494a72b7c..9d8836cd0c1b 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/components/ipa/core/src/wlan_ipa_core.c +++ b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/components/ipa/core/src/wlan_ipa_core.c @@ -926,6 +926,33 @@ wlan_ipa_send_skb_to_network(qdf_nbuf_t skb, ipa_ctx->ipa_rx_net_send_count++; } +/** + * wlan_ipa_eapol_intrabss_fwd_check() - Check if eapol pkt intrabss fwd is + * allowed or not + * @ipa_ctx: IPA global context + * @vdev_id: vdev id + * @nbuf: network buffer + * + * Return: true if intrabss fwd is allowed for eapol else false + */ +static bool +wlan_ipa_eapol_intrabss_fwd_check(struct wlan_ipa_priv *ipa_ctx, + uint8_t vdev_id, qdf_nbuf_t nbuf) +{ + uint8_t *vdev_mac_addr; + + vdev_mac_addr = cdp_get_vdev_mac_addr(ipa_ctx->dp_soc, vdev_id); + + if (!vdev_mac_addr) + return false; + + if (qdf_mem_cmp(qdf_nbuf_data(nbuf) + QDF_NBUF_DEST_MAC_OFFSET, + vdev_mac_addr, QDF_MAC_ADDR_SIZE)) + return false; + + return true; +} + /** * __wlan_ipa_w2i_cb() - WLAN to IPA callback handler * @priv: pointer to private data registered with IPA (we register a @@ -943,6 +970,9 @@ static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt, uint8_t iface_id; uint8_t session_id = 0xff; struct wlan_ipa_iface_context *iface_context; + bool is_eapol_wapi = false; + struct qdf_mac_addr peer_mac_addr = QDF_MAC_ADDR_ZERO_INIT; + bool fwd_allowed = true; ipa_ctx = (struct wlan_ipa_priv *)priv; if (!ipa_ctx) { @@ -988,10 +1018,44 @@ static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt, } iface_context->stats.num_rx_ipa_excep++; + if (iface_context->device_mode == QDF_STA_MODE) + qdf_copy_macaddr(&peer_mac_addr, &iface_context->bssid); + else if (iface_context->device_mode == QDF_SAP_MODE) + qdf_mem_copy(&peer_mac_addr.bytes[0], + qdf_nbuf_data(skb) + + QDF_NBUF_SRC_MAC_OFFSET, + QDF_MAC_ADDR_SIZE); + + if (qdf_nbuf_is_ipv4_eapol_pkt(skb)) { + is_eapol_wapi = true; + if (iface_context->device_mode == QDF_SAP_MODE) + fwd_allowed = + wlan_ipa_eapol_intrabss_fwd_check(ipa_ctx, + iface_context->session_id, skb); + } else if (qdf_nbuf_is_ipv4_wapi_pkt(skb)) { + is_eapol_wapi = true; + } + + /* + * Check for peer authorized state before allowing + * non-EAPOL/WAPI frames to be intrabss forwarded + * or submitted to stack. + */ + if (cdp_peer_state_get(ipa_ctx->dp_soc, + iface_context->session_id, + &peer_mac_addr.bytes[0]) != + OL_TXRX_PEER_STATE_AUTH && !is_eapol_wapi) { + ipa_err_rl("Non EAPOL/WAPI packet received when peer "QDF_MAC_ADDR_FMT" is unauthorized", + QDF_MAC_ADDR_REF(peer_mac_addr.bytes)); + ipa_ctx->ipa_rx_internal_drop_count++; + dev_kfree_skb_any(skb); + return; + } + /* Disable to forward Intra-BSS Rx packets when * ap_isolate=1 in hostapd.conf */ - if (!ipa_ctx->ap_intrabss_fwd) { + if (!ipa_ctx->ap_intrabss_fwd && fwd_allowed) { /* * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send * all Rx packets to IPA uC, which need to be forwarded @@ -1409,12 +1473,16 @@ static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context) iface_context->dev->name, wlan_ipa_is_ipv6_enabled(ipa_ctx->config)); + if (iface_context->device_mode == QDF_SAP_MODE) + ipa_ctx->num_sap_connected--; + qdf_spin_lock_bh(&iface_context->interface_lock); iface_context->dev = NULL; iface_context->device_mode = QDF_MAX_NO_OF_MODE; iface_context->session_id = WLAN_IPA_MAX_SESSION; qdf_spin_unlock_bh(&iface_context->interface_lock); iface_context->ifa_address = 0; + qdf_zero_macaddr(&iface_context->bssid); if (!iface_context->ipa_ctx->num_iface) { ipa_err("NUM INTF 0, Invalid"); QDF_ASSERT(0); @@ -1568,6 +1636,9 @@ static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx, ipa_ctx->num_iface++; + if (device_mode == QDF_SAP_MODE) + ipa_ctx->num_sap_connected++; + ipa_debug("exit: num_iface=%d", ipa_ctx->num_iface); return status; @@ -1591,6 +1662,11 @@ static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx) { ipa_debug("enter"); + if (ipa_ctx->num_sap_connected > 1) { + ipa_debug("Multiple SAP connected. Not enabling pipes. Exit"); + return QDF_STATUS_E_PERM; + } + if (wlan_ipa_uc_enable_pipes(ipa_ctx) != QDF_STATUS_SUCCESS) { ipa_err("IPA WDI Pipe activation failed"); return QDF_STATUS_E_BUSY; @@ -1899,6 +1975,67 @@ static QDF_STATUS wlan_ipa_send_msg(qdf_netdev_t net_dev, return QDF_STATUS_SUCCESS; } +/** + * wlan_ipa_handle_multiple_sap_evt() - Handle multiple SAP connect/disconnect + * @ipa_ctx: IPA global context + * @type: IPA event type. + * + * This function is used to disable pipes when multiple SAP are connected and + * enable pipes back when only one SAP is connected. + * + * Return: None + */ +static inline +void wlan_ipa_handle_multiple_sap_evt(struct wlan_ipa_priv *ipa_ctx, + qdf_ipa_wlan_event type) +{ + struct wlan_ipa_iface_context *iface_ctx; + int i; + + if (type == QDF_IPA_AP_DISCONNECT) { + ipa_debug("Multiple SAP disconnecting. Enabling IPA"); + + if (ipa_ctx->sap_num_connected_sta > 0) + wlan_ipa_uc_handle_first_con(ipa_ctx); + + for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) { + iface_ctx = &ipa_ctx->iface_context[i]; + + if (iface_ctx->device_mode == QDF_SAP_MODE) { + wlan_ipa_uc_offload_enable_disable(ipa_ctx, + SIR_AP_RX_DATA_OFFLOAD, + iface_ctx->session_id, + true); + break; + } + } + } else if (type == QDF_IPA_AP_CONNECT) { + ipa_debug("Multiple SAP connected. Disabling IPA"); + + for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) { + iface_ctx = &ipa_ctx->iface_context[i]; + + if (iface_ctx->device_mode == QDF_SAP_MODE) { + wlan_ipa_uc_offload_enable_disable(ipa_ctx, + SIR_AP_RX_DATA_OFFLOAD, + iface_ctx->session_id, + false); + } + } + + if (!ipa_ctx->ipa_pipes_down) + wlan_ipa_uc_disable_pipes(ipa_ctx, true); + } +} + +static inline void +wlan_ipa_save_bssid_iface_ctx(struct wlan_ipa_priv *ipa_ctx, uint8_t iface_id, + uint8_t *mac_addr) +{ + qdf_mem_copy(ipa_ctx->iface_context[iface_id].bssid.bytes, + mac_addr, QDF_MAC_ADDR_SIZE); +} + /** * __wlan_ipa_wlan_evt() - IPA event handler * @net_dev: Interface net device @@ -2048,6 +2185,11 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, break; } } + + if (ipa_ctx->num_sap_connected == 1) { + wlan_ipa_handle_multiple_sap_evt(ipa_ctx, + type); + } } return QDF_STATUS_SUCCESS; @@ -2094,6 +2236,10 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, ipa_ctx->vdev_to_iface[session_id] = wlan_ipa_get_ifaceid(ipa_ctx, session_id); + wlan_ipa_save_bssid_iface_ctx(ipa_ctx, + ipa_ctx->vdev_to_iface[session_id], + mac_addr); + if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) && (ipa_ctx->sap_num_connected_sta > 0 || wlan_ipa_is_sta_only_offload_enabled()) && @@ -2162,8 +2308,13 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) { qdf_mutex_release(&ipa_ctx->event_lock); - wlan_ipa_uc_offload_enable_disable(ipa_ctx, - SIR_AP_RX_DATA_OFFLOAD, session_id, true); + if (ipa_ctx->num_sap_connected == 1) { + wlan_ipa_uc_offload_enable_disable(ipa_ctx, + SIR_AP_RX_DATA_OFFLOAD, + session_id, true); + } else { + wlan_ipa_handle_multiple_sap_evt(ipa_ctx, type); + } qdf_mutex_acquire(&ipa_ctx->event_lock); } @@ -2300,6 +2451,9 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, } } + if (ipa_ctx->num_sap_connected == 1) + wlan_ipa_handle_multiple_sap_evt(ipa_ctx, type); + qdf_mutex_release(&ipa_ctx->event_lock); break; @@ -3091,6 +3245,7 @@ QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx, ipa_ctx->ipa_p_rx_packets = 0; ipa_ctx->resource_loading = false; ipa_ctx->resource_unloading = false; + ipa_ctx->num_sap_connected = 0; ipa_ctx->sta_connected = 0; ipa_ctx->ipa_pipes_down = true; qdf_atomic_set(&ipa_ctx->pipes_disabled, 1); diff --git a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c index 3f62f2b73941..e494c8d0085e 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c +++ b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/dp/txrx3.0/dp_fisa_rx.c @@ -818,6 +818,7 @@ dp_rx_fisa_flush_udp_flow(struct dp_vdev *vdev, } qdf_nbuf_set_next(fisa_flow->head_skb, NULL); + QDF_NBUF_CB_RX_NUM_ELEMENTS_IN_LIST(fisa_flow->head_skb) = 1; if (fisa_flow->last_skb) qdf_nbuf_set_next(fisa_flow->last_skb, NULL); @@ -1230,6 +1231,7 @@ QDF_STATUS dp_fisa_rx(struct dp_soc *soc, struct dp_vdev *vdev, head_nbuf); deliver_nbuf: /* Deliver without FISA */ + QDF_NBUF_CB_RX_NUM_ELEMENTS_IN_LIST(head_nbuf) = 1; qdf_nbuf_set_next(head_nbuf, NULL); hex_dump_skb_data(head_nbuf, false); if (!vdev->osif_rx || QDF_STATUS_SUCCESS != diff --git a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/dp/txrx3.0/dp_rx_thread.c b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/dp/txrx3.0/dp_rx_thread.c index 7788791ead33..6bffa2f9a7a7 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/dp/txrx3.0/dp_rx_thread.c +++ b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/dp/txrx3.0/dp_rx_thread.c @@ -154,6 +154,7 @@ QDF_STATUS dp_check_and_update_pending(struct dp_rx_tm_handle_cmn uint32_t rx_pending_lo_threshold; uint32_t nbuf_queued_total = 0; uint32_t nbuf_dequeued_total = 0; + uint32_t rx_flushed_total = 0; uint32_t pending = 0; int i; @@ -184,11 +185,14 @@ QDF_STATUS dp_check_and_update_pending(struct dp_rx_tm_handle_cmn rx_tm_hdl->rx_thread[i]->stats.nbuf_queued_total; nbuf_dequeued_total += rx_tm_hdl->rx_thread[i]->stats.nbuf_dequeued; + rx_flushed_total += + rx_tm_hdl->rx_thread[i]->stats.rx_flushed; } } - if (nbuf_queued_total > nbuf_dequeued_total) - pending = nbuf_queued_total - nbuf_dequeued_total; + if (nbuf_queued_total > (nbuf_dequeued_total + rx_flushed_total)) + pending = nbuf_queued_total - (nbuf_dequeued_total + + rx_flushed_total); if (unlikely(pending > rx_pending_hl_threshold)) qdf_atomic_set(&rx_tm_hdl->allow_dropping, 1); diff --git a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c index c613bbc6c1b4..742f1c87e5a6 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c +++ b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c @@ -17369,6 +17369,9 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy, if (pairwise) wma_set_peer_ucast_cipher(mac_address.bytes, cipher); + cdp_peer_flush_frags(cds_get_context(QDF_MODULE_ID_SOC), + wlan_vdev_get_id(vdev), mac_address.bytes); + switch (adapter->device_mode) { case QDF_IBSS_MODE: errno = wlan_hdd_add_key_ibss(adapter, pairwise, key_index, diff --git a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/hdd/src/wlan_hdd_softap_tx_rx.c b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/hdd/src/wlan_hdd_softap_tx_rx.c index 92728f213e25..1020a939f43a 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -1130,6 +1130,15 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *adapter_context, qdf_nbuf_t rx_buf) true, STA_INFO_SOFTAP_RX_PACKET_CBK); } + + if (qdf_unlikely(qdf_nbuf_is_ipv4_eapol_pkt(skb) && + qdf_mem_cmp(qdf_nbuf_data(skb) + + QDF_NBUF_DEST_MAC_OFFSET, + adapter->mac_addr.bytes, + QDF_MAC_ADDR_SIZE))) { + qdf_nbuf_free(skb); + continue; + } hdd_event_eapol_log(skb, QDF_RX); qdf_dp_trace_log_pkt(adapter->vdev_id, diff --git a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/mac/inc/qwlan_version.h b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/mac/inc/qwlan_version.h index b8ddbc8059e4..8e7d4b829cd9 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/mac/inc/qwlan_version.h +++ b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/mac/inc/qwlan_version.h @@ -34,27 +34,27 @@ #define QWLAN_VERSION_PATCH 022 #if defined(CONFIG_LITHIUM) #if defined(QCA_WIFI_QCA6390) //Hastings -#define QWLAN_VERSION_EXTRA "U-HS201223A" +#define QWLAN_VERSION_EXTRA "U-HS210304" #elif defined(QCA_WIFI_QCA6490) // Hastings Prime -#define QWLAN_VERSION_EXTRA "U-HP201223A" +#define QWLAN_VERSION_EXTRA "U-HP210304" #else #define QWLAN_VERSION_EXTRA "U-QCOM" #endif #else -#define QWLAN_VERSION_EXTRA "U-HL201223A" +#define QWLAN_VERSION_EXTRA "U-HL210304" #endif #define QWLAN_VERSION_BUILD 4 #if defined(CONFIG_LITHIUM) #if defined(QCA_WIFI_QCA6390) //Hastings -#define QWLAN_VERSIONSTR "5.2.022.4U-HS201223A" +#define QWLAN_VERSIONSTR "5.2.022.4U-HS210304" #elif defined(QCA_WIFI_QCA6490) // Hastings Prime -#define QWLAN_VERSIONSTR "5.2.022.4U-HP201223A" +#define QWLAN_VERSIONSTR "5.2.022.4U-HP210304" #else #define QWLAN_VERSIONSTR "5.2.022.4U-QCOM" #endif #else -#define QWLAN_VERSIONSTR "5.2.022.4U-HL201223A" +#define QWLAN_VERSIONSTR "5.2.022.4U-HL210304" #endif #endif /* QWLAN_VERSION_H */ diff --git a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/wma/src/wma_mgmt.c b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/wma/src/wma_mgmt.c index 16b7f50428b1..87cde06d2852 100644 --- a/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/wma/src/wma_mgmt.c +++ b/drivers/net/wireless/qualcomm/qca6390/qcacld-3.0/core/wma/src/wma_mgmt.c @@ -902,45 +902,6 @@ static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity) return 0; } -#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) - -/** - * wma_unified_peer_state_update() - update peer state - * @sta_mac: pointer to sta mac addr - * @bss_addr: bss address - * @sta_type: sta entry type - * - * - * Return: None - */ -static void -wma_unified_peer_state_update( - uint8_t *sta_mac, - uint8_t *bss_addr, - uint8_t sta_type) -{ - void *soc = cds_get_context(QDF_MODULE_ID_SOC); - - if (STA_ENTRY_TDLS_PEER == sta_type) - cdp_peer_state_update(soc, sta_mac, - OL_TXRX_PEER_STATE_AUTH); - else - cdp_peer_state_update(soc, bss_addr, - OL_TXRX_PEER_STATE_AUTH); -} -#else - -static inline void -wma_unified_peer_state_update( - uint8_t *sta_mac, - uint8_t *bss_addr, - uint8_t sta_type) -{ - void *soc = cds_get_context(QDF_MODULE_ID_SOC); - - cdp_peer_state_update(soc, bss_addr, OL_TXRX_PEER_STATE_AUTH); -} -#endif #define CFG_CTRL_MASK 0xFF00 #define CFG_DATA_MASK 0x00FF @@ -1506,9 +1467,6 @@ QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma, if (params->wpa_rsn >> 1) cmd->need_gtk_2_way = 1; - wma_unified_peer_state_update(params->staMac, - params->bssId, params->staType); - #ifdef FEATURE_WLAN_WAPI if (params->encryptType == eSIR_ED_WPI) { ret = wma_vdev_set_param(wma->wmi_handle, params->smesessionId, diff --git a/drivers/samsung/debug/sec_debug.c b/drivers/samsung/debug/sec_debug.c index 71da26d8d708..e81ed0662be8 100644 --- a/drivers/samsung/debug/sec_debug.c +++ b/drivers/samsung/debug/sec_debug.c @@ -802,17 +802,17 @@ static int __init __sec_debug_dt_addr_init(void) { return 0; } static int __init force_upload_setup(char *en) { get_option(&en, &force_upload); - return 1; + return 0; } -__setup("androidboot.force_upload=", force_upload_setup); +early_param("androidboot.force_upload", force_upload_setup); /* for sec debug level */ static int __init sec_debug_level_setup(char *str) { get_option(&str, &sec_dbg_level); - return 1; + return 0; } -__setup("androidboot.debug_level=", sec_debug_level_setup); +early_param("androidboot.debug_level", sec_debug_level_setup); static int __init sec_debug_init(void) { diff --git a/drivers/security/samsung/five_tee_driver/Kconfig b/drivers/security/samsung/five_tee_driver/Kconfig index 097375836db0..f374aee59cf1 100644 --- a/drivers/security/samsung/five_tee_driver/Kconfig +++ b/drivers/security/samsung/five_tee_driver/Kconfig @@ -68,7 +68,6 @@ config FIVE_TRUSTLET_PATH config FIVE_EARLY_LOAD_TRUSTED_APP bool "Load trusted application in early boot" depends on FIVE_TEE_DRIVER - default y if FIVE_USE_QSEE default n help Enable the load of trusted application on during initialization of driver diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index a4bbb3086318..9160aab151a6 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -660,7 +660,7 @@ msm_get_crash(struct device *dev, { pr_err("intentional cdsp runtime failed! comment out-just footprint!\n"); #ifndef CONFIG_SEC_CDSP_NOT_CRASH_ENG - BUG_ON(1); + //BUG_ON(1); #endif /* CONFIG_SEC_CDSP_NOT_CRASH_ENG */ return snprintf(buf, PAGE_SIZE, "Qualcomm Technologies, Inc\n"); } diff --git a/fs/block_dev.c b/fs/block_dev.c index 51c4520af7c5..049101f55ca9 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1463,10 +1463,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) */ if (!for_part) { ret = devcgroup_inode_permission(bdev->bd_inode, perm); - if (ret != 0) { - bdput(bdev); + if (ret != 0) return ret; - } } restart: @@ -1535,8 +1533,10 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) goto out_clear; BUG_ON(for_part); ret = __blkdev_get(whole, mode, 1); - if (ret) + if (ret) { + bdput(whole); goto out_clear; + } bdev->bd_contains = whole; bdev->bd_part = disk_get_part(disk, partno); if (!(disk->flags & GENHD_FL_UP) || @@ -1586,7 +1586,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) disk_unblock_events(disk); put_disk_and_module(disk); out: - bdput(bdev); return ret; } @@ -1672,6 +1671,9 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder) bdput(whole); } + if (res) + bdput(bdev); + return res; } EXPORT_SYMBOL(blkdev_get); diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 9077b3ebea08..728d7716bf4f 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -227,7 +227,7 @@ struct xt_table { unsigned int valid_hooks; /* Man behind the curtain... */ - struct xt_table_info *private; + struct xt_table_info __rcu *private; /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; @@ -449,6 +449,9 @@ xt_get_per_cpu_counter(struct xt_counters *cnt, unsigned int cpu) struct nf_hook_ops *xt_hook_ops_alloc(const struct xt_table *, nf_hookfn *); +struct xt_table_info +*xt_table_get_private_protected(const struct xt_table *table); + #ifdef CONFIG_COMPAT #include diff --git a/include/linux/ologk.h b/include/linux/ologk.h index 0b2c69a92597..cde05be84193 100644 --- a/include/linux/ologk.h +++ b/include/linux/ologk.h @@ -2,6 +2,7 @@ #define _OLOG_KERNEL_H_ #include +#include "olog.pb.h" #define OLOG_CPU_FREQ_FILTER 1500000 #define PERFLOG_MUTEX_THRESHOLD 20 @@ -11,4 +12,3 @@ #define perflog_evt(...) #endif - diff --git a/kernel/signal.c b/kernel/signal.c index bb7722cac55f..0b4003180684 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1218,7 +1218,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, #endif /* [SystemF/W, si_code is 0 : from userspace, si_code is over 0 : from kernel */ - if (info != SEND_SIG_NOINFO && info != SEND_SIG_PRIV) { + if (!is_si_special(info)) { if ((current->pid != 1) && ((sig == SIGKILL && !strncmp("main", t->group_leader->comm, 4)) || ((sig == SIGKILL || sig == SIGSEGV) && !strncmp("system_server", t->group_leader->comm, 13)))) { diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 4efa5e33513e..59c0b1a86e51 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -244,7 +244,7 @@ static struct { /** * icmp_global_allow - Are we allowed to send one more ICMP message ? * - * Uses a token bucket to limit our ICMP messages to sysctl_icmp_msgs_per_sec. + * Uses a token bucket to limit our ICMP messages to ~sysctl_icmp_msgs_per_sec. * Returns false if we reached the limit and can not send another packet. * Note: called with BH disabled */ @@ -272,7 +272,10 @@ bool icmp_global_allow(void) } credit = min_t(u32, icmp_global.credit + incr, sysctl_icmp_msgs_burst); if (credit) { - credit--; + /* We want to use a credit of one in average, but need to randomize + * it for security reasons. + */ + credit = max_t(int, credit - prandom_u32_max(3), 0); rc = true; } WRITE_ONCE(icmp_global.credit, credit); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 51d2f7567ee9..ac0762ddd4e5 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -202,7 +202,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, local_bh_disable(); addend = xt_write_recseq_begin(); - private = READ_ONCE(table->private); /* Address dependency. */ + private = rcu_access_pointer(table->private); cpu = smp_processor_id(); table_base = private->entries; jumpstack = (struct arpt_entry **)private->jumpstack[cpu]; @@ -648,7 +648,7 @@ static struct xt_counters *alloc_counters(const struct xt_table *table) { unsigned int countersize; struct xt_counters *counters; - const struct xt_table_info *private = table->private; + const struct xt_table_info *private = xt_table_get_private_protected(table); /* We need atomic snapshot of counters: rest doesn't change * (other than comefrom, which userspace doesn't care @@ -672,7 +672,7 @@ static int copy_entries_to_user(unsigned int total_size, unsigned int off, num; const struct arpt_entry *e; struct xt_counters *counters; - struct xt_table_info *private = table->private; + struct xt_table_info *private = xt_table_get_private_protected(table); int ret = 0; void *loc_cpu_entry; @@ -807,7 +807,7 @@ static int get_info(struct net *net, void __user *user, t = xt_request_find_table_lock(net, NFPROTO_ARP, name); if (!IS_ERR(t)) { struct arpt_getinfo info; - const struct xt_table_info *private = t->private; + const struct xt_table_info *private = xt_table_get_private_protected(t); #ifdef CONFIG_COMPAT struct xt_table_info tmp; @@ -860,7 +860,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr, t = xt_find_table_lock(net, NFPROTO_ARP, get.name); if (!IS_ERR(t)) { - const struct xt_table_info *private = t->private; + const struct xt_table_info *private = xt_table_get_private_protected(t); if (get.size == private->size) ret = copy_entries_to_user(private->size, @@ -1018,7 +1018,7 @@ static int do_add_counters(struct net *net, const void __user *user, } local_bh_disable(); - private = t->private; + private = xt_table_get_private_protected(t); if (private->number != tmp.num_counters) { ret = -EINVAL; goto unlock_up_free; @@ -1355,7 +1355,7 @@ static int compat_copy_entries_to_user(unsigned int total_size, void __user *userptr) { struct xt_counters *counters; - const struct xt_table_info *private = table->private; + const struct xt_table_info *private = xt_table_get_private_protected(table); void __user *pos; unsigned int size; int ret = 0; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 62934d3cd8c4..520aedb73cd3 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -261,7 +261,7 @@ ipt_do_table(struct sk_buff *skb, WARN_ON(!(table->valid_hooks & (1 << hook))); local_bh_disable(); addend = xt_write_recseq_begin(); - private = READ_ONCE(table->private); /* Address dependency. */ + private = rcu_access_pointer(table->private); cpu = smp_processor_id(); table_base = private->entries; jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; @@ -794,7 +794,7 @@ static struct xt_counters *alloc_counters(const struct xt_table *table) { unsigned int countersize; struct xt_counters *counters; - const struct xt_table_info *private = table->private; + const struct xt_table_info *private = xt_table_get_private_protected(table); /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care @@ -818,7 +818,7 @@ copy_entries_to_user(unsigned int total_size, unsigned int off, num; const struct ipt_entry *e; struct xt_counters *counters; - const struct xt_table_info *private = table->private; + const struct xt_table_info *private = xt_table_get_private_protected(table); int ret = 0; const void *loc_cpu_entry; @@ -968,7 +968,7 @@ static int get_info(struct net *net, void __user *user, t = xt_request_find_table_lock(net, AF_INET, name); if (!IS_ERR(t)) { struct ipt_getinfo info; - const struct xt_table_info *private = t->private; + const struct xt_table_info *private = xt_table_get_private_protected(t); #ifdef CONFIG_COMPAT struct xt_table_info tmp; @@ -1022,7 +1022,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr, t = xt_find_table_lock(net, AF_INET, get.name); if (!IS_ERR(t)) { - const struct xt_table_info *private = t->private; + const struct xt_table_info *private = xt_table_get_private_protected(t); if (get.size == private->size) ret = copy_entries_to_user(private->size, t, uptr->entrytable); @@ -1177,7 +1177,7 @@ do_add_counters(struct net *net, const void __user *user, } local_bh_disable(); - private = t->private; + private = xt_table_get_private_protected(t); if (private->number != tmp.num_counters) { ret = -EINVAL; goto unlock_up_free; @@ -1572,7 +1572,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, void __user *userptr) { struct xt_counters *counters; - const struct xt_table_info *private = table->private; + const struct xt_table_info *private = xt_table_get_private_protected(table); void __user *pos; unsigned int size; int ret = 0; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 06341def335c..b66451e4bf8e 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -283,7 +283,7 @@ ip6t_do_table(struct sk_buff *skb, local_bh_disable(); addend = xt_write_recseq_begin(); - private = READ_ONCE(table->private); /* Address dependency. */ + private = rcu_access_pointer(table->private); cpu = smp_processor_id(); table_base = private->entries; jumpstack = (struct ip6t_entry **)private->jumpstack[cpu]; @@ -810,7 +810,7 @@ static struct xt_counters *alloc_counters(const struct xt_table *table) { unsigned int countersize; struct xt_counters *counters; - const struct xt_table_info *private = table->private; + const struct xt_table_info *private = xt_table_get_private_protected(table); /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care @@ -834,7 +834,7 @@ copy_entries_to_user(unsigned int total_size, unsigned int off, num; const struct ip6t_entry *e; struct xt_counters *counters; - const struct xt_table_info *private = table->private; + const struct xt_table_info *private = xt_table_get_private_protected(table); int ret = 0; const void *loc_cpu_entry; @@ -984,7 +984,7 @@ static int get_info(struct net *net, void __user *user, t = xt_request_find_table_lock(net, AF_INET6, name); if (!IS_ERR(t)) { struct ip6t_getinfo info; - const struct xt_table_info *private = t->private; + const struct xt_table_info *private = xt_table_get_private_protected(t); #ifdef CONFIG_COMPAT struct xt_table_info tmp; @@ -1039,7 +1039,7 @@ get_entries(struct net *net, struct ip6t_get_entries __user *uptr, t = xt_find_table_lock(net, AF_INET6, get.name); if (!IS_ERR(t)) { - struct xt_table_info *private = t->private; + struct xt_table_info *private = xt_table_get_private_protected(t); if (get.size == private->size) ret = copy_entries_to_user(private->size, t, uptr->entrytable); @@ -1193,7 +1193,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, } local_bh_disable(); - private = t->private; + private = xt_table_get_private_protected(t); if (private->number != tmp.num_counters) { ret = -EINVAL; goto unlock_up_free; @@ -1581,7 +1581,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, void __user *userptr) { struct xt_counters *counters; - const struct xt_table_info *private = table->private; + const struct xt_table_info *private = xt_table_get_private_protected(table); void __user *pos; unsigned int size; int ret = 0; diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 3bab89dbc371..12ad141f7efc 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -1354,6 +1354,14 @@ struct xt_counters *xt_counters_alloc(unsigned int counters) } EXPORT_SYMBOL(xt_counters_alloc); +struct xt_table_info +*xt_table_get_private_protected(const struct xt_table *table) +{ + return rcu_dereference_protected(table->private, + mutex_is_locked(&xt[table->af].mutex)); +} +EXPORT_SYMBOL(xt_table_get_private_protected); + struct xt_table_info * xt_replace_table(struct xt_table *table, unsigned int num_counters, @@ -1361,7 +1369,6 @@ xt_replace_table(struct xt_table *table, int *error) { struct xt_table_info *private; - unsigned int cpu; int ret; ret = xt_jumpstack_alloc(newinfo); @@ -1371,47 +1378,19 @@ xt_replace_table(struct xt_table *table, } /* Do the substitution. */ - local_bh_disable(); - private = table->private; + private = xt_table_get_private_protected(table); /* Check inside lock: is the old number correct? */ if (num_counters != private->number) { pr_debug("num_counters != table->private->number (%u/%u)\n", num_counters, private->number); - local_bh_enable(); *error = -EAGAIN; return NULL; } newinfo->initial_entries = private->initial_entries; - /* - * Ensure contents of newinfo are visible before assigning to - * private. - */ - smp_wmb(); - table->private = newinfo; - - /* make sure all cpus see new ->private value */ - smp_wmb(); - - /* - * Even though table entries have now been swapped, other CPU's - * may still be using the old entries... - */ - local_bh_enable(); - - /* ... so wait for even xt_recseq on all cpus */ - for_each_possible_cpu(cpu) { - seqcount_t *s = &per_cpu(xt_recseq, cpu); - u32 seq = raw_read_seqcount(s); - - if (seq & 1) { - do { - cond_resched(); - cpu_relax(); - } while (seq == raw_read_seqcount(s)); - } - } + rcu_assign_pointer(table->private, newinfo); + synchronize_rcu(); #ifdef CONFIG_AUDIT if (audit_enabled) { @@ -1452,12 +1431,12 @@ struct xt_table *xt_register_table(struct net *net, } /* Simplifies replace_table code. */ - table->private = bootstrap; + rcu_assign_pointer(table->private, bootstrap); if (!xt_replace_table(table, 0, newinfo, &ret)) goto unlock; - private = table->private; + private = xt_table_get_private_protected(table); pr_debug("table->private->number = %u\n", private->number); /* save number of initial entries */ @@ -1480,7 +1459,8 @@ void *xt_unregister_table(struct xt_table *table) struct xt_table_info *private; mutex_lock(&xt[table->af].mutex); - private = table->private; + private = xt_table_get_private_protected(table); + RCU_INIT_POINTER(table->private, NULL); list_del(&table->list); mutex_unlock(&xt[table->af].mutex); kfree(table); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index bf6fcbaa3eec..8844256fb726 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2160,11 +2160,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, int skb_len = skb->len; unsigned int snaplen, res; unsigned long status = TP_STATUS_USER; - unsigned short macoff, netoff, hdrlen; + unsigned short macoff, hdrlen; + unsigned int netoff; struct sk_buff *copy_skb = NULL; struct timespec ts; __u32 ts_status; bool is_drop_n_account = false; + unsigned int slot_id = 0; bool do_vnet = false; /* struct tpacket{2,3}_hdr is aligned to a multiple of TPACKET_ALIGNMENT. @@ -2222,6 +2224,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, } macoff = netoff - maclen; } + if (netoff > USHRT_MAX) { + spin_lock(&sk->sk_receive_queue.lock); + po->stats.stats1.tp_drops++; + spin_unlock(&sk->sk_receive_queue.lock); + goto drop_n_restore; + } if (po->tp_version <= TPACKET_V2) { if (macoff + snaplen > po->rx_ring.frame_size) { if (po->copy_thresh && @@ -2261,6 +2269,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, if (!h.raw) goto drop_n_account; + if (po->tp_version <= TPACKET_V2) { + slot_id = po->rx_ring.head; + if (test_bit(slot_id, po->rx_ring.rx_owner_map)) + goto drop_n_account; + __set_bit(slot_id, po->rx_ring.rx_owner_map); + } + if (do_vnet && virtio_net_hdr_from_skb(skb, h.raw + macoff - sizeof(struct virtio_net_hdr), @@ -2366,7 +2381,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, #endif if (po->tp_version <= TPACKET_V2) { + spin_lock(&sk->sk_receive_queue.lock); __packet_set_status(po, h.raw, status); + __clear_bit(slot_id, po->rx_ring.rx_owner_map); + spin_unlock(&sk->sk_receive_queue.lock); sk->sk_data_ready(sk); } else { prb_clear_blk_fill_status(&po->rx_ring); @@ -4260,6 +4278,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, { struct pgv *pg_vec = NULL; struct packet_sock *po = pkt_sk(sk); + unsigned long *rx_owner_map = NULL; int was_running, order = 0; struct packet_ring_buffer *rb; struct sk_buff_head *rb_queue; @@ -4345,6 +4364,12 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, } break; default: + if (!tx_ring) { + rx_owner_map = bitmap_alloc(req->tp_frame_nr, + GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO); + if (!rx_owner_map) + goto out_free_pg_vec; + } break; } } @@ -4374,6 +4399,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, err = 0; spin_lock_bh(&rb_queue->lock); swap(rb->pg_vec, pg_vec); + if (po->tp_version <= TPACKET_V2) + swap(rb->rx_owner_map, rx_owner_map); rb->frame_max = (req->tp_frame_nr - 1); rb->head = 0; rb->frame_size = req->tp_frame_size; @@ -4405,6 +4432,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, } out_free_pg_vec: + bitmap_free(rx_owner_map); if (pg_vec) free_pg_vec(pg_vec, order, req->tp_block_nr); out: diff --git a/net/packet/internal.h b/net/packet/internal.h index c70a2794456f..f10294800aaf 100644 --- a/net/packet/internal.h +++ b/net/packet/internal.h @@ -70,7 +70,10 @@ struct packet_ring_buffer { unsigned int __percpu *pending_refcnt; - struct tpacket_kbdq_core prb_bdqc; + union { + unsigned long *rx_owner_map; + struct tpacket_kbdq_core prb_bdqc; + }; }; extern struct mutex fanout_mutex; diff --git a/security/samsung/five/five_cache.h b/security/samsung/five/five_cache.h index a40bfa019f96..d3cf579fb8e7 100644 --- a/security/samsung/five/five_cache.h +++ b/security/samsung/five/five_cache.h @@ -20,7 +20,7 @@ #ifndef __LINUX_FIVE_CACHE_H #define __LINUX_FIVE_CACHE_H -#include "security/integrity/integrity.h" +#include "../../integrity/integrity.h" enum five_file_integrity five_get_cache_status( const struct integrity_iint_cache *iint); diff --git a/security/samsung/five/five_crypto.c b/security/samsung/five/five_crypto.c index 959030acdaa9..699275fd4bb1 100644 --- a/security/samsung/five/five_crypto.c +++ b/security/samsung/five/five_crypto.c @@ -33,7 +33,7 @@ #include "five.h" #include "five_crypto_comp.h" #include "five_porting.h" -#include "security/integrity/integrity.h" +#include "../../integrity/integrity.h" struct ahash_completion { struct completion completion; diff --git a/security/samsung/five/five_dmverity.c b/security/samsung/five/five_dmverity.c index 8b92d011ae45..59704ffd76a0 100644 --- a/security/samsung/five/five_dmverity.c +++ b/security/samsung/five/five_dmverity.c @@ -20,8 +20,8 @@ #include "five_dmverity.h" #include "five.h" -#include "drivers/md/dm.h" -#include "drivers/block/loop.h" +#include "../../drivers/md/dm.h" +#include "../../drivers/block/loop.h" #ifdef CONFIG_FIVE_DEBUG #include diff --git a/techpack/audio/config/kona_bloomx.h b/techpack/audio/config/kona_bloomx.h index f077db323fe9..57e1f2a554d4 100644 --- a/techpack/audio/config/kona_bloomx.h +++ b/techpack/audio/config/kona_bloomx.h @@ -42,7 +42,7 @@ #define CONFIG_VOICE_MHI 1 #define CONFIG_DIGITAL_CDC_RSC_MGR 1 #define CONFIG_SEC_SND_ADAPTATION 1 -#define CONFIG_SEC_SND_DEBUG 1 +//#define CONFIG_SEC_SND_DEBUG 1 #define CONFIG_SEC_SND_PRIMARY 1 #define CONFIG_SEC_PCIE_L1SS_CTRL 1 #define CONFIG_SEC_AFE_REMOTE_MIC 1 diff --git a/techpack/audio/config/kona_f2.h b/techpack/audio/config/kona_f2.h index f077db323fe9..57e1f2a554d4 100644 --- a/techpack/audio/config/kona_f2.h +++ b/techpack/audio/config/kona_f2.h @@ -42,7 +42,7 @@ #define CONFIG_VOICE_MHI 1 #define CONFIG_DIGITAL_CDC_RSC_MGR 1 #define CONFIG_SEC_SND_ADAPTATION 1 -#define CONFIG_SEC_SND_DEBUG 1 +//#define CONFIG_SEC_SND_DEBUG 1 #define CONFIG_SEC_SND_PRIMARY 1 #define CONFIG_SEC_PCIE_L1SS_CTRL 1 #define CONFIG_SEC_AFE_REMOTE_MIC 1 diff --git a/techpack/audio/config/kona_gts7xl.h b/techpack/audio/config/kona_gts7xl.h index a5cd0a0b3a88..51b7876d8a24 100644 --- a/techpack/audio/config/kona_gts7xl.h +++ b/techpack/audio/config/kona_gts7xl.h @@ -42,7 +42,7 @@ #define CONFIG_VOICE_MHI 1 #define CONFIG_DIGITAL_CDC_RSC_MGR 1 #define CONFIG_SEC_SND_ADAPTATION 1 -#define CONFIG_SEC_SND_DEBUG 1 +//#define CONFIG_SEC_SND_DEBUG 1 #define CONFIG_SEC_SND_PRIMARY 1 #define CONFIG_SEC_PCIE_L1SS_CTRL 1 #define CONFIG_SEC_AFE_REMOTE_MIC 1 \ No newline at end of file diff --git a/techpack/audio/config/kona_r8.h b/techpack/audio/config/kona_r8.h index f077db323fe9..57e1f2a554d4 100644 --- a/techpack/audio/config/kona_r8.h +++ b/techpack/audio/config/kona_r8.h @@ -42,7 +42,7 @@ #define CONFIG_VOICE_MHI 1 #define CONFIG_DIGITAL_CDC_RSC_MGR 1 #define CONFIG_SEC_SND_ADAPTATION 1 -#define CONFIG_SEC_SND_DEBUG 1 +//#define CONFIG_SEC_SND_DEBUG 1 #define CONFIG_SEC_SND_PRIMARY 1 #define CONFIG_SEC_PCIE_L1SS_CTRL 1 #define CONFIG_SEC_AFE_REMOTE_MIC 1 diff --git a/techpack/audio/config/kona_victory.h b/techpack/audio/config/kona_victory.h index f077db323fe9..57e1f2a554d4 100644 --- a/techpack/audio/config/kona_victory.h +++ b/techpack/audio/config/kona_victory.h @@ -42,7 +42,7 @@ #define CONFIG_VOICE_MHI 1 #define CONFIG_DIGITAL_CDC_RSC_MGR 1 #define CONFIG_SEC_SND_ADAPTATION 1 -#define CONFIG_SEC_SND_DEBUG 1 +//#define CONFIG_SEC_SND_DEBUG 1 #define CONFIG_SEC_SND_PRIMARY 1 #define CONFIG_SEC_PCIE_L1SS_CTRL 1 #define CONFIG_SEC_AFE_REMOTE_MIC 1 diff --git a/techpack/audio/dsp/q6core.c b/techpack/audio/dsp/q6core.c index 392b09dec8e7..96d5c6b3bbdc 100644 --- a/techpack/audio/dsp/q6core.c +++ b/techpack/audio/dsp/q6core.c @@ -725,6 +725,11 @@ int q6core_get_avcs_api_version_per_service(uint32_t service_id) return ret; } + if (q6core_lcl.q6core_avcs_ver_info.ver_info == NULL) { + pr_err("%s:: ver_info is NULL\n"); + return -EINVAL; + } + cached_ver_info = q6core_lcl.q6core_avcs_ver_info.ver_info; num_services = cached_ver_info->avcs_fwk_version.num_services; diff --git a/techpack/display/msm/dp/dp_display.c b/techpack/display/msm/dp/dp_display.c index a121b280c981..2faf7f5bca6e 100644 --- a/techpack/display/msm/dp/dp_display.c +++ b/techpack/display/msm/dp/dp_display.c @@ -4594,7 +4594,7 @@ static bool secdp_check_supported_resolution(struct dp_display_private *dp, ret = true; #ifndef SECDP_IGNORE_PREFER_IF_DEX_RES_EXIST - if (ret) { + if (ret && !sec->has_prefer) { #else if (ret && !secdp_check_dex_ratio(sec->prefer_ratio)) { #endif