diff options
544 files changed, 24493 insertions, 7633 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 188d46e13d4..b679a62dab5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -3390,21 +3390,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. that this also can be controlled per-workqueue for workqueues visible under /sys/bus/workqueue/. - workqueue.power_efficient - Per-cpu workqueues are generally preferred because - they show better performance thanks to cache - locality; unfortunately, per-cpu workqueues tend to - be more power hungry than unbound workqueues. - - Enabling this makes the per-cpu workqueues which - were observed to contribute significantly to power - consumption unbound, leading to measurably lower - power usage at the cost of small performance - overhead. - - The default value of this parameter is determined by - the config option CONFIG_WQ_POWER_EFFICIENT_DEFAULT. - x2apic_phys [X86-64,APIC] Use x2apic physical mode instead of default x2apic cluster mode on platforms supporting x2apic. diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index 3f35e2dc34a..3af5ae6c9c1 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt @@ -45,11 +45,6 @@ Kernel Pointers: users. The behaviour of %pK depends on the kptr_restrict sysctl - see Documentation/sysctl/kernel.txt for more details. - %pP 0x01234567 or 0x0123456789abcdef - - For printing kernel pointers which should always be shown, even to - unprivileged users. - Struct Resources: %pr [mem 0x60000000-0x6fffffff flags 0x2200] or diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 0eb7cb99537..d438fd2c21a 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -334,15 +334,6 @@ values to unprivileged users is a concern. When kptr_restrict is set to (2), kernel pointers printed using %pK will be replaced with 0's regardless of privileges. -When kptr_restrict is set to (3), kernel pointers printed using -%p and %pK will be replaced with 0's regardless of privileges, -however kernel pointers printed using %pP will continue to be printed. - -When kptr_restrict is set to (4), kernel pointers printed with -%p, %pK, %pa, and %p[rR] will be replaced with 0's regardless of -privileges. Kernel pointers printed using %pP will continue to be -printed. - ============================================================== kstack_depth_to_print: (X86 only) diff --git a/MAINTAINERS b/MAINTAINERS index 5bcf562c019..c54de5f47e3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7139,6 +7139,16 @@ S: Maintained F: drivers/mmc/host/sdhci.* F: drivers/mmc/host/sdhci-pltfm.[ch] +SECURE COMPUTING +M: Kees Cook <keescook@chromium.org> +T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git seccomp +S: Supported +F: kernel/seccomp.c +F: include/uapi/linux/seccomp.h +F: include/linux/seccomp.h +K: \bsecure_computing +K: \bTIF_SECCOMP\b + SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF) M: Anton Vorontsov <avorontsov@ru.mvista.com> L: linuxppc-dev@lists.ozlabs.org @@ -1,8 +1,8 @@ VERSION = 3 PATCHLEVEL = 10 -SUBLEVEL = 107 +SUBLEVEL = 108 EXTRAVERSION = -NAME = TOSSUG Baby Fish +NAME = END-OF-LIFE # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -331,7 +331,7 @@ include $(srctree)/scripts/Kbuild.include AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld -CC = $(CROSS_COMPILE)gcc +REAL_CC = $(CROSS_COMPILE)gcc CPP = $(CC) -E AR = $(CROSS_COMPILE)ar NM = $(CROSS_COMPILE)nm @@ -345,6 +345,10 @@ DEPMOD = /sbin/depmod PERL = perl CHECK = sparse +# Use the wrapper for the compiler. This wrapper scans for new +# warnings and causes the build to stop upon encountering them. +CC = $(srctree)/scripts/gcc-wrapper.py $(REAL_CC) + CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ -Wbitwise -Wno-return-void $(CF) CFLAGS_MODULE = diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg index 644f8f8b6a3..abe92f78f65 100644 --- a/android/configs/android-base.cfg +++ b/android/configs/android-base.cfg @@ -1,4 +1,6 @@ # KEEP ALPHABETICALLY SORTED +# CONFIG_DEVKMEM is not set +# CONFIG_DEVMEM is not set # CONFIG_INET_LRO is not set # CONFIG_MODULES is not set # CONFIG_NFSD is not set diff --git a/arch/arm/boot/dts/qcom/msm8952-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8952-gpu.dtsi index 4007ab1593c..b7a0995769c 100644 --- a/arch/arm/boot/dts/qcom/msm8952-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/msm8952-gpu.dtsi @@ -56,7 +56,7 @@ qcom,chipid = <0x04000510>; - qcom,initial-pwrlevel = <4>; + qcom,initial-pwrlevel = <3>; qcom,idle-timeout = <80>; //msecs qcom,strtstp-sleepwake; diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index ce01364a96e..992d4046bb8 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -21,3 +21,49 @@ config SHARP_SCOOP config FIQ_GLUE bool select FIQ + +config FIQ_DEBUGGER + bool "FIQ Mode Serial Debugger" + select FIQ + select FIQ_GLUE + default n + help + The FIQ serial debugger can accept commands even when the + kernel is unresponsive due to being stuck with interrupts + disabled. + + +config FIQ_DEBUGGER_NO_SLEEP + bool "Keep serial debugger active" + depends on FIQ_DEBUGGER + default n + help + Enables the serial debugger at boot. Passing + fiq_debugger.no_sleep on the kernel commandline will + override this config option. + +config FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON + bool "Don't disable wakeup IRQ when debugger is active" + depends on FIQ_DEBUGGER + default n + help + Don't disable the wakeup irq when enabling the uart clock. This will + cause extra interrupts, but it makes the serial debugger usable with + on some MSM radio builds that ignore the uart clock request in power + collapse. + +config FIQ_DEBUGGER_CONSOLE + bool "Console on FIQ Serial Debugger port" + depends on FIQ_DEBUGGER + default n + help + Enables a console so that printk messages are displayed on + the debugger serial port as the occur. + +config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE + bool "Put the FIQ debugger into console mode by default" + depends on FIQ_DEBUGGER_CONSOLE + default n + help + If enabled, this puts the fiq debugger into console mode by default. + Otherwise, the fiq debugger will start out in debug mode. diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 76e765d1856..a5bb6641670 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -4,6 +4,7 @@ obj-y += firmware.o +obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger.o obj-$(CONFIG_FIQ_GLUE) += fiq_glue.o fiq_glue_setup.o obj-$(CONFIG_ICST) += icst.o obj-$(CONFIG_SA1111) += sa1111.o diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c new file mode 100644 index 00000000000..65b943c7630 --- /dev/null +++ b/arch/arm/common/fiq_debugger.c @@ -0,0 +1,1376 @@ +/* + * arch/arm/common/fiq_debugger.c + * + * Serial Debugger Interface accessed through an FIQ interrupt. + * + * Copyright (C) 2008 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <stdarg.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/console.h> +#include <linux/interrupt.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/kernel_stat.h> +#include <linux/kmsg_dump.h> +#include <linux/irq.h> +#include <linux/delay.h> +#include <linux/reboot.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/smp.h> +#include <linux/timer.h> +#include <linux/tty.h> +#include <linux/tty_flip.h> +#include <linux/wakelock.h> + +#include <asm/fiq_debugger.h> +#include <asm/fiq_glue.h> +#include <asm/stacktrace.h> + +#include <linux/uaccess.h> + +#include "fiq_debugger_ringbuf.h" + +#define DEBUG_MAX 64 +#define MAX_UNHANDLED_FIQ_COUNT 1000000 + +#define MAX_FIQ_DEBUGGER_PORTS 4 + +#define THREAD_INFO(sp) ((struct thread_info *) \ + ((unsigned long)(sp) & ~(THREAD_SIZE - 1))) + +struct fiq_debugger_state { + struct fiq_glue_handler handler; + + int fiq; + int uart_irq; + int signal_irq; + int wakeup_irq; + bool wakeup_irq_no_set_wake; + struct clk *clk; + struct fiq_debugger_pdata *pdata; + struct platform_device *pdev; + + char debug_cmd[DEBUG_MAX]; + int debug_busy; + int debug_abort; + + char debug_buf[DEBUG_MAX]; + int debug_count; + + bool no_sleep; + bool debug_enable; + bool ignore_next_wakeup_irq; + struct timer_list sleep_timer; + spinlock_t sleep_timer_lock; + bool uart_enabled; + struct wake_lock debugger_wake_lock; + bool console_enable; + int current_cpu; + atomic_t unhandled_fiq_count; + bool in_fiq; + + struct work_struct work; + spinlock_t work_lock; + char work_cmd[DEBUG_MAX]; + +#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE + spinlock_t console_lock; + struct console console; + struct tty_port tty_port; + struct fiq_debugger_ringbuf *tty_rbuf; + bool syslog_dumping; +#endif + + unsigned int last_irqs[NR_IRQS]; + unsigned int last_local_timer_irqs[NR_CPUS]; +}; + +#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE +struct tty_driver *fiq_tty_driver; +#endif + +#ifdef CONFIG_FIQ_DEBUGGER_NO_SLEEP +static bool initial_no_sleep = true; +#else +static bool initial_no_sleep; +#endif + +#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE +static bool initial_debug_enable = true; +static bool initial_console_enable = true; +#else +static bool initial_debug_enable; +static bool initial_console_enable; +#endif + +static bool fiq_kgdb_enable; + +module_param_named(no_sleep, initial_no_sleep, bool, 0644); +module_param_named(debug_enable, initial_debug_enable, bool, 0644); +module_param_named(console_enable, initial_console_enable, bool, 0644); +module_param_named(kgdb_enable, fiq_kgdb_enable, bool, 0644); + +#ifdef CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON +static inline void enable_wakeup_irq(struct fiq_debugger_state *state) {} +static inline void disable_wakeup_irq(struct fiq_debugger_state *state) {} +#else +static inline void enable_wakeup_irq(struct fiq_debugger_state *state) +{ + if (state->wakeup_irq < 0) + return; + enable_irq(state->wakeup_irq); + if (!state->wakeup_irq_no_set_wake) + enable_irq_wake(state->wakeup_irq); +} +static inline void disable_wakeup_irq(struct fiq_debugger_state *state) +{ + if (state->wakeup_irq < 0) + return; + disable_irq_nosync(state->wakeup_irq); + if (!state->wakeup_irq_no_set_wake) + disable_irq_wake(state->wakeup_irq); +} +#endif + +static bool inline debug_have_fiq(struct fiq_debugger_state *state) +{ + return (state->fiq >= 0); +} + +static void debug_force_irq(struct fiq_debugger_state *state) +{ + unsigned int irq = state->signal_irq; + + if (WARN_ON(!debug_have_fiq(state))) + return; + if (state->pdata->force_irq) { + state->pdata->force_irq(state->pdev, irq); + } else { + struct irq_chip *chip = irq_get_chip(irq); + if (chip && chip->irq_retrigger) + chip->irq_retrigger(irq_get_irq_data(irq)); + } +} + +static void debug_uart_enable(struct fiq_debugger_state *state) +{ + if (state->clk) + clk_enable(state->clk); + if (state->pdata->uart_enable) + state->pdata->uart_enable(state->pdev); +} + +static void debug_uart_disable(struct fiq_debugger_state *state) +{ + if (state->pdata->uart_disable) + state->pdata->uart_disable(state->pdev); + if (state->clk) + clk_disable(state->clk); +} + +static void debug_uart_flush(struct fiq_debugger_state *state) +{ + if (state->pdata->uart_flush) + state->pdata->uart_flush(state->pdev); +} + +static void debug_putc(struct fiq_debugger_state *state, char c) +{ + state->pdata->uart_putc(state->pdev, c); +} + +static void debug_puts(struct fiq_debugger_state *state, char *s) +{ + unsigned c; + while ((c = *s++)) { + if (c == '\n') + debug_putc(state, '\r'); + debug_putc(state, c); + } +} + +static void debug_prompt(struct fiq_debugger_state *state) +{ + debug_puts(state, "debug> "); +} + +static void dump_kernel_log(struct fiq_debugger_state *state) +{ + char buf[512]; + size_t len; + struct kmsg_dumper dumper = { .active = true }; + + + kmsg_dump_rewind_nolock(&dumper); + while (kmsg_dump_get_line_nolock(&dumper, true, buf, + sizeof(buf) - 1, &len)) { + buf[len] = 0; + debug_puts(state, buf); + } +} + +static char *mode_name(unsigned cpsr) +{ + switch (cpsr & MODE_MASK) { + case USR_MODE: return "USR"; + case FIQ_MODE: return "FIQ"; + case IRQ_MODE: return "IRQ"; + case SVC_MODE: return "SVC"; + case ABT_MODE: return "ABT"; + case UND_MODE: return "UND"; + case SYSTEM_MODE: return "SYS"; + default: return "???"; + } +} + +static int debug_printf(void *cookie, const char *fmt, ...) +{ + struct fiq_debugger_state *state = cookie; + char buf[256]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + debug_puts(state, buf); + return state->debug_abort; +} + +/* Safe outside fiq context */ +static int debug_printf_nfiq(void *cookie, const char *fmt, ...) +{ + struct fiq_debugger_state *state = cookie; + char buf[256]; + va_list ap; + unsigned long irq_flags; + + va_start(ap, fmt); + vsnprintf(buf, 128, fmt, ap); + va_end(ap); + + local_irq_save(irq_flags); + debug_puts(state, buf); + debug_uart_flush(state); + local_irq_restore(irq_flags); + return state->debug_abort; +} + +static void dump_regs(struct fiq_debugger_state *state, unsigned *regs) +{ + debug_printf(state, " r0 %08x r1 %08x r2 %08x r3 %08x\n", + regs[0], regs[1], regs[2], regs[3]); + debug_printf(state, " r4 %08x r5 %08x r6 %08x r7 %08x\n", + regs[4], regs[5], regs[6], regs[7]); + debug_printf(state, " r8 %08x r9 %08x r10 %08x r11 %08x mode %s\n", + regs[8], regs[9], regs[10], regs[11], + mode_name(regs[16])); + if ((regs[16] & MODE_MASK) == USR_MODE) + debug_printf(state, " ip %08x sp %08x lr %08x pc %08x " + "cpsr %08x\n", regs[12], regs[13], regs[14], + regs[15], regs[16]); + else + debug_printf(state, " ip %08x sp %08x lr %08x pc %08x " + "cpsr %08x spsr %08x\n", regs[12], regs[13], + regs[14], regs[15], regs[16], regs[17]); +} + +struct mode_regs { + unsigned long sp_svc; + unsigned long lr_svc; + unsigned long spsr_svc; + + unsigned long sp_abt; + unsigned long lr_abt; + unsigned long spsr_abt; + + unsigned long sp_und; + unsigned long lr_und; + unsigned long spsr_und; + + unsigned long sp_irq; + unsigned long lr_irq; + unsigned long spsr_irq; + + unsigned long r8_fiq; + unsigned long r9_fiq; + unsigned long r10_fiq; + unsigned long r11_fiq; + unsigned long r12_fiq; + unsigned long sp_fiq; + unsigned long lr_fiq; + unsigned long spsr_fiq; +}; + +void __naked get_mode_regs(struct mode_regs *regs) +{ + asm volatile ( + "mrs r1, cpsr\n" + "msr cpsr_c, #0xd3 @(SVC_MODE | PSR_I_BIT | PSR_F_BIT)\n" + "stmia r0!, {r13 - r14}\n" + "mrs r2, spsr\n" + "msr cpsr_c, #0xd7 @(ABT_MODE | PSR_I_BIT | PSR_F_BIT)\n" + "stmia r0!, {r2, r13 - r14}\n" + "mrs r2, spsr\n" + "msr cpsr_c, #0xdb @(UND_MODE | PSR_I_BIT | PSR_F_BIT)\n" + "stmia r0!, {r2, r13 - r14}\n" + "mrs r2, spsr\n" + "msr cpsr_c, #0xd2 @(IRQ_MODE | PSR_I_BIT | PSR_F_BIT)\n" + "stmia r0!, {r2, r13 - r14}\n" + "mrs r2, spsr\n" + "msr cpsr_c, #0xd1 @(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)\n" + "stmia r0!, {r2, r8 - r14}\n" + "mrs r2, spsr\n" + "stmia r0!, {r2}\n" + "msr cpsr_c, r1\n" + "bx lr\n"); +} + + +static void dump_allregs(struct fiq_debugger_state *state, unsigned *regs) +{ + struct mode_regs mode_regs; + dump_regs(state, regs); + get_mode_regs(&mode_regs); + debug_printf(state, " svc: sp %08x lr %08x spsr %08x\n", + mode_regs.sp_svc, mode_regs.lr_svc, mode_regs.spsr_svc); + debug_printf(state, " abt: sp %08x lr %08x spsr %08x\n", + mode_regs.sp_abt, mode_regs.lr_abt, mode_regs.spsr_abt); + debug_printf(state, " und: sp %08x lr %08x spsr %08x\n", + mode_regs.sp_und, mode_regs.lr_und, mode_regs.spsr_und); + debug_printf(state, " irq: sp %08x lr %08x spsr %08x\n", + mode_regs.sp_irq, mode_regs.lr_irq, mode_regs.spsr_irq); + debug_printf(state, " fiq: r8 %08x r9 %08x r10 %08x r11 %08x " + "r12 %08x\n", + mode_regs.r8_fiq, mode_regs.r9_fiq, mode_regs.r10_fiq, + mode_regs.r11_fiq, mode_regs.r12_fiq); + debug_printf(state, " fiq: sp %08x lr %08x spsr %08x\n", + mode_regs.sp_fiq, mode_regs.lr_fiq, mode_regs.spsr_fiq); +} + +static void dump_irqs(struct fiq_debugger_state *state) +{ + int n; + struct irq_desc *desc; + + debug_printf(state, "irqnr total since-last status name\n"); + for_each_irq_desc(n, desc) { + struct irqaction *act = desc->action; + if (!act && !kstat_irqs(n)) + continue; + debug_printf(state, "%5d: %10u %11u %8x %s\n", n, + kstat_irqs(n), + kstat_irqs(n) - state->last_irqs[n], + desc->status_use_accessors, + (act && act->name) ? act->name : "???"); + state->last_irqs[n] = kstat_irqs(n); + } +} + +struct stacktrace_state { + struct fiq_debugger_state *state; + unsigned int depth; +}; + +static int report_trace(struct stackframe *frame, void *d) +{ + struct stacktrace_state *sts = d; + + if (sts->depth) { + debug_printf(sts->state, + " pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n", + frame->pc, frame->pc, frame->lr, frame->lr, + frame->sp, frame->fp); + sts->depth--; + return 0; + } + debug_printf(sts->state, " ...\n"); + + return sts->depth == 0; +} + +struct frame_tail { + struct frame_tail *fp; + unsigned long sp; + unsigned long lr; +} __attribute__((packed)); + +static struct frame_tail *user_backtrace(struct fiq_debugger_state *state, + struct frame_tail *tail) +{ + struct frame_tail buftail[2]; + + /* Also check accessibility of one struct frame_tail beyond */ + if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) { + debug_printf(state, " invalid frame pointer %p\n", tail); + return NULL; + } + if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) { + debug_printf(state, + " failed to copy frame pointer %p\n", tail); + return NULL; + } + + debug_printf(state, " %p\n", buftail[0].lr); + + /* frame pointers should strictly progress back up the stack + * (towards higher addresses) */ + if (tail >= buftail[0].fp) + return NULL; + + return buftail[0].fp-1; +} + +void dump_stacktrace(struct fiq_debugger_state *state, + struct pt_regs * const regs, unsigned int depth, void *ssp) +{ + struct frame_tail *tail; + struct thread_info *real_thread_info = THREAD_INFO(ssp); + struct stacktrace_state sts; + + sts.depth = depth; + sts.state = state; + *current_thread_info() = *real_thread_info; + + if (!current) + debug_printf(state, "current NULL\n"); + else + debug_printf(state, "pid: %d comm: %s\n", + current->pid, current->comm); + dump_regs(state, (unsigned *)regs); + + if (!user_mode(regs)) { + struct stackframe frame; + frame.fp = regs->ARM_fp; + frame.sp = regs->ARM_sp; + frame.lr = regs->ARM_lr; + frame.pc = regs->ARM_pc; + debug_printf(state, + " pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n", + regs->ARM_pc, regs->ARM_pc, regs->ARM_lr, regs->ARM_lr, + regs->ARM_sp, regs->ARM_fp); + walk_stackframe(&frame, report_trace, &sts); + return; + } + + tail = ((struct frame_tail *) regs->ARM_fp) - 1; + while (depth-- && tail && !((unsigned long) tail & 3)) + tail = user_backtrace(state, tail); +} + +static void do_ps(struct fiq_debugger_state *state) +{ + struct task_struct *g; + struct task_struct *p; + unsigned task_state; + static const char stat_nam[] = "RSDTtZX"; + + debug_printf(state, "pid ppid prio task pc\n"); + read_lock(&tasklist_lock); + do_each_thread(g, p) { + task_state = p->state ? __ffs(p->state) + 1 : 0; + debug_printf(state, + "%5d %5d %4d ", p->pid, p->parent->pid, p->prio); + debug_printf(state, "%-13.13s %c", p->comm, + task_state >= sizeof(stat_nam) ? '?' : stat_nam[task_state]); + if (task_state == TASK_RUNNING) + debug_printf(state, " running\n"); + else + debug_printf(state, " %08lx\n", thread_saved_pc(p)); + } while_each_thread(g, p); + read_unlock(&tasklist_lock); +} + +#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE +static void begin_syslog_dump(struct fiq_debugger_state *state) +{ + state->syslog_dumping = true; +} + +static void end_syslog_dump(struct fiq_debugger_state *state) +{ + state->syslog_dumping = false; +} +#else +extern int do_syslog(int type, char __user *bug, int count); +static void begin_syslog_dump(struct fiq_debugger_state *state) +{ + do_syslog(5 /* clear */, NULL, 0); +} + +static void end_syslog_dump(struct fiq_debugger_state *state) +{ + dump_kernel_log(state); +} +#endif + +static void do_sysrq(struct fiq_debugger_state *state, char rq) +{ + if ((rq == 'g' || rq == 'G') && !fiq_kgdb_enable) { + debug_printf(state, "sysrq-g blocked\n"); + return; + } + begin_syslog_dump(state); + handle_sysrq(rq); + end_syslog_dump(state); +} + +#ifdef CONFIG_KGDB +static void do_kgdb(struct fiq_debugger_state *state) +{ + if (!fiq_kgdb_enable) { + debug_printf(state, "kgdb through fiq debugger not enabled\n"); + return; + } + + debug_printf(state, "enabling console and triggering kgdb\n"); + state->console_enable = true; + handle_sysrq('g'); +} +#endif + +static void debug_schedule_work(struct fiq_debugger_state *state, char *cmd) +{ + unsigned long flags; + + spin_lock_irqsave(&state->work_lock, flags); + if (state->work_cmd[0] != '\0') { + debug_printf(state, "work command processor busy\n"); + spin_unlock_irqrestore(&state->work_lock, flags); + return; + } + + strlcpy(state->work_cmd, cmd, sizeof(state->work_cmd)); + spin_unlock_irqrestore(&state->work_lock, flags); + + schedule_work(&state->work); +} + +static void debug_work(struct work_struct *work) +{ + struct fiq_debugger_state *state; + char work_cmd[DEBUG_MAX]; + char *cmd; + unsigned long flags; + + state = container_of(work, struct fiq_debugger_state, work); + + spin_lock_irqsave(&state->work_lock, flags); + + strlcpy(work_cmd, state->work_cmd, sizeof(work_cmd)); + state->work_cmd[0] = '\0'; + + spin_unlock_irqrestore(&state->work_lock, flags); + + cmd = work_cmd; + if (!strncmp(cmd, "reboot", 6)) { + cmd += 6; + while (*cmd == ' ') + cmd++; + if (cmd != '\0') + kernel_restart(cmd); + else + kernel_restart(NULL); + } else { + debug_printf(state, "unknown work command '%s'\n", work_cmd); + } +} + +/* This function CANNOT be called in FIQ context */ +static void debug_irq_exec(struct fiq_debugger_state *state, char *cmd) +{ + if (!strcmp(cmd, "ps")) + do_ps(state); + if (!strcmp(cmd, "sysrq")) + do_sysrq(state, 'h'); + if (!strncmp(cmd, "sysrq ", 6)) + do_sysrq(state, cmd[6]); +#ifdef CONFIG_KGDB + if (!strcmp(cmd, "kgdb")) + do_kgdb(state); +#endif + if (!strncmp(cmd, "reboot", 6)) + debug_schedule_work(state, cmd); +} + +static void debug_help(struct fiq_debugger_state *state) +{ + debug_printf(state, "FIQ Debugger commands:\n" + " pc PC status\n" + " regs Register dump\n" + " allregs Extended Register dump\n" + " bt Stack trace\n" + " reboot [<c>] Reboot with command <c>\n" + " reset [<c>] Hard reset with command <c>\n" + " irqs Interupt status\n" + " kmsg Kernel log\n" + " version Kernel version\n"); + debug_printf(state, " sleep Allow sleep while in FIQ\n" + " nosleep Disable sleep while in FIQ\n" + " console Switch terminal to console\n" + " cpu Current CPU\n" + " cpu <number> Switch to CPU<number>\n"); + debug_printf(state, " ps Process list\n" + " sysrq sysrq options\n" + " sysrq <param> Execute sysrq with <param>\n"); +#ifdef CONFIG_KGDB + debug_printf(state, " kgdb Enter kernel debugger\n"); +#endif +} + +static void take_affinity(void *info) +{ + struct fiq_debugger_state *state = info; + struct cpumask cpumask; + + cpumask_clear(&cpumask); + cpumask_set_cpu(get_cpu(), &cpumask); + + irq_set_affinity(state->uart_irq, &cpumask); +} + +static void switch_cpu(struct fiq_debugger_state *state, int cpu) +{ + if (!debug_have_fiq(state)) + smp_call_function_single(cpu, take_affinity, state, false); + state->current_cpu = cpu; +} + +static bool debug_fiq_exec(struct fiq_debugger_state *state, + const char *cmd, unsigned *regs, void *svc_sp) +{ + bool signal_helper = false; + + if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) { + debug_help(state); + } else if (!strcmp(cmd, "pc")) { + debug_printf(state, " pc %08x cpsr %08x mode %s\n", + regs[15], regs[16], mode_name(regs[16])); + } else if (!strcmp(cmd, "regs")) { + dump_regs(state, regs); + } else if (!strcmp(cmd, "allregs")) { + dump_allregs(state, regs); + } else if (!strcmp(cmd, "bt")) { + dump_stacktrace(state, (struct pt_regs *)regs, 100, svc_sp); + } else if (!strncmp(cmd, "reset", 5)) { + cmd += 5; + while (*cmd == ' ') + cmd++; + if (*cmd) { + char tmp_cmd[32]; + strlcpy(tmp_cmd, cmd, sizeof(tmp_cmd)); + machine_restart(tmp_cmd); + } else { + machine_restart(NULL); + } + } else if (!strcmp(cmd, "irqs")) { + dump_irqs(state); + } else if (!strcmp(cmd, "kmsg")) { + dump_kernel_log(state); + } else if (!strcmp(cmd, "version")) { + debug_printf(state, "%s\n", linux_banner); + } else if (!strcmp(cmd, "sleep")) { + state->no_sleep = false; + debug_printf(state, "enabling sleep\n"); + } else if (!strcmp(cmd, "nosleep")) { + state->no_sleep = true; + debug_printf(state, "disabling sleep\n"); + } else if (!strcmp(cmd, "console")) { + debug_printf(state, "console mode\n"); + debug_uart_flush(state); + state->console_enable = true; + } else if (!strcmp(cmd, "cpu")) { + debug_printf(state, "cpu %d\n", state->current_cpu); + } else if (!strncmp(cmd, "cpu ", 4)) { + unsigned long cpu = 0; + if (strict_strtoul(cmd + 4, 10, &cpu) == 0) + switch_cpu(state, cpu); + else + debug_printf(state, "invalid cpu\n"); + debug_printf(state, "cpu %d\n", state->current_cpu); + } else { + if (state->debug_busy) { + debug_printf(state, + "command processor busy. trying to abort.\n"); + state->debug_abort = -1; + } else { + strcpy(state->debug_cmd, cmd); + state->debug_busy = 1; + } + + return true; + } + if (!state->console_enable) + debug_prompt(state); + + return signal_helper; +} + +static void sleep_timer_expired(unsigned long data) +{ + struct fiq_debugger_state *state = (struct fiq_debugger_state *)data; + unsigned long flags; + + spin_lock_irqsave(&state->sleep_timer_lock, flags); + if (state->uart_enabled && !state->no_sleep) { + if (state->debug_enable && !state->console_enable) { + state->debug_enable = false; + debug_printf_nfiq(state, "suspending fiq debugger\n"); + } + state->ignore_next_wakeup_irq = true; + debug_uart_disable(state); + state->uart_enabled = false; + enable_wakeup_irq(state); + } + wake_unlock(&state->debugger_wake_lock); + spin_unlock_irqrestore(&state->sleep_timer_lock, flags); +} + +static void handle_wakeup(struct fiq_debugger_state *state) +{ + unsigned long flags; + + spin_lock_irqsave(&state->sleep_timer_lock, flags); + if (state->wakeup_irq >= 0 && state->ignore_next_wakeup_irq) { + state->ignore_next_wakeup_irq = false; + } else if (!state->uart_enabled) { + wake_lock(&state->debugger_wake_lock); + debug_uart_enable(state); + state->uart_enabled = true; + disable_wakeup_irq(state); + mod_timer(&state->sleep_timer, jiffies + HZ / 2); + } + spin_unlock_irqrestore(&state->sleep_timer_lock, flags); +} + +static irqreturn_t wakeup_irq_handler(int irq, void *dev) +{ + struct fiq_debugger_state *state = dev; + + if (!state->no_sleep) + debug_puts(state, "WAKEUP\n"); + handle_wakeup(state); + + return IRQ_HANDLED; +} + +static void debug_handle_console_irq_context(struct fiq_debugger_state *state) +{ +#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE) + if (state->tty_port.ops) { + int i; + int count = fiq_debugger_ringbuf_level(state->tty_rbuf); + for (i = 0; i < count; i++) { + int c = fiq_debugger_ringbuf_peek(state->tty_rbuf, 0); + tty_insert_flip_char(&state->tty_port, c, TTY_NORMAL); + if (!fiq_debugger_ringbuf_consume(state->tty_rbuf, 1)) + pr_warn("fiq tty failed to consume byte\n"); + } + tty_flip_buffer_push(&state->tty_port); + } +#endif +} + +static void debug_handle_irq_context(struct fiq_debugger_state *state) +{ + if (!state->no_sleep) { + unsigned long flags; + + spin_lock_irqsave(&state->sleep_timer_lock, flags); + wake_lock(&state->debugger_wake_lock); + mod_timer(&state->sleep_timer, jiffies + HZ * 5); + spin_unlock_irqrestore(&state->sleep_timer_lock, flags); + } + debug_handle_console_irq_context(state); + if (state->debug_busy) { + debug_irq_exec(state, state->debug_cmd); + if (!state->console_enable) + debug_prompt(state); + state->debug_busy = 0; + } +} + +static int debug_getc(struct fiq_debugger_state *state) +{ + return state->pdata->uart_getc(state->pdev); +} + +static bool debug_handle_uart_interrupt(struct fiq_debugger_state *state, + int this_cpu, void *regs, void *svc_sp) +{ + int c; + static int last_c; + int count = 0; + bool signal_helper = false; + + if (this_cpu != state->current_cpu) { + if (state->in_fiq) + return false; + + if (atomic_inc_return(&state->unhandled_fiq_count) != + MAX_UNHANDLED_FIQ_COUNT) + return false; + + debug_printf(state, "fiq_debugger: cpu %d not responding, " + "reverting to cpu %d\n", state->current_cpu, + this_cpu); + + atomic_set(&state->unhandled_fiq_count, 0); + switch_cpu(state, this_cpu); + return false; + } + + state->in_fiq = true; + + while ((c = debug_getc(state)) != FIQ_DEBUGGER_NO_CHAR) { + count++; + if (!state->debug_enable) { + if ((c == 13) || (c == 10)) { + state->debug_enable = true; + state->debug_count = 0; + debug_prompt(state); + } + } else if (c == FIQ_DEBUGGER_BREAK) { + state->console_enable = false; + debug_puts(state, "fiq debugger mode\n"); + state->debug_count = 0; + debug_prompt(state); +#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE + } else if (state->console_enable && state->tty_rbuf) { + fiq_debugger_ringbuf_push(state->tty_rbuf, c); + signal_helper = true; +#endif + } else if ((c >= ' ') && (c < 127)) { + if (state->debug_count < (DEBUG_MAX - 1)) { + state->debug_buf[state->debug_count++] = c; + debug_putc(state, c); + } + } else if ((c == 8) || (c == 127)) { + if (state->debug_count > 0) { + state->debug_count--; + debug_putc(state, 8); + debug_putc(state, ' '); + debug_putc(state, 8); + } + } else if ((c == 13) || (c == 10)) { + if (c == '\r' || (c == '\n' && last_c != '\r')) { + debug_putc(state, '\r'); + debug_putc(state, '\n'); + } + if (state->debug_count) { + state->debug_buf[state->debug_count] = 0; + state->debug_count = 0; + signal_helper |= + debug_fiq_exec(state, state->debug_buf, + regs, svc_sp); + } else { + debug_prompt(state); + } + } + last_c = c; + } + if (!state->console_enable) + debug_uart_flush(state); + if (state->pdata->fiq_ack) + state->pdata->fiq_ack(state->pdev, state->fiq); + + /* poke sleep timer if necessary */ + if (state->debug_enable && !state->no_sleep) + signal_helper = true; + + atomic_set(&state->unhandled_fiq_count, 0); + state->in_fiq = false; + + return signal_helper; +} + +static void debug_fiq(struct fiq_glue_handler *h, void *regs, void *svc_sp) +{ + struct fiq_debugger_state *state = + container_of(h, struct fiq_debugger_state, handler); + unsigned int this_cpu = THREAD_INFO(svc_sp)->cpu; + bool need_irq; + + need_irq = debug_handle_uart_interrupt(state, this_cpu, regs, svc_sp); + if (need_irq) + debug_force_irq(state); +} + +/* + * When not using FIQs, we only use this single interrupt as an entry point. + * This just effectively takes over the UART interrupt and does all the work + * in this context. + */ +static irqreturn_t debug_uart_irq(int irq, void *dev) +{ + struct fiq_debugger_state *state = dev; + bool not_done; + + handle_wakeup(state); + + /* handle the debugger irq in regular context */ + not_done = debug_handle_uart_interrupt(state, smp_processor_id(), + get_irq_regs(), + current_thread_info()); + if (not_done) + debug_handle_irq_context(state); + + return IRQ_HANDLED; +} + +/* + * If FIQs are used, not everything can happen in fiq context. + * FIQ handler does what it can and then signals this interrupt to finish the + * job in irq context. + */ +static irqreturn_t debug_signal_irq(int irq, void *dev) +{ + struct fiq_debugger_state *state = dev; + + if (state->pdata->force_irq_ack) + state->pdata->force_irq_ack(state->pdev, state->signal_irq); + + debug_handle_irq_context(state); + + return IRQ_HANDLED; +} + +static void debug_resume(struct fiq_glue_handler *h) +{ + struct fiq_debugger_state *state = + container_of(h, struct fiq_debugger_state, handler); + if (state->pdata->uart_resume) + state->pdata->uart_resume(state->pdev); +} + +#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE) +struct tty_driver *debug_console_device(struct console *co, int *index) +{ + *index = co->index; + return fiq_tty_driver; +} + +static void debug_console_write(struct console *co, + const char *s, unsigned int count) +{ + struct fiq_debugger_state *state; + unsigned long flags; + + state = container_of(co, struct fiq_debugger_state, console); + + if (!state->console_enable && !state->syslog_dumping) + return; + + debug_uart_enable(state); + spin_lock_irqsave(&state->console_lock, flags); + while (count--) { + if (*s == '\n') + debug_putc(state, '\r'); + debug_putc(state, *s++); + } + debug_uart_flush(state); + spin_unlock_irqrestore(&state->console_lock, flags); + debug_uart_disable(state); +} + +static struct console fiq_debugger_console = { + .name = "ttyFIQ", + .device = debug_console_device, + .write = debug_console_write, + .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_ENABLED, +}; + +int fiq_tty_open(struct tty_struct *tty, struct file *filp) +{ + int line = tty->index; + struct fiq_debugger_state **states = tty->driver->driver_state; + struct fiq_debugger_state *state = states[line]; + + return tty_port_open(&state->tty_port, tty, filp); +} + +void fiq_tty_close(struct tty_struct *tty, struct file *filp) +{ + tty_port_close(tty->port, tty, filp); +} + +int fiq_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + int i; + int line = tty->index; + struct fiq_debugger_state **states = tty->driver->driver_state; + struct fiq_debugger_state *state = states[line]; + + if (!state->console_enable) + return count; + + debug_uart_enable(state); + spin_lock_irq(&state->console_lock); + for (i = 0; i < count; i++) + debug_putc(state, *buf++); + spin_unlock_irq(&state->console_lock); + debug_uart_disable(state); + + return count; +} + +int fiq_tty_write_room(struct tty_struct *tty) +{ + return 16; +} + +#ifdef CONFIG_CONSOLE_POLL +static int fiq_tty_poll_init(struct tty_driver *driver, int line, char *options) +{ + return 0; +} + +static int fiq_tty_poll_get_char(struct tty_driver *driver, int line) +{ + struct fiq_debugger_state **states = driver->driver_state; + struct fiq_debugger_state *state = states[line]; + int c = NO_POLL_CHAR; + + debug_uart_enable(state); + if (debug_have_fiq(state)) { + int count = fiq_debugger_ringbuf_level(state->tty_rbuf); + if (count > 0) { + c = fiq_debugger_ringbuf_peek(state->tty_rbuf, 0); + fiq_debugger_ringbuf_consume(state->tty_rbuf, 1); + } + } else { + c = debug_getc(state); + if (c == FIQ_DEBUGGER_NO_CHAR) + c = NO_POLL_CHAR; + } + debug_uart_disable(state); + + return c; +} + +static void fiq_tty_poll_put_char(struct tty_driver *driver, int line, char ch) +{ + struct fiq_debugger_state **states = driver->driver_state; + struct fiq_debugger_state *state = states[line]; + debug_uart_enable(state); + debug_putc(state, ch); + debug_uart_disable(state); +} +#endif + +static const struct tty_port_operations fiq_tty_port_ops; + +static const struct tty_operations fiq_tty_driver_ops = { + .write = fiq_tty_write, + .write_room = fiq_tty_write_room, + .open = fiq_tty_open, + .close = fiq_tty_close, +#ifdef CONFIG_CONSOLE_POLL + .poll_init = fiq_tty_poll_init, + .poll_get_char = fiq_tty_poll_get_char, + .poll_put_char = fiq_tty_poll_put_char, +#endif +}; + +static int fiq_debugger_tty_init(void) +{ + int ret; + struct fiq_debugger_state **states = NULL; + + states = kzalloc(sizeof(*states) * MAX_FIQ_DEBUGGER_PORTS, GFP_KERNEL); + if (!states) { + pr_err("Failed to allocate fiq debugger state structres\n"); + return -ENOMEM; + } + + fiq_tty_driver = alloc_tty_driver(MAX_FIQ_DEBUGGER_PORTS); + if (!fiq_tty_driver) { + pr_err("Failed to allocate fiq debugger tty\n"); + ret = -ENOMEM; + goto err_free_state; + } + + fiq_tty_driver->owner = THIS_MODULE; + fiq_tty_driver->driver_name = "fiq-debugger"; + fiq_tty_driver->name = "ttyFIQ"; + fiq_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + fiq_tty_driver->subtype = SERIAL_TYPE_NORMAL; + fiq_tty_driver->init_termios = tty_std_termios; + fiq_tty_driver->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV; + fiq_tty_driver->driver_state = states; + + fiq_tty_driver->init_termios.c_cflag = + B115200 | CS8 | CREAD | HUPCL | CLOCAL; + fiq_tty_driver->init_termios.c_ispeed = 115200; + fiq_tty_driver->init_termios.c_ospeed = 115200; + + tty_set_operations(fiq_tty_driver, &fiq_tty_driver_ops); + + ret = tty_register_driver(fiq_tty_driver); + if (ret) { + pr_err("Failed to register fiq tty: %d\n", ret); + goto err_free_tty; + } + + pr_info("Registered FIQ tty driver\n"); + return 0; + +err_free_tty: + put_tty_driver(fiq_tty_driver); + fiq_tty_driver = NULL; +err_free_state: + kfree(states); + return ret; +} + +static int fiq_debugger_tty_init_one(struct fiq_debugger_state *state) +{ + int ret; + struct device *tty_dev; + struct fiq_debugger_state **states = fiq_tty_driver->driver_state; + + states[state->pdev->id] = state; + + state->tty_rbuf = fiq_debugger_ringbuf_alloc(1024); + if (!state->tty_rbuf) { + pr_err("Failed to allocate fiq debugger ringbuf\n"); + ret = -ENOMEM; + goto err; + } + + tty_port_init(&state->tty_port); + state->tty_port.ops = &fiq_tty_port_ops; + + tty_dev = tty_port_register_device(&state->tty_port, fiq_tty_driver, + state->pdev->id, &state->pdev->dev); + if (IS_ERR(tty_dev)) { + pr_err("Failed to register fiq debugger tty device\n"); + ret = PTR_ERR(tty_dev); + goto err; + } + + device_set_wakeup_capable(tty_dev, 1); + + pr_info("Registered fiq debugger ttyFIQ%d\n", state->pdev->id); + + return 0; + +err: + fiq_debugger_ringbuf_free(state->tty_rbuf); + state->tty_rbuf = NULL; + return ret; +} +#endif + +static int fiq_debugger_dev_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct fiq_debugger_state *state = platform_get_drvdata(pdev); + + if (state->pdata->uart_dev_suspend) + return state->pdata->uart_dev_suspend(pdev); + return 0; +} + +static int fiq_debugger_dev_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct fiq_debugger_state *state = platform_get_drvdata(pdev); + + if (state->pdata->uart_dev_resume) + return state->pdata->uart_dev_resume(pdev); + return 0; +} + +static int fiq_debugger_probe(struct platform_device *pdev) +{ + int ret; + struct fiq_debugger_pdata *pdata = dev_get_platdata(&pdev->dev); + struct fiq_debugger_state *state; + int fiq; + int uart_irq; + + if (pdev->id >= MAX_FIQ_DEBUGGER_PORTS) + return -EINVAL; + + if (!pdata->uart_getc || !pdata->uart_putc) + return -EINVAL; + if ((pdata->uart_enable && !pdata->uart_disable) || + (!pdata->uart_enable && pdata->uart_disable)) + return -EINVAL; + + fiq = platform_get_irq_byname(pdev, "fiq"); + uart_irq = platform_get_irq_byname(pdev, "uart_irq"); + + /* uart_irq mode and fiq mode are mutually exclusive, but one of them + * is required */ + if ((uart_irq < 0 && fiq < 0) || (uart_irq >= 0 && fiq >= 0)) + return -EINVAL; + if (fiq >= 0 && !pdata->fiq_enable) + return -EINVAL; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + setup_timer(&state->sleep_timer, sleep_timer_expired, + (unsigned long)state); + state->pdata = pdata; + state->pdev = pdev; + state->no_sleep = initial_no_sleep; + state->debug_enable = initial_debug_enable; + state->console_enable = initial_console_enable; + + state->fiq = fiq; + state->uart_irq = uart_irq; + state->signal_irq = platform_get_irq_byname(pdev, "signal"); + state->wakeup_irq = platform_get_irq_byname(pdev, "wakeup"); + + INIT_WORK(&state->work, debug_work); + spin_lock_init(&state->work_lock); + + platform_set_drvdata(pdev, state); + + spin_lock_init(&state->sleep_timer_lock); + + if (state->wakeup_irq < 0 && debug_have_fiq(state)) + state->no_sleep = true; + state->ignore_next_wakeup_irq = !state->no_sleep; + + wake_lock_init(&state->debugger_wake_lock, + WAKE_LOCK_SUSPEND, "serial-debug"); + + state->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(state->clk)) + state->clk = NULL; + + /* do not call pdata->uart_enable here since uart_init may still + * need to do some initialization before uart_enable can work. + * So, only try to manage the clock during init. + */ + if (state->clk) + clk_enable(state->clk); + + if (pdata->uart_init) { + ret = pdata->uart_init(pdev); + if (ret) + goto err_uart_init; + } + + debug_printf_nfiq(state, "<hit enter %sto activate fiq debugger>\n", + state->no_sleep ? "" : "twice "); + + if (debug_have_fiq(state)) { + state->handler.fiq = debug_fiq; + state->handler.resume = debug_resume; + ret = fiq_glue_register_handler(&state->handler); + if (ret) { + pr_err("%s: could not install fiq handler\n", __func__); + goto err_register_fiq; + } + + pdata->fiq_enable(pdev, state->fiq, 1); + } else { + ret = request_irq(state->uart_irq, debug_uart_irq, + IRQF_NO_SUSPEND, "debug", state); + if (ret) { + pr_err("%s: could not install irq handler\n", __func__); + goto err_register_irq; + } + + /* for irq-only mode, we want this irq to wake us up, if it + * can. + */ + enable_irq_wake(state->uart_irq); + } + + if (state->clk) + clk_disable(state->clk); + + if (state->signal_irq >= 0) { + ret = request_irq(state->signal_irq, debug_signal_irq, + IRQF_TRIGGER_RISING, "debug-signal", state); + if (ret) + pr_err("serial_debugger: could not install signal_irq"); + } + + if (state->wakeup_irq >= 0) { + ret = request_irq(state->wakeup_irq, wakeup_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_DISABLED, + "debug-wakeup", state); + if (ret) { + pr_err("serial_debugger: " + "could not install wakeup irq\n"); + state->wakeup_irq = -1; + } else { + ret = enable_irq_wake(state->wakeup_irq); + if (ret) { + pr_err("serial_debugger: " + "could not enable wakeup\n"); + state->wakeup_irq_no_set_wake = true; + } + } + } + if (state->no_sleep) + handle_wakeup(state); + +#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE) + spin_lock_init(&state->console_lock); + state->console = fiq_debugger_console; + state->console.index = pdev->id; + if (!console_set_on_cmdline) + add_preferred_console(state->console.name, + state->console.index, NULL); + register_console(&state->console); + fiq_debugger_tty_init_one(state); +#endif + return 0; + +err_register_irq: +err_register_fiq: + if (pdata->uart_free) + pdata->uart_free(pdev); +err_uart_init: + if (state->clk) + clk_disable(state->clk); + if (state->clk) + clk_put(state->clk); + wake_lock_destroy(&state->debugger_wake_lock); + platform_set_drvdata(pdev, NULL); + kfree(state); + return ret; +} + +static const struct dev_pm_ops fiq_debugger_dev_pm_ops = { + .suspend = fiq_debugger_dev_suspend, + .resume = fiq_debugger_dev_resume, +}; + +static struct platform_driver fiq_debugger_driver = { + .probe = fiq_debugger_probe, + .driver = { + .name = "fiq_debugger", + .pm = &fiq_debugger_dev_pm_ops, + }, +}; + +static int __init fiq_debugger_init(void) +{ +#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE) + fiq_debugger_tty_init(); +#endif + return platform_driver_register(&fiq_debugger_driver); +} + +postcore_initcall(fiq_debugger_init); diff --git a/arch/arm/common/fiq_debugger_ringbuf.h b/arch/arm/common/fiq_debugger_ringbuf.h new file mode 100644 index 00000000000..2649b558108 --- /dev/null +++ b/arch/arm/common/fiq_debugger_ringbuf.h @@ -0,0 +1,94 @@ +/* + * arch/arm/common/fiq_debugger_ringbuf.c + * + * simple lockless ringbuffer + * + * Copyright (C) 2010 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/slab.h> + +struct fiq_debugger_ringbuf { + int len; + int head; + int tail; + u8 buf[]; +}; + + +static inline struct fiq_debugger_ringbuf *fiq_debugger_ringbuf_alloc(int len) +{ + struct fiq_debugger_ringbuf *rbuf; + + rbuf = kzalloc(sizeof(*rbuf) + len, GFP_KERNEL); + if (rbuf == NULL) + return NULL; + + rbuf->len = len; + rbuf->head = 0; + rbuf->tail = 0; + smp_mb(); + + return rbuf; +} + +static inline void fiq_debugger_ringbuf_free(struct fiq_debugger_ringbuf *rbuf) +{ + kfree(rbuf); +} + +static inline int fiq_debugger_ringbuf_level(struct fiq_debugger_ringbuf *rbuf) +{ + int level = rbuf->head - rbuf->tail; + + if (level < 0) + level = rbuf->len + level; + + return level; +} + +static inline int fiq_debugger_ringbuf_room(struct fiq_debugger_ringbuf *rbuf) +{ + return rbuf->len - fiq_debugger_ringbuf_level(rbuf) - 1; +} + +static inline u8 +fiq_debugger_ringbuf_peek(struct fiq_debugger_ringbuf *rbuf, int i) +{ + return rbuf->buf[(rbuf->tail + i) % rbuf->len]; +} + +static inline int +fiq_debugger_ringbuf_consume(struct fiq_debugger_ringbuf *rbuf, int count) +{ + count = min(count, fiq_debugger_ringbuf_level(rbuf)); + + rbuf->tail = (rbuf->tail + count) % rbuf->len; + smp_mb(); + + return count; +} + +static inline int +fiq_debugger_ringbuf_push(struct fiq_debugger_ringbuf *rbuf, u8 datum) +{ + if (fiq_debugger_ringbuf_room(rbuf) == 0) + return 0; + + rbuf->buf[rbuf->head] = datum; + smp_mb(); + rbuf->head = (rbuf->head + 1) % rbuf->len; + smp_mb(); + + return 1; +} diff --git a/arch/arm/configs/athene_defconfig b/arch/arm/configs/athene_defconfig index 48d0616a2cc..4ad2df4d640 100644 --- a/arch/arm/configs/athene_defconfig +++ b/arch/arm/configs/athene_defconfig @@ -1,7 +1,6 @@ - # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.10.104 Kernel Configuration +# Linux/arm 3.10.107 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -105,6 +104,8 @@ CONFIG_RCU_FANOUT_LEAF=16 CONFIG_RCU_FAST_NO_HZ=y # CONFIG_TREE_RCU_TRACE is not set CONFIG_RCU_BOOST=y +CONFIG_RCU_BOOST_PRIO=1 +CONFIG_RCU_BOOST_DELAY=500 # CONFIG_RCU_NOCB_CPU is not set CONFIG_IKCONFIG=y # CONFIG_IKCONFIG_PROC is not set @@ -272,8 +273,8 @@ CONFIG_CGROUP_BFQIO=y # CONFIG_DEFAULT_DEADLINE is not set # CONFIG_DEFAULT_ROW is not set CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set # CONFIG_DEFAULT_BFQ is not set +# CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" CONFIG_ASN1=y CONFIG_UNINLINE_SPIN_UNLOCK=y @@ -448,6 +449,7 @@ CONFIG_MULTI_IRQ_HANDLER=y # CONFIG_ARM_ERRATA_764369 is not set # CONFIG_ARM_ERRATA_775420 is not set # CONFIG_ARM_ERRATA_798181 is not set +# CONFIG_FIQ_DEBUGGER is not set # # Bus support @@ -639,7 +641,6 @@ CONFIG_PM=y CONFIG_ARCH_HAS_OPP=y CONFIG_PM_OPP=y CONFIG_PM_CLK=y -CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y CONFIG_CPU_PM=y CONFIG_SUSPEND_TIME=y CONFIG_SUSPEND_TIME_TIMEKEEPING=y @@ -882,7 +883,6 @@ CONFIG_IP_NF_MATCH_RPFILTER=y CONFIG_IP_NF_MATCH_TTL=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y -# CONFIG_IP_NF_TARGET_REJECT_SKERR is not set # CONFIG_IP_NF_TARGET_ULOG is not set CONFIG_NF_NAT_IPV4=y CONFIG_IP_NF_TARGET_MASQUERADE=y @@ -920,7 +920,6 @@ CONFIG_IP6_NF_MATCH_RPFILTER=y # CONFIG_IP6_NF_TARGET_HL is not set CONFIG_IP6_NF_FILTER=y CONFIG_IP6_NF_TARGET_REJECT=y -# CONFIG_IP6_NF_TARGET_REJECT_SKERR is not set CONFIG_IP6_NF_MANGLE=y CONFIG_IP6_NF_RAW=y # CONFIG_IP6_NF_SECURITY is not set @@ -1234,7 +1233,7 @@ CONFIG_USB_EXT_TYPE_C_PERICOM=y CONFIG_USB_EXT_TYPE_C_TI=y # CONFIG_TI_DRV2667 is not set # CONFIG_QCOM_LIQUID_DOCK is not set -CONFIG_UID_CPUTIME=y +CONFIG_UID_SYS_STATS=y CONFIG_DROPBOX=y CONFIG_ALSA_TO_H2W=y # CONFIG_C2PORT is not set @@ -1336,6 +1335,8 @@ CONFIG_DM_REQ_CRYPT=y # CONFIG_DM_FLAKEY is not set CONFIG_DM_VERITY=y # CONFIG_DM_VERITY_FEC is not set +# CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE_128 is not set +CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE=1 # CONFIG_DM_ANDROID_VERITY is not set # CONFIG_TARGET_CORE is not set CONFIG_NETDEVICES=y @@ -1641,7 +1642,6 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_ST1232 is not set # CONFIG_TOUCHSCREEN_TPS6507X is not set # CONFIG_TOUCHSCREEN_FT5X06 is not set -# CONFIG_TOUCHSCREEN_MSTAR21XX is not set CONFIG_TOUCHSCREEN_GEN_VKEYS=y # CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set # CONFIG_TOUCHSCREEN_GT9XX is not set @@ -1656,7 +1656,7 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_MMI=y CONFIG_INPUT_MISC=y # CONFIG_INPUT_AD714X is not set # CONFIG_INPUT_BMA150 is not set -# CONFIG_INPUT_HBTP_INPUT is not set +CONFIG_INPUT_HBTP_INPUT=y # CONFIG_INPUT_MMA8450 is not set # CONFIG_INPUT_MPU3050 is not set # CONFIG_SENSORS_MPU6050 is not set @@ -1775,10 +1775,10 @@ CONFIG_HW_RANDOM=y # CONFIG_HW_RANDOM_ATMEL is not set # CONFIG_HW_RANDOM_EXYNOS is not set CONFIG_HW_RANDOM_MSM=y -# CONFIG_DEVPORT is not set # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set +# CONFIG_DCC_TTY is not set CONFIG_MSM_SMD_PKT=y CONFIG_MSM_ADSPRPC=y # CONFIG_MSM_RDBG is not set @@ -1854,6 +1854,7 @@ CONFIG_SPMI=y CONFIG_SPMI_MSM_PMIC_ARB=y # CONFIG_SPMI_MSM_PMIC_ARB_PANIC_ON_SPURIOUS_IRQ is not set CONFIG_MSM_QPNP_INT=y +# CONFIG_MSM_SPMI_DEBUGFS_RO is not set # # Qualcomm MSM SSBI bus support @@ -3160,7 +3161,6 @@ CONFIG_ION=y # CONFIG_ION_TEST is not set CONFIG_ION_MSM=y # CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS is not set -# CONFIG_FIQ_DEBUGGER is not set # CONFIG_FIQ_WATCHDOG is not set # CONFIG_USB_WPAN_HCD is not set # CONFIG_WIMAX_GDM72XX is not set @@ -3414,6 +3414,7 @@ CONFIG_EXT3_FS_XATTR=y CONFIG_EXT4_FS=y # CONFIG_EXT4_FS_POSIX_ACL is not set CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_FS_ENCRYPTION is not set # CONFIG_EXT4_DEBUG is not set CONFIG_F2FS_FS=y CONFIG_F2FS_STAT_FS=y @@ -3442,12 +3443,15 @@ CONFIG_DNOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_FANOTIFY is not set CONFIG_QUOTA=y -# CONFIG_PRINT_QUOTA_WARNING is not set0 -# CONFIG_QUOTACTL is not set +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +# CONFIG_PRINT_QUOTA_WARNING is not set +# CONFIG_QUOTA_DEBUG is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y # CONFIG_AUTOFS4_FS is not set CONFIG_FUSE_FS=y # CONFIG_CUSE is not set -CONFIG_ADRENO_IDLER=y # # Caches diff --git a/arch/arm/include/asm/fiq_debugger.h b/arch/arm/include/asm/fiq_debugger.h new file mode 100644 index 00000000000..4d274883ba6 --- /dev/null +++ b/arch/arm/include/asm/fiq_debugger.h @@ -0,0 +1,64 @@ +/* + * arch/arm/include/asm/fiq_debugger.h + * + * Copyright (C) 2010 Google, Inc. + * Author: Colin Cross <ccross@android.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _ARCH_ARM_MACH_TEGRA_FIQ_DEBUGGER_H_ +#define _ARCH_ARM_MACH_TEGRA_FIQ_DEBUGGER_H_ + +#include <linux/serial_core.h> + +#define FIQ_DEBUGGER_NO_CHAR NO_POLL_CHAR +#define FIQ_DEBUGGER_BREAK 0x00ff0100 + +#define FIQ_DEBUGGER_FIQ_IRQ_NAME "fiq" +#define FIQ_DEBUGGER_SIGNAL_IRQ_NAME "signal" +#define FIQ_DEBUGGER_WAKEUP_IRQ_NAME "wakeup" + +/** + * struct fiq_debugger_pdata - fiq debugger platform data + * @uart_resume: used to restore uart state right before enabling + * the fiq. + * @uart_enable: Do the work necessary to communicate with the uart + * hw (enable clocks, etc.). This must be ref-counted. + * @uart_disable: Do the work necessary to disable the uart hw + * (disable clocks, etc.). This must be ref-counted. + * @uart_dev_suspend: called during PM suspend, generally not needed + * for real fiq mode debugger. + * @uart_dev_resume: called during PM resume, generally not needed + * for real fiq mode debugger. + */ +struct fiq_debugger_pdata { + int (*uart_init)(struct platform_device *pdev); + void (*uart_free)(struct platform_device *pdev); + int (*uart_resume)(struct platform_device *pdev); + int (*uart_getc)(struct platform_device *pdev); + void (*uart_putc)(struct platform_device *pdev, unsigned int c); + void (*uart_flush)(struct platform_device *pdev); + void (*uart_enable)(struct platform_device *pdev); + void (*uart_disable)(struct platform_device *pdev); + + int (*uart_dev_suspend)(struct platform_device *pdev); + int (*uart_dev_resume)(struct platform_device *pdev); + + void (*fiq_enable)(struct platform_device *pdev, unsigned int fiq, + bool enable); + void (*fiq_ack)(struct platform_device *pdev, unsigned int fiq); + + void (*force_irq)(struct platform_device *pdev, unsigned int irq); + void (*force_irq_ack)(struct platform_device *pdev, unsigned int irq); +}; + +#endif diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 943504f53f5..eeb40452d6d 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h @@ -155,7 +155,15 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) { - __pmd_populate(pmdp, page_to_phys(ptep), _PAGE_USER_TABLE); + extern pmdval_t user_pmd_table; + pmdval_t prot; + + if (__LINUX_ARM_ARCH__ >= 6 && !IS_ENABLED(CONFIG_ARM_LPAE)) + prot = user_pmd_table; + else + prot = _PAGE_USER_TABLE; + + __pmd_populate(pmdp, page_to_phys(ptep), prot); } #define pmd_pgtable(pmd) pmd_page(pmd) diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h index 5cfba15cb40..5e68278e953 100644 --- a/arch/arm/include/asm/pgtable-2level-hwdef.h +++ b/arch/arm/include/asm/pgtable-2level-hwdef.h @@ -20,12 +20,14 @@ #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) #define PMD_TYPE_TABLE (_AT(pmdval_t, 1) << 0) #define PMD_TYPE_SECT (_AT(pmdval_t, 2) << 0) +#define PMD_PXNTABLE (_AT(pmdval_t, 1) << 2) /* v7 */ #define PMD_BIT4 (_AT(pmdval_t, 1) << 4) #define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5) #define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */ /* * - section */ +#define PMD_SECT_PXN (_AT(pmdval_t, 1) << 0) /* v7 */ #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) #define PMD_SECT_XN (_AT(pmdval_t, 1) << 4) /* v6 */ diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h index e0fab5b2f01..043bc389f38 100644 --- a/arch/arm/include/asm/pgtable-3level-hwdef.h +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h @@ -75,6 +75,7 @@ #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */ +#define PTE_EXT_PXN (_AT(pteval_t, 1) << 53) /* PXN */ #define PTE_EXT_XN (_AT(pteval_t, 1) << 54) /* XN */ /* diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 6b103894f8e..f25b6119e02 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -31,7 +31,6 @@ #include <mach/hardware.h> #include <mach/irqs.h> -#include <mach/reset.h> #include "generic.h" @@ -135,7 +134,6 @@ static void sa1100_power_off(void) void sa11x0_restart(enum reboot_mode mode, const char *cmd) { - clear_reset_status(RESET_STATUS_ALL); if (mode == REBOOT_SOFT) { /* Jump into ROM at address 0 */ soft_restart(0); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 1e1f4f45174..83434b993f6 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -51,6 +51,8 @@ EXPORT_SYMBOL(empty_zero_page); */ pmd_t *top_pmd; +pmdval_t user_pmd_table = _PAGE_USER_TABLE; + #define CPOLICY_UNCACHED 0 #define CPOLICY_BUFFERED 1 #define CPOLICY_WRITETHROUGH 2 @@ -543,6 +545,25 @@ static void __init build_mem_type_table(void) s2_pgprot = cp->pte_s2; hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte; +#ifndef CONFIG_ARM_LPAE + /* + * We don't use domains on ARMv6 (since this causes problems with + * v6/v7 kernels), so we must use a separate memory type for user + * r/o, kernel r/w to map the vectors page. + */ + if (cpu_arch == CPU_ARCH_ARMv6) + vecs_pgprot |= L_PTE_MT_VECTORS; + + /* + * Check is it with support for the PXN bit + * in the Short-descriptor translation table format descriptors. + */ + if (cpu_arch == CPU_ARCH_ARMv7 && + (read_cpuid_ext(CPUID_EXT_MMFR0) & 0xF) >= 4) { + user_pmd_table |= PMD_PXNTABLE; + } +#endif + /* * We don't use domains on ARMv6 (since this causes problems with * v6/v7 kernels), so we must use a separate memory type for user @@ -622,6 +643,11 @@ static void __init build_mem_type_table(void) } kern_pgprot |= PTE_EXT_AF; vecs_pgprot |= PTE_EXT_AF; + + /* + * Set PXN for user mappings + */ + user_pgprot |= PTE_EXT_PXN; #endif for (i = 0; i < 16; i++) { diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 2dba280f6b3..9d49bea25a6 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -37,6 +37,7 @@ config ARM64 select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_AUDITSYSCALL + select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_C_RECORDMCOUNT select HAVE_CC_STACKPROTECTOR @@ -586,6 +587,20 @@ config SECCOMP defined by each seccomp mode. +config SECCOMP + bool "Enable seccomp to safely compute untrusted bytecode" + ---help--- + This kernel feature is useful for number crunching applications + that may need to compute untrusted bytecode during their + execution. By using pipes or other transports made available to + the process as file descriptors supporting the read/write + syscalls, it's possible to isolate those applications in + their own address space using seccomp. Once seccomp is + enabled via prctl(PR_SET_SECCOMP), it cannot be disabled + and the task is only allowed to execute a few safe syscalls + defined by each seccomp mode. + + endmenu menu "Boot options" diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h index c136fd53c84..164e2bbe9af 100644 --- a/arch/arm64/include/uapi/asm/ptrace.h +++ b/arch/arm64/include/uapi/asm/ptrace.h @@ -23,6 +23,7 @@ #include <asm/hwcap.h> +#define PTRACE_SET_SYSCALL 23 /* * PSR bits diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 17b99ae8dbd..6db6c3b56a3 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -507,7 +507,7 @@ el0_inv: mov x0, sp mov x1, #BAD_SYNC mrs x2, esr_el1 - b bad_el0_sync + b bad_mode ENDPROC(el0_sync) .align 6 diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index b907a6d0ac1..b46415dfb5e 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -164,6 +164,7 @@ static int fpsimd_cpu_pm_notifier(struct notifier_block *self, case CPU_PM_ENTER: if (current->mm) fpsimd_save_state(¤t->thread.fpsimd_state); + this_cpu_write(fpsimd_last_state, NULL); break; case CPU_PM_EXIT: if (current->mm) diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index dbb52c0dad5..cbd09984e1a 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -707,8 +707,10 @@ static int compat_gpr_get(struct task_struct *target, kbuf += sizeof(reg); } else { ret = copy_to_user(ubuf, ®, sizeof(reg)); - if (ret) + if (ret) { + ret = -EFAULT; break; + } ubuf += sizeof(reg); } @@ -746,8 +748,10 @@ static int compat_gpr_set(struct task_struct *target, kbuf += sizeof(reg); } else { ret = copy_from_user(®, ubuf, sizeof(reg)); - if (ret) - return ret; + if (ret) { + ret = -EFAULT; + break; + } ubuf += sizeof(reg); } @@ -1121,7 +1125,19 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { - return ptrace_request(child, request, addr, data); + int ret; + + switch (request) { + case PTRACE_SET_SYSCALL: + task_pt_regs(child)->syscallno = data; + ret = 0; + break; + default: + ret = ptrace_request(child, request, addr, data); + break; + } + + return ret; } enum ptrace_syscall_dir { diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 207e11ad5fe..0ff794a482d 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -499,7 +499,11 @@ static int c_show(struct seq_file *m, void *v) #endif seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24); - seq_printf(m, "CPU architecture: 8\n"); + seq_printf(m, "CPU architecture: %s\n", +#if IS_ENABLED(CONFIG_ARMV7_COMPAT_CPUINFO) + is_compat_task() ? "8" : +#endif + "AArch64"); seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15); seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff); seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15); diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 0e1447cbadd..2198961ebad 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -406,33 +406,16 @@ asmlinkage long do_ni_syscall(struct pt_regs *regs) } /* - * bad_mode handles the impossible case in the exception vector. This is always - * fatal. + * bad_mode handles the impossible case in the exception vector. */ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr) { - console_verbose(); - - pr_crit("Bad mode in %s handler detected, code 0x%08x\n", - handler[reason], esr); - - die("Oops - bad mode", regs, 0); - local_irq_disable(); - panic("bad mode"); -} - -/* - * bad_el0_sync handles unexpected, but potentially recoverable synchronous - * exceptions taken from EL0. Unlike bad_mode, this returns. - */ -asmlinkage void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr) -{ siginfo_t info; void __user *pc = (void __user *)instruction_pointer(regs); console_verbose(); - pr_crit("Bad EL0 synchronous exception detected on CPU%d, code 0x%08x\n", - smp_processor_id(), esr); + pr_crit("Bad mode in %s handler detected, code 0x%08x\n", + handler[reason], esr); __show_regs(regs); info.si_signo = SIGILL; @@ -446,7 +429,7 @@ asmlinkage void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr) arm64_check_cache_ecc(NULL); } - force_sig_info(info.si_signo, &info, current); + arm64_notify_die("Oops - bad mode", regs, &info, 0); } void __pte_error(const char *file, int line, unsigned long val) diff --git a/arch/arm64/kernel/vdso/vdso.S b/arch/arm64/kernel/vdso/vdso.S index 60c1db54b41..82379a70ef0 100644 --- a/arch/arm64/kernel/vdso/vdso.S +++ b/arch/arm64/kernel/vdso/vdso.S @@ -21,9 +21,8 @@ #include <linux/const.h> #include <asm/page.h> - __PAGE_ALIGNED_DATA - .globl vdso_start, vdso_end + .section .rodata .balign PAGE_SIZE vdso_start: .incbin "arch/arm64/kernel/vdso/vdso.so" diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h index e28a3e0eb3c..582d8b61ce5 100644 --- a/arch/mips/include/asm/branch.h +++ b/arch/mips/include/asm/branch.h @@ -44,10 +44,7 @@ static inline int compute_return_epc(struct pt_regs *regs) return __microMIPS_compute_return_epc(regs); if (cpu_has_mips16) return __MIPS16e_compute_return_epc(regs); - return regs->cp0_epc; - } - - if (!delay_slot(regs)) { + } else if (!delay_slot(regs)) { regs->cp0_epc += 4; return 0; } diff --git a/arch/mips/include/uapi/asm/unistd.h b/arch/mips/include/uapi/asm/unistd.h index 1dee279f966..af4d5c0a2f0 100644 --- a/arch/mips/include/uapi/asm/unistd.h +++ b/arch/mips/include/uapi/asm/unistd.h @@ -369,16 +369,22 @@ #define __NR_process_vm_writev (__NR_Linux + 346) #define __NR_kcmp (__NR_Linux + 347) #define __NR_finit_module (__NR_Linux + 348) +/* Backporting seccomp, skip a few ... + * #define __NR_sched_setattr (__NR_Linux + 349) + * #define __NR_sched_getattr (__NR_Linux + 350) + * #define __NR_renameat2 (__NR_Linux + 351) + */ +#define __NR_seccomp (__NR_Linux + 352) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 348 +#define __NR_Linux_syscalls 352 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 348 +#define __NR_O32_Linux_syscalls 352 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -695,16 +701,22 @@ #define __NR_kcmp (__NR_Linux + 306) #define __NR_finit_module (__NR_Linux + 307) #define __NR_getdents64 (__NR_Linux + 308) +/* Backporting seccomp, skip a few ... + * #define __NR_sched_setattr (__NR_Linux + 309) + * #define __NR_sched_getattr (__NR_Linux + 310) + * #define __NR_renameat2 (__NR_Linux + 311) + */ +#define __NR_seccomp (__NR_Linux + 312) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 308 +#define __NR_Linux_syscalls 312 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 308 +#define __NR_64_Linux_syscalls 312 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -1025,15 +1037,21 @@ #define __NR_process_vm_writev (__NR_Linux + 310) #define __NR_kcmp (__NR_Linux + 311) #define __NR_finit_module (__NR_Linux + 312) +/* Backporting seccomp, skip a few ... + * #define __NR_sched_setattr (__NR_Linux + 313) + * #define __NR_sched_getattr (__NR_Linux + 314) + * #define __NR_renameat2 (__NR_Linux + 315) + */ +#define __NR_seccomp (__NR_Linux + 316) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 312 +#define __NR_Linux_syscalls 316 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 312 +#define __NR_N32_Linux_syscalls 316 #endif /* _UAPI_ASM_UNISTD_H */ diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 46c2ad0703a..63b942f613c 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -200,7 +200,7 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs) * * @regs: Pointer to pt_regs * @insn: branch instruction to decode - * @returns: -EFAULT on error and forces SIGBUS, and on success + * @returns: -EFAULT on error and forces SIGILL, and on success * returns 0 or BRANCH_LIKELY_TAKEN as appropriate after * evaluating the branch. */ @@ -297,6 +297,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, /* * These are unconditional and in j_format. */ + case jalx_op: case jal_op: regs->regs[31] = regs->cp0_epc + 8; case j_op: @@ -436,8 +437,9 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, return ret; sigill: - printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm); - force_sig(SIGBUS, current); + pr_info("%s: DSP branch but not DSP ASE - sending SIGILL.\n", + current->comm); + force_sig(SIGILL, current); return -EFAULT; } EXPORT_SYMBOL_GPL(__compute_return_epc_for_insn); diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index ed5bafb5d63..a5a93acdc2c 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -593,6 +593,12 @@ einval: li v0, -ENOSYS sys sys_process_vm_writev 6 sys sys_kcmp 5 sys sys_finit_module 3 + /* Backporting seccomp, skip a few ... */ + sys sys_ni_syscall 0 /* sys_sched_setattr */ + sys sys_ni_syscall 0 /* sys_sched_getattr */ /* 4350 */ + sys sys_ni_syscall 0 /* sys_renameat2 */ + sys sys_seccomp 3 + .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index be6627ead61..4220ab5d554 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -424,4 +424,8 @@ sys_call_table: PTR sys_kcmp PTR sys_finit_module PTR sys_getdents64 + sys sys_ni_syscall /* sys_sched_setattr */ + sys sys_ni_syscall /* sys_sched_getattr */ /* 5310 */ + sys sys_ni_syscall /* sys_renameat2 */ + sys sys_seccomp .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index b657fbefc46..de0d435acb4 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -417,4 +417,8 @@ EXPORT(sysn32_call_table) PTR compat_sys_process_vm_writev /* 6310 */ PTR sys_kcmp PTR sys_finit_module + sys sys_ni_syscall /* sys_sched_setattr */ + sys sys_ni_syscall /* sys_sched_getattr */ + sys sys_ni_syscall /* sys_renameat2 */ /* 6315 */ + sys sys_seccomp .size sysn32_call_table,.-sysn32_call_table diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index bf56d7e271d..b32e2dfbb9c 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -541,4 +541,8 @@ sys_call_table: PTR compat_sys_process_vm_writev PTR sys_kcmp PTR sys_finit_module - .size sys_call_table,.-sys_call_table + sys sys_ni_syscall /* sys_sched_setattr */ + sys sys_ni_syscall /* sys_sched_getattr */ /* 4350 */ + sys sys_ni_syscall /* sys_renameat2 */ + sys sys_seccomp + .size sys32_call_table,.-sys32_call_table diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index b79d13f95bf..eb0f4dfb385 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -140,7 +140,7 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) "1: ll %[old], (%[addr]) \n" " move %[tmp], %[new] \n" "2: sc %[tmp], (%[addr]) \n" - " bnez %[tmp], 4f \n" + " beqz %[tmp], 4f \n" "3: \n" " .subsection 2 \n" "4: b 1b \n" diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 3d492a823a5..dbddc9ccf27 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -2002,6 +2002,35 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return 0; } +/* + * Emulate FPU instructions. + * + * If we use FPU hardware, then we have been typically called to handle + * an unimplemented operation, such as where an operand is a NaN or + * denormalized. In that case exit the emulation loop after a single + * iteration so as to let hardware execute any subsequent instructions. + * + * If we have no FPU hardware or it has been disabled, then continue + * emulating floating-point instructions until one of these conditions + * has occurred: + * + * - a non-FPU instruction has been encountered, + * + * - an attempt to emulate has ended with a signal, + * + * - the ISA mode has been switched. + * + * We need to terminate the emulation loop if we got switched to the + * MIPS16 mode, whether supported or not, so that we do not attempt + * to emulate a MIPS16 instruction as a regular MIPS FPU instruction. + * Similarly if we got switched to the microMIPS mode and only the + * regular MIPS mode is supported, so that we do not attempt to emulate + * a microMIPS instruction as a regular MIPS FPU instruction. Or if + * we got switched to the regular MIPS mode and only the microMIPS mode + * is supported, so that we do not attempt to emulate a regular MIPS + * instruction that should cause an Address Error exception instead. + * For simplicity we always terminate upon an ISA mode switch. + */ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, int has_fpu, void *__user *fault_addr) { @@ -2093,6 +2122,15 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, break; if (sig) break; + /* + * We have to check for the ISA bit explicitly here, + * because `get_isa16_mode' may return 0 if support + * for code compression has been globally disabled, + * or otherwise we may produce the wrong signal or + * even proceed successfully where we must not. + */ + if ((xcp->cp0_epc ^ prevepc) & 0x1) + break; cond_resched(); } while (xcp->cp0_epc > prevepc); diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h index e3b1d41c89b..84bcdfa410f 100644 --- a/arch/powerpc/include/asm/atomic.h +++ b/arch/powerpc/include/asm/atomic.h @@ -501,7 +501,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) * Atomically increments @v by 1, so long as @v is non-zero. * Returns non-zero if @v was non-zero, and zero otherwise. */ -static __inline__ long atomic64_inc_not_zero(atomic64_t *v) +static __inline__ int atomic64_inc_not_zero(atomic64_t *v) { long t1, t2; @@ -520,7 +520,7 @@ static __inline__ long atomic64_inc_not_zero(atomic64_t *v) : "r" (&v->counter) : "cc", "xer", "memory"); - return t1; + return t1 != 0; } #endif /* __powerpc64__ */ diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 469d7715d6a..954168be787 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1136,7 +1136,7 @@ " .llong 0\n" \ " .llong 0\n" \ ".previous" \ - : "=r" (rval) : "i" (CPU_FTR_CELL_TB_BUG)); rval;}) + : "=r" (rval) : "i" (CPU_FTR_CELL_TB_BUG) : "cr0"); rval;}) #else #define mftb() ({unsigned long rval; \ asm volatile("mftb %0" : "=r" (rval)); rval;}) diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 11f5b03a0b0..762c10d46d6 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -529,6 +529,15 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) regs->gpr[2] = (unsigned long)(((func_descr_t *)jp->entry)->toc); #endif + /* + * jprobes use jprobe_return() which skips the normal return + * path of the function, and this messes up the accounting of the + * function graph tracer. + * + * Pause function graph tracing while performing the jprobe function. + */ + pause_graph_tracing(); + return 1; } @@ -551,6 +560,8 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) * saved regs... */ memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); + /* It's OK to start function graph tracing again */ + unpause_graph_tracing(); preempt_enable_no_resched(); return 1; } diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 08490ecc465..23da15ff779 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -863,6 +863,19 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) goto instr_done; #endif case 19: /* mfcr */ + if ((instr >> 20) & 1) { + imm = 0xf0000000UL; + for (sh = 0; sh < 8; ++sh) { + if (instr & (0x80000 >> sh)) { + regs->gpr[rd] = regs->ccr & imm; + break; + } + imm >>= 4; + } + + goto instr_done; + } + regs->gpr[rd] = regs->ccr; regs->gpr[rd] &= 0xffffffffUL; goto instr_done; diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index d8e8eefbe24..86ec87dc1f5 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -296,13 +296,13 @@ static inline unsigned type in##bwl##_p(int port) \ static inline void outs##bwl(int port, const void *addr, unsigned long count) \ { \ asm volatile("rep; outs" #bwl \ - : "+S"(addr), "+c"(count) : "d"(port)); \ + : "+S"(addr), "+c"(count) : "d"(port) : "memory"); \ } \ \ static inline void ins##bwl(int port, void *addr, unsigned long count) \ { \ asm volatile("rep; ins" #bwl \ - : "+D"(addr), "+c"(count) : "d"(port)); \ + : "+D"(addr), "+c"(count) : "d"(port) : "memory"); \ } BUILDIO(b, b, char) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 3cd8bfc3c4b..bc37ddeaa62 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1581,8 +1581,10 @@ void __init enable_IR_x2apic(void) int ret, x2apic_enabled = 0; int hardware_init_ret; +#ifdef CONFIG_X86_IO_APIC if (skip_ioapic_setup) return; +#endif /* Make sure irq_remap_ops are initialized */ setup_irq_remapping_ops(); diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index c4ff2a91613..c95ece93f35 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -159,8 +159,8 @@ void kvm_async_pf_task_wait(u32 token) */ rcu_irq_exit(); native_safe_halt(); - rcu_irq_enter(); local_irq_disable(); + rcu_irq_enter(); } } if (!n.halted) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index d9016e4a80f..be138952728 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8014,7 +8014,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, * (KVM doesn't change it)- no reason to call set_cr4_guest_host_mask(); */ vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK); - kvm_set_cr4(vcpu, vmcs12->host_cr4); + vmx_set_cr4(vcpu, vmcs12->host_cr4); /* shadow page tables on either EPT or shadow page tables */ kvm_set_cr3(vcpu, vmcs12->host_cr3); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b70b67bde90..3d316cafff9 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4596,6 +4596,8 @@ static bool emulator_get_segment(struct x86_emulate_ctxt *ctxt, u16 *selector, if (var.unusable) { memset(desc, 0, sizeof(*desc)); + if (base3) + *base3 = 0; return false; } diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c index 73a6d7395bd..58e7e9d4bbc 100644 --- a/arch/x86/mm/numa_32.c +++ b/arch/x86/mm/numa_32.c @@ -100,5 +100,6 @@ void __init initmem_init(void) printk(KERN_DEBUG "High memory starts at vaddr %08lx\n", (ulong) pfn_to_kaddr(highstart_pfn)); + __vmalloc_start_set = true; setup_bootmem_allocator(); } diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 3c9f13059b1..014984d199e 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -80,7 +80,7 @@ static const int bfq_back_max = 16 * 1024; static const int bfq_back_penalty = 2; /* Idling period duration, in jiffies. */ -static int bfq_slice_idle = 0; +static int bfq_slice_idle = HZ / 125; /* Default maximum budget values, in sectors and number of requests. */ static const int bfq_default_max_budget = 16 * 1024; @@ -4170,6 +4170,12 @@ static struct elevator_type iosched_bfq = { static int __init bfq_init(void) { + /* + * Can be 0 on HZ < 1000 setups. + */ + if (bfq_slice_idle == 0) + bfq_slice_idle = 1; + if (bfq_timeout_async == 0) bfq_timeout_async = 1; diff --git a/block/bfq-sched.c b/block/bfq-sched.c index c3828a45b67..d0890c6d4c1 100644 --- a/block/bfq-sched.c +++ b/block/bfq-sched.c @@ -1046,9 +1046,6 @@ static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, entity = __bfq_lookup_next_entity(st + i, false); if (entity != NULL) { if (extract) { - if (sd->next_in_service != entity) { - entity = __bfq_lookup_next_entity(st + i, true); - } bfq_check_next_in_service(sd, entity); bfq_active_extract(st + i, entity); sd->in_service_entity = entity; diff --git a/block/blk-ioc.c b/block/blk-ioc.c index 4464c823cff..9c4bb8266bc 100644 --- a/block/blk-ioc.c +++ b/block/blk-ioc.c @@ -144,8 +144,7 @@ void put_io_context(struct io_context *ioc) if (atomic_long_dec_and_test(&ioc->refcount)) { spin_lock_irqsave(&ioc->lock, flags); if (!hlist_empty(&ioc->icq_list)) - queue_work(system_power_efficient_wq, - &ioc->release_work); + schedule_work(&ioc->release_work); else free_ioc = true; spin_unlock_irqrestore(&ioc->lock, flags); diff --git a/block/genhd.c b/block/genhd.c index cfca0645088..a240c76be9b 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1515,11 +1515,9 @@ static void __disk_unblock_events(struct gendisk *disk, bool check_now) intv = disk_events_poll_jiffies(disk); set_timer_slack(&ev->dwork.timer, intv / 4); if (check_now) - queue_delayed_work(system_freezable_power_efficient_wq, - &ev->dwork, 0); + queue_delayed_work(system_freezable_wq, &ev->dwork, 0); else if (intv) - queue_delayed_work(system_freezable_power_efficient_wq, - &ev->dwork, intv); + queue_delayed_work(system_freezable_wq, &ev->dwork, intv); out_unlock: spin_unlock_irqrestore(&ev->lock, flags); } @@ -1562,8 +1560,7 @@ void disk_flush_events(struct gendisk *disk, unsigned int mask) spin_lock_irq(&ev->lock); ev->clearing |= mask; if (!ev->block) - mod_delayed_work(system_freezable_power_efficient_wq, - &ev->dwork, 0); + mod_delayed_work(system_freezable_wq, &ev->dwork, 0); spin_unlock_irq(&ev->lock); } @@ -1656,8 +1653,7 @@ static void disk_check_events(struct disk_events *ev, intv = disk_events_poll_jiffies(disk); if (!ev->block && intv) - queue_delayed_work(system_freezable_power_efficient_wq, - &ev->dwork, intv); + queue_delayed_work(system_freezable_wq, &ev->dwork, intv); spin_unlock_irq(&ev->lock); diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index ea05c531db2..8e2747401d3 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -92,8 +92,10 @@ static int skcipher_alloc_sgl(struct sock *sk) sg_init_table(sgl->sg, MAX_SGL_ENTS + 1); sgl->cur = 0; - if (sg) + if (sg) { scatterwalk_sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg); + sg_unmark_end(sg + (MAX_SGL_ENTS - 1)); + } list_add_tail(&sgl->list, &ctx->tsgl); } diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index 8a66221d95b..496557a15f7 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -233,8 +233,6 @@ static int blkcipher_walk_next(struct blkcipher_desc *desc, return blkcipher_walk_done(desc, walk, -EINVAL); } - bsize = min(walk->walk_blocksize, n); - walk->flags &= ~(BLKCIPHER_WALK_SLOW | BLKCIPHER_WALK_COPY | BLKCIPHER_WALK_DIFF); if (!scatterwalk_aligned(&walk->in, walk->alignmask) || @@ -247,6 +245,7 @@ static int blkcipher_walk_next(struct blkcipher_desc *desc, } } + bsize = min(walk->walk_blocksize, n); n = scatterwalk_clamp(&walk->in, n); n = scatterwalk_clamp(&walk->out, n); diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 070b843c37e..8cff7cae733 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -988,6 +988,7 @@ static int ghes_remove(struct platform_device *ghes_dev) if (list_empty(&ghes_sci)) unregister_acpi_hed_notifier(&ghes_notifier_sci); mutex_unlock(&ghes_list_mutex); + synchronize_rcu(); break; case ACPI_HEST_NOTIFY_NMI: mutex_lock(&ghes_list_mutex); diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index fcae5fa2e1b..95b6371e1fe 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -492,23 +492,22 @@ static void acpi_global_event_handler(u32 event_type, acpi_handle device, static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle) { - int result = 0; + int result; if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) - goto end; + return -EINVAL; if (index < num_gpes) { result = acpi_get_gpe_device(index, handle); if (result) { ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND, "Invalid GPE 0x%x", index)); - goto end; + return result; } result = acpi_get_gpe_status(*handle, index, status); } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) result = acpi_get_event_status(index - num_gpes, status); -end: return result; } diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 2516c8bd12b..2e18e6d9508 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2132,7 +2132,7 @@ static void binder_transaction(struct binder_proc *proc, if (!IS_ALIGNED(extra_buffers_size, sizeof(u64))) { binder_user_error("%d:%d got transaction with unaligned buffers size, %lld\n", proc->pid, thread->pid, - extra_buffers_size); + (u64)extra_buffers_size); return_error = BR_FAILED_REPLY; goto err_bad_offset; } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index f3f0801a0e8..aa4e36b3a59 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2794,10 +2794,12 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) static struct ata_device *ata_find_dev(struct ata_port *ap, int devno) { if (!sata_pmp_attached(ap)) { - if (likely(devno < ata_link_max_devices(&ap->link))) + if (likely(devno >= 0 && + devno < ata_link_max_devices(&ap->link))) return &ap->link.device[devno]; } else { - if (likely(devno < ap->nr_pmp_links)) + if (likely(devno >= 0 && + devno < ap->nr_pmp_links)) return &ap->pmp_link[devno].device[0]; } diff --git a/drivers/base/core.c b/drivers/base/core.c index 36b92969858..a1b4e620f96 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1161,7 +1161,8 @@ done: kobject_del(&dev->kobj); Error: cleanup_glue_dir(dev, glue_dir); - put_device(parent); + if (parent) + put_device(parent); name_error: kfree(dev->p); dev->p = NULL; diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index dd19658d5a8..563b63f3876 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -1066,8 +1066,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, dev_set_uevent_suppress(f_dev, false); dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); if (timeout != MAX_SCHEDULE_TIMEOUT) - queue_delayed_work(system_power_efficient_wq, - &fw_priv->timeout_work, timeout); + schedule_delayed_work(&fw_priv->timeout_work, timeout); kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); } @@ -1772,8 +1771,8 @@ static void device_uncache_fw_images_work(struct work_struct *work) */ static void device_uncache_fw_images_delay(unsigned long delay) { - queue_delayed_work(system_power_efficient_wq, &fw_cache.work, - msecs_to_jiffies(delay)); + schedule_delayed_work(&fw_cache.work, + msecs_to_jiffies(delay)); } static int fw_pm_notify(struct notifier_block *notify_block, diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 95009a2ffcc..12508dbd0b0 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1692,7 +1692,7 @@ int pm_genpd_add_subdomain_names(const char *master_name, int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, struct generic_pm_domain *subdomain) { - struct gpd_link *link; + struct gpd_link *l, *link; int ret = -EINVAL; if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)) @@ -1701,7 +1701,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, start: genpd_acquire_lock(genpd); - list_for_each_entry(link, &genpd->master_links, master_node) { + list_for_each_entry_safe(link, l, &genpd->master_links, master_node) { if (link->slave != subdomain) continue; diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 72d1bdd3630..6847c618ca8 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -28,6 +28,7 @@ #include <linux/sched.h> #include <linux/async.h> #include <linux/suspend.h> +#include <linux/cpuidle.h> #include <linux/timer.h> #include <linux/wakeup_reason.h> diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 8066a7d7b22..4f034ee9a90 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -15,18 +15,10 @@ #include <linux/seq_file.h> #include <linux/debugfs.h> #include <linux/types.h> -#include <linux/moduleparam.h> #include <trace/events/power.h> #include "power.h" -static bool enable_qcom_rx_wakelock_ws = true; -module_param(enable_qcom_rx_wakelock_ws, bool, 0644); -static bool enable_wlan_extscan_wl_ws = true; -module_param(enable_wlan_extscan_wl_ws, bool, 0644); -static bool enable_ipa_ws = true; -module_param(enable_ipa_ws, bool, 0644); - /* * If set, the suspend/hibernate code will abort transitions to a sleep state * if wakeup events are registered during or immediately before the transition. @@ -382,73 +374,6 @@ int device_set_wakeup_enable(struct device *dev, bool enable) } EXPORT_SYMBOL_GPL(device_set_wakeup_enable); -#ifdef CONFIG_PM_AUTOSLEEP -static void update_prevent_sleep_time(struct wakeup_source *ws, ktime_t now) -{ - ktime_t delta = ktime_sub(now, ws->start_prevent_time); - ws->prevent_sleep_time = ktime_add(ws->prevent_sleep_time, delta); -} -#else -static inline void update_prevent_sleep_time(struct wakeup_source *ws, - ktime_t now) {} -#endif - -/** - * wakup_source_deactivate - Mark given wakeup source as inactive. - * @ws: Wakeup source to handle. - * - * Update the @ws' statistics and notify the PM core that the wakeup source has - * become inactive by decrementing the counter of wakeup events being processed - * and incrementing the counter of registered wakeup events. - */ -static void wakeup_source_deactivate(struct wakeup_source *ws) -{ - unsigned int cnt, inpr, cec; - ktime_t duration; - ktime_t now; - - ws->relax_count++; - /* - * __pm_relax() may be called directly or from a timer function. - * If it is called directly right after the timer function has been - * started, but before the timer function calls __pm_relax(), it is - * possible that __pm_stay_awake() will be called in the meantime and - * will set ws->active. Then, ws->active may be cleared immediately - * by the __pm_relax() called from the timer function, but in such a - * case ws->relax_count will be different from ws->active_count. - */ - if (ws->relax_count != ws->active_count) { - ws->relax_count--; - return; - } - - ws->active = false; - - now = ktime_get(); - duration = ktime_sub(now, ws->last_time); - ws->total_time = ktime_add(ws->total_time, duration); - if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time)) - ws->max_time = duration; - - ws->last_time = now; - del_timer(&ws->timer); - ws->timer_expires = 0; - - if (ws->autosleep_enabled) - update_prevent_sleep_time(ws, now); - - /* - * Increment the counter of registered wakeup events and decrement the - * couter of wakeup events in progress simultaneously. - */ - cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count); - trace_wakeup_source_deactivate(ws->name, cec); - - split_counters(&cnt, &inpr); - if (!inpr && waitqueue_active(&wakeup_count_wait_queue)) - wake_up(&wakeup_count_wait_queue); -} - /** * wakeup_source_not_registered - validate the given wakeup source. * @ws: Wakeup source to be validated. @@ -503,17 +428,6 @@ static void wakeup_source_activate(struct wakeup_source *ws) { unsigned int cec; - if ((!enable_ipa_ws && !strncmp(ws->name, "IPA_WS", 6)) || - (!enable_wlan_extscan_wl_ws && - !strncmp(ws->name, "wlan_extscan_wl", 15)) || - (!enable_qcom_rx_wakelock_ws && - !strncmp(ws->name, "qcom_rx_wakelock", 16))) { - if (ws->active) - wakeup_source_deactivate(ws); - - return; - } - if (WARN(wakeup_source_not_registered(ws), "unregistered wakeup source\n")) return; @@ -598,6 +512,73 @@ void pm_stay_awake(struct device *dev) } EXPORT_SYMBOL_GPL(pm_stay_awake); +#ifdef CONFIG_PM_AUTOSLEEP +static void update_prevent_sleep_time(struct wakeup_source *ws, ktime_t now) +{ + ktime_t delta = ktime_sub(now, ws->start_prevent_time); + ws->prevent_sleep_time = ktime_add(ws->prevent_sleep_time, delta); +} +#else +static inline void update_prevent_sleep_time(struct wakeup_source *ws, + ktime_t now) {} +#endif + +/** + * wakup_source_deactivate - Mark given wakeup source as inactive. + * @ws: Wakeup source to handle. + * + * Update the @ws' statistics and notify the PM core that the wakeup source has + * become inactive by decrementing the counter of wakeup events being processed + * and incrementing the counter of registered wakeup events. + */ +static void wakeup_source_deactivate(struct wakeup_source *ws) +{ + unsigned int cnt, inpr, cec; + ktime_t duration; + ktime_t now; + + ws->relax_count++; + /* + * __pm_relax() may be called directly or from a timer function. + * If it is called directly right after the timer function has been + * started, but before the timer function calls __pm_relax(), it is + * possible that __pm_stay_awake() will be called in the meantime and + * will set ws->active. Then, ws->active may be cleared immediately + * by the __pm_relax() called from the timer function, but in such a + * case ws->relax_count will be different from ws->active_count. + */ + if (ws->relax_count != ws->active_count) { + ws->relax_count--; + return; + } + + ws->active = false; + + now = ktime_get(); + duration = ktime_sub(now, ws->last_time); + ws->total_time = ktime_add(ws->total_time, duration); + if (ktime_to_ns(duration) > ktime_to_ns(ws->max_time)) + ws->max_time = duration; + + ws->last_time = now; + del_timer(&ws->timer); + ws->timer_expires = 0; + + if (ws->autosleep_enabled) + update_prevent_sleep_time(ws, now); + + /* + * Increment the counter of registered wakeup events and decrement the + * couter of wakeup events in progress simultaneously. + */ + cec = atomic_add_return(MAX_IN_PROGRESS, &combined_event_count); + trace_wakeup_source_deactivate(ws->name, cec); + + split_counters(&cnt, &inpr); + if (!inpr && waitqueue_active(&wakeup_count_wait_queue)) + wake_up(&wakeup_count_wait_queue); +} + /** * __pm_relax - Notify the PM core that processing of a wakeup event has ended. * @ws: Wakeup source object associated with the source of the event. diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 5643de97bee..a2fd0bc62fa 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -601,6 +601,10 @@ config DEVPORT Say Y here if you want to support the /dev/port device. The /dev/port device is similar to /dev/mem, but for I/O ports. +config DCC_TTY + tristate "DCC tty driver" + depends on ARM + source "drivers/s390/char/Kconfig" config MSM_SMD_PKT diff --git a/drivers/char/Makefile b/drivers/char/Makefile index befc95e19ab..6d8c70b77b1 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_PCMCIA) += pcmcia/ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o obj-$(CONFIG_TCG_TPM) += tpm/ +obj-$(CONFIG_DCC_TTY) += dcc_tty.o obj-$(CONFIG_PS3_FLASH) += ps3flash.o obj-$(CONFIG_JS_RTC) += js-rtc.o diff --git a/drivers/char/dcc_tty.c b/drivers/char/dcc_tty.c new file mode 100644 index 00000000000..a787accdcb1 --- /dev/null +++ b/drivers/char/dcc_tty.c @@ -0,0 +1,326 @@ +/* drivers/char/dcc_tty.c + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/console.h> +#include <linux/hrtimer.h> +#include <linux/tty.h> +#include <linux/tty_driver.h> +#include <linux/tty_flip.h> + +MODULE_DESCRIPTION("DCC TTY Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.0"); + +static spinlock_t g_dcc_tty_lock = SPIN_LOCK_UNLOCKED; +static struct hrtimer g_dcc_timer; +static char g_dcc_buffer[16]; +static int g_dcc_buffer_head; +static int g_dcc_buffer_count; +static unsigned g_dcc_write_delay_usecs = 1; +static struct tty_driver *g_dcc_tty_driver; +static struct tty_struct *g_dcc_tty; +static int g_dcc_tty_open_count; + +static void dcc_poll_locked(void) +{ + char ch; + int rch; + int written; + + while (g_dcc_buffer_count) { + ch = g_dcc_buffer[g_dcc_buffer_head]; + asm( + "mrc 14, 0, r15, c0, c1, 0\n" + "mcrcc 14, 0, %1, c0, c5, 0\n" + "movcc %0, #1\n" + "movcs %0, #0\n" + : "=r" (written) + : "r" (ch) + ); + if (written) { + if (ch == '\n') + g_dcc_buffer[g_dcc_buffer_head] = '\r'; + else { + g_dcc_buffer_head = (g_dcc_buffer_head + 1) % ARRAY_SIZE(g_dcc_buffer); + g_dcc_buffer_count--; + if (g_dcc_tty) + tty_wakeup(g_dcc_tty); + } + g_dcc_write_delay_usecs = 1; + } else { + if (g_dcc_write_delay_usecs > 0x100) + break; + g_dcc_write_delay_usecs <<= 1; + udelay(g_dcc_write_delay_usecs); + } + } + + if (g_dcc_tty && !test_bit(TTY_THROTTLED, &g_dcc_tty->flags)) { + asm( + "mrc 14, 0, %0, c0, c1, 0\n" + "tst %0, #(1 << 30)\n" + "moveq %0, #-1\n" + "mrcne 14, 0, %0, c0, c5, 0\n" + : "=r" (rch) + ); + if (rch >= 0) { + ch = rch; + tty_insert_flip_string(g_dcc_tty, &ch, 1); + tty_flip_buffer_push(g_dcc_tty); + } + } + + + if (g_dcc_buffer_count) + hrtimer_start(&g_dcc_timer, ktime_set(0, g_dcc_write_delay_usecs * NSEC_PER_USEC), HRTIMER_MODE_REL); + else + hrtimer_start(&g_dcc_timer, ktime_set(0, 20 * NSEC_PER_MSEC), HRTIMER_MODE_REL); +} + +static int dcc_tty_open(struct tty_struct * tty, struct file * filp) +{ + int ret; + unsigned long irq_flags; + + spin_lock_irqsave(&g_dcc_tty_lock, irq_flags); + if (g_dcc_tty == NULL || g_dcc_tty == tty) { + g_dcc_tty = tty; + g_dcc_tty_open_count++; + ret = 0; + } else + ret = -EBUSY; + spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags); + + printk("dcc_tty_open, tty %p, f_flags %x, returned %d\n", tty, filp->f_flags, ret); + + return ret; +} + +static void dcc_tty_close(struct tty_struct * tty, struct file * filp) +{ + printk("dcc_tty_close, tty %p, f_flags %x\n", tty, filp->f_flags); + if (g_dcc_tty == tty) { + if (--g_dcc_tty_open_count == 0) + g_dcc_tty = NULL; + } +} + +static int dcc_write(const unsigned char *buf_start, int count) +{ + const unsigned char *buf = buf_start; + unsigned long irq_flags; + int copy_len; + int space_left; + int tail; + + if (count < 1) + return 0; + + spin_lock_irqsave(&g_dcc_tty_lock, irq_flags); + do { + tail = (g_dcc_buffer_head + g_dcc_buffer_count) % ARRAY_SIZE(g_dcc_buffer); + copy_len = ARRAY_SIZE(g_dcc_buffer) - tail; + space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count; + if (copy_len > space_left) + copy_len = space_left; + if (copy_len > count) + copy_len = count; + memcpy(&g_dcc_buffer[tail], buf, copy_len); + g_dcc_buffer_count += copy_len; + buf += copy_len; + count -= copy_len; + if (copy_len < count && copy_len < space_left) { + space_left -= copy_len; + copy_len = count; + if (copy_len > space_left) { + copy_len = space_left; + } + memcpy(g_dcc_buffer, buf, copy_len); + buf += copy_len; + count -= copy_len; + g_dcc_buffer_count += copy_len; + } + dcc_poll_locked(); + space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count; + } while(count && space_left); + spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags); + return buf - buf_start; +} + +static int dcc_tty_write(struct tty_struct * tty, const unsigned char *buf, int count) +{ + int ret; + /* printk("dcc_tty_write %p, %d\n", buf, count); */ + ret = dcc_write(buf, count); + if (ret != count) + printk("dcc_tty_write %p, %d, returned %d\n", buf, count, ret); + return ret; +} + +static int dcc_tty_write_room(struct tty_struct *tty) +{ + int space_left; + unsigned long irq_flags; + + spin_lock_irqsave(&g_dcc_tty_lock, irq_flags); + space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count; + spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags); + return space_left; +} + +static int dcc_tty_chars_in_buffer(struct tty_struct *tty) +{ + int ret; + asm( + "mrc 14, 0, %0, c0, c1, 0\n" + "mov %0, %0, LSR #30\n" + "and %0, %0, #1\n" + : "=r" (ret) + ); + return ret; +} + +static void dcc_tty_unthrottle(struct tty_struct * tty) +{ + unsigned long irq_flags; + + spin_lock_irqsave(&g_dcc_tty_lock, irq_flags); + dcc_poll_locked(); + spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags); +} + +static enum hrtimer_restart dcc_tty_timer_func(struct hrtimer *timer) +{ + unsigned long irq_flags; + + spin_lock_irqsave(&g_dcc_tty_lock, irq_flags); + dcc_poll_locked(); + spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags); + return HRTIMER_NORESTART; +} + +void dcc_console_write(struct console *co, const char *b, unsigned count) +{ +#if 1 + dcc_write(b, count); +#else + /* blocking printk */ + while (count > 0) { + int written; + written = dcc_write(b, count); + if (written) { + b += written; + count -= written; + } + } +#endif +} + +static struct tty_driver *dcc_console_device(struct console *c, int *index) +{ + *index = 0; + return g_dcc_tty_driver; +} + +static int __init dcc_console_setup(struct console *co, char *options) +{ + if (co->index != 0) + return -ENODEV; + return 0; +} + + +static struct console dcc_console = +{ + .name = "ttyDCC", + .write = dcc_console_write, + .device = dcc_console_device, + .setup = dcc_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +static struct tty_operations dcc_tty_ops = { + .open = dcc_tty_open, + .close = dcc_tty_close, + .write = dcc_tty_write, + .write_room = dcc_tty_write_room, + .chars_in_buffer = dcc_tty_chars_in_buffer, + .unthrottle = dcc_tty_unthrottle, +}; + +static int __init dcc_tty_init(void) +{ + int ret; + + hrtimer_init(&g_dcc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + g_dcc_timer.function = dcc_tty_timer_func; + + g_dcc_tty_driver = alloc_tty_driver(1); + if (!g_dcc_tty_driver) { + printk(KERN_ERR "dcc_tty_probe: alloc_tty_driver failed\n"); + ret = -ENOMEM; + goto err_alloc_tty_driver_failed; + } + g_dcc_tty_driver->owner = THIS_MODULE; + g_dcc_tty_driver->driver_name = "dcc"; + g_dcc_tty_driver->name = "ttyDCC"; + g_dcc_tty_driver->major = 0; // auto assign + g_dcc_tty_driver->minor_start = 0; + g_dcc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + g_dcc_tty_driver->subtype = SERIAL_TYPE_NORMAL; + g_dcc_tty_driver->init_termios = tty_std_termios; + g_dcc_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(g_dcc_tty_driver, &dcc_tty_ops); + ret = tty_register_driver(g_dcc_tty_driver); + if (ret) { + printk(KERN_ERR "dcc_tty_probe: tty_register_driver failed, %d\n", ret); + goto err_tty_register_driver_failed; + } + tty_register_device(g_dcc_tty_driver, 0, NULL); + + register_console(&dcc_console); + hrtimer_start(&g_dcc_timer, ktime_set(0, 0), HRTIMER_MODE_REL); + + return 0; + +err_tty_register_driver_failed: + put_tty_driver(g_dcc_tty_driver); + g_dcc_tty_driver = NULL; +err_alloc_tty_driver_failed: + return ret; +} + +static void __exit dcc_tty_exit(void) +{ + int ret; + + tty_unregister_device(g_dcc_tty_driver, 0); + ret = tty_unregister_driver(g_dcc_tty_driver); + if (ret < 0) { + printk(KERN_ERR "dcc_tty_remove: tty_unregister_driver failed, %d\n", ret); + } else { + put_tty_driver(g_dcc_tty_driver); + } + g_dcc_tty_driver = NULL; +} + +module_init(dcc_tty_init); +module_exit(dcc_tty_exit); + + diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 9d908497f89..ab127334032 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -1846,7 +1846,9 @@ long diagchar_ioctl(struct file *filp, mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_DCI_EVENT_STATUS: + mutex_lock(&driver->dci_mutex); result = diag_ioctl_dci_event_status(ioarg); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_DCI_CLEAR_LOGS: mutex_lock(&driver->dci_mutex); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 24f46c34640..7932c6bc314 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -501,9 +501,6 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy, int ret; char str_governor[16]; struct cpufreq_policy new_policy; - char *envp[3]; - char buf1[64]; - char buf2[64]; ret = cpufreq_get_policy(&new_policy, policy->cpu); if (ret) @@ -527,13 +524,6 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy, sysfs_notify(&policy->kobj, NULL, "scaling_governor"); - snprintf(buf1, sizeof(buf1), "GOV=%s", policy->governor->name); - snprintf(buf2, sizeof(buf2), "CPU=%u", policy->cpu); - envp[0] = buf1; - envp[1] = buf2; - envp[2] = NULL; - kobject_uevent_env(cpufreq_global_kobject, KOBJ_ADD, envp); - if (ret) return ret; else diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 25a70d06c5b..55836a538a6 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -204,8 +204,8 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf, int ret; ret = sscanf(buf, "%u", &input); - /* cannot be lower than 11 otherwise freq will not fall */ - if (ret != 1 || input < 11 || input > 100 || + /* cannot be lower than 1 otherwise freq will not fall */ + if (ret != 1 || input < 1 || input > 100 || input >= cs_tuners->up_threshold) return -EINVAL; diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 58e14414048..521bf7761ae 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -131,15 +131,25 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) * timer would not have fired during CPU-idle periods. Hence * an unusually large 'wall_time' (as compared to the sampling * rate) indicates this scenario. + * + * prev_load can be zero in two cases and we must recalculate it + * for both cases: + * - during long idle intervals + * - explicitly set to zero */ - if (unlikely(wall_time > (2 * sampling_rate)) && - j_cdbs->copy_prev_load) { + if (unlikely(wall_time > (2 * sampling_rate) && + j_cdbs->prev_load)) { load = j_cdbs->prev_load; - j_cdbs->copy_prev_load = false; + + /* + * Perform a destructive copy, to ensure that we copy + * the previous load only once, upon the first wake-up + * from idle. + */ + j_cdbs->prev_load = 0; } else { load = 100 * (wall_time - idle_time) / wall_time; j_cdbs->prev_load = load; - j_cdbs->copy_prev_load = true; } if (load > max_load) @@ -369,7 +379,6 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, (j_cdbs->prev_cpu_wall - j_cdbs->prev_cpu_idle); j_cdbs->prev_load = 100 * prev_load / (unsigned int) j_cdbs->prev_cpu_wall; - j_cdbs->copy_prev_load = true; if (ignore_nice) j_cdbs->prev_cpu_nice = @@ -414,6 +423,11 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, break; case CPUFREQ_GOV_LIMITS: + mutex_lock(&dbs_data->mutex); + if (!cpu_cdbs->cur_policy) { + mutex_unlock(&dbs_data->mutex); + break; + } mutex_lock(&cpu_cdbs->timer_mutex); if (policy->max < cpu_cdbs->cur_policy->cur) __cpufreq_driver_target(cpu_cdbs->cur_policy, @@ -423,6 +437,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, policy->min, CPUFREQ_RELATION_L); dbs_check_cpu(dbs_data, cpu); mutex_unlock(&cpu_cdbs->timer_mutex); + mutex_unlock(&dbs_data->mutex); break; } return 0; diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 2e920847ef7..279318f6753 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -134,12 +134,13 @@ struct cpu_dbs_common_info { u64 prev_cpu_idle; u64 prev_cpu_wall; u64 prev_cpu_nice; - unsigned int prev_load; /* - * Flag to ensure that we copy the previous load only once, upon the - * first wake-up from idle. + * Used to keep track of load in the previous interval. However, when + * explicitly set to zero, it is used as a flag to ensure that we copy + * the previous load to the current interval only once, upon the first + * wake-up from idle. */ - bool copy_prev_load; + unsigned int prev_load; struct cpufreq_policy *cur_policy; struct delayed_work work; /* diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index 079e7574289..93e879fa42b 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -471,6 +471,9 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif) } } else { new_freq = choose_freq(pcpu, loadadjfreq); + if (new_freq > tunables->hispeed_freq && + pcpu->target_freq < tunables->hispeed_freq) + new_freq = tunables->hispeed_freq; } if (cpu_load <= MAX_LOCAL_LOAD && diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 90cdb7aa4c0..d0c29bb6a82 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -526,7 +526,7 @@ static void add_all_freq_table(unsigned int freq) unsigned int size; size = sizeof(unsigned int) * (all_freq_table->table_size + 1); all_freq_table->freq_table = krealloc(all_freq_table->freq_table, - size, GFP_KERNEL); + size, GFP_ATOMIC); if (IS_ERR(all_freq_table->freq_table)) { pr_warn("Could not reallocate memory for freq_table\n"); all_freq_table->freq_table = NULL; diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 4e32b8fa31d..3458d27f63b 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -115,7 +115,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, .driver_data = ~0, .frequency = 0, }; - unsigned int diff, i; + unsigned int i; pr_debug("request for target %u kHz (relation: %u) for cpu %u\n", target_freq, relation, policy->cpu); @@ -125,7 +125,6 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, suboptimal.frequency = ~0; break; case CPUFREQ_RELATION_L: - case CPUFREQ_RELATION_C: optimal.frequency = ~0; break; } @@ -163,15 +162,6 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, } } break; - case CPUFREQ_RELATION_C: - diff = abs(freq - target_freq); - if (diff < optimal.frequency || - (diff == optimal.frequency && - freq > table[optimal.driver_data].frequency)) { - optimal.frequency = diff; - optimal.driver_data = i; - } - break; } } if (optimal.driver_data > i) { diff --git a/drivers/cpufreq/qcom-cpufreq.c b/drivers/cpufreq/qcom-cpufreq.c index b71f39cb185..9bb76429935 100644 --- a/drivers/cpufreq/qcom-cpufreq.c +++ b/drivers/cpufreq/qcom-cpufreq.c @@ -244,17 +244,13 @@ static int msm_cpufreq_suspend(void) static int msm_cpufreq_resume(void) { - int cpu; -#ifndef CONFIG_CPU_BOOST - int ret; + int cpu, ret; struct cpufreq_policy policy; -#endif for_each_possible_cpu(cpu) { per_cpu(cpufreq_suspend, cpu).device_suspended = 0; } -#ifndef CONFIG_CPU_BOOST /* * Freq request might be rejected during suspend, resulting * in policy->cur violating min/max constraint. @@ -276,7 +272,6 @@ static int msm_cpufreq_resume(void) cpu); } put_online_cpus(); -#endif return NOTIFY_DONE; } diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c index 600c9ad07cd..17fcd1ff49e 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c @@ -421,7 +421,6 @@ static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) rate = clk_get_rate(s3c_freq->hclk); if (rate < 133 * 1000 * 1000) { pr_err("cpufreq: HCLK not at 133MHz\n"); - clk_put(s3c_freq->hclk); ret = -EINVAL; goto err_armclk; } diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index e9d8b235f68..34815a74d90 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c @@ -476,7 +476,7 @@ static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in, ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); if (!ret) { /* in progress */ - wait_for_completion_interruptible(&result.completion); + wait_for_completion(&result.completion); ret = result.err; #ifdef DEBUG print_hex_dump(KERN_ERR, "digested key@"xstr(__LINE__)": ", diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c index 87138d2adb5..fd6bc0bc56c 100644 --- a/drivers/crypto/caam/key_gen.c +++ b/drivers/crypto/caam/key_gen.c @@ -107,7 +107,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); if (!ret) { /* in progress */ - wait_for_completion_interruptible(&result.completion); + wait_for_completion(&result.completion); ret = result.err; #ifdef DEBUG print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ", diff --git a/drivers/crypto/msm/compat_qcedev.c b/drivers/crypto/msm/compat_qcedev.c index 97ae990b537..08a764e25ef 100644 --- a/drivers/crypto/msm/compat_qcedev.c +++ b/drivers/crypto/msm/compat_qcedev.c @@ -1,7 +1,7 @@ /* * QTI CE 32-bit compatibility syscall for 64-bit systems * - * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -97,7 +97,6 @@ static int compat_get_qcedev_vbuf_info( for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { err |= get_user(vaddr, &vbuf32->src[i].vaddr); - vbuf->src[i].vaddr = NULL; err |= put_user(vaddr, (compat_uptr_t *)&vbuf->src[i].vaddr); err |= get_user(len, &vbuf32->src[i].len); err |= put_user(len, &vbuf->src[i].len); @@ -105,7 +104,6 @@ static int compat_get_qcedev_vbuf_info( for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { err |= get_user(vaddr, &vbuf32->dst[i].vaddr); - vbuf->dst[i].vaddr = NULL; err |= put_user(vaddr, (compat_uptr_t *)&vbuf->dst[i].vaddr); err |= get_user(len, &vbuf32->dst[i].len); err |= put_user(len, &vbuf->dst[i].len); @@ -123,7 +121,6 @@ static int compat_put_qcedev_vbuf_info( for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { err |= get_user(vaddr, (compat_uptr_t *)&vbuf->src[i].vaddr); - vbuf32->src[i].vaddr = 0; err |= put_user(vaddr, &vbuf32->src[i].vaddr); err |= get_user(len, &vbuf->src[i].len); err |= put_user(len, &vbuf32->src[i].len); @@ -131,7 +128,6 @@ static int compat_put_qcedev_vbuf_info( for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { err |= get_user(vaddr, (compat_uptr_t *)&vbuf->dst[i].vaddr); - vbuf32->dst[i].vaddr = 0; err |= put_user(vaddr, &vbuf32->dst[i].vaddr); err |= get_user(len, &vbuf->dst[i].len); err |= put_user(len, &vbuf32->dst[i].len); @@ -276,7 +272,6 @@ static int compat_get_qcedev_sha_op_req( for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { err |= get_user(vaddr, &data32->data[i].vaddr); - data->data[i].vaddr = 0; err |= put_user(vaddr, (compat_uptr_t *)&data->data[i].vaddr); err |= get_user(len, &data32->data[i].len); err |= put_user(len, &data->data[i].len); @@ -295,7 +290,6 @@ static int compat_get_qcedev_sha_op_req( err |= get_user(diglen, &data32->diglen); err |= put_user(diglen, &data->diglen); err |= get_user(authkey, &data32->authkey); - data->authkey = NULL; err |= put_user(authkey, (compat_uptr_t *)&data->authkey); err |= get_user(authklen, &data32->authklen); err |= put_user(authklen, &data->authklen); @@ -322,7 +316,6 @@ static int compat_put_qcedev_sha_op_req( for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { err |= get_user(vaddr, (compat_uptr_t *)&data->data[i].vaddr); - data32->data[i].vaddr = 0; err |= put_user(vaddr, &data32->data[i].vaddr); err |= get_user(len, &data->data[i].len); err |= put_user(len, &data32->data[i].len); @@ -341,7 +334,6 @@ static int compat_put_qcedev_sha_op_req( err |= get_user(diglen, &data->diglen); err |= put_user(diglen, &data32->diglen); err |= get_user(authkey, (compat_uptr_t *)&data->authkey); - data32->authkey = 0; err |= put_user(authkey, &data32->authkey); err |= get_user(authklen, &data->authklen); err |= put_user(authklen, &data32->authklen); diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index bbdde2206c7..db0925b8f3f 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -2061,6 +2061,10 @@ static int _sha_complete(struct qce_device *pce_dev) uint32_t result_dump_status; areq = (struct ahash_request *) pce_dev->areq; + if (!areq) { + pr_err("sha operation error. areq is NULL\n"); + return -ENXIO; + } qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents, DMA_TO_DEVICE); memcpy(digest, (char *)(&pce_dev->ce_sps.result->auth_iv[0]), @@ -5513,6 +5517,5 @@ int qce_hw_support(void *handle, struct ce_hw_support *ce_support) } EXPORT_SYMBOL(qce_hw_support); - MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Crypto Engine driver"); diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c index f670d2d58c2..9b093294439 100644 --- a/drivers/crypto/msm/qcrypto.c +++ b/drivers/crypto/msm/qcrypto.c @@ -3613,6 +3613,7 @@ static int _sha1_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int len) { struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(&tfm->base); + int ret = 0; memset(&sha_ctx->authkey[0], 0, SHA1_BLOCK_SIZE); if (len <= SHA1_BLOCK_SIZE) { memcpy(&sha_ctx->authkey[0], key, len); @@ -3620,16 +3621,19 @@ static int _sha1_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, } else { sha_ctx->alg = QCE_HASH_SHA1; sha_ctx->diglen = SHA1_DIGEST_SIZE; - _sha_hmac_setkey(tfm, key, len); + ret = _sha_hmac_setkey(tfm, key, len); + if (ret) + pr_err("SHA1 hmac setkey failed\n"); sha_ctx->authkey_in_len = SHA1_BLOCK_SIZE; } - return 0; + return ret; } static int _sha256_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int len) { struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(&tfm->base); + int ret = 0; memset(&sha_ctx->authkey[0], 0, SHA256_BLOCK_SIZE); if (len <= SHA256_BLOCK_SIZE) { @@ -3638,11 +3642,13 @@ static int _sha256_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, } else { sha_ctx->alg = QCE_HASH_SHA256; sha_ctx->diglen = SHA256_DIGEST_SIZE; - _sha_hmac_setkey(tfm, key, len); + ret = _sha_hmac_setkey(tfm, key, len); + if (ret) + pr_err("SHA256 hmac setkey failed\n"); sha_ctx->authkey_in_len = SHA256_BLOCK_SIZE; } - return 0; + return ret; } static int _sha_hmac_init_ihash(struct ahash_request *req, diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 057d894eee6..6e5ba44dfaa 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -623,7 +623,7 @@ static void talitos_unregister_rng(struct device *dev) * crypto alg */ #define TALITOS_CRA_PRIORITY 3000 -#define TALITOS_MAX_KEY_SIZE 96 +#define TALITOS_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE) #define TALITOS_MAX_IV_LENGTH 16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */ #define MD5_BLOCK_SIZE 64 @@ -1380,6 +1380,11 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *cipher, { struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); + if (keylen > TALITOS_MAX_KEY_SIZE) { + crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + memcpy(&ctx->key, key, keylen); ctx->keylen = keylen; diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 7816b923857..a4d9c6a7aac 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -79,15 +79,6 @@ config DEVFREQ_GOV_MSM_ADRENO_TZ Sets the frequency using a "on-demand" algorithm. This governor is unlikely to be useful for other devices. -config ADRENO_IDLER - tristate "MSM Adreno idler" - depends on DEVFREQ_GOV_MSM_ADRENO_TZ - help - Uses a different calculation method on top of Adreno TZ - just for calculating frequency for idle to reduce the - wasted power coming from stock Adreno TZ while - maintaining high-performance. - config MSM_BIMC_BWMON tristate "MSM BIMC Bandwidth monitor hardware" depends on ARCH_MSM diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile index 7fd3d000af1..97b550b08dc 100644 --- a/drivers/devfreq/Makefile +++ b/drivers/devfreq/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_CPUFREQ) += governor_cpufreq.o obj-$(CONFIG_DEVFREQ_GOV_MSM_ADRENO_TZ) += governor_msm_adreno_tz.o -obj-$(CONFIG_ADRENO_IDLER) += adreno_idler.o obj-$(CONFIG_DEVFREQ_GOV_MSM_CPUFREQ) += governor_msm_cpufreq.o obj-$(CONFIG_ARCH_MSM_KRAIT) += krait-l2pm.o obj-$(CONFIG_MSM_BIMC_BWMON) += bimc-bwmon.o diff --git a/drivers/devfreq/adreno_idler.c b/drivers/devfreq/adreno_idler.c deleted file mode 100644 index 0e6cd27b1b1..00000000000 --- a/drivers/devfreq/adreno_idler.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Author: Park Ju Hyung aka arter97 <qkrwngud825@gmail.com> - * - * Copyright 2015 Park Ju Hyung - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -/* - * Adreno idler - Idling algorithm, - * an efficient workaround for msm-adreno-tz's overheads. - * - * Main goal is to lower the power consumptions while maintaining high-performance. - * - * Since msm-adreno-tz tends to *not* use the lowest frequency even on idle, - * Adreno idler replaces msm-adreno-tz's algorithm when it comes to - * calculating idle frequency(mostly by ondemand's method). - * The higher frequencies are not touched with this algorithm, so high-demanding - * games will (most likely) not suffer from worsened performance. - */ - -#include <linux/module.h> -#include <linux/devfreq.h> -#include <linux/msm_adreno_devfreq.h> - -#define ADRENO_IDLER_MAJOR_VERSION 1 -#define ADRENO_IDLER_MINOR_VERSION 1 - -/* stats.busy_time threshold for determining if the given workload is idle. - Any workload higher than this will be treated as a non-idle workload. - Adreno idler will more actively try to ramp down the frequency - if this is set to a higher value. */ -static unsigned long idleworkload = 5000; -module_param_named(adreno_idler_idleworkload, idleworkload, ulong, 0664); - -/* Number of events to wait before ramping down the frequency. - The idlewait'th events before current one must be all idle before - Adreno idler ramps down the frequency. - This implementation is to prevent micro-lags on scrolling or playing games. - Adreno idler will more actively try to ramp down the frequency - if this is set to a lower value. */ -static unsigned int idlewait = 20; -module_param_named(adreno_idler_idlewait, idlewait, uint, 0664); - -/* Taken from ondemand */ -static unsigned int downdifferential = 20; -module_param_named(adreno_idler_downdifferential, downdifferential, uint, 0664); - -/* Master switch to activate the whole routine */ -static bool adreno_idler_active = true; -module_param_named(adreno_idler_active, adreno_idler_active, bool, 0664); - -static unsigned int idlecount = 0; - -int adreno_idler(struct devfreq_dev_status stats, struct devfreq *devfreq, - unsigned long *freq) -{ - if (!adreno_idler_active) - return 0; - - if (stats.busy_time < idleworkload) { - /* busy_time >= idleworkload should be considered as a non-idle workload. */ - idlecount++; - if (*freq == devfreq->profile->freq_table[devfreq->profile->max_state - 1]) { - /* Frequency is already at its lowest. - No need to calculate things, so bail out. */ - return 1; - } - if (idlecount >= idlewait && - stats.busy_time * 100 < stats.total_time * downdifferential) { - /* We are idle for (idlewait + 1)'th time! Ramp down the frequency now. */ - *freq = devfreq->profile->freq_table[devfreq->profile->max_state - 1]; - idlecount--; - return 1; - } - } else { - idlecount = 0; - /* Do not return 1 here and allow rest of the algorithm to - figure out the appropriate frequency for current workload. - It can even set it back to the lowest frequency. */ - } - return 0; -} -EXPORT_SYMBOL(adreno_idler); - -static int __init adreno_idler_init(void) -{ - pr_info("adreno_idler: version %d.%d by arter97\n", - ADRENO_IDLER_MAJOR_VERSION, - ADRENO_IDLER_MINOR_VERSION); - - return 0; -} -subsys_initcall(adreno_idler_init); - -static void __exit adreno_idler_exit(void) -{ - return; -} -module_exit(adreno_idler_exit); - -MODULE_AUTHOR("Park Ju Hyung <qkrwngud825@gmail.com>"); -MODULE_DESCRIPTION("'adreno_idler - A powersaver for Adreno TZ" - "Control idle algorithm for Adreno GPU series"); -MODULE_LICENSE("GPL"); diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index a5b09deba52..582b4d31c46 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -349,6 +349,7 @@ void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay) unsigned int new_delay = *delay; mutex_lock(&devfreq->lock); + devfreq->profile->polling_ms = new_delay; if (devfreq->stop_polling) goto out; @@ -825,7 +826,6 @@ static ssize_t store_polling_interval(struct device *dev, if (ret != 1) return -EINVAL; - df->profile->polling_ms = value; df->governor->event_handler(df, DEVFREQ_GOV_INTERVAL, &value); ret = count; @@ -977,26 +977,6 @@ static ssize_t show_trans_table(struct device *dev, struct device_attribute *att return len; } -static ssize_t show_time_in_state(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct devfreq *devfreq = to_devfreq(dev); - - ssize_t len = 0; - int i, err; - unsigned int max_state = devfreq->profile->max_state; - - err = devfreq_update_status(devfreq, devfreq->previous_freq); - if (err) - return 0; - - for (i = 0; i < max_state; i++) { - len += sprintf(buf + len, "%u %u\n", devfreq->profile->freq_table[i], - jiffies_to_msecs(devfreq->time_in_state[i])); - } - return len; -} - static struct device_attribute devfreq_attrs[] = { __ATTR(governor, S_IRUGO | S_IWUSR, show_governor, store_governor), __ATTR(available_governors, S_IRUGO, show_available_governors, NULL), @@ -1008,7 +988,6 @@ static struct device_attribute devfreq_attrs[] = { __ATTR(min_freq, S_IRUGO | S_IWUSR, show_min_freq, store_min_freq), __ATTR(max_freq, S_IRUGO | S_IWUSR, show_max_freq, store_max_freq), __ATTR(trans_stat, S_IRUGO, show_trans_table, NULL), - __ATTR(time_in_state, S_IRUGO, show_time_in_state, NULL), { }, }; @@ -1020,10 +999,7 @@ static int __init devfreq_init(void) return PTR_ERR(devfreq_class); } - devfreq_wq = - alloc_workqueue("devfreq_wq", - WQ_HIGHPRI | WQ_UNBOUND | WQ_FREEZABLE | - WQ_MEM_RECLAIM, 0); + devfreq_wq = create_freezable_workqueue("devfreq_wq"); if (IS_ERR(devfreq_wq)) { class_destroy(devfreq_class); pr_err("%s: couldn't create workqueue\n", __FILE__); diff --git a/drivers/devfreq/governor_gpubw_mon.c b/drivers/devfreq/governor_gpubw_mon.c index 1e78c8649d5..ff4a67ace9e 100644 --- a/drivers/devfreq/governor_gpubw_mon.c +++ b/drivers/devfreq/governor_gpubw_mon.c @@ -63,9 +63,6 @@ static int devfreq_gpubw_get_target(struct devfreq *df, int norm_ab; unsigned long ab_mbytes = 0; - if (priv == NULL) - return 0; - stats.private_data = &b; result = df->profile->get_dev_status(df->dev.parent, &stats); diff --git a/drivers/devfreq/governor_msm_adreno_tz.c b/drivers/devfreq/governor_msm_adreno_tz.c index e6b8bb457b9..d68ae652c88 100644 --- a/drivers/devfreq/governor_msm_adreno_tz.c +++ b/drivers/devfreq/governor_msm_adreno_tz.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -25,8 +25,7 @@ #include "governor.h" static DEFINE_SPINLOCK(tz_lock); -static DEFINE_SPINLOCK(sample_lock); -static DEFINE_SPINLOCK(suspend_lock); + /* * FLOOR is 5msec to capture up to 3 re-draws * per frame for 60fps content. @@ -63,115 +62,18 @@ static DEFINE_SPINLOCK(suspend_lock); #define TAG "msm_adreno_tz: " -static u64 suspend_time; -static u64 suspend_start; -static unsigned long acc_total, acc_relative_busy; - -static struct msm_adreno_extended_profile *partner_gpu_profile; +struct msm_adreno_extended_profile *partner_gpu_profile; static void do_partner_start_event(struct work_struct *work); static void do_partner_stop_event(struct work_struct *work); static void do_partner_suspend_event(struct work_struct *work); static void do_partner_resume_event(struct work_struct *work); -static struct workqueue_struct *workqueue; - -/* - * Returns GPU suspend time in millisecond. - */ -u64 suspend_time_ms(void) -{ - u64 suspend_sampling_time; - u64 time_diff = 0; - - if (suspend_start == 0) - return 0; - - suspend_sampling_time = (u64)ktime_to_ms(ktime_get()); - time_diff = suspend_sampling_time - suspend_start; - /* Update the suspend_start sample again */ - suspend_start = suspend_sampling_time; - return time_diff; -} - -static ssize_t gpu_load_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - unsigned long sysfs_busy_perc; - /* - * Average out the samples taken since last read - * This will keep the average value in sync with - * with the client sampling duration. - */ - spin_lock(&sample_lock); - sysfs_busy_perc = (acc_relative_busy * 100) / acc_total; - - /* Reset the parameters */ - acc_total = 0; - acc_relative_busy = 0; - spin_unlock(&sample_lock); - return snprintf(buf, PAGE_SIZE, "%lu\n", sysfs_busy_perc); -} - -/* - * Returns the time in ms for which gpu was in suspend state - * since last time the entry is read. - */ -static ssize_t suspend_time_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - u64 time_diff = 0; - - spin_lock(&suspend_lock); - time_diff = suspend_time_ms(); - /* - * Adding the previous suspend time also as the gpu - * can go and come out of suspend states in between - * reads also and we should have the total suspend - * since last read. - */ - time_diff += suspend_time; - suspend_time = 0; - spin_unlock(&suspend_lock); - - return snprintf(buf, PAGE_SIZE, "%llu\n", time_diff); -} - -static DEVICE_ATTR(gpu_load, 0444, gpu_load_show, NULL); - -static DEVICE_ATTR(suspend_time, 0444, - suspend_time_show, - NULL); - -static const struct device_attribute *adreno_tz_attr_list[] = { - &dev_attr_gpu_load, - &dev_attr_suspend_time, - NULL -}; - -void compute_work_load(struct devfreq_dev_status *stats, - struct devfreq_msm_adreno_tz_data *priv, - struct devfreq *devfreq) -{ - spin_lock(&sample_lock); - /* - * Keep collecting the stats till the client - * reads it. Average of all samples and reset - * is done when the entry is read - */ - acc_total += stats->total_time; - acc_relative_busy += (stats->busy_time * stats->current_frequency) / - devfreq->profile->freq_table[0]; - spin_unlock(&sample_lock); -} - /* Trap into the TrustZone, and call funcs there. */ static int __secure_tz_reset_entry2(unsigned int *scm_data, u32 size_scm_data, bool is_64) { int ret; - /* sync memory before sending the commands to tz */ + /* sync memory before sending the commands to tz*/ __iowmb(); if (!is_64) { @@ -197,7 +99,7 @@ static int __secure_tz_update_entry3(unsigned int *scm_data, u32 size_scm_data, int *val, u32 size_val, bool is_64) { int ret; - /* sync memory before sending the commands to tz */ + /* sync memory before sending the commands to tz*/ __iowmb(); if (!is_64) { @@ -274,10 +176,6 @@ static int tz_init(struct devfreq_msm_adreno_tz_data *priv, return ret; } -#ifdef CONFIG_ADRENO_IDLER -extern int adreno_idler(struct devfreq_dev_status stats, struct devfreq *devfreq, - unsigned long *freq); -#endif static int tz_get_target_freq(struct devfreq *devfreq, unsigned long *freq, u32 *flag) { @@ -295,27 +193,10 @@ static int tz_get_target_freq(struct devfreq *devfreq, unsigned long *freq, return result; } - /* Prevent overflow */ - if (stats.busy_time >= (1 << 24) || stats.total_time >= (1 << 24)) { - stats.busy_time >>= 7; - stats.total_time >>= 7; - } - *freq = stats.current_frequency; - *flag = 0; - -#ifdef CONFIG_ADRENO_IDLER - if (adreno_idler(stats, devfreq, freq)) { - /* adreno_idler has asked to bail out now */ - return 0; - } -#endif - priv->bin.total_time += stats.total_time; priv->bin.busy_time += stats.busy_time; - /* Update the GPU load statistics */ - compute_work_load(&stats, priv, devfreq); /* * Do not waste CPU cycles running this algorithm if * the GPU just started, or if less than FLOOR time @@ -437,6 +318,8 @@ static int tz_start(struct devfreq *devfreq) return -EINVAL; } + gpu_profile->partner_wq = create_freezable_workqueue + ("governor_msm_adreno_tz_wq"); INIT_WORK(&gpu_profile->partner_start_event_ws, do_partner_start_event); INIT_WORK(&gpu_profile->partner_stop_event_ws, @@ -453,23 +336,21 @@ static int tz_start(struct devfreq *devfreq) return ret; } - for (i = 0; adreno_tz_attr_list[i] != NULL; i++) - device_create_file(&devfreq->dev, adreno_tz_attr_list[i]); - return kgsl_devfreq_add_notifier(devfreq->dev.parent, &priv->nb); } static int tz_stop(struct devfreq *devfreq) { - int i; struct devfreq_msm_adreno_tz_data *priv = devfreq->data; + struct msm_adreno_extended_profile *gpu_profile = container_of( + (devfreq->profile), + struct msm_adreno_extended_profile, + profile); kgsl_devfreq_del_notifier(devfreq->dev.parent, &priv->nb); - for (i = 0; adreno_tz_attr_list[i] != NULL; i++) - device_remove_file(&devfreq->dev, adreno_tz_attr_list[i]); - - flush_workqueue(workqueue); + flush_workqueue(gpu_profile->partner_wq); + destroy_workqueue(gpu_profile->partner_wq); /* leaving the governor and cleaning the pointer to private data */ devfreq->data = NULL; @@ -491,7 +372,6 @@ static int tz_suspend(struct devfreq *devfreq) static int tz_handler(struct devfreq *devfreq, unsigned int event, void *data) { int result; - struct msm_adreno_extended_profile *gpu_profile = container_of( (devfreq->profile), struct msm_adreno_extended_profile, @@ -504,33 +384,14 @@ static int tz_handler(struct devfreq *devfreq, unsigned int event, void *data) break; case DEVFREQ_GOV_STOP: - /* Queue the stop work before the TZ is stopped */ - if (partner_gpu_profile && partner_gpu_profile->bus_devfreq) - queue_work(workqueue, - &gpu_profile->partner_stop_event_ws); - spin_lock(&suspend_lock); - suspend_start = 0; - spin_unlock(&suspend_lock); result = tz_stop(devfreq); break; case DEVFREQ_GOV_SUSPEND: result = tz_suspend(devfreq); - if (!result) { - spin_lock(&suspend_lock); - /* Collect the start sample for suspend time */ - suspend_start = (u64)ktime_to_ms(ktime_get()); - spin_unlock(&suspend_lock); - } break; case DEVFREQ_GOV_RESUME: - spin_lock(&suspend_lock); - suspend_time += suspend_time_ms(); - /* Reset the suspend_start when gpu resumes */ - suspend_start = 0; - spin_unlock(&suspend_lock); - case DEVFREQ_GOV_INTERVAL: /* ignored, this governor doesn't use polling */ default: @@ -541,15 +402,19 @@ static int tz_handler(struct devfreq *devfreq, unsigned int event, void *data) if (partner_gpu_profile && partner_gpu_profile->bus_devfreq) switch (event) { case DEVFREQ_GOV_START: - queue_work(workqueue, + queue_work(gpu_profile->partner_wq, &gpu_profile->partner_start_event_ws); break; + case DEVFREQ_GOV_STOP: + queue_work(gpu_profile->partner_wq, + &gpu_profile->partner_stop_event_ws); + break; case DEVFREQ_GOV_SUSPEND: - queue_work(workqueue, + queue_work(gpu_profile->partner_wq, &gpu_profile->partner_suspend_event_ws); break; case DEVFREQ_GOV_RESUME: - queue_work(workqueue, + queue_work(gpu_profile->partner_wq, &gpu_profile->partner_resume_event_ws); break; } @@ -559,16 +424,9 @@ static int tz_handler(struct devfreq *devfreq, unsigned int event, void *data) static void _do_partner_event(struct work_struct *work, unsigned int event) { - struct devfreq *bus_devfreq; - - if (partner_gpu_profile == NULL) - return; + struct devfreq *bus_devfreq = partner_gpu_profile->bus_devfreq; - bus_devfreq = partner_gpu_profile->bus_devfreq; - - if (bus_devfreq != NULL && - bus_devfreq->governor && - bus_devfreq->governor->event_handler) + if (bus_devfreq->governor && bus_devfreq->governor->event_handler) bus_devfreq->governor->event_handler(bus_devfreq, event, NULL); } @@ -601,22 +459,18 @@ static struct devfreq_governor msm_adreno_tz = { static int __init msm_adreno_tz_init(void) { - workqueue = create_freezable_workqueue("governor_msm_adreno_tz_wq"); - if (workqueue == NULL) - return -ENOMEM; - return devfreq_add_governor(&msm_adreno_tz); } subsys_initcall(msm_adreno_tz_init); static void __exit msm_adreno_tz_exit(void) { - int ret = devfreq_remove_governor(&msm_adreno_tz); + int ret; + ret = devfreq_remove_governor(&msm_adreno_tz); if (ret) pr_err(TAG "failed to remove governor %d\n", ret); - if (workqueue != NULL) - destroy_workqueue(workqueue); + return; } module_exit(msm_adreno_tz_exit); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 89664933861..a3a70283bde 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -368,6 +368,8 @@ void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes) return fifo_state->static_buffer; else { fifo_state->dynamic_buffer = vmalloc(bytes); + if (!fifo_state->dynamic_buffer) + goto out_err; return fifo_state->dynamic_buffer; } } diff --git a/drivers/gpu/msm/adreno_a4xx.c b/drivers/gpu/msm/adreno_a4xx.c index cad2fff34dd..01bf2415254 100644 --- a/drivers/gpu/msm/adreno_a4xx.c +++ b/drivers/gpu/msm/adreno_a4xx.c @@ -551,10 +551,6 @@ static void a4xx_enable_hwcg(struct kgsl_device *device) kgsl_regwrite(device, A4XX_RBBM_CLOCK_CTL, 0); else kgsl_regwrite(device, A4XX_RBBM_CLOCK_CTL, 0xAAAAAAAA); - - /* MMI_STOPSHIP: Disable HW clock gating in all GPU blocks */ - kgsl_regwrite(device, A4XX_RBBM_CLOCK_CTL, 0); - kgsl_regwrite(device, A4XX_RBBM_CLOCK_CTL2, 0); } diff --git a/drivers/gpu/msm/kgsl_cmdbatch.c b/drivers/gpu/msm/kgsl_cmdbatch.c index 7dfd691d84c..065686a2a49 100644 --- a/drivers/gpu/msm/kgsl_cmdbatch.c +++ b/drivers/gpu/msm/kgsl_cmdbatch.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -107,6 +107,7 @@ static void _kgsl_cmdbatch_timer(unsigned long data) struct kgsl_device *device; struct kgsl_cmdbatch *cmdbatch = (struct kgsl_cmdbatch *) data; struct kgsl_cmdbatch_sync_event *event; + unsigned long flags; if (cmdbatch == NULL || cmdbatch->context == NULL) return; @@ -121,14 +122,14 @@ static void _kgsl_cmdbatch_timer(unsigned long data) kgsl_context_dump(cmdbatch->context); clear_bit(CMDBATCH_FLAG_FENCE_LOG, &cmdbatch->priv); - spin_lock(&cmdbatch->lock); + spin_lock_irqsave(&cmdbatch->lock, flags); /* Print all the fences */ list_for_each_entry(event, &cmdbatch->synclist, node) { if (KGSL_CMD_SYNCPOINT_TYPE_FENCE == event->type && event->handle && event->handle->fence) kgsl_sync_fence_log(event->handle->fence); } - spin_unlock(&cmdbatch->lock); + spin_unlock_irqrestore(&cmdbatch->lock, flags); dev_err(device->dev, "--gpu syncpoint deadlock print end--\n"); } @@ -184,15 +185,15 @@ static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device, struct kgsl_cmdbatch_sync_event *event) { struct kgsl_cmdbatch_sync_event *e, *tmp; + unsigned long flags; int sched = 0; int removed = 0; /* - * We may have cmdbatch timer running, which also uses same lock, - * take a lock with software interrupt disabled (bh) to avoid - * spin lock recursion. + * cmdbatch timer or event callback might run at this time in interrupt + * context and uses same lock. So use irq-save version of spin lock. */ - spin_lock_bh(&event->cmdbatch->lock); + spin_lock_irqsave(&event->cmdbatch->lock, flags); /* * sync events that are contained by a cmdbatch which has been @@ -207,8 +208,9 @@ static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device, } } + event->handle = NULL; sched = list_empty(&event->cmdbatch->synclist) ? 1 : 0; - spin_unlock_bh(&event->cmdbatch->lock); + spin_unlock_irqrestore(&event->cmdbatch->lock, flags); /* If the list is empty delete the canary timer */ if (sched) @@ -269,19 +271,22 @@ void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch) struct kgsl_cmdbatch_sync_event *event, *tmpsync; LIST_HEAD(cancel_synclist); int sched = 0; - + unsigned long flags; if (IS_ERR_OR_NULL(cmdbatch)) return; /* Zap the canary timer */ del_timer_sync(&cmdbatch->timer); - /* non-bh because we just destroyed timer */ - spin_lock(&cmdbatch->lock); + /* + * callback might run in interrupt context + * so need to use irqsave version of spinlocks. + */ + spin_lock_irqsave(&cmdbatch->lock, flags); /* Empty the synclist before canceling events */ list_splice_init(&cmdbatch->synclist, &cancel_synclist); - spin_unlock(&cmdbatch->lock); + spin_unlock_irqrestore(&cmdbatch->lock, flags); /* * Finish canceling events outside the cmdbatch spinlock and @@ -303,8 +308,15 @@ void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch) kgsl_cmdbatch_sync_func, event); } else if (event->type == KGSL_CMD_SYNCPOINT_TYPE_FENCE) { /* Put events that are successfully canceled */ - if (kgsl_sync_fence_async_cancel(event->handle)) + spin_lock_irqsave(&cmdbatch->lock, flags); + + if (kgsl_sync_fence_async_cancel(event->handle)) { + event->handle = NULL; + spin_unlock_irqrestore(&cmdbatch->lock, flags); kgsl_cmdbatch_sync_event_put(event); + } else { + spin_unlock_irqrestore(&cmdbatch->lock, flags); + } } /* Put events that have been removed from the synclist */ @@ -365,7 +377,7 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, { struct kgsl_cmd_syncpoint_fence *sync = priv; struct kgsl_cmdbatch_sync_event *event; - + unsigned long flags; event = kzalloc(sizeof(*event), GFP_KERNEL); if (event == NULL) return -ENOMEM; @@ -392,11 +404,6 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, kref_get(&event->refcount); - /* non-bh because, we haven't started cmdbatch timer yet */ - spin_lock(&cmdbatch->lock); - list_add(&event->node, &cmdbatch->synclist); - spin_unlock(&cmdbatch->lock); - /* * Increment the reference count for the async callback. * Decrement when the callback is successfully canceled, when @@ -404,6 +411,10 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, */ kref_get(&event->refcount); + + spin_lock_irqsave(&cmdbatch->lock, flags); + list_add(&event->node, &cmdbatch->synclist); + event->handle = kgsl_sync_fence_async_wait(sync->fd, kgsl_cmdbatch_sync_fence_func, event); @@ -411,17 +422,14 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, int ret = PTR_ERR(event->handle); event->handle = NULL; - - /* Failed to add the event to the async callback */ - kgsl_cmdbatch_sync_event_put(event); - /* Remove event from the synclist */ - spin_lock(&cmdbatch->lock); list_del(&event->node); - spin_unlock(&cmdbatch->lock); + spin_unlock_irqrestore(&cmdbatch->lock, flags); + /* Put for event removal from the synclist */ kgsl_cmdbatch_sync_event_put(event); - - /* Event no longer needed by this function */ + /* Unable to add event to the async callback so a put */ + kgsl_cmdbatch_sync_event_put(event); + /* Put since event no longer needed by this function */ kgsl_cmdbatch_sync_event_put(event); /* @@ -435,6 +443,7 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, } trace_syncpoint_fence(cmdbatch, event->handle->name); + spin_unlock_irqrestore(&cmdbatch->lock, flags); /* * Event was successfully added to the synclist, the async diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 343d9339fe1..7bf7469e2b7 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -791,19 +791,12 @@ static ssize_t kgsl_pwrctrl_gpuclk_show(struct device *dev, struct device_attribute *attr, char *buf) { - unsigned long freq; struct kgsl_device *device = kgsl_device_from_dev(dev); struct kgsl_pwrctrl *pwr; if (device == NULL) return 0; pwr = &device->pwrctrl; - - if (device->state == KGSL_STATE_SLUMBER) - freq = pwr->pwrlevels[pwr->num_pwrlevels - 1].gpu_freq; - else - freq = kgsl_pwrctrl_active_freq(pwr); - - return snprintf(buf, PAGE_SIZE, "%lu\n", freq); + return snprintf(buf, PAGE_SIZE, "%ld\n", kgsl_pwrctrl_active_freq(pwr)); } static ssize_t kgsl_pwrctrl_idle_timer_store(struct device *dev, diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 700145b1508..602f1637317 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -510,17 +510,18 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, goto inval; field = report->field[uref->field_index]; + } - if (cmd == HIDIOCGCOLLECTIONINDEX) { - if (uref->usage_index >= field->maxusage) - goto inval; - } else if (uref->usage_index >= field->report_count) + if (cmd == HIDIOCGCOLLECTIONINDEX) { + if (uref->usage_index >= field->maxusage) goto inval; - } + } else if (uref->usage_index >= field->report_count) + goto inval; - if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && - (uref_multi->num_values > HID_MAX_MULTI_USAGES || - uref->usage_index + uref_multi->num_values > field->report_count)) + else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && + (uref_multi->num_values > HID_MAX_MULTI_USAGES || + uref->usage_index + uref_multi->num_values > + field->report_count)) goto inval; switch (cmd) { diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 9d539cbfc83..c0e4143bee9 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1323,6 +1323,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) /* add the driver to the list of i2c drivers in the driver core */ driver->driver.owner = owner; driver->driver.bus = &i2c_bus_type; + INIT_LIST_HEAD(&driver->clients); /* When registration returns, the driver core * will have called probe() for all matching-but-unbound devices. @@ -1341,7 +1342,6 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); - INIT_LIST_HEAD(&driver->clients); /* Walk the adapters that are already present */ i2c_for_each_dev(driver, __process_new_driver); diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 5f5f20f4223..c61f3e7aa35 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -6670,7 +6670,7 @@ static void qib_7322_txchk_change(struct qib_devdata *dd, u32 start, unsigned long flags; while (wait) { - unsigned long shadow; + unsigned long shadow = 0; int cstart, previ = -1; /* diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 8292554bccb..7604ae54d7b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -165,11 +165,11 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) out: mutex_unlock(&ppriv->vlan_mutex); + rtnl_unlock(); + if (result) free_netdev(priv->dev); - rtnl_unlock(); - return result; } diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 0734f1b0bdc..a0a6b5762cf 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -1200,9 +1200,6 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id struct usb_endpoint_descriptor *ep_irq_in; int ep_irq_in_idx; int i, error; - - if (intf->cur_altsetting->desc.bNumEndpoints != 2) - return -ENODEV; if (intf->cur_altsetting->desc.bNumEndpoints != 2) return -ENODEV; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index c9346bf6156..4f0d5a6cbd6 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -955,6 +955,16 @@ config TOUCHSCREEN_FT5X06_GESTURE If unsure, say N. +config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + bool "Synaptics DSX firmware update extra sysfs attributes" + depends on TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE + help + Say Y here to enable support for extra sysfs attributes + supporting firmware update in a development environment. + This does not affect the core or other subsystem attributes. + + If unsure, say N. + config TOUCHSCREEN_GEN_VKEYS tristate "Touchscreen Virtual Keys Driver" help diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c index 409988fce55..cac9c7a29a1 100644 --- a/drivers/input/touchscreen/synaptics_fw_update.c +++ b/drivers/input/touchscreen/synaptics_fw_update.c @@ -1305,6 +1305,7 @@ write_config: return retval; } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static int fwu_start_write_config(void) { int retval; @@ -1357,6 +1358,7 @@ static int fwu_start_write_config(void) return retval; } +#endif static int fwu_do_write_lockdown(bool reset) { @@ -1404,6 +1406,7 @@ exit: return retval; } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static int fwu_start_write_lockdown(void) { if (parse_header()) @@ -1507,6 +1510,7 @@ static int fwu_do_read_config(void) exit: return retval; } +#endif static int fwu_do_reflash(void) { @@ -1732,6 +1736,7 @@ int synaptics_fw_updater(void) } EXPORT_SYMBOL(synaptics_fw_updater); +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static ssize_t fwu_sysfs_show_image(struct file *data_file, struct kobject *kobj, struct bin_attribute *attributes, char *buf, loff_t pos, size_t count) @@ -2155,6 +2160,7 @@ static ssize_t fwu_sysfs_package_id_show(struct device *dev, (pkg_id[1] << 8) | pkg_id[0], (pkg_id[3] << 8) | pkg_id[2]); } +#endif static int synaptics_rmi4_debug_dump_info(struct seq_file *m, void *v) { @@ -2188,6 +2194,7 @@ static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, return; } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS static struct bin_attribute dev_attr_data = { .attr = { .name = "data", @@ -2197,8 +2204,10 @@ static struct bin_attribute dev_attr_data = { .read = fwu_sysfs_show_image, .write = fwu_sysfs_store_image, }; +#endif static struct device_attribute attrs[] = { +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS __ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP, fwu_sysfs_image_name_show, fwu_sysfs_image_name_store), @@ -2247,6 +2256,7 @@ static struct device_attribute attrs[] = { __ATTR(package_id, S_IRUGO, fwu_sysfs_package_id_show, synaptics_rmi4_store_error), +#endif }; @@ -2332,6 +2342,29 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) fwu->initialized = true; fwu->polling_mode = false; +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, + &dev_attr_data); + if (retval < 0) { + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to create sysfs bin file\n", + __func__); + goto exit_free_mem; + } +#endif + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->i2c_client->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto exit_remove_attrs; + } + } + temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, fwu->rmi4_data->dir, fwu->rmi4_data, &debug_dump_info_fops); @@ -2340,13 +2373,13 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) "%s: Failed to create debugfs dump info file\n", __func__); retval = PTR_ERR(temp); - goto exit_free_mem; + goto exit_remove_attrs; } fwu->ts_info = kzalloc(RMI4_INFO_MAX_LEN, GFP_KERNEL); if (!fwu->ts_info) { dev_err(&rmi4_data->i2c_client->dev, "Not enough memory\n"); - goto exit_free_debugfs; + goto exit_free_ts_info; } synaptics_rmi4_update_debug_info(); @@ -2358,41 +2391,20 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) &fwu->fwu_work, msecs_to_jiffies(1000)); #endif - retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, - &dev_attr_data); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to create sysfs bin file\n", - __func__); - goto exit_free_ts_info; - } - - for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { - retval = sysfs_create_file(&rmi4_data->i2c_client->dev.kobj, - &attrs[attr_count].attr); - if (retval < 0) { - dev_err(&rmi4_data->i2c_client->dev, - "%s: Failed to create sysfs attributes\n", - __func__); - retval = -ENODEV; - goto exit_remove_attrs; - } - } return 0; - +exit_free_ts_info: + debugfs_remove(temp); exit_remove_attrs: for (attr_count--; attr_count >= 0; attr_count--) { sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, &attrs[attr_count].attr); } +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +#endif -exit_free_ts_info: - kfree(fwu->ts_info); -exit_free_debugfs: - debugfs_remove(temp); exit_free_mem: kfree(fwu->fn_ptr); @@ -2408,7 +2420,9 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) { unsigned char attr_count; +#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +#endif for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 2825a446df7..9a8b80094fb 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -3402,6 +3402,7 @@ static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova, mutex_unlock(&domain->api_lock); domain_flush_tlb_pde(domain); + domain_flush_complete(domain); return unmap_size; } diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 37470ee7c85..4d874427101 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1806,6 +1806,11 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks, long pages; struct bitmap_page *new_bp; + if (bitmap->storage.file && !init) { + pr_info("md: cannot resize file-based bitmap\n"); + return -EINVAL; + } + if (chunksize == 0) { /* If there is enough space, leave the chunk size unchanged, * else increase by factor of two until there is enough space. diff --git a/drivers/md/dm-android-verity.c b/drivers/md/dm-android-verity.c index bb76926ab63..17cdfa8279d 100644 --- a/drivers/md/dm-android-verity.c +++ b/drivers/md/dm-android-verity.c @@ -576,15 +576,15 @@ static int add_as_linear_device(struct dm_target *ti, char *dev) DM_LINEAR_TARGET_OFFSET}; int err = 0; - android_verity_target.dtr = linear_target.dtr, - android_verity_target.map = linear_target.map, - android_verity_target.status = linear_target.status, - android_verity_target.ioctl = linear_target.ioctl, - android_verity_target.merge = linear_target.merge, - android_verity_target.iterate_devices = linear_target.iterate_devices, + android_verity_target.dtr = dm_linear_dtr, + android_verity_target.map = dm_linear_map, + android_verity_target.status = dm_linear_status, + android_verity_target.ioctl = dm_linear_ioctl, + android_verity_target.merge = dm_linear_merge, + android_verity_target.iterate_devices = dm_linear_iterate_devices, android_verity_target.io_hints = NULL; - err = linear_target.ctr(ti, DM_LINEAR_ARGS, linear_table_args); + err = dm_linear_ctr(ti, DM_LINEAR_ARGS, linear_table_args); if (!err) { DMINFO("Added android-verity as a linear target"); diff --git a/drivers/md/dm-android-verity.h b/drivers/md/dm-android-verity.h index fe53863c664..efb79652489 100644 --- a/drivers/md/dm-android-verity.h +++ b/drivers/md/dm-android-verity.h @@ -94,4 +94,16 @@ struct bio_read { }; extern struct target_type linear_target; + +extern void dm_linear_dtr(struct dm_target *ti); +extern int dm_linear_map(struct dm_target *ti, struct bio *bio); +extern void dm_linear_status(struct dm_target *ti, status_type_t type, + unsigned status_flags, char *result, unsigned maxlen); +extern int dm_linear_ioctl(struct dm_target *ti, unsigned int cmd, + unsigned long arg); +extern int dm_linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm, + struct bio_vec *biovec, int max_size); +extern int dm_linear_iterate_devices(struct dm_target *ti, + iterate_devices_callout_fn fn, void *data); +extern int dm_linear_ctr(struct dm_target *ti, unsigned int argc, char **argv); #endif /* DM_ANDROID_VERITY_H */ diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 800286668ee..f63e07d3a77 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -25,7 +25,7 @@ struct linear_c { /* * Construct a linear mapping: <dev_path> <offset> */ -static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) +int dm_linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) { struct linear_c *lc; unsigned long long tmp; @@ -64,7 +64,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) return -EINVAL; } -static void linear_dtr(struct dm_target *ti) +void dm_linear_dtr(struct dm_target *ti) { struct linear_c *lc = (struct linear_c *) ti->private; @@ -88,14 +88,14 @@ static void linear_map_bio(struct dm_target *ti, struct bio *bio) bio->bi_sector = linear_map_sector(ti, bio->bi_sector); } -static int linear_map(struct dm_target *ti, struct bio *bio) +int dm_linear_map(struct dm_target *ti, struct bio *bio) { linear_map_bio(ti, bio); return DM_MAPIO_REMAPPED; } -static void linear_status(struct dm_target *ti, status_type_t type, +void dm_linear_status(struct dm_target *ti, status_type_t type, unsigned status_flags, char *result, unsigned maxlen) { struct linear_c *lc = (struct linear_c *) ti->private; @@ -112,7 +112,7 @@ static void linear_status(struct dm_target *ti, status_type_t type, } } -static int linear_ioctl(struct dm_target *ti, unsigned int cmd, +int dm_linear_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) { struct linear_c *lc = (struct linear_c *) ti->private; @@ -129,7 +129,7 @@ static int linear_ioctl(struct dm_target *ti, unsigned int cmd, return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); } -static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm, +int dm_linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm, struct bio_vec *biovec, int max_size) { struct linear_c *lc = ti->private; @@ -144,7 +144,7 @@ static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm, return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); } -static int linear_iterate_devices(struct dm_target *ti, +int dm_linear_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) { struct linear_c *lc = ti->private; @@ -152,17 +152,17 @@ static int linear_iterate_devices(struct dm_target *ti, return fn(ti, lc->dev, lc->start, ti->len, data); } -struct target_type linear_target = { +static struct target_type linear_target = { .name = "linear", .version = {1, 2, 1}, .module = THIS_MODULE, - .ctr = linear_ctr, - .dtr = linear_dtr, - .map = linear_map, - .status = linear_status, - .ioctl = linear_ioctl, - .merge = linear_merge, - .iterate_devices = linear_iterate_devices, + .ctr = dm_linear_ctr, + .dtr = dm_linear_dtr, + .map = dm_linear_map, + .status = dm_linear_status, + .ioctl = dm_linear_ioctl, + .merge = dm_linear_merge, + .iterate_devices = dm_linear_iterate_devices, }; int __init dm_linear_init(void) diff --git a/drivers/md/md.c b/drivers/md/md.c index 7c45286e266..95eb53f6841 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1898,7 +1898,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) } sb = page_address(rdev->sb_page); sb->data_size = cpu_to_le64(num_sectors); - sb->super_offset = rdev->sb_start; + sb->super_offset = cpu_to_le64(rdev->sb_start); sb->sb_csum = calc_sb_1_csum(sb); md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size, rdev->sb_page); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index f53f4f89550..b4de9c3e5ca 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1569,11 +1569,24 @@ retry_write: mbio->bi_private = r10_bio; atomic_inc(&r10_bio->remaining); + + cb = blk_check_plugged(raid10_unplug, mddev, + sizeof(*plug)); + if (cb) + plug = container_of(cb, struct raid10_plug_cb, + cb); + else + plug = NULL; spin_lock_irqsave(&conf->device_lock, flags); - bio_list_add(&conf->pending_bio_list, mbio); - conf->pending_count++; + if (plug) { + bio_list_add(&plug->pending, mbio); + plug->pending_cnt++; + } else { + bio_list_add(&conf->pending_bio_list, mbio); + conf->pending_count++; + } spin_unlock_irqrestore(&conf->device_lock, flags); - if (!mddev_check_plugged(mddev)) + if (!plug) md_wakeup_thread(mddev->thread); } } diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 93609091cb2..9dad717fb78 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -1706,27 +1706,9 @@ static long vpfe_param_handler(struct file *file, void *priv, switch (cmd) { case VPFE_CMD_S_CCDC_RAW_PARAMS: + ret = -EINVAL; v4l2_warn(&vpfe_dev->v4l2_dev, - "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n"); - if (ccdc_dev->hw_ops.set_params) { - ret = ccdc_dev->hw_ops.set_params(param); - if (ret) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "Error setting parameters in CCDC\n"); - goto unlock_out; - } - ret = vpfe_get_ccdc_image_format(vpfe_dev, - &vpfe_dev->fmt); - if (ret < 0) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "Invalid image format at CCDC\n"); - goto unlock_out; - } - } else { - ret = -EINVAL; - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n"); - } + "VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n"); break; default: ret = -ENOTTY; diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c index bb279e79f76..cf531fc2faf 100644 --- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c +++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c @@ -369,6 +369,7 @@ static int msm_fd_open(struct file *file) ctx->vb2_q.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ctx->vb2_q.io_modes = VB2_USERPTR; ctx->vb2_q.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; + mutex_init(&ctx->lock); ret = vb2_queue_init(&ctx->vb2_q); if (ret < 0) { dev_err(device->dev, "Error queue init\n"); @@ -402,7 +403,9 @@ static int msm_fd_release(struct file *file) { struct fd_ctx *ctx = msm_fd_ctx_from_fh(file->private_data); + mutex_lock(&ctx->lock); vb2_queue_release(&ctx->vb2_q); + mutex_unlock(&ctx->lock); vfree(ctx->stats); @@ -428,7 +431,9 @@ static unsigned int msm_fd_poll(struct file *file, struct fd_ctx *ctx = msm_fd_ctx_from_fh(file->private_data); unsigned int ret; + mutex_lock(&ctx->lock); ret = vb2_poll(&ctx->vb2_q, file, wait); + mutex_unlock(&ctx->lock); if (atomic_read(&ctx->subscribed_for_event)) { poll_wait(file, &ctx->fh.wait, wait); @@ -666,9 +671,9 @@ static int msm_fd_reqbufs(struct file *file, int ret; struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh); - mutex_lock(&ctx->fd_device->recovery_lock); + mutex_lock(&ctx->lock); ret = vb2_reqbufs(&ctx->vb2_q, req); - mutex_unlock(&ctx->fd_device->recovery_lock); + mutex_unlock(&ctx->lock); return ret; } @@ -684,9 +689,9 @@ static int msm_fd_qbuf(struct file *file, void *fh, int ret; struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh); - mutex_lock(&ctx->fd_device->recovery_lock); + mutex_lock(&ctx->lock); ret = vb2_qbuf(&ctx->vb2_q, pb); - mutex_unlock(&ctx->fd_device->recovery_lock); + mutex_unlock(&ctx->lock); return ret; } @@ -703,9 +708,9 @@ static int msm_fd_dqbuf(struct file *file, int ret; struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh); - mutex_lock(&ctx->fd_device->recovery_lock); + mutex_lock(&ctx->lock); ret = vb2_dqbuf(&ctx->vb2_q, pb, file->f_flags & O_NONBLOCK); - mutex_unlock(&ctx->fd_device->recovery_lock); + mutex_unlock(&ctx->lock); return ret; } @@ -721,7 +726,9 @@ static int msm_fd_streamon(struct file *file, struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh); int ret; + mutex_lock(&ctx->lock); ret = vb2_streamon(&ctx->vb2_q, buf_type); + mutex_unlock(&ctx->lock); if (ret < 0) dev_err(ctx->fd_device->dev, "Stream on fails\n"); @@ -740,7 +747,9 @@ static int msm_fd_streamoff(struct file *file, struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh); int ret; + mutex_lock(&ctx->lock); ret = vb2_streamoff(&ctx->vb2_q, buf_type); + mutex_unlock(&ctx->lock); if (ret < 0) dev_err(ctx->fd_device->dev, "Stream off fails\n"); diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h index 84ffa8c2414..930cc3f4893 100644 --- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h +++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h @@ -153,6 +153,8 @@ struct fd_ctx { struct msm_fd_mem_pool mem_pool; struct msm_fd_stats *stats; struct msm_fd_buf_handle work_buf; + struct completion *wait_stop_stream; + struct mutex lock; }; /* diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c index 577251ca7a3..c83ad8ef1c1 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c @@ -90,8 +90,8 @@ struct msm_isp_bufq *msm_isp_get_bufq( uint32_t bufq_index = bufq_handle & 0xFF; if ((bufq_handle == 0) || - (bufq_index > buf_mgr->num_buf_q) || - (bufq_index >= BUF_MGR_NUM_BUF_Q) ) + (bufq_index >= buf_mgr->num_buf_q) || + (bufq_index >= BUF_MGR_NUM_BUF_Q)) return NULL; bufq = &buf_mgr->bufq[bufq_index]; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c index d5ccf415574..bd89f3f2eaf 100644..100755 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c @@ -823,12 +823,18 @@ int msm_isp_update_stats_stream(struct vfe_device *vfe_dev, void *arg) struct msm_vfe_axi_stream_cfg_update_info *update_info = NULL; struct msm_isp_sw_framskip *sw_skip_info = NULL; + if (update_cmd->num_streams > MSM_ISP_STATS_MAX) { + pr_err("%s: Invalid num_streams %d\n", + __func__, update_cmd->num_streams); + return -EINVAL; + } + /*validate request*/ for (i = 0; i < update_cmd->num_streams; i++) { update_info = &update_cmd->update_info[i]; /*check array reference bounds*/ if (STATS_IDX(update_info->stream_handle) - > vfe_dev->hw_info->stats_hw_info->num_stats_type) { + >= vfe_dev->hw_info->stats_hw_info->num_stats_type) { pr_err("%s: stats idx %d out of bound!", __func__, STATS_IDX(update_info->stream_handle)); return -EINVAL; diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c index dd228992fa4..4a886eb22ef 100644 --- a/drivers/media/platform/msm/camera_v2/msm.c +++ b/drivers/media/platform/msm/camera_v2/msm.c @@ -31,7 +31,6 @@ #include "msm_sd.h" #include <media/msmb_generic_buf_mgr.h> - static struct v4l2_device *msm_v4l2_dev; static struct list_head ordered_sd_list; @@ -140,7 +139,7 @@ typedef int (*msm_queue_find_func)(void *d1, void *d2); #define msm_queue_find(queue, type, member, func, data) ({\ unsigned long flags; \ struct msm_queue_head *__q = (queue); \ - type *node = 0; \ + type *node = NULL; \ typeof(node) __ret = NULL; \ msm_queue_find_func __f = (func); \ spin_lock_irqsave(&__q->lock, flags); \ @@ -256,22 +255,46 @@ void msm_delete_stream(unsigned int session_id, unsigned int stream_id) struct msm_session *session = NULL; struct msm_stream *stream = NULL; unsigned long flags; + int try_count = 0; session = msm_queue_find(msm_session_q, struct msm_session, list, __msm_queue_find_session, &session_id); + if (!session) return; - stream = msm_queue_find(&session->stream_q, struct msm_stream, - list, __msm_queue_find_stream, &stream_id); - if (!stream) - return; - spin_lock_irqsave(&(session->stream_q.lock), flags); - list_del_init(&stream->list); - session->stream_q.len--; - kfree(stream); - stream = NULL; - spin_unlock_irqrestore(&(session->stream_q.lock), flags); + while (1) { + + if (try_count > 5) { + pr_err("%s : not able to delete stream %d\n", + __func__, __LINE__); + break; + } + + write_lock(&session->stream_rwlock); + try_count++; + stream = msm_queue_find(&session->stream_q, struct msm_stream, + list, __msm_queue_find_stream, &stream_id); + + if (!stream) { + write_unlock(&session->stream_rwlock); + return; + } + + if (msm_vb2_get_stream_state(stream) != 1) { + write_unlock(&session->stream_rwlock); + continue; + } + + spin_lock_irqsave(&(session->stream_q.lock), flags); + list_del_init(&stream->list); + session->stream_q.len--; + kfree(stream); + stream = NULL; + spin_unlock_irqrestore(&(session->stream_q.lock), flags); + write_unlock(&session->stream_rwlock); + break; + } } @@ -338,6 +361,11 @@ static void msm_add_sd_in_position(struct msm_sd_subdev *msm_subdev, struct msm_sd_subdev *temp_sd; list_for_each_entry(temp_sd, sd_list, list) { + if (temp_sd == msm_subdev) { + pr_err("%s :Fail to add the same sd %d\n", + __func__, __LINE__); + return; + } if (msm_subdev->close_seq < temp_sd->close_seq) { list_add_tail(&msm_subdev->list, &temp_sd->list); return; @@ -399,6 +427,7 @@ int msm_create_session(unsigned int session_id, struct video_device *vdev) msm_enqueue(msm_session_q, &session->list); mutex_init(&session->lock); mutex_init(&session->close_lock); + rwlock_init(&session->stream_rwlock); return 0; } @@ -929,17 +958,25 @@ static struct v4l2_file_operations msm_fops = { #endif }; -struct msm_stream *msm_get_stream(unsigned int session_id, - unsigned int stream_id) +struct msm_session *msm_get_session(unsigned int session_id) { struct msm_session *session; - struct msm_stream *stream; session = msm_queue_find(msm_session_q, struct msm_session, list, __msm_queue_find_session, &session_id); if (!session) return ERR_PTR(-EINVAL); + return session; +} +EXPORT_SYMBOL(msm_get_session); + + +struct msm_stream *msm_get_stream(struct msm_session *session, + unsigned int stream_id) +{ + struct msm_stream *stream; + stream = msm_queue_find(&session->stream_q, struct msm_stream, list, __msm_queue_find_stream, &stream_id); @@ -993,6 +1030,33 @@ struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q) return NULL; } +struct msm_session *msm_get_session_from_vb2q(struct vb2_queue *q) +{ + struct msm_session *session; + struct msm_stream *stream; + unsigned long flags1; + unsigned long flags2; + + spin_lock_irqsave(&msm_session_q->lock, flags1); + list_for_each_entry(session, &(msm_session_q->list), list) { + spin_lock_irqsave(&(session->stream_q.lock), flags2); + list_for_each_entry( + stream, &(session->stream_q.list), list) { + if (stream->vb2_q == q) { + spin_unlock_irqrestore + (&(session->stream_q.lock), flags2); + spin_unlock_irqrestore + (&msm_session_q->lock, flags1); + return session; + } + } + spin_unlock_irqrestore(&(session->stream_q.lock), flags2); + } + spin_unlock_irqrestore(&msm_session_q->lock, flags1); + return NULL; +} +EXPORT_SYMBOL(msm_get_session_from_vb2q); + static struct v4l2_subdev *msm_sd_find(const char *name) { unsigned long flags; diff --git a/drivers/media/platform/msm/camera_v2/msm.h b/drivers/media/platform/msm/camera_v2/msm.h index 6eba37b95df..095a6db0526 100644 --- a/drivers/media/platform/msm/camera_v2/msm.h +++ b/drivers/media/platform/msm/camera_v2/msm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -108,6 +108,7 @@ struct msm_session { struct msm_queue_head stream_q; struct mutex lock; struct mutex close_lock; + rwlock_t stream_rwlock; }; void msm_pm_qos_update_request(int val); @@ -121,10 +122,12 @@ int msm_create_stream(unsigned int session_id, void msm_delete_stream(unsigned int session_id, unsigned int stream_id); int msm_create_command_ack_q(unsigned int session_id, unsigned int stream_id); void msm_delete_command_ack_q(unsigned int session_id, unsigned int stream_id); -struct msm_stream *msm_get_stream(unsigned int session_id, +struct msm_session *msm_get_session(unsigned int session_id); +struct msm_stream *msm_get_stream(struct msm_session *session, unsigned int stream_id); struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id, unsigned int stream_id); struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q); +struct msm_session *msm_get_session_from_vb2q(struct vb2_queue *q); struct msm_session *msm_session_find(unsigned int session_id); #endif /*_MSM_H */ diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c index d90af616b59..18436734f4f 100644 --- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c +++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c @@ -205,8 +205,8 @@ static void msm_buf_mngr_sd_shutdown(struct msm_buf_mngr_device *dev, if (!list_empty(&dev->buf_qhead)) { list_for_each_entry_safe(bufs, save, &dev->buf_qhead, entry) { - pr_info("%s: Delete invalid bufs =%lx, session_id=%u, bufs->ses_id=%d, str_id=%d, idx=%d\n", - __func__, (unsigned long)bufs, session->session, + pr_info("%s: Delete invalid bufs =%pK, session_id=%u, bufs->ses_id=%d, str_id=%d, idx=%d\n", + __func__, (void *)bufs, session->session, bufs->session_id, bufs->stream_id, bufs->vb2_buf->v4l2_buf.index); if (session->session == bufs->session_id) { diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c index 8b756f12b31..63f21097b6e 100644 --- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c +++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -43,16 +43,24 @@ static int msm_vb2_queue_setup(struct vb2_queue *q, int msm_vb2_buf_init(struct vb2_buffer *vb) { struct msm_stream *stream; + struct msm_session *session; struct msm_vb2_buffer *msm_vb2_buf; + session = msm_get_session_from_vb2q(vb->vb2_queue); + if (IS_ERR_OR_NULL(session)) + return -EINVAL; + + read_lock(&session->stream_rwlock); + stream = msm_get_stream_from_vb2q(vb->vb2_queue); if (!stream) { pr_err("%s: Couldn't find stream\n", __func__); + read_unlock(&session->stream_rwlock); return -EINVAL; } msm_vb2_buf = container_of(vb, struct msm_vb2_buffer, vb2_buf); msm_vb2_buf->in_freeq = 0; - + read_unlock(&session->stream_rwlock); return 0; } @@ -60,6 +68,7 @@ static void msm_vb2_buf_queue(struct vb2_buffer *vb) { struct msm_vb2_buffer *msm_vb2; struct msm_stream *stream; + struct msm_session *session; unsigned long flags; msm_vb2 = container_of(vb, struct msm_vb2_buffer, vb2_buf); @@ -69,21 +78,30 @@ static void msm_vb2_buf_queue(struct vb2_buffer *vb) return; } + session = msm_get_session_from_vb2q(vb->vb2_queue); + if (IS_ERR_OR_NULL(session)) + return; + + read_lock(&session->stream_rwlock); + stream = msm_get_stream_from_vb2q(vb->vb2_queue); if (!stream) { pr_err("%s:%d] NULL stream", __func__, __LINE__); + read_unlock(&session->stream_rwlock); return; } spin_lock_irqsave(&stream->stream_lock, flags); list_add_tail(&msm_vb2->list, &stream->queued_list); spin_unlock_irqrestore(&stream->stream_lock, flags); + read_unlock(&session->stream_rwlock); } static int msm_vb2_buf_finish(struct vb2_buffer *vb) { struct msm_vb2_buffer *msm_vb2; struct msm_stream *stream; + struct msm_session *session; unsigned long flags; struct msm_vb2_buffer *msm_vb2_entry, *temp; @@ -94,9 +112,16 @@ static int msm_vb2_buf_finish(struct vb2_buffer *vb) return -EINVAL; } + session = msm_get_session_from_vb2q(vb->vb2_queue); + if (IS_ERR_OR_NULL(session)) + return -EINVAL; + + read_lock(&session->stream_rwlock); + stream = msm_get_stream_from_vb2q(vb->vb2_queue); if (!stream) { pr_err("%s:%d] NULL stream", __func__, __LINE__); + read_unlock(&session->stream_rwlock); return -EINVAL; } @@ -109,6 +134,7 @@ static int msm_vb2_buf_finish(struct vb2_buffer *vb) } } spin_unlock_irqrestore(&stream->stream_lock, flags); + read_unlock(&session->stream_rwlock); return 0; } @@ -116,6 +142,7 @@ static void msm_vb2_buf_cleanup(struct vb2_buffer *vb) { struct msm_vb2_buffer *msm_vb2; struct msm_stream *stream; + struct msm_session *session; unsigned long flags; msm_vb2 = container_of(vb, struct msm_vb2_buffer, vb2_buf); @@ -125,17 +152,43 @@ static void msm_vb2_buf_cleanup(struct vb2_buffer *vb) return; } + session = msm_get_session_from_vb2q(vb->vb2_queue); + if (IS_ERR_OR_NULL(session)) + return; + + read_lock(&session->stream_rwlock); + stream = msm_get_stream_from_vb2q(vb->vb2_queue); if (!stream) { - pr_err_ratelimited("%s:%d] NULL stream", __func__, __LINE__); + pr_err("%s:%d] NULL stream", __func__, __LINE__); + read_unlock(&session->stream_rwlock); return; } spin_lock_irqsave(&stream->stream_lock, flags); INIT_LIST_HEAD(&stream->queued_list); spin_unlock_irqrestore(&stream->stream_lock, flags); + read_unlock(&session->stream_rwlock); } +int msm_vb2_get_stream_state(struct msm_stream *stream) +{ + struct msm_vb2_buffer *msm_vb2, *temp; + unsigned long flags; + int rc = 1; + + spin_lock_irqsave(&stream->stream_lock, flags); + list_for_each_entry_safe(msm_vb2, temp, &(stream->queued_list), list) { + if (msm_vb2->in_freeq != 0) { + rc = 0; + break; + } + } + spin_unlock_irqrestore(&stream->stream_lock, flags); + return rc; +} +EXPORT_SYMBOL(msm_vb2_get_stream_state); + static struct vb2_ops msm_vb2_get_q_op = { .queue_setup = msm_vb2_queue_setup, .buf_init = msm_vb2_buf_init, @@ -188,14 +241,23 @@ static struct vb2_buffer *msm_vb2_get_buf(int session_id, unsigned int stream_id) { struct msm_stream *stream; + struct msm_session *session; struct vb2_buffer *vb2_buf = NULL; struct msm_vb2_buffer *msm_vb2 = NULL; unsigned long flags; - stream = msm_get_stream(session_id, stream_id); - if (IS_ERR_OR_NULL(stream)) + session = msm_get_session(session_id); + if (IS_ERR_OR_NULL(session)) return NULL; + read_lock(&session->stream_rwlock); + + stream = msm_get_stream(session, stream_id); + if (IS_ERR_OR_NULL(stream)) { + read_unlock(&session->stream_rwlock); + return NULL; + } + spin_lock_irqsave(&stream->stream_lock, flags); if (!stream->vb2_q) { @@ -218,6 +280,7 @@ static struct vb2_buffer *msm_vb2_get_buf(int session_id, vb2_buf = NULL; end: spin_unlock_irqrestore(&stream->stream_lock, flags); + read_unlock(&session->stream_rwlock); return vb2_buf; } @@ -225,13 +288,23 @@ static int msm_vb2_put_buf(struct vb2_buffer *vb, int session_id, unsigned int stream_id) { struct msm_stream *stream; + struct msm_session *session; struct msm_vb2_buffer *msm_vb2; struct vb2_buffer *vb2_buf = NULL; int rc = 0; unsigned long flags; - stream = msm_get_stream(session_id, stream_id); - if (IS_ERR_OR_NULL(stream)) + + session = msm_get_session(session_id); + if (IS_ERR_OR_NULL(session)) + return -EINVAL; + + read_lock(&session->stream_rwlock); + + stream = msm_get_stream(session, stream_id); + if (IS_ERR_OR_NULL(stream)) { + read_unlock(&session->stream_rwlock); return -EINVAL; + } spin_lock_irqsave(&stream->stream_lock, flags); if (vb) { @@ -244,6 +317,7 @@ static int msm_vb2_put_buf(struct vb2_buffer *vb, int session_id, pr_err("VB buffer is INVALID vb=%pK, ses_id=%d, str_id=%d\n", vb, session_id, stream_id); spin_unlock_irqrestore(&stream->stream_lock, flags); + read_unlock(&session->stream_rwlock); return -EINVAL; } msm_vb2 = @@ -259,6 +333,7 @@ static int msm_vb2_put_buf(struct vb2_buffer *vb, int session_id, rc = -EINVAL; } spin_unlock_irqrestore(&stream->stream_lock, flags); + read_unlock(&session->stream_rwlock); return rc; } @@ -268,12 +343,22 @@ static int msm_vb2_buf_done(struct vb2_buffer *vb, int session_id, unsigned long flags; struct msm_vb2_buffer *msm_vb2; struct msm_stream *stream; + struct msm_session *session; struct vb2_buffer *vb2_buf = NULL; int rc = 0; - stream = msm_get_stream(session_id, stream_id); - if (IS_ERR_OR_NULL(stream)) + session = msm_get_session(session_id); + if (IS_ERR_OR_NULL(session)) + return 0; + + read_lock(&session->stream_rwlock); + + stream = msm_get_stream(session, stream_id); + if (IS_ERR_OR_NULL(stream)) { + read_unlock(&session->stream_rwlock); return -EINVAL; + } + spin_lock_irqsave(&stream->stream_lock, flags); if (vb) { list_for_each_entry(msm_vb2, &(stream->queued_list), list) { @@ -285,6 +370,7 @@ static int msm_vb2_buf_done(struct vb2_buffer *vb, int session_id, pr_err("VB buffer is INVALID ses_id=%d, str_id=%d, vb=%pK\n", session_id, stream_id, vb); spin_unlock_irqrestore(&stream->stream_lock, flags); + read_unlock(&session->stream_rwlock); return -EINVAL; } msm_vb2 = @@ -302,6 +388,7 @@ static int msm_vb2_buf_done(struct vb2_buffer *vb, int session_id, rc = -EINVAL; } spin_unlock_irqrestore(&stream->stream_lock, flags); + read_unlock(&session->stream_rwlock); return rc; } @@ -309,12 +396,22 @@ static int msm_vb2_flush_buf(int session_id, unsigned int stream_id) { unsigned long flags; struct msm_vb2_buffer *msm_vb2; + struct msm_session *session; struct msm_stream *stream; struct vb2_buffer *vb2_buf = NULL; - stream = msm_get_stream(session_id, stream_id); - if (IS_ERR_OR_NULL(stream)) + session = msm_get_session(session_id); + if (IS_ERR_OR_NULL(session)) return -EINVAL; + + read_lock(&session->stream_rwlock); + + stream = msm_get_stream(session, stream_id); + if (IS_ERR_OR_NULL(stream)) { + read_unlock(&session->stream_rwlock); + return -EINVAL; + } + spin_lock_irqsave(&stream->stream_lock, flags); list_for_each_entry(msm_vb2, &(stream->queued_list), list) { vb2_buf = &(msm_vb2->vb2_buf); @@ -323,6 +420,7 @@ static int msm_vb2_flush_buf(int session_id, unsigned int stream_id) msm_vb2->in_freeq = 0; } spin_unlock_irqrestore(&stream->stream_lock, flags); + read_unlock(&session->stream_rwlock); return 0; } @@ -342,4 +440,3 @@ int msm_vb2_request_cb(struct msm_sd_req_vb2_q *req) return 0; } - diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h index 7082f8583d1..b04d31b1e44 100644 --- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h +++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -66,5 +66,6 @@ struct msm_stream { struct vb2_ops *msm_vb2_get_q_ops(void); struct vb2_mem_ops *msm_vb2_get_q_mem_ops(void); int msm_vb2_request_cb(struct msm_sd_req_vb2_q *req_sd); +int msm_vb2_get_stream_state(struct msm_stream *stream); #endif /*_MSM_VB_H */ diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c index 5af2eafb122..742401b7814 100644..100755 --- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c +++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014,2016-2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -17,7 +17,8 @@ #undef CDBG #define CDBG(fmt, args...) pr_debug(fmt, ##args) #define S_I2C_DBG(fmt, args...) pr_debug(fmt, ##args) - +#define MAX_I2C_ADDR_TYPE_SIZE (MSM_CAMERA_I2C_3B_ADDR + 1) +#define MAX_I2C_DATA_TYPE_SIZE (MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA + 1) #define I2C_COMPARE_MATCH 0 #define I2C_COMPARE_MISMATCH 1 #define I2C_POLL_MAX_ITERATION 20 @@ -27,7 +28,7 @@ int32_t msm_camera_cci_i2c_read(struct msm_camera_i2c_client *client, enum msm_camera_i2c_data_type data_type) { int32_t rc = -EFAULT; - unsigned char buf[client->addr_type+data_type]; + unsigned char buf[MAX_I2C_ADDR_TYPE_SIZE + MAX_I2C_DATA_TYPE_SIZE]; struct msm_camera_cci_ctrl cci_ctrl; if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c index f96cae163de..bf0ebfd9936 100755 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015,2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -103,7 +103,11 @@ static int32_t msm_sensor_driver_create_i2c_v4l_subdev s_ctrl->msm_sd.sd.entity.name = s_ctrl->msm_sd.sd.name; s_ctrl->sensordata->sensor_info->session_id = session_id; s_ctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x3; - msm_sd_register(&s_ctrl->msm_sd); + rc = msm_sd_register(&s_ctrl->msm_sd); + if (rc < 0) { + pr_err("failed: msm_sd_register rc %d", rc); + return rc; + } CDBG("%s:%d\n", __func__, __LINE__); return rc; } @@ -133,7 +137,11 @@ static int32_t msm_sensor_driver_create_v4l_subdev s_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_SENSOR; s_ctrl->msm_sd.sd.entity.name = s_ctrl->msm_sd.sd.name; s_ctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x3; - msm_sd_register(&s_ctrl->msm_sd); + rc = msm_sd_register(&s_ctrl->msm_sd); + if (rc < 0) { + pr_err("failed: msm_sd_register rc %d", rc); + return rc; + } msm_sensor_v4l2_subdev_fops = v4l2_subdev_fops; #ifdef CONFIG_COMPAT msm_sensor_v4l2_subdev_fops.compat_ioctl32 = @@ -927,12 +935,6 @@ CSID_TG: pr_err("%s probe succeeded", slave_info->sensor_name); /* - Set probe succeeded flag to 1 so that no other camera shall - * probed on this slot - */ - s_ctrl->is_probe_succeed = 1; - - /* * Update the subdevice id of flash-src based on availability in kernel. */ if (strlen(slave_info->flash_name) == 0) { @@ -984,6 +986,11 @@ CSID_TG: msm_sensor_fill_sensor_info(s_ctrl, probed_info, entity_name); + /* + * Set probe succeeded flag to 1 so that no other camera shall + * probed on this slot + */ + s_ctrl->is_probe_succeed = 1; return rc; camera_power_down: diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c index 1ec825524a2..5b18bc36742 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c +++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c @@ -427,11 +427,13 @@ static long msm_ois_subdev_ioctl(struct v4l2_subdev *sd, pr_err("o_ctrl->i2c_client.i2c_func_tbl NULL\n"); return -EINVAL; } else { + mutex_lock(o_ctrl->ois_mutex); rc = msm_ois_power_down(o_ctrl); if (rc < 0) { pr_err("%s:%d OIS Power down failed\n", __func__, __LINE__); } + mutex_unlock(o_ctrl->ois_mutex); return msm_ois_close(sd, NULL); } default: @@ -596,6 +598,10 @@ static long msm_ois_subdev_do_ioctl( parg = &ois_data; break; } + break; + case VIDIOC_MSM_OIS_CFG: + pr_err("%s: invalid cmd 0x%x received\n", __func__, cmd); + return -EINVAL; } rc = msm_ois_subdev_ioctl(sd, cmd, parg); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c index 8168dc6b999..43a42661d79 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c @@ -17,7 +17,7 @@ #include "vidc_hfi_api.h" #define MAX_DBG_BUF_SIZE 4096 -int msm_vidc_debug = 0; +int msm_vidc_debug = VIDC_ERR | VIDC_WARN; int msm_vidc_debug_out = VIDC_OUT_PRINTK; int msm_fw_debug = 0x18; int msm_fw_debug_mode = 0x1; diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 72e3fa65248..257bb7a6ff5 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -1530,7 +1530,7 @@ static void imon_incoming_packet(struct imon_context *ictx, if (kc == KEY_KEYBOARD && !ictx->release_code) { ictx->last_keycode = kc; if (!nomouse) { - ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1; + ictx->pad_mouse = !ictx->pad_mouse; dev_dbg(dev, "toggling to %s mode\n", ictx->pad_mouse ? "mouse" : "keyboard"); spin_unlock_irqrestore(&ictx->kc_lock, flags); diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c index 9515f3a68f8..122815e1cb6 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c @@ -123,15 +123,10 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) memset(&tvdata,0,sizeof(tvdata)); eeprom = pvr2_eeprom_fetch(hdw); - if (!eeprom) return -EINVAL; - - { - struct i2c_client fake_client; - /* Newer version expects a useless client interface */ - fake_client.addr = hdw->eeprom_addr; - fake_client.adapter = &hdw->i2c_adap; - tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom); - } + if (!eeprom) + return -EINVAL; + + tveeprom_hauppauge_analog(NULL, &tvdata, eeprom); trace_eeprom("eeprom assumed v4l tveeprom module"); trace_eeprom("eeprom direct call results:"); diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index a6487754b37..8e6b851e755 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -264,7 +264,7 @@ static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_ struct v4l2_standard32 { __u32 index; - compat_u64 id; + __u32 id[2]; /* __u64 would get the alignment wrong */ __u8 name[24]; struct v4l2_fract frameperiod; /* Frames, not fields */ __u32 framelines; @@ -284,7 +284,7 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 { if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || put_user(kp->index, &up->index) || - put_user(kp->id, &up->id) || + copy_to_user(up->id, &kp->id, sizeof(__u64)) || copy_to_user(up->name, kp->name, 24) || copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || put_user(kp->framelines, &up->framelines) || @@ -593,10 +593,10 @@ struct v4l2_input32 { __u32 type; /* Type of input */ __u32 audioset; /* Associated audios (bitfield) */ __u32 tuner; /* Associated tuner */ - compat_u64 std; + v4l2_std_id std; __u32 status; __u32 reserved[4]; -}; +} __attribute__ ((packed)); /* The 64-bit v4l2_input struct has extra padding at the end of the struct. Otherwise it is identical to the 32-bit version. */ @@ -740,7 +740,6 @@ struct v4l2_event32 { struct v4l2_event_ctrl ctrl; struct v4l2_event_frame_sync frame_sync; __u8 data[64]; - compat_s64 value64; } u; __u32 pending; __u32 sequence; diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index c7576a503e5..2afadd00d3f 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -380,8 +380,8 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata) * and use SDR Mode */ reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE - | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); + reg |= OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF; } else if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_HSIC) { /* diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 7d394ca8545..7a997360f3f 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -69,10 +69,9 @@ obj-$(CONFIG_QCOM_LIQUID_DOCK) += qcom_liquid_dock.o obj-y += qcom/ obj-$(CONFIG_USB_EXT_TYPE_C_PERICOM) += type-c-pericom.o obj-$(CONFIG_USB_EXT_TYPE_C_TI) += type-c-ti.o -obj-$(CONFIG_UID_CPUTIME) += uid_cputime.o +obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o obj-$(CONFIG_ALSA_TO_H2W) += alsa-to-h2w-headset.o obj-$(CONFIG_MOT_UTAG) += utag/ obj-$(CONFIG_SENSORS_STML0XX) += stml0xx/ obj-$(CONFIG_DROPBOX) += dropbox.o obj-$(CONFIG_SEC_DRIVER) += sec/ -obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o
\ No newline at end of file diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c index 5484301d57d..3dc61ea7dc6 100644 --- a/drivers/misc/c2port/c2port-duramar2150.c +++ b/drivers/misc/c2port/c2port-duramar2150.c @@ -129,8 +129,8 @@ static int __init duramar2150_c2port_init(void) duramar2150_c2port_dev = c2port_device_register("uc", &duramar2150_c2port_ops, NULL); - if (!duramar2150_c2port_dev) { - ret = -ENODEV; + if (IS_ERR(duramar2150_c2port_dev)) { + ret = PTR_ERR(duramar2150_c2port_dev); goto free_region; } diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c index e7c28a663b6..5543059ab64 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c @@ -17,7 +17,6 @@ #include "q6audio_common.h" #include "audio_utils_aio.h" #include <sound/msm-audio-effects-q6-v2.h> -#include <sound/msm-dts-eagle.h> #define MAX_CHANNELS_SUPPORTED 8 #define WAIT_TIMEDOUT_DURATION_SECS 1 @@ -53,31 +52,11 @@ static void audio_effects_init_pp(struct audio_client *ac) pr_err("%s: audio client null to init pp\n", __func__); return; } - switch (ac->topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_1); - if (ret < 0) - pr_err("%s: Send SoftVolume1 Param failed ret=%d\n", - __func__, ret); - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_2); - if (ret < 0) - pr_err("%s: Send SoftVolume2 Param failed ret=%d\n", - __func__, ret); - - msm_dts_eagle_init_master_module(ac); - - break; - default: - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_1); - if (ret < 0) - pr_err("%s: Send SoftVolume Param failed ret=%d\n", - __func__, ret); - break; - } + ret = q6asm_set_softvolume_v2(ac, &softvol, + SOFT_VOLUME_INSTANCE_1); + if (ret < 0) + pr_err("%s: Send SoftVolume Param failed ret=%d\n", + __func__, ret); } static void audio_effects_deinit_pp(struct audio_client *ac) @@ -86,13 +65,6 @@ static void audio_effects_deinit_pp(struct audio_client *ac) pr_err("%s: audio client null to deinit pp\n", __func__); return; } - switch (ac->topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - msm_dts_eagle_deinit_master_module(ac); - break; - default: - break; - } } static void audio_effects_event_handler(uint32_t opcode, uint32_t token, @@ -428,33 +400,6 @@ static long audio_effects_set_pp_param(struct q6audio_effects *effects, &(effects->audio_effects.topo_switch_vol), (long *)&values[1], SOFT_VOLUME_INSTANCE_2); break; - case DTS_EAGLE_MODULE_ENABLE: - pr_debug("%s: DTS_EAGLE_MODULE_ENABLE\n", __func__); - if (msm_audio_effects_is_effmodule_supp_in_top( - effects_module, effects->ac->topology)) { - /* - * HPX->OFF: first disable HPX and then - * enable SA+ - * HPX->ON: first disable SA+ and then - * enable HPX - */ - bool hpx_state = (bool)values[1]; - if (hpx_state) - msm_audio_effects_enable_extn(effects->ac, - &(effects->audio_effects), - false); - msm_dts_eagle_enable_asm(effects->ac, - hpx_state, - AUDPROC_MODULE_ID_DTS_HPX_PREMIX); - msm_dts_eagle_enable_asm(effects->ac, - hpx_state, - AUDPROC_MODULE_ID_DTS_HPX_POSTMIX); - if (!hpx_state) - msm_audio_effects_enable_extn(effects->ac, - &(effects->audio_effects), - true); - } - break; default: pr_err("%s: Invalid effects config module\n", __func__); rc = -EINVAL; diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c index 066329df584..c8b09e4ff37 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c @@ -1057,6 +1057,8 @@ static int audio_aio_async_write(struct q6audio_aio *audio, struct audio_client *ac; struct audio_aio_write_param param; + memset(¶m, 0, sizeof(param)); + if (!audio || !buf_node) { pr_err("%s NULL pointer audio=[0x%pK], buf_node=[0x%pK]\n", __func__, audio, buf_node); diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index dc78b865a59..2da76ce8274 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -6147,11 +6147,16 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, void *cmd_buf = NULL; size_t cmd_len; struct sglist_info *table = data->sglistinfo_ptr; + void *req_ptr = NULL; + void *resp_ptr = NULL; ret = __qseecom_qteec_validate_msg(data, req); if (ret) return ret; + req_ptr = req->req_ptr; + resp_ptr = req->resp_ptr; + /* find app_id & img_name from list */ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); list_for_each_entry(ptr_app, &qseecom.registered_app_list_head, @@ -6171,6 +6176,11 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, return -ENOENT; } + req->req_ptr = (void *)__qseecom_uvirt_to_kvirt(data, + (uintptr_t)req->req_ptr); + req->resp_ptr = (void *)__qseecom_uvirt_to_kvirt(data, + (uintptr_t)req->resp_ptr); + if ((cmd_id == QSEOS_TEE_OPEN_SESSION) || (cmd_id == QSEOS_TEE_REQUEST_CANCELLATION)) { ret = __qseecom_update_qteec_req_buf( @@ -6182,10 +6192,10 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, if (qseecom.qsee_version < QSEE_VERSION_40) { ireq.app_id = data->client.app_id; ireq.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, - (uintptr_t)req->req_ptr); + (uintptr_t)req_ptr); ireq.req_len = req->req_len; ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, - (uintptr_t)req->resp_ptr); + (uintptr_t)resp_ptr); ireq.resp_len = req->resp_len; ireq.sglistinfo_ptr = (uint32_t)virt_to_phys(table); ireq.sglistinfo_len = SGLISTINFO_TABLE_SIZE; @@ -6196,10 +6206,10 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, } else { ireq_64bit.app_id = data->client.app_id; ireq_64bit.req_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data, - (uintptr_t)req->req_ptr); + (uintptr_t)req_ptr); ireq_64bit.req_len = req->req_len; ireq_64bit.resp_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data, - (uintptr_t)req->resp_ptr); + (uintptr_t)resp_ptr); ireq_64bit.resp_len = req->resp_len; if ((data->client.app_arch == ELFCLASS32) && ((ireq_64bit.req_ptr >= diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c index 3c031f9b0cd..e2d45b4f3bd 100644 --- a/drivers/misc/uid_sys_stats.c +++ b/drivers/misc/uid_sys_stats.c @@ -21,7 +21,6 @@ #include <linux/list.h> #include <linux/proc_fs.h> #include <linux/profile.h> -#include <linux/rtmutex.h> #include <linux/sched.h> #include <linux/seq_file.h> #include <linux/slab.h> @@ -30,27 +29,8 @@ #define UID_HASH_BITS 10 DECLARE_HASHTABLE(hash_table, UID_HASH_BITS); -static DEFINE_RT_MUTEX(uid_lock); -static struct proc_dir_entry *cpu_parent; -static struct proc_dir_entry *io_parent; -static struct proc_dir_entry *proc_parent; - -struct io_stats { - u64 read_bytes; - u64 write_bytes; - u64 rchar; - u64 wchar; - u64 fsync; -}; - -#define UID_STATE_FOREGROUND 0 -#define UID_STATE_BACKGROUND 1 -#define UID_STATE_BUCKET_SIZE 2 - -#define UID_STATE_TOTAL_CURR 2 -#define UID_STATE_TOTAL_LAST 3 -#define UID_STATE_DEAD_TASKS 4 -#define UID_STATE_SIZE 5 +static DEFINE_MUTEX(uid_lock); +static struct proc_dir_entry *parent; struct uid_entry { uid_t uid; @@ -60,8 +40,6 @@ struct uid_entry { cputime_t active_stime; unsigned long long active_power; unsigned long long power; - int state; - struct io_stats io[UID_STATE_SIZE]; struct hlist_node hash; }; @@ -94,7 +72,7 @@ static struct uid_entry *find_or_register_uid(uid_t uid) return uid_entry; } -static int uid_cputime_show(struct seq_file *m, void *v) +static int uid_stat_show(struct seq_file *m, void *v) { struct uid_entry *uid_entry; struct task_struct *task, *temp; @@ -104,7 +82,7 @@ static int uid_cputime_show(struct seq_file *m, void *v) unsigned long bkt; uid_t uid; - rt_mutex_lock(&uid_lock); + mutex_lock(&uid_lock); hash_for_each(hash_table, bkt, uid_entry, hash) { uid_entry->active_stime = 0; @@ -118,7 +96,7 @@ static int uid_cputime_show(struct seq_file *m, void *v) uid_entry = find_or_register_uid(uid); if (!uid_entry) { read_unlock(&tasklist_lock); - rt_mutex_unlock(&uid_lock); + mutex_unlock(&uid_lock); pr_err("%s: failed to find the uid_entry for uid %d\n", __func__, uid); return -ENOMEM; @@ -150,17 +128,17 @@ static int uid_cputime_show(struct seq_file *m, void *v) total_power); } - rt_mutex_unlock(&uid_lock); + mutex_unlock(&uid_lock); return 0; } -static int uid_cputime_open(struct inode *inode, struct file *file) +static int uid_stat_open(struct inode *inode, struct file *file) { - return single_open(file, uid_cputime_show, PDE_DATA(inode)); + return single_open(file, uid_stat_show, PDE_DATA(inode)); } -static const struct file_operations uid_cputime_fops = { - .open = uid_cputime_open, +static const struct file_operations uid_stat_fops = { + .open = uid_stat_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, @@ -197,7 +175,7 @@ static ssize_t uid_remove_write(struct file *file, kstrtol(end_uid, 10, &uid_end) != 0) { return -EINVAL; } - rt_mutex_lock(&uid_lock); + mutex_lock(&uid_lock); for (; uid_start <= uid_end; uid_start++) { hash_for_each_possible_safe(hash_table, uid_entry, tmp, @@ -209,7 +187,7 @@ static ssize_t uid_remove_write(struct file *file, } } - rt_mutex_unlock(&uid_lock); + mutex_unlock(&uid_lock); return count; } @@ -219,213 +197,6 @@ static const struct file_operations uid_remove_fops = { .write = uid_remove_write, }; -static u64 compute_write_bytes(struct task_struct *task) -{ - if (task->ioac.write_bytes <= task->ioac.cancelled_write_bytes) - return 0; - - return task->ioac.write_bytes - task->ioac.cancelled_write_bytes; -} - -static void add_uid_io_stats(struct uid_entry *uid_entry, - struct task_struct *task, int slot) -{ - struct io_stats *io_slot = &uid_entry->io[slot]; - - io_slot->read_bytes += task->ioac.read_bytes; - io_slot->write_bytes += compute_write_bytes(task); - io_slot->rchar += task->ioac.rchar; - io_slot->wchar += task->ioac.wchar; - io_slot->fsync += task->ioac.syscfs; -} - -static void compute_uid_io_bucket_stats(struct io_stats *io_bucket, - struct io_stats *io_curr, - struct io_stats *io_last, - struct io_stats *io_dead) -{ - s64 delta; - - delta = io_curr->read_bytes + io_dead->read_bytes - - io_last->read_bytes; - if (delta > 0) - io_bucket->read_bytes += delta; - - delta = io_curr->write_bytes + io_dead->write_bytes - - io_last->write_bytes; - if (delta > 0) - io_bucket->write_bytes += delta; - - delta = io_curr->rchar + io_dead->rchar - io_last->rchar; - if (delta > 0) - io_bucket->rchar += delta; - - delta = io_curr->wchar + io_dead->wchar - io_last->wchar; - if (delta > 0) - io_bucket->wchar += delta; - - delta = io_curr->fsync + io_dead->fsync - io_last->fsync; - if (delta > 0) - io_bucket->fsync += delta; - - io_last->read_bytes = io_curr->read_bytes; - io_last->write_bytes = io_curr->write_bytes; - io_last->rchar = io_curr->rchar; - io_last->wchar = io_curr->wchar; - io_last->fsync = io_curr->fsync; - - memset(io_dead, 0, sizeof(struct io_stats)); -} - -static void update_io_stats_all_locked(void) -{ - struct uid_entry *uid_entry; - struct task_struct *task, *temp; - struct user_namespace *user_ns = current_user_ns(); - unsigned long bkt; - uid_t uid; - - hash_for_each(hash_table, bkt, uid_entry, hash) - memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0, - sizeof(struct io_stats)); - - rcu_read_lock(); - do_each_thread(temp, task) { - uid = from_kuid_munged(user_ns, task_uid(task)); - uid_entry = find_or_register_uid(uid); - if (!uid_entry) - continue; - add_uid_io_stats(uid_entry, task, UID_STATE_TOTAL_CURR); - } while_each_thread(temp, task); - rcu_read_unlock(); - - hash_for_each(hash_table, bkt, uid_entry, hash) { - compute_uid_io_bucket_stats(&uid_entry->io[uid_entry->state], - &uid_entry->io[UID_STATE_TOTAL_CURR], - &uid_entry->io[UID_STATE_TOTAL_LAST], - &uid_entry->io[UID_STATE_DEAD_TASKS]); - } -} - -static void update_io_stats_uid_locked(struct uid_entry *uid_entry) -{ - struct task_struct *task, *temp; - struct user_namespace *user_ns = current_user_ns(); - - memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0, - sizeof(struct io_stats)); - - rcu_read_lock(); - do_each_thread(temp, task) { - if (from_kuid_munged(user_ns, task_uid(task)) != uid_entry->uid) - continue; - add_uid_io_stats(uid_entry, task, UID_STATE_TOTAL_CURR); - } while_each_thread(temp, task); - rcu_read_unlock(); - - compute_uid_io_bucket_stats(&uid_entry->io[uid_entry->state], - &uid_entry->io[UID_STATE_TOTAL_CURR], - &uid_entry->io[UID_STATE_TOTAL_LAST], - &uid_entry->io[UID_STATE_DEAD_TASKS]); -} - -static int uid_io_show(struct seq_file *m, void *v) -{ - struct uid_entry *uid_entry; - unsigned long bkt; - - rt_mutex_lock(&uid_lock); - - update_io_stats_all_locked(); - - hash_for_each(hash_table, bkt, uid_entry, hash) { - seq_printf(m, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", - uid_entry->uid, - uid_entry->io[UID_STATE_FOREGROUND].rchar, - uid_entry->io[UID_STATE_FOREGROUND].wchar, - uid_entry->io[UID_STATE_FOREGROUND].read_bytes, - uid_entry->io[UID_STATE_FOREGROUND].write_bytes, - uid_entry->io[UID_STATE_BACKGROUND].rchar, - uid_entry->io[UID_STATE_BACKGROUND].wchar, - uid_entry->io[UID_STATE_BACKGROUND].read_bytes, - uid_entry->io[UID_STATE_BACKGROUND].write_bytes, - uid_entry->io[UID_STATE_FOREGROUND].fsync, - uid_entry->io[UID_STATE_BACKGROUND].fsync); - } - - rt_mutex_unlock(&uid_lock); - - return 0; -} - -static int uid_io_open(struct inode *inode, struct file *file) -{ - return single_open(file, uid_io_show, PDE_DATA(inode)); -} - -static const struct file_operations uid_io_fops = { - .open = uid_io_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int uid_procstat_open(struct inode *inode, struct file *file) -{ - return single_open(file, NULL, NULL); -} - -static ssize_t uid_procstat_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos) -{ - struct uid_entry *uid_entry; - uid_t uid; - int argc, state; - char input[128]; - - if (count >= sizeof(input)) - return -EINVAL; - - if (copy_from_user(input, buffer, count)) - return -EFAULT; - - input[count] = '\0'; - - argc = sscanf(input, "%u %d", &uid, &state); - if (argc != 2) - return -EINVAL; - - if (state != UID_STATE_BACKGROUND && state != UID_STATE_FOREGROUND) - return -EINVAL; - - rt_mutex_lock(&uid_lock); - - uid_entry = find_or_register_uid(uid); - if (!uid_entry) { - rt_mutex_unlock(&uid_lock); - return -EINVAL; - } - - if (uid_entry->state == state) { - rt_mutex_unlock(&uid_lock); - return count; - } - - update_io_stats_uid_locked(uid_entry); - - uid_entry->state = state; - - rt_mutex_unlock(&uid_lock); - - return count; -} - -static const struct file_operations uid_procstat_fops = { - .open = uid_procstat_open, - .release = single_release, - .write = uid_procstat_write, -}; - static int process_notifier(struct notifier_block *self, unsigned long cmd, void *v) { @@ -437,7 +208,7 @@ static int process_notifier(struct notifier_block *self, if (!task) return NOTIFY_OK; - rt_mutex_lock(&uid_lock); + mutex_lock(&uid_lock); uid = from_kuid_munged(current_user_ns(), task_uid(task)); uid_entry = find_or_register_uid(uid); if (!uid_entry) { @@ -451,10 +222,8 @@ static int process_notifier(struct notifier_block *self, uid_entry->power += task->cpu_power; task->cpu_power = ULLONG_MAX; - add_uid_io_stats(uid_entry, task, UID_STATE_DEAD_TASKS); - exit: - rt_mutex_unlock(&uid_lock); + mutex_unlock(&uid_lock); return NOTIFY_OK; } @@ -462,51 +231,25 @@ static struct notifier_block process_notifier_block = { .notifier_call = process_notifier, }; -static int __init proc_uid_sys_stats_init(void) +static int __init proc_uid_cputime_init(void) { hash_init(hash_table); - cpu_parent = proc_mkdir("uid_cputime", NULL); - if (!cpu_parent) { - pr_err("%s: failed to create uid_cputime proc entry\n", - __func__); - goto err; + parent = proc_mkdir("uid_cputime", NULL); + if (!parent) { + pr_err("%s: failed to create proc entry\n", __func__); + return -ENOMEM; } - proc_create_data("remove_uid_range", 0222, cpu_parent, - &uid_remove_fops, NULL); - proc_create_data("show_uid_stat", 0444, cpu_parent, - &uid_cputime_fops, NULL); - - io_parent = proc_mkdir("uid_io", NULL); - if (!io_parent) { - pr_err("%s: failed to create uid_io proc entry\n", - __func__); - goto err; - } + proc_create_data("remove_uid_range", S_IWUGO, parent, &uid_remove_fops, + NULL); - proc_create_data("stats", 0444, io_parent, - &uid_io_fops, NULL); - - proc_parent = proc_mkdir("uid_procstat", NULL); - if (!proc_parent) { - pr_err("%s: failed to create uid_procstat proc entry\n", - __func__); - goto err; - } - - proc_create_data("set", 0222, proc_parent, - &uid_procstat_fops, NULL); + proc_create_data("show_uid_stat", S_IRUGO, parent, &uid_stat_fops, + NULL); profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block); return 0; - -err: - remove_proc_subtree("uid_cputime", NULL); - remove_proc_subtree("uid_io", NULL); - remove_proc_subtree("uid_procstat", NULL); - return -ENOMEM; } -early_initcall(proc_uid_sys_stats_init); +early_initcall(proc_uid_cputime_init); diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index a4a86d42275..eab295f0f3a 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -707,12 +707,10 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, goto cmd_done; } -#ifdef CONFIG_MMC_FFU if (idata->ic.opcode == MMC_FFU_INVOKE_OP) { err = mmc_ffu_invoke(card, idata->buf); goto cmd_done; } -#endif cmd.opcode = idata->ic.opcode; cmd.arg = idata->ic.arg; diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index d5455c76061..503f37850fb 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -335,7 +335,7 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv, } cf->can_id = id & ESD_IDMASK; - cf->can_dlc = get_can_dlc(msg->msg.rx.dlc); + cf->can_dlc = get_can_dlc(msg->msg.rx.dlc & ~ESD_RTR); if (id & ESD_EXTID) cf->can_id |= CAN_EFF_FLAG; diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 5409fe876a4..69bc0a0eb42 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -905,10 +905,10 @@ static void korina_restart_task(struct work_struct *work) DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR, &lp->rx_dma_regs->dmasm); - korina_free_ring(dev); - napi_disable(&lp->napi); + korina_free_ring(dev); + if (korina_init(dev) < 0) { printk(KERN_ERR "%s: cannot restart device\n", dev->name); return; @@ -1069,12 +1069,12 @@ static int korina_close(struct net_device *dev) tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR; writel(tmp, &lp->rx_dma_regs->dmasm); - korina_free_ring(dev); - napi_disable(&lp->napi); cancel_work_sync(&lp->restart_task); + korina_free_ring(dev); + free_irq(lp->rx_irq, dev); free_irq(lp->tx_irq, dev); free_irq(lp->ovr_irq, dev); diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c index 31d02649be4..d22482b4974 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -113,8 +113,13 @@ static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem, if (!buf) return -ENOMEM; + if (offset_in_page(buf)) { + dma_free_coherent(dev, PAGE_SIZE << order, + buf, sg_dma_address(mem)); + return -ENOMEM; + } + sg_set_buf(mem, buf, PAGE_SIZE << order); - BUG_ON(mem->offset); sg_dma_len(mem) = PAGE_SIZE << order; return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 3fb2643d05b..8c58001aff1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -511,8 +511,6 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) return -ENOSYS; } - mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz; - dev->caps.hca_core_clock = hca_param.hca_core_clock; memset(&dev_cap, 0, sizeof(dev_cap)); diff --git a/drivers/net/ethernet/msm/msm_rmnet_bam.c b/drivers/net/ethernet/msm/msm_rmnet_bam.c index ace94a472a3..94e25db91ab 100644 --- a/drivers/net/ethernet/msm/msm_rmnet_bam.c +++ b/drivers/net/ethernet/msm/msm_rmnet_bam.c @@ -731,7 +731,7 @@ static int rmnet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; default: - DBG0("[%s] error: rmnet_ioct called for unsupported cmd[%d]", + pr_err("[%s] error: rmnet_ioct called for unsupported cmd[%d]", dev->name, cmd); return -EINVAL; } diff --git a/drivers/net/ethernet/msm/msm_rmnet_smux.c b/drivers/net/ethernet/msm/msm_rmnet_smux.c index b731e77b3b5..3c2cd63ddd0 100644 --- a/drivers/net/ethernet/msm/msm_rmnet_smux.c +++ b/drivers/net/ethernet/msm/msm_rmnet_smux.c @@ -778,7 +778,7 @@ static int rmnet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; default: - DBG0("[%s] error: rmnet_ioct called for unsupported cmd[%d]", + pr_err("[%s] error: rmnet_ioct called for unsupported cmd[%d]", dev->name, cmd); return -EINVAL; } diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c index 10093f0c4c0..00a80587b47 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c @@ -724,7 +724,7 @@ static void ql_build_coredump_seg_header( seg_hdr->cookie = MPI_COREDUMP_COOKIE; seg_hdr->segNum = seg_number; seg_hdr->segSize = seg_size; - memcpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1); + strncpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1); } /* diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index b7268b3dae7..5f5f84ad069 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -398,7 +398,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, * * Return: Total number of bytes received */ -static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) +static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen) { void __iomem *addr; u16 length, proto_type; @@ -438,7 +438,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) /* Check if received ethernet frame is a raw ethernet frame * or an IP packet or an ARP packet */ - if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) { + if (proto_type > ETH_DATA_LEN) { if (proto_type == ETH_P_IP) { length = ((ntohl(in_be32(addr + @@ -446,6 +446,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) & XEL_RPLR_LENGTH_MASK); + length = min_t(u16, length, ETH_DATA_LEN); length += ETH_HLEN + ETH_FCS_LEN; } else if (proto_type == ETH_P_ARP) @@ -458,6 +459,9 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) /* Use the length in the frame, plus the header and trailer */ length = proto_type + ETH_HLEN + ETH_FCS_LEN; + if (WARN_ON(length > maxlen)) + length = maxlen; + /* Read from the EmacLite device */ xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET), data, length); @@ -632,7 +636,7 @@ static void xemaclite_rx_handler(struct net_device *dev) skb_reserve(skb, 2); - len = xemaclite_recv_data(lp, (u8 *) skb->data); + len = xemaclite_recv_data(lp, (u8 *) skb->data, len); if (!len) { dev->stats.rx_errors++; diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 202fe1ff198..b23f36a5b0d 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -656,8 +656,6 @@ static int marvell_read_status(struct phy_device *phydev) if (adv < 0) return adv; - lpa &= adv; - if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) phydev->duplex = DUPLEX_FULL; else diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index db49e0b84dc..bd245c3039e 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -458,7 +458,7 @@ void phy_start_machine(struct phy_device *phydev, { phydev->adjust_state = handler; - queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, HZ); + schedule_delayed_work(&phydev->state_queue, HZ); } /** @@ -519,7 +519,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat) disable_irq_nosync(irq); atomic_inc(&phydev->irq_disable); - queue_work(system_power_efficient_wq, &phydev->phy_queue); + schedule_work(&phydev->phy_queue); return IRQ_HANDLED; } @@ -674,7 +674,7 @@ static void phy_change(struct work_struct *work) /* reschedule state queue work to run as soon as possible */ cancel_delayed_work_sync(&phydev->state_queue); - queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, 0); + schedule_delayed_work(&phydev->state_queue, 0); return; @@ -937,8 +937,7 @@ void phy_state_machine(struct work_struct *work) if (err < 0) phy_error(phydev); - queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, - PHY_STATE_TIME * HZ); + schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ); } static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad, diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 5225d4321e7..0a3ad7ba2be 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2121,8 +2121,10 @@ start_again: hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI, TEAM_CMD_OPTIONS_GET); - if (!hdr) + if (!hdr) { + nlmsg_free(skb); return -EMSGSIZE; + } if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; @@ -2389,8 +2391,10 @@ start_again: hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI, TEAM_CMD_PORT_LIST_GET); - if (!hdr) + if (!hdr) { + nlmsg_free(skb); return -EMSGSIZE; + } if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c index bb43dec6bd1..8e82c147916 100644 --- a/drivers/net/wireless/cnss/cnss_pci.c +++ b/drivers/net/wireless/cnss/cnss_pci.c @@ -149,7 +149,6 @@ static DEFINE_SPINLOCK(pci_link_down_lock); #define FW_IMAGE_MISSION (0x02) #define FW_IMAGE_BDATA (0x03) #define FW_IMAGE_PRINT (0x04) -#define FW_SETUP_DELAY 2000 #define SEG_METADATA (0x01) #define SEG_NON_PAGED (0x02) @@ -270,10 +269,8 @@ static struct cnss_data { u32 fw_dma_size; u32 fw_seg_count; struct segment_memory fw_seg_mem[MAX_NUM_OF_SEGMENTS]; - atomic_t fw_store_in_progress; /* Firmware setup complete lock */ struct mutex fw_setup_stat_lock; - struct completion fw_setup_complete; void *bdata_cpu; dma_addr_t bdata_dma; u32 bdata_dma_size; @@ -1187,15 +1184,6 @@ int cnss_get_fw_image(struct image_desc_info *image_desc_info) !penv->fw_seg_count || !penv->bdata_seg_count) return -EINVAL; - /* Check for firmware setup trigger by usersapce is in progress - * and wait for complition of firmware setup. - */ - - if (atomic_read(&penv->fw_store_in_progress)) { - wait_for_completion_timeout(&penv->fw_setup_complete, - msecs_to_jiffies(FW_SETUP_DELAY)); - } - mutex_lock(&penv->fw_setup_stat_lock); image_desc_info->fw_addr = penv->fw_dma; image_desc_info->fw_size = penv->fw_dma_size; @@ -1293,7 +1281,9 @@ static int cnss_wlan_pci_probe(struct pci_dev *pdev, goto err_pcie_suspend; } + mutex_lock(&penv->fw_setup_stat_lock); cnss_wlan_fw_mem_alloc(pdev); + mutex_unlock(&penv->fw_setup_stat_lock); ret = device_create_file(&penv->pldev->dev, &dev_attr_wlan_setup); @@ -1546,17 +1536,11 @@ static ssize_t fw_image_setup_store(struct device *dev, if (!penv) return -ENODEV; - if (atomic_read(&penv->fw_store_in_progress)) { - pr_info("%s: Firmware setup in progress\n", __func__); - return 0; - } - - atomic_set(&penv->fw_store_in_progress, 1); - init_completion(&penv->fw_setup_complete); + mutex_lock(&penv->fw_setup_stat_lock); + pr_info("%s: Firmware setup in progress\n", __func__); if (kstrtoint(buf, 0, &val)) { - atomic_set(&penv->fw_store_in_progress, 0); - complete(&penv->fw_setup_complete); + mutex_unlock(&penv->fw_setup_stat_lock); return -EINVAL; } @@ -1567,8 +1551,7 @@ static ssize_t fw_image_setup_store(struct device *dev, if (ret != 0) { pr_err("%s: Invalid parsing of FW image files %d", __func__, ret); - atomic_set(&penv->fw_store_in_progress, 0); - complete(&penv->fw_setup_complete); + mutex_unlock(&penv->fw_setup_stat_lock); return -EINVAL; } penv->fw_image_setup = val; @@ -1578,9 +1561,8 @@ static ssize_t fw_image_setup_store(struct device *dev, penv->bmi_test = val; } - atomic_set(&penv->fw_store_in_progress, 0); - complete(&penv->fw_setup_complete); - + pr_info("%s: Firmware setup completed\n", __func__); + mutex_unlock(&penv->fw_setup_stat_lock); return count; } @@ -1665,17 +1647,21 @@ int cnss_get_codeswap_struct(struct codeswap_codeseg_info *swap_seg) { struct codeswap_codeseg_info *cnss_seg_info = penv->cnss_seg_info; + mutex_lock(&penv->fw_setup_stat_lock); if (!cnss_seg_info) { swap_seg = NULL; + mutex_unlock(&penv->fw_setup_stat_lock); return -ENOENT; } if (!atomic_read(&penv->fw_available)) { pr_debug("%s: fw is not available\n", __func__); + mutex_unlock(&penv->fw_setup_stat_lock); return -ENOENT; } *swap_seg = *cnss_seg_info; + mutex_unlock(&penv->fw_setup_stat_lock); return 0; } @@ -1694,15 +1680,6 @@ static void cnss_wlan_memory_expansion(void) u_int32_t total_length = 0; struct pci_dev *pdev; - /* Check for firmware setup trigger by usersapce is in progress - * and wait for complition of firmware setup. - */ - - if (atomic_read(&penv->fw_store_in_progress)) { - wait_for_completion_timeout(&penv->fw_setup_complete, - msecs_to_jiffies(FW_SETUP_DELAY)); - } - mutex_lock(&penv->fw_setup_stat_lock); pdev = penv->pdev; dev = &pdev->dev; @@ -2447,6 +2424,7 @@ static int cnss_probe(struct platform_device *pdev) penv->vreg_info.wlan_reg = NULL; penv->vreg_info.state = VREG_OFF; penv->pci_register_again = false; + mutex_init(&penv->fw_setup_stat_lock); ret = cnss_wlan_get_resources(pdev); if (ret) @@ -2602,8 +2580,6 @@ skip_ramdump: memset(phys_to_virt(0), 0, SZ_4K); #endif - atomic_set(&penv->fw_store_in_progress, 0); - mutex_init(&penv->fw_setup_stat_lock); ret = device_create_file(dev, &dev_attr_fw_image_setup); if (ret) { pr_err("cnss: fw_image_setup sys file creation failed\n"); diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c index ca9ff0ac711..59615c4c847 100644 --- a/drivers/platform/msm/ipa/ipa.c +++ b/drivers/platform/msm/ipa/ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/drivers/platform/msm/ipa/ipa_flt.c b/drivers/platform/msm/ipa/ipa_flt.c index b179737c318..4e2119b9715 100644 --- a/drivers/platform/msm/ipa/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_flt.c @@ -1023,7 +1023,7 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, goto error; } - if (rt_tbl->cookie != IPA_COOKIE) { + if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) { IPAERR("RT table cookie is invalid\n"); goto error; } @@ -1044,7 +1044,7 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, } INIT_LIST_HEAD(&entry->link); entry->rule = *rule; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_FLT_COOKIE; entry->rt_tbl = rt_tbl; entry->tbl = tbl; if (add_rear) { @@ -1063,13 +1063,19 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } *rule_hdl = id; entry->id = id; IPADBG("add flt rule rule_cnt=%d\n", tbl->rule_cnt); return 0; - +ipa_insert_failed: + tbl->rule_cnt--; + if (entry->rt_tbl) + entry->rt_tbl->ref_cnt--; + list_del(&entry->link); + kmem_cache_free(ipa_ctx->flt_rule_cache, entry); error: return -EPERM; } @@ -1085,7 +1091,7 @@ static int __ipa_del_flt_rule(u32 rule_hdl) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_FLT_COOKIE) { IPAERR("bad params\n"); return -EINVAL; } @@ -1117,7 +1123,7 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, goto error; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_FLT_COOKIE) { IPAERR("bad params\n"); goto error; } @@ -1138,7 +1144,7 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, goto error; } - if (rt_tbl->cookie != IPA_COOKIE) { + if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) { IPAERR("RT table cookie is invalid\n"); goto error; } diff --git a/drivers/platform/msm/ipa/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_hdr.c index f4cd470d22a..f0614e323c2 100644 --- a/drivers/platform/msm/ipa/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_hdr.c @@ -480,7 +480,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, { struct ipa_hdr_entry *hdr_entry; struct ipa_hdr_proc_ctx_entry *entry; - struct ipa_hdr_proc_ctx_offset_entry *offset; + struct ipa_hdr_proc_ctx_offset_entry *offset = NULL; u32 bin; struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl; int id; @@ -495,7 +495,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, } hdr_entry = ipa_id_find(proc_ctx->hdr_hdl); - if (!hdr_entry || (hdr_entry->cookie != IPA_COOKIE)) { + if (!hdr_entry || (hdr_entry->cookie != IPA_HDR_COOKIE)) { IPAERR("hdr_hdl is invalid\n"); return -EINVAL; } @@ -512,7 +512,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, entry->hdr = hdr_entry; if (add_ref_hdr) hdr_entry->ref_cnt++; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_PROC_HDR_COOKIE; needed_len = (proc_ctx->type == IPA_HDR_PROC_NONE) ? sizeof(struct ipa_hdr_proc_ctx_add_hdr_seq) : @@ -564,6 +564,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; proc_ctx->proc_ctx_hdl = id; @@ -571,6 +572,13 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, return 0; +ipa_insert_failed: + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + list_del(&entry->link); + htbl->proc_ctx_cnt--; bad_len: hdr_entry->ref_cnt--; entry->cookie = 0; @@ -582,7 +590,7 @@ bad_len: static int __ipa_add_hdr(struct ipa_hdr_add *hdr) { struct ipa_hdr_entry *entry; - struct ipa_hdr_offset_entry *offset; + struct ipa_hdr_offset_entry *offset = NULL; u32 bin; struct ipa_hdr_tbl *htbl = &ipa_ctx->hdr_tbl; int id; @@ -613,7 +621,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) entry->type = hdr->type; entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid; entry->eth2_ofst = hdr->eth2_ofst; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_HDR_COOKIE; if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0]) bin = IPA_HDR_BIN0; @@ -696,6 +704,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; hdr->hdr_hdl = id; @@ -720,10 +729,19 @@ fail_add_proc_ctx: entry->ref_cnt--; hdr->hdr_hdl = 0; ipa_id_remove(id); +ipa_insert_failed: + if (entry->is_hdr_proc_ctx) { + dma_unmap_single(ipa_ctx->pdev, entry->phys_base, + entry->hdr_len, DMA_TO_DEVICE); + } else { + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + } + htbl->hdr_cnt--; list_del(&entry->link); - dma_unmap_single(ipa_ctx->pdev, entry->phys_base, - entry->hdr_len, DMA_TO_DEVICE); bad_hdr_len: entry->cookie = 0; kmem_cache_free(ipa_ctx->hdr_cache, entry); @@ -738,7 +756,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl; entry = ipa_id_find(proc_ctx_hdl); - if (!entry || (entry->cookie != IPA_COOKIE)) { + if (!entry || (entry->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("bad parm\n"); return -EINVAL; } @@ -789,7 +807,7 @@ int __ipa_del_hdr(u32 hdr_hdl, bool by_user) return -EINVAL; } - if (!entry || (entry->cookie != IPA_COOKIE)) { + if (!entry || (entry->cookie != IPA_HDR_COOKIE)) { IPAERR("bad parm\n"); return -EINVAL; } @@ -1354,7 +1372,7 @@ int ipa_put_hdr(u32 hdr_hdl) goto bail; } - if (entry == NULL || entry->cookie != IPA_COOKIE) { + if (entry == NULL || entry->cookie != IPA_HDR_COOKIE) { IPAERR("bad params\n"); result = -EINVAL; goto bail; diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h index 2ea952c8bd8..0d12d17dcb4 100644 --- a/drivers/platform/msm/ipa/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_i.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -33,6 +33,12 @@ #define DRV_NAME "ipa" #define NAT_DEV_NAME "ipaNatTable" #define IPA_COOKIE 0x57831603 +#define IPA_RT_RULE_COOKIE 0x57831604 +#define IPA_RT_TBL_COOKIE 0x57831605 +#define IPA_FLT_COOKIE 0x57831606 +#define IPA_HDR_COOKIE 0x57831607 +#define IPA_PROC_HDR_COOKIE 0x57831608 + #define MTU_BYTE 1500 #define IPA_MAX_NUM_PIPES 0x14 @@ -183,8 +189,8 @@ struct ipa_mem_buffer { */ struct ipa_flt_entry { struct list_head link; - struct ipa_flt_rule rule; u32 cookie; + struct ipa_flt_rule rule; struct ipa_flt_tbl *tbl; struct ipa_rt_tbl *rt_tbl; u32 hw_len; @@ -209,13 +215,13 @@ struct ipa_flt_entry { */ struct ipa_rt_tbl { struct list_head link; + u32 cookie; struct list_head head_rt_rule_list; char name[IPA_RESOURCE_NAME_MAX]; u32 idx; u32 rule_cnt; u32 ref_cnt; struct ipa_rt_tbl_set *set; - u32 cookie; bool in_sys; u32 sz; struct ipa_mem_buffer curr_mem; @@ -246,6 +252,7 @@ struct ipa_rt_tbl { */ struct ipa_hdr_entry { struct list_head link; + u32 cookie; u8 hdr[IPA_HDR_MAX_SIZE]; u32 hdr_len; char name[IPA_RESOURCE_NAME_MAX]; @@ -255,7 +262,6 @@ struct ipa_hdr_entry { dma_addr_t phys_base; struct ipa_hdr_proc_ctx_entry *proc_ctx; struct ipa_hdr_offset_entry *offset_entry; - u32 cookie; u32 ref_cnt; int id; u8 is_eth2_ofst_valid; @@ -340,10 +346,10 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq { */ struct ipa_hdr_proc_ctx_entry { struct list_head link; + u32 cookie; enum ipa_hdr_proc_type type; struct ipa_hdr_proc_ctx_offset_entry *offset_entry; struct ipa_hdr_entry *hdr; - u32 cookie; u32 ref_cnt; int id; bool user_deleted; @@ -399,8 +405,8 @@ struct ipa_flt_tbl { */ struct ipa_rt_entry { struct list_head link; - struct ipa_rt_rule rule; u32 cookie; + struct ipa_rt_rule rule; struct ipa_rt_tbl *tbl; struct ipa_hdr_entry *hdr; struct ipa_hdr_proc_ctx_entry *proc_ctx; diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c index 87a88dc6aaa..e5786ffa270 100644 --- a/drivers/platform/msm/ipa/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_rt.c @@ -880,7 +880,7 @@ static struct ipa_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, INIT_LIST_HEAD(&entry->link); strlcpy(entry->name, name, IPA_RESOURCE_NAME_MAX); entry->set = set; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_RT_TBL_COOKIE; entry->in_sys = (ip == IPA_IP_v4) ? !ipa_ctx->ip4_rt_tbl_lcl : !ipa_ctx->ip6_rt_tbl_lcl; set->tbl_cnt++; @@ -893,12 +893,16 @@ static struct ipa_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; } return entry; +ipa_insert_failed: + set->tbl_cnt--; + list_del(&entry->link); fail_rt_idx_alloc: entry->cookie = 0; kmem_cache_free(ipa_ctx->rt_tbl_cache, entry); @@ -911,7 +915,7 @@ static int __ipa_del_rt_tbl(struct ipa_rt_tbl *entry) enum ipa_ip_type ip = IPA_IP_MAX; u32 id; - if (entry == NULL || (entry->cookie != IPA_COOKIE)) { + if (entry == NULL || (entry->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("bad parms\n"); return -EINVAL; } @@ -925,8 +929,10 @@ static int __ipa_del_rt_tbl(struct ipa_rt_tbl *entry) ip = IPA_IP_v4; else if (entry->set == &ipa_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + return -EPERM; + } if (!entry->in_sys) { list_del(&entry->link); @@ -965,13 +971,14 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, if (rule->hdr_hdl) { hdr = ipa_id_find(rule->hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_COOKIE)) { + if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); goto error; } } else if (rule->hdr_proc_ctx_hdl) { proc_ctx = ipa_id_find(rule->hdr_proc_ctx_hdl); - if ((proc_ctx == NULL) || (proc_ctx->cookie != IPA_COOKIE)) { + if ((proc_ctx == NULL) || + (proc_ctx->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("rt rule does not point to valid proc ctx\n"); goto error; } @@ -979,7 +986,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, tbl = __ipa_add_rt_tbl(ip, name); - if (tbl == NULL || (tbl->cookie != IPA_COOKIE)) { + if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("bad params\n"); goto error; } @@ -1000,7 +1007,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, goto error; } INIT_LIST_HEAD(&entry->link); - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_RT_RULE_COOKIE; entry->rule = *rule; entry->tbl = tbl; entry->hdr = hdr; @@ -1090,7 +1097,7 @@ int __ipa_del_rt_rule(u32 rule_hdl) return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_RT_RULE_COOKIE) { IPAERR("bad params\n"); return -EINVAL; } @@ -1328,7 +1335,7 @@ int ipa_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup) } mutex_lock(&ipa_ctx->lock); entry = __ipa_find_rt_tbl(lookup->ip, lookup->name); - if (entry && entry->cookie == IPA_COOKIE) { + if (entry && entry->cookie == IPA_RT_TBL_COOKIE) { entry->ref_cnt++; lookup->hdl = entry->id; @@ -1366,7 +1373,7 @@ int ipa_put_rt_tbl(u32 rt_tbl_hdl) goto ret; } - if ((entry->cookie != IPA_COOKIE) || entry->ref_cnt == 0) { + if ((entry->cookie != IPA_RT_TBL_COOKIE) || entry->ref_cnt == 0) { IPAERR("bad parms\n"); result = -EINVAL; goto ret; @@ -1376,8 +1383,11 @@ int ipa_put_rt_tbl(u32 rt_tbl_hdl) ip = IPA_IP_v4; else if (entry->set == &ipa_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + result = -EINVAL; + goto ret; + } entry->ref_cnt--; if (entry->ref_cnt == 0 && entry->rule_cnt == 0) { @@ -1405,7 +1415,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) if (rtrule->rule.hdr_hdl) { hdr = ipa_id_find(rtrule->rule.hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_COOKIE)) { + if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); goto error; } @@ -1417,7 +1427,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) goto error; } - if (entry->cookie != IPA_COOKIE) { + if (entry->cookie != IPA_RT_RULE_COOKIE) { IPAERR("bad params\n"); goto error; } diff --git a/drivers/platform/msm/ipa/rmnet_ipa.c b/drivers/platform/msm/ipa/rmnet_ipa.c index 7d3b5554f6e..d7f4b043d50 100644 --- a/drivers/platform/msm/ipa/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/rmnet_ipa.c @@ -68,6 +68,7 @@ static void *subsys_notify_handle; u32 apps_to_ipa_hdl, ipa_to_apps_hdl; /* get handler from ipa */ static struct mutex ipa_to_apps_pipe_handle_guard; +static struct mutex add_mux_channel_lock; static int wwan_add_ul_flt_rule_to_ipa(void); static int wwan_del_ul_flt_rule_to_ipa(void); static void ipa_wwan_msg_free_cb(void*, u32, u32); @@ -1345,9 +1346,11 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) rmnet_mux_val.mux_id); return rc; } + mutex_lock(&add_mux_channel_lock); if (rmnet_index >= MAX_NUM_OF_MUX_CHANNEL) { IPAWANERR("Exceed mux_channel limit(%d)\n", rmnet_index); + mutex_unlock(&add_mux_channel_lock); return -EFAULT; } IPAWANDBG("ADD_MUX_CHANNEL(%d, name: %s)\n", @@ -1375,6 +1378,7 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) IPAWANERR("device %s reg IPA failed\n", extend_ioctl_data.u. rmnet_mux_val.vchannel_name); + mutex_unlock(&add_mux_channel_lock); return -ENODEV; } mux_channel[rmnet_index].mux_channel_set = true; @@ -1387,6 +1391,7 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) mux_channel[rmnet_index].ul_flt_reg = false; } rmnet_index++; + mutex_unlock(&add_mux_channel_lock); break; case RMNET_IOCTL_SET_EGRESS_DATA_FORMAT: IPAWANDBG("get RMNET_IOCTL_SET_EGRESS_DATA_FORMAT\n"); @@ -2710,6 +2715,7 @@ static int __init ipa_wwan_init(void) mutex_init(&ipa_to_apps_pipe_handle_guard); ipa_to_apps_hdl = -1; + mutex_init(&add_mux_channel_lock); ipa_qmi_init(); @@ -2720,19 +2726,21 @@ static int __init ipa_wwan_init(void) return platform_driver_register(&rmnet_ipa_driver); else return (int)PTR_ERR(subsys_notify_handle); - } +} static void __exit ipa_wwan_cleanup(void) { int ret; ipa_qmi_cleanup(); mutex_destroy(&ipa_to_apps_pipe_handle_guard); + mutex_destroy(&add_mux_channel_lock); ret = subsys_notif_unregister_notifier(subsys_notify_handle, &ssr_notifier); if (ret) IPAWANERR( "Error subsys_notif_unregister_notifier system %s, ret=%d\n", SUBSYS_MODEM, ret); + platform_driver_unregister(&rmnet_ipa_driver); } diff --git a/drivers/platform/msm/mhi/mhi_sys.c b/drivers/platform/msm/mhi/mhi_sys.c index d57ac8c0e21..9603b6a91db 100644 --- a/drivers/platform/msm/mhi/mhi_sys.c +++ b/drivers/platform/msm/mhi/mhi_sys.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -188,22 +188,6 @@ static const struct file_operations mhi_dbgfs_ev_fops = { .write = NULL, }; -static ssize_t mhi_dbgfs_trigger_msi(struct file *fp, const char __user *buf, - size_t count, loff_t *offp) -{ - u32 msi_nr = 0; - void *irq_ctxt = &((mhi_devices.device_list[0]).pcie_device->dev); - if (copy_from_user(&msi_nr, buf, sizeof(msi_nr))) - return -ENOMEM; - mhi_msi_handlr(msi_nr, irq_ctxt); - return 0; -} - -static const struct file_operations mhi_dbgfs_trigger_msi_fops = { - .read = NULL, - .write = mhi_dbgfs_trigger_msi, -}; - static ssize_t mhi_dbgfs_state_read(struct file *fp, char __user *buf, size_t count, loff_t *offp) { @@ -303,7 +287,6 @@ int mhi_init_debugfs(struct mhi_device_ctxt *mhi_dev_ctxt) { struct dentry *mhi_chan_stats; struct dentry *mhi_state_stats; - struct dentry *mhi_msi_trigger; struct dentry *mhi_ev_stats; mhi_dev_ctxt->mhi_parent_folder = debugfs_create_dir("mhi", NULL); @@ -332,21 +315,12 @@ int mhi_init_debugfs(struct mhi_device_ctxt *mhi_dev_ctxt) &mhi_dbgfs_state_fops); if (mhi_state_stats == NULL) goto clean_ev_stats; - mhi_msi_trigger = debugfs_create_file("mhi_msi_trigger", - 0444, - mhi_dev_ctxt->mhi_parent_folder, - mhi_dev_ctxt, - &mhi_dbgfs_trigger_msi_fops); - if (mhi_msi_trigger == NULL) - goto clean_state; mhi_dev_ctxt->chan_info = kmalloc(MHI_LOG_SIZE, GFP_KERNEL); if (mhi_dev_ctxt->chan_info == NULL) goto clean_all; return 0; clean_all: - debugfs_remove(mhi_msi_trigger); -clean_state: debugfs_remove(mhi_state_stats); clean_ev_stats: debugfs_remove(mhi_ev_stats); diff --git a/drivers/platform/msm/msm_bus/msm_bus_dbg.c b/drivers/platform/msm/msm_bus/msm_bus_dbg.c index d7d2ff384ad..df3d39e51b4 100644 --- a/drivers/platform/msm/msm_bus/msm_bus_dbg.c +++ b/drivers/platform/msm/msm_bus/msm_bus_dbg.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, 2014-2015, The Linux Foundation. All rights +/* Copyright (c) 2010-2012, 2014-2015, 2017 The Linux Foundation. All rights * reserved. * * This program is free software; you can redistribute it and/or modify @@ -38,7 +38,7 @@ static struct dentry *clients; static struct dentry *dir; static DEFINE_MUTEX(msm_bus_dbg_fablist_lock); -static DEFINE_MUTEX(cl_list_lock); +static DEFINE_RT_MUTEX(msm_bus_dbg_cllist_lock); struct msm_bus_dbg_state { uint32_t cl; uint8_t enable; @@ -285,14 +285,14 @@ DEFINE_SIMPLE_ATTRIBUTE(shell_client_en_fops, msm_bus_dbg_en_get, static ssize_t client_data_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - ssize_t ret; int bsize = 0; uint32_t cl = (uint32_t)(uintptr_t)file->private_data; struct msm_bus_cldata *cldata = NULL; const struct msm_bus_client_handle *handle = file->private_data; int found = 0; + ssize_t ret; - mutex_lock(&cl_list_lock); + rt_mutex_lock(&msm_bus_dbg_cllist_lock); list_for_each_entry(cldata, &cl_list, list) { if ((cldata->clid == cl) || (cldata->handle && (cldata->handle == handle))) { @@ -302,14 +302,15 @@ static ssize_t client_data_read(struct file *file, char __user *buf, } if (!found) { - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); return 0; } bsize = cldata->size; ret = simple_read_from_buffer(buf, count, ppos, cldata->buffer, bsize); - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return ret; } @@ -339,16 +340,16 @@ int msm_bus_dbg_add_client(const struct msm_bus_client_handle *pdata) { struct msm_bus_cldata *cldata; - mutex_lock(&cl_list_lock); + cldata = kzalloc(sizeof(struct msm_bus_cldata), GFP_KERNEL); if (!cldata) { MSM_BUS_DBG("Failed to allocate memory for client data\n"); - mutex_unlock(&cl_list_lock); return -ENOMEM; } cldata->handle = pdata; + rt_mutex_lock(&msm_bus_dbg_cllist_lock); list_add_tail(&cldata->list, &cl_list); - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); return 0; } @@ -361,7 +362,7 @@ int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata, bool found = false; char *buf = NULL; - mutex_lock(&cl_list_lock); + rt_mutex_lock(&msm_bus_dbg_cllist_lock); list_for_each_entry(cldata, &cl_list, list) { if (cldata->handle == pdata) { found = true; @@ -370,14 +371,14 @@ int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata, } if (!found) { - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); return -ENOENT; } if (cldata->file == NULL) { if (pdata->name == NULL) { MSM_BUS_DBG("Client doesn't have a name\n"); - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); return -EINVAL; } pr_debug("\n%s setting up debugfs %s", __func__, pdata->name); @@ -407,10 +408,11 @@ int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata, i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%llu ", ib); i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n"); cldata->size = i; + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); trace_bus_update_request((int)ts.tv_sec, (int)ts.tv_nsec, pdata->name, pdata->mas, pdata->slv, ab, ib); - mutex_unlock(&cl_list_lock); + return i; } @@ -418,7 +420,7 @@ void msm_bus_dbg_remove_client(const struct msm_bus_client_handle *pdata) { struct msm_bus_cldata *cldata = NULL; - mutex_lock(&cl_list_lock); + rt_mutex_lock(&msm_bus_dbg_cllist_lock); list_for_each_entry(cldata, &cl_list, list) { if (cldata->handle == pdata) { debugfs_remove(cldata->file); @@ -427,7 +429,7 @@ void msm_bus_dbg_remove_client(const struct msm_bus_client_handle *pdata) break; } } - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); } static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata, @@ -435,11 +437,9 @@ static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata, { struct msm_bus_cldata *cldata; - mutex_lock(&cl_list_lock); cldata = kmalloc(sizeof(struct msm_bus_cldata), GFP_KERNEL); if (!cldata) { MSM_BUS_DBG("Failed to allocate memory for client data\n"); - mutex_unlock(&cl_list_lock); return -ENOMEM; } cldata->pdata = pdata; @@ -447,8 +447,9 @@ static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata, cldata->clid = clid; cldata->file = file; cldata->size = 0; + rt_mutex_lock(&msm_bus_dbg_cllist_lock); list_add_tail(&cldata->list, &cl_list); - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); return 0; } @@ -456,7 +457,7 @@ static void msm_bus_dbg_free_client(uint32_t clid) { struct msm_bus_cldata *cldata = NULL; - mutex_lock(&cl_list_lock); + rt_mutex_lock(&msm_bus_dbg_cllist_lock); list_for_each_entry(cldata, &cl_list, list) { if (cldata->clid == clid) { debugfs_remove(cldata->file); @@ -465,7 +466,7 @@ static void msm_bus_dbg_free_client(uint32_t clid) break; } } - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); } static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, @@ -477,7 +478,7 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, struct timespec ts; int found = 0; - mutex_lock(&cl_list_lock); + rt_mutex_lock(&msm_bus_dbg_cllist_lock); list_for_each_entry(cldata, &cl_list, list) { if (cldata->clid == clid) { found = 1; @@ -486,14 +487,14 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, } if (!found) { - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); return -ENOENT; } if (cldata->file == NULL) { if (pdata->name == NULL) { + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); MSM_BUS_DBG("Client doesn't have a name\n"); - mutex_unlock(&cl_list_lock); return -EINVAL; } cldata->file = msm_bus_dbg_create(pdata->name, S_IRUGO, @@ -540,20 +541,9 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, cldata->index = index; cldata->size = i; - mutex_unlock(&cl_list_lock); - return i; -} + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); -static int msm_bus_dbg_update_request(struct msm_bus_cldata *cldata, int index) -{ - int ret = 0; - - if ((index < 0) || (index > cldata->pdata->num_usecases)) { - MSM_BUS_DBG("Invalid index!\n"); - return -EINVAL; - } - ret = msm_bus_scale_client_update_request(cldata->clid, index); - return ret; + return i; } static ssize_t msm_bus_dbg_update_request_write(struct file *file, @@ -565,20 +555,26 @@ static ssize_t msm_bus_dbg_update_request_write(struct file *file, char *chid; char *buf = kmalloc((sizeof(char) * (cnt + 1)), GFP_KERNEL); int found = 0; + uint32_t clid; + ssize_t res = cnt; if (!buf || IS_ERR(buf)) { MSM_BUS_ERR("Memory allocation for buffer failed\n"); return -ENOMEM; } - if (cnt == 0) - return 0; - if (copy_from_user(buf, ubuf, cnt)) - return -EFAULT; + if (cnt == 0) { + res = 0; + goto out; + } + if (copy_from_user(buf, ubuf, cnt)) { + res = -EFAULT; + goto out; + } buf[cnt] = '\0'; chid = buf; MSM_BUS_DBG("buffer: %s\n size: %zu\n", buf, sizeof(ubuf)); - mutex_lock(&cl_list_lock); + rt_mutex_lock(&msm_bus_dbg_cllist_lock); list_for_each_entry(cldata, &cl_list, list) { if (strnstr(chid, cldata->pdata->name, cnt)) { found = 1; @@ -589,23 +585,35 @@ static ssize_t msm_bus_dbg_update_request_write(struct file *file, if (ret) { MSM_BUS_DBG("Index conversion" " failed\n"); - mutex_unlock(&cl_list_lock); - return -EFAULT; + rt_mutex_unlock( + &msm_bus_dbg_cllist_lock); + res = -EFAULT; + goto out; } } else { MSM_BUS_DBG("Error parsing input. Index not" " found\n"); found = 0; } + if ((index < 0) || + (index > cldata->pdata->num_usecases)) { + MSM_BUS_DBG("Invalid index!\n"); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + res = -EINVAL; + goto out; + } + clid = cldata->clid; break; } } + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); if (found) - msm_bus_dbg_update_request(cldata, index); - mutex_unlock(&cl_list_lock); + msm_bus_scale_client_update_request(clid, index); + +out: kfree(buf); - return cnt; + return res; } /** @@ -628,8 +636,10 @@ static ssize_t fabric_data_read(struct file *file, char __user *buf, break; } } - if (!found) + if (!found) { + mutex_unlock(&msm_bus_dbg_fablist_lock); return -ENOENT; + } bsize = fablist->size; ret = simple_read_from_buffer(buf, count, ppos, fablist->buffer, bsize); @@ -718,8 +728,10 @@ static int msm_bus_dbg_fill_fab_buffer(const char *fabname, break; } } - if (!found) + if (!found) { + mutex_unlock(&msm_bus_dbg_fablist_lock); return -ENOENT; + } if (fablist->file == NULL) { MSM_BUS_DBG("Fabric dbg entry does not exist\n"); @@ -770,7 +782,8 @@ static ssize_t msm_bus_dbg_dump_clients_read(struct file *file, "\nDumping curent client votes to trace log\n"); if (*ppos) goto exit_dump_clients_read; - mutex_lock(&cl_list_lock); + + rt_mutex_lock(&msm_bus_dbg_cllist_lock); list_for_each_entry(cldata, &cl_list, list) { if (IS_ERR_OR_NULL(cldata->pdata)) continue; @@ -786,7 +799,7 @@ static ssize_t msm_bus_dbg_dump_clients_read(struct file *file, cldata->pdata->active_only); } } - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); exit_dump_clients_read: return simple_read_from_buffer(buf, count, ppos, msg, cnt); } @@ -911,7 +924,7 @@ static int __init msm_bus_debugfs_init(void) goto err; } - mutex_lock(&cl_list_lock); + rt_mutex_lock(&msm_bus_dbg_cllist_lock); list_for_each_entry(cldata, &cl_list, list) { if (cldata->pdata) { if (cldata->pdata->name == NULL) { @@ -931,7 +944,8 @@ static int __init msm_bus_debugfs_init(void) &client_data_fops); } } - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + if (debugfs_create_file("dump_clients", S_IRUGO | S_IWUSR, clients, NULL, &msm_bus_dbg_dump_clients_fops) == NULL) goto err; @@ -943,6 +957,7 @@ static int __init msm_bus_debugfs_init(void) if (fablist->file == NULL) { MSM_BUS_DBG("Cannot create files for commit data\n"); kfree(rules_buf); + mutex_unlock(&msm_bus_dbg_fablist_lock); goto err; } } @@ -962,12 +977,13 @@ static void __exit msm_bus_dbg_teardown(void) struct msm_bus_cldata *cldata = NULL, *cldata_temp; debugfs_remove_recursive(dir); - mutex_lock(&cl_list_lock); + + rt_mutex_lock(&msm_bus_dbg_cllist_lock); list_for_each_entry_safe(cldata, cldata_temp, &cl_list, list) { list_del(&cldata->list); kfree(cldata); } - mutex_unlock(&cl_list_lock); + rt_mutex_unlock(&msm_bus_dbg_cllist_lock); mutex_lock(&msm_bus_dbg_fablist_lock); list_for_each_entry_safe(fablist, fablist_temp, &fabdata_list, list) { diff --git a/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c b/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c index 594bccfaf81..a876484859e 100644 --- a/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c +++ b/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c @@ -137,7 +137,6 @@ static ssize_t bus_floor_vote_store_api(struct device *dev, pr_err("%s:return error", __func__); return -EINVAL; } - name[9] = '\0'; pr_info("%s: name %s vote %llu\n", __func__, name, vote_khz); diff --git a/drivers/power/qcom/msm-core.c b/drivers/power/qcom/msm-core.c index f040d20a40f..f644950fe46 100644 --- a/drivers/power/qcom/msm-core.c +++ b/drivers/power/qcom/msm-core.c @@ -297,7 +297,7 @@ static __ref int do_sampling(void *data) static int prev_temp[NR_CPUS]; while (!kthread_should_stop()) { - wait_for_completion_interruptible(&sampling_completion); + wait_for_completion(&sampling_completion); cancel_delayed_work(&sampling_work); mutex_lock(&kthread_update_mutex); @@ -319,8 +319,7 @@ static __ref int do_sampling(void *data) if (!poll_ms) goto unlock; - queue_delayed_work(system_power_efficient_wq, - &sampling_work, + schedule_delayed_work(&sampling_work, msecs_to_jiffies(poll_ms)); unlock: mutex_unlock(&kthread_update_mutex); diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c index 634d6202cf1..94792aced42 100644 --- a/drivers/power/qpnp-fg.c +++ b/drivers/power/qpnp-fg.c @@ -1769,7 +1769,7 @@ static int set_prop_jeita_temp(struct fg_chip *chip, cancel_delayed_work_sync( &chip->update_jeita_setting); - queue_delayed_work(system_power_efficient_wq, + schedule_delayed_work( &chip->update_jeita_setting, 0); return rc; @@ -2085,7 +2085,7 @@ wait: update_sram_data(chip, &resched_ms); out: - queue_delayed_work(system_power_efficient_wq, + schedule_delayed_work( &chip->update_sram_data, msecs_to_jiffies(resched_ms)); } @@ -2166,11 +2166,9 @@ out: if (rc) pr_err("failed to write BATT_TEMP_OFF rc=%d\n", rc); } - - queue_delayed_work(system_power_efficient_wq, + schedule_delayed_work( &chip->update_temp_work, msecs_to_jiffies(TEMP_PERIOD_UPDATE_MS)); - fg_relax(&chip->update_temp_wakeup_source); } @@ -3317,8 +3315,7 @@ static void status_change_work(struct work_struct *work) */ if (chip->last_sram_update_time + 5 < current_time) { cancel_delayed_work(&chip->update_sram_data); - queue_delayed_work(system_power_efficient_wq, - &chip->update_sram_data, + schedule_delayed_work(&chip->update_sram_data, msecs_to_jiffies(0)); } if (chip->cyc_ctr.en) @@ -3814,7 +3811,7 @@ static irqreturn_t fg_batt_missing_irq_handler(int irq, void *_chip) INIT_COMPLETION(chip->batt_id_avail); schedule_work(&chip->batt_profile_init); cancel_delayed_work(&chip->update_sram_data); - queue_delayed_work(system_power_efficient_wq, + schedule_delayed_work( &chip->update_sram_data, msecs_to_jiffies(0)); } else { @@ -3926,8 +3923,7 @@ static irqreturn_t fg_empty_soc_irq_handler(int irq, void *_chip) if (soc_rt_sts & SOC_EMPTY) { chip->soc_empty = true; fg_stay_awake(&chip->empty_check_wakeup_source); - queue_delayed_work(system_power_efficient_wq, - &chip->check_empty_work, + schedule_delayed_work(&chip->check_empty_work, msecs_to_jiffies(FG_EMPTY_DEBOUNCE_MS)); } else { chip->soc_empty = false; @@ -6149,7 +6145,7 @@ static void delayed_init_work(struct work_struct *work) /* release memory access before update_sram_data is called */ fg_mem_release(chip); - queue_delayed_work(system_power_efficient_wq, + schedule_delayed_work( &chip->update_jeita_setting, msecs_to_jiffies(INIT_JEITA_DELAY_MS)); @@ -6479,7 +6475,7 @@ static void check_and_update_sram_data(struct fg_chip *chip) else time_left = 0; - queue_delayed_work(system_power_efficient_wq, + schedule_delayed_work( &chip->update_temp_work, msecs_to_jiffies(time_left * 1000)); next_update_time = chip->last_sram_update_time @@ -6490,7 +6486,7 @@ static void check_and_update_sram_data(struct fg_chip *chip) else time_left = 0; - queue_delayed_work(system_power_efficient_wq, + schedule_delayed_work( &chip->update_sram_data, msecs_to_jiffies(time_left * 1000)); } diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 6f6eed8dce7..5fe1cbaf581 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1935,9 +1935,8 @@ int regulator_disable_deferred(struct regulator *regulator, int ms) rdev->deferred_disables++; mutex_unlock(&rdev->mutex); - ret = queue_delayed_work(system_power_efficient_wq, - &rdev->disable_work, - msecs_to_jiffies(ms)); + ret = schedule_delayed_work(&rdev->disable_work, + msecs_to_jiffies(ms)); if (ret < 0) return ret; else diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index bf13e73ecab..0f3581b7a2e 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -556,19 +556,32 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, if (fsf) { rec->fsf_req_id = fsf->req_id; + rec->pl_len = FCP_RESP_WITH_EXT; fcp_rsp = (struct fcp_resp_with_ext *) &(fsf->qtcb->bottom.io.fcp_rsp); + /* mandatory parts of FCP_RSP IU in this SCSI record */ memcpy(&rec->fcp_rsp, fcp_rsp, FCP_RESP_WITH_EXT); if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) { fcp_rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; rec->fcp_rsp_info = fcp_rsp_info->rsp_code; + rec->pl_len += be32_to_cpu(fcp_rsp->ext.fr_rsp_len); } if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) { - rec->pl_len = min((u16)SCSI_SENSE_BUFFERSIZE, - (u16)ZFCP_DBF_PAY_MAX_REC); - zfcp_dbf_pl_write(dbf, sc->sense_buffer, rec->pl_len, - "fcp_sns", fsf->req_id); + rec->pl_len += be32_to_cpu(fcp_rsp->ext.fr_sns_len); } + /* complete FCP_RSP IU in associated PAYload record + * but only if there are optional parts + */ + if (fcp_rsp->resp.fr_flags != 0) + zfcp_dbf_pl_write( + dbf, fcp_rsp, + /* at least one full PAY record + * but not beyond hardware response field + */ + min_t(u16, max_t(u16, rec->pl_len, + ZFCP_DBF_PAY_MAX_REC), + FSF_FCP_RSP_SIZE), + "fcp_riu", fsf->req_id); } debug_event(dbf->scsi, level, rec, sizeof(*rec)); diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index a8165f14255..712a8484a7b 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -323,7 +323,11 @@ void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req) { struct fsf_qtcb *qtcb = req->qtcb; - if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) && + if (unlikely(req->status & (ZFCP_STATUS_FSFREQ_DISMISSED | + ZFCP_STATUS_FSFREQ_ERROR))) { + zfcp_dbf_hba_fsf_resp("fs_rerr", 3, req); + + } else if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) && (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { zfcp_dbf_hba_fsf_resp("fs_perr", 1, req); diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h index b1d2024ed51..c2e40e10b29 100644 --- a/drivers/s390/scsi/zfcp_fc.h +++ b/drivers/s390/scsi/zfcp_fc.h @@ -4,7 +4,7 @@ * Fibre Channel related definitions and inline functions for the zfcp * device driver * - * Copyright IBM Corp. 2009 + * Copyright IBM Corp. 2009, 2017 */ #ifndef ZFCP_FC_H @@ -291,6 +291,10 @@ void zfcp_fc_eval_fcp_rsp(struct fcp_resp_with_ext *fcp_rsp, !(rsp_flags & FCP_SNS_LEN_VAL) && fcp_rsp->resp.fr_status == SAM_STAT_GOOD) set_host_byte(scsi, DID_ERROR); + } else if (unlikely(rsp_flags & FCP_RESID_OVER)) { + /* FCP_DL was not sufficient for SCSI data length */ + if (fcp_rsp->resp.fr_status == SAM_STAT_GOOD) + set_host_byte(scsi, DID_ERROR); } } diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index ad5718401ea..d27b49194d6 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2286,7 +2286,8 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd) fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0); - if (scsi_prot_sg_count(scsi_cmnd)) { + if ((scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) && + scsi_prot_sg_count(scsi_cmnd)) { zfcp_qdio_set_data_div(qdio, &req->qdio_req, scsi_prot_sg_count(scsi_cmnd)); retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 66c37e77ac7..8ec101a4a5e 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -294,8 +294,10 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) zfcp_erp_wait(adapter); ret = fc_block_scsi_eh(scpnt); - if (ret) + if (ret) { + zfcp_dbf_scsi_devreset("fiof", scpnt, tm_flags); return ret; + } if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_RUNNING)) { @@ -303,8 +305,10 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) return SUCCESS; } } - if (!fsf_req) + if (!fsf_req) { + zfcp_dbf_scsi_devreset("reqf", scpnt, tm_flags); return FAILED; + } wait_for_completion(&fsf_req->completion); diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index e1c8be06de9..f94fcda1285 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -464,7 +464,7 @@ static int clariion_prep_fn(struct scsi_device *sdev, struct request *req) static int clariion_std_inquiry(struct scsi_device *sdev, struct clariion_dh_data *csdev) { - int err; + int err = SCSI_DH_OK; char *sp_model; err = send_inquiry_cmd(sdev, 0, csdev); diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index bf60c631abb..3b0f02c146d 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -299,6 +299,8 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, return -EINVAL; if (start > ha->optrom_size) return -EINVAL; + if (size > ha->optrom_size - start) + size = ha->optrom_size - start; switch (val) { case 0: @@ -320,8 +322,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, return -EINVAL; ha->optrom_region_start = start; - ha->optrom_region_size = start + size > ha->optrom_size ? - ha->optrom_size - start : size; + ha->optrom_region_size = start + size; ha->optrom_state = QLA_SREADING; ha->optrom_buffer = vmalloc(ha->optrom_region_size); @@ -388,8 +389,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, } ha->optrom_region_start = start; - ha->optrom_region_size = start + size > ha->optrom_size ? - ha->optrom_size - start : size; + ha->optrom_region_size = start + size; ha->optrom_state = QLA_SWRITING; ha->optrom_buffer = vmalloc(ha->optrom_region_size); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 40fe8a77236..c11b82e7095 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2342,10 +2342,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (mem_only) { if (pci_enable_device_mem(pdev)) - goto probe_out; + return ret; } else { if (pci_enable_device(pdev)) - goto probe_out; + return ret; } /* This may fail but that's ok */ @@ -2355,7 +2355,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (!ha) { ql_log_pci(ql_log_fatal, pdev, 0x0009, "Unable to allocate memory for ha.\n"); - goto probe_out; + goto disable_device; } ql_dbg_pci(ql_dbg_init, pdev, 0x000a, "Memory allocated for ha=%p.\n", ha); @@ -2899,7 +2899,7 @@ iospace_config_failed: kfree(ha); ha = NULL; -probe_out: +disable_device: pci_disable_device(pdev); return ret; } diff --git a/drivers/soc/qcom/mpm-of.c b/drivers/soc/qcom/mpm-of.c index 6ce72e66b73..06416595578 100644 --- a/drivers/soc/qcom/mpm-of.c +++ b/drivers/soc/qcom/mpm-of.c @@ -662,7 +662,7 @@ static void msm_mpm_work_fn(struct work_struct *work) unsigned long flags; while (1) { bool allow; - wait_for_completion_interruptible(&wake_wq); + wait_for_completion(&wake_wq); spin_lock_irqsave(&msm_mpm_lock, flags); allow = msm_mpm_irqs_detectable(true) && msm_mpm_gpio_irqs_detectable(true); diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index 12d329e37bd..a03facab903 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -771,13 +771,13 @@ out: up_read(&pil_pm_rwsem); if (ret) { if (priv->region) { + if (desc->clear_fw_region && priv->region_start) + pil_clear_segment(desc); dma_free_attrs(desc->dev, priv->region_size, priv->region, priv->region_start, &desc->attrs); priv->region = NULL; } - if (desc->clear_fw_region && priv->region_start) - pil_clear_segment(desc); pil_release_mmap(desc); } return ret; diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c index 62ccf5ee7bc..fe545897440 100644 --- a/drivers/soc/qcom/qdsp6v2/voice_svc.c +++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -42,6 +42,12 @@ struct voice_svc_prvt { struct list_head response_queue; wait_queue_head_t response_wait; spinlock_t response_lock; + /* + * This mutex ensures responses are processed in sequential order and + * that no two threads access and free the same response at the same + * time. + */ + struct mutex response_mutex_lock; }; struct apr_data { @@ -498,6 +504,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, goto done; } + mutex_lock(&prtd->response_mutex_lock); spin_lock_irqsave(&prtd->response_lock, spin_flags); if (list_empty(&prtd->response_queue)) { @@ -511,7 +518,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, pr_debug("%s: Read timeout\n", __func__); ret = -ETIMEDOUT; - goto done; + goto unlock; } else if (ret > 0 && !list_empty(&prtd->response_queue)) { pr_debug("%s: Interrupt recieved for response\n", __func__); @@ -519,7 +526,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, pr_debug("%s: Interrupted by SIGNAL %d\n", __func__, ret); - goto done; + goto unlock; } spin_lock_irqsave(&prtd->response_lock, spin_flags); @@ -538,7 +545,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, __func__, count, size); ret = -ENOMEM; - goto done; + goto unlock; } if (!access_ok(VERIFY_WRITE, arg, size)) { @@ -546,7 +553,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, __func__); ret = -EPERM; - goto done; + goto unlock; } ret = copy_to_user(arg, &resp->resp, @@ -556,7 +563,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, pr_err("%s: copy_to_user failed %d\n", __func__, ret); ret = -EPERM; - goto done; + goto unlock; } spin_lock_irqsave(&prtd->response_lock, spin_flags); @@ -570,6 +577,8 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, ret = count; +unlock: + mutex_unlock(&prtd->response_mutex_lock); done: return ret; } @@ -625,6 +634,7 @@ static int voice_svc_open(struct inode *inode, struct file *file) INIT_LIST_HEAD(&prtd->response_queue); init_waitqueue_head(&prtd->response_wait); spin_lock_init(&prtd->response_lock); + mutex_init(&prtd->response_mutex_lock); file->private_data = (void *)prtd; /* Current APR implementation doesn't support session based @@ -675,6 +685,7 @@ static int voice_svc_release(struct inode *inode, struct file *file) pr_err("%s: Failed to dereg MVM %d\n", __func__, ret); } + mutex_lock(&prtd->response_mutex_lock); spin_lock_irqsave(&prtd->response_lock, spin_flags); while (!list_empty(&prtd->response_queue)) { @@ -688,6 +699,9 @@ static int voice_svc_release(struct inode *inode, struct file *file) } spin_unlock_irqrestore(&prtd->response_lock, spin_flags); + mutex_unlock(&prtd->response_mutex_lock); + + mutex_destroy(&prtd->response_mutex_lock); kfree(file->private_data); file->private_data = NULL; diff --git a/drivers/soc/qcom/rpm-smd.c b/drivers/soc/qcom/rpm-smd.c index 860582f78c9..4d173d1ee80 100644 --- a/drivers/soc/qcom/rpm-smd.c +++ b/drivers/soc/qcom/rpm-smd.c @@ -916,7 +916,7 @@ static void msm_rpm_smd_work(struct work_struct *work) char buf[MAX_ERR_BUFFER_SIZE] = {0}; while (1) { - wait_for_completion_interruptible(&data_ready); + wait_for_completion(&data_ready); spin_lock(&msm_rpm_data.smd_lock_read); while (smd_is_pkt_avail(msm_rpm_data.ch_info)) { diff --git a/drivers/soc/qcom/smp2p_spinlock_test.c b/drivers/soc/qcom/smp2p_spinlock_test.c index 5bc1930ee7c..648c18b9e71 100644 --- a/drivers/soc/qcom/smp2p_spinlock_test.c +++ b/drivers/soc/qcom/smp2p_spinlock_test.c @@ -1,6 +1,6 @@ /* drivers/soc/qcom/smp2p_spinlock_test.c * - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -516,7 +516,7 @@ static void smp2p_ut_remote_spinlock_ssr(struct seq_file *s) int spinlock_owner = 0; struct workqueue_struct *ws = NULL; - struct rmt_spinlock_work_item work_item; + struct rmt_spinlock_work_item work_item = { .has_locked = false }; seq_printf(s, " Running %s Test\n", __func__); diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 838c6dd895f..82d6da52477 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2015, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -44,6 +44,7 @@ #define SMEM_IMAGE_VERSION_OEM_OFFSET 96 #define SMEM_IMAGE_VERSION_PARTITION_APPS 10 +static DECLARE_RWSEM(current_image_rwsem); enum { HW_PLATFORM_UNKNOWN = 0, HW_PLATFORM_SURF = 1, @@ -811,7 +812,9 @@ msm_get_image_version(struct device *dev, __func__); return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "Unknown"); } + down_read(¤t_image_rwsem); string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s\n", string_address); } @@ -824,15 +827,20 @@ msm_set_image_version(struct device *dev, { char *store_address; - if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) + down_read(¤t_image_rwsem); + if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { + up_read(¤t_image_rwsem); return count; + } store_address = socinfo_get_image_version_base_address(); if (IS_ERR_OR_NULL(store_address)) { pr_err("%s : Failed to get image version base address", __func__); + up_read(¤t_image_rwsem); return count; } store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); snprintf(store_address, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s", buf); return count; } @@ -851,7 +859,9 @@ msm_get_image_variant(struct device *dev, return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "Unknown"); } + down_read(¤t_image_rwsem); string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); string_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET; return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s\n", string_address); @@ -865,15 +875,20 @@ msm_set_image_variant(struct device *dev, { char *store_address; - if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) + down_read(¤t_image_rwsem); + if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { + up_read(¤t_image_rwsem); return count; + } store_address = socinfo_get_image_version_base_address(); if (IS_ERR_OR_NULL(store_address)) { pr_err("%s : Failed to get image version base address", __func__); + up_read(¤t_image_rwsem); return count; } store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); store_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET; snprintf(store_address, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s", buf); return count; @@ -892,7 +907,9 @@ msm_get_image_crm_version(struct device *dev, __func__); return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "Unknown"); } + down_read(¤t_image_rwsem); string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); string_address += SMEM_IMAGE_VERSION_OEM_OFFSET; return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s\n", string_address); @@ -906,15 +923,20 @@ msm_set_image_crm_version(struct device *dev, { char *store_address; - if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) + down_read(¤t_image_rwsem); + if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { + up_read(¤t_image_rwsem); return count; + } store_address = socinfo_get_image_version_base_address(); if (IS_ERR_OR_NULL(store_address)) { pr_err("%s : Failed to get image version base address", __func__); + up_read(¤t_image_rwsem); return count; } store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(¤t_image_rwsem); store_address += SMEM_IMAGE_VERSION_OEM_OFFSET; snprintf(store_address, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s", buf); return count; @@ -925,8 +947,14 @@ msm_get_image_number(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", + int ret; + + down_read(¤t_image_rwsem); + ret = snprintf(buf, PAGE_SIZE, "%d\n", current_image); + up_read(¤t_image_rwsem); + return ret; + } static ssize_t @@ -938,10 +966,12 @@ msm_select_image(struct device *dev, struct device_attribute *attr, ret = kstrtoint(buf, 10, &digit); if (ret) return ret; + down_write(¤t_image_rwsem); if (0 <= digit && digit < SMEM_IMAGE_VERSION_BLOCKS_COUNT) current_image = digit; else current_image = 0; + up_write(¤t_image_rwsem); return count; } diff --git a/drivers/soc/qcom/watchdog_v2.c b/drivers/soc/qcom/watchdog_v2.c index 3f89b05ef01..5ada2418973 100644 --- a/drivers/soc/qcom/watchdog_v2.c +++ b/drivers/soc/qcom/watchdog_v2.c @@ -14,9 +14,9 @@ #include <linux/kernel.h> #include <linux/io.h> #include <linux/delay.h> -#include <linux/workqueue.h> #include <linux/slab.h> #include <linux/jiffies.h> +#include <linux/kthread.h> #include <linux/mutex.h> #include <linux/sched.h> #include <linux/interrupt.h> @@ -26,6 +26,7 @@ #include <linux/cpu.h> #include <linux/cpu_pm.h> #include <linux/platform_device.h> +#include <linux/sched/rt.h> #include <soc/qcom/scm.h> #include <soc/qcom/memory_dump.h> #include <soc/qcom/watchdog.h> @@ -50,7 +51,6 @@ #define SCM_SET_REGSAVE_CMD 0x2 #define SCM_SVC_SEC_WDOG_DIS 0x7 -static struct workqueue_struct *wdog_wq; static struct msm_watchdog_data *wdog_data; static struct msm_watchdog_data *g_wdog_dd; @@ -74,12 +74,13 @@ struct msm_watchdog_data { void *scm_regsave; cpumask_t alive_mask; struct mutex disable_lock; - struct work_struct init_dogwork_struct; - struct delayed_work dogwork_struct; bool irq_ppi; struct msm_watchdog_data __percpu **wdog_cpu_dd; struct notifier_block panic_blk; bool enabled; + struct task_struct *watchdog_task; + struct timer_list pet_timer; + struct completion pet_complete; phys_addr_t cpu_ctx_addr; size_t cpu_ctx_size_percpu; }; @@ -108,9 +109,6 @@ module_param(WDT_HZ, long, 0); static int ipi_opt_en; module_param(ipi_opt_en, int, 0); -static void pet_watchdog_work(struct work_struct *work); -static void init_watchdog_work(struct work_struct *work); - static void dump_cpu_alive_mask(struct msm_watchdog_data *wdog_dd) { static char alive_mask_buf[MASK_SIZE]; @@ -192,7 +190,7 @@ static void wdog_disable(struct msm_watchdog_data *wdog_dd) smp_mb(); atomic_notifier_chain_unregister(&panic_notifier_list, &wdog_dd->panic_blk); - cancel_delayed_work_sync(&wdog_dd->dogwork_struct); + del_timer_sync(&wdog_dd->pet_timer); /* may be suspended after the first write above */ __raw_writel(0, wdog_dd->base + WDT0_EN); mb(); @@ -200,20 +198,6 @@ static void wdog_disable(struct msm_watchdog_data *wdog_dd) pr_info("MSM Apps Watchdog deactivated.\n"); } -struct wdog_disable_work_data { - struct work_struct work; - struct completion complete; - struct msm_watchdog_data *wdog_dd; -}; - -static void wdog_disable_work(struct work_struct *work) -{ - struct wdog_disable_work_data *work_data = - container_of(work, struct wdog_disable_work_data, work); - wdog_disable(work_data->wdog_dd); - complete(&work_data->complete); -} - static ssize_t wdog_disable_get(struct device *dev, struct device_attribute *attr, char *buf) { @@ -232,7 +216,6 @@ static ssize_t wdog_disable_set(struct device *dev, { int ret; u8 disable; - struct wdog_disable_work_data work_data; struct msm_watchdog_data *wdog_dd = dev_get_drvdata(dev); ret = kstrtou8(buf, 10, &disable); @@ -264,11 +247,7 @@ static ssize_t wdog_disable_set(struct device *dev, mutex_unlock(&wdog_dd->disable_lock); return -EIO; } - work_data.wdog_dd = wdog_dd; - init_completion(&work_data.complete); - INIT_WORK_ONSTACK(&work_data.work, wdog_disable_work); - queue_work(wdog_wq, &work_data.work); - wait_for_completion(&work_data.complete); + wdog_disable(wdog_dd); mutex_unlock(&wdog_dd->disable_lock); } else { pr_err("invalid operation, only disable = 1 supported\n"); @@ -334,24 +313,37 @@ static void ping_other_cpus(struct msm_watchdog_data *wdog_dd) } } -static void pet_watchdog_work(struct work_struct *work) +static void pet_task_wakeup(unsigned long data) { - unsigned long delay_time; - struct delayed_work *delayed_work = to_delayed_work(work); - struct msm_watchdog_data *wdog_dd = container_of(delayed_work, - struct msm_watchdog_data, - dogwork_struct); - delay_time = msecs_to_jiffies(wdog_dd->pet_time); - if (enable) { - if (wdog_dd->do_ipi_ping) - ping_other_cpus(wdog_dd); - pet_watchdog(wdog_dd); + struct msm_watchdog_data *wdog_dd = + (struct msm_watchdog_data *)data; + complete(&wdog_dd->pet_complete); +} + +static __ref int watchdog_kthread(void *arg) +{ + struct msm_watchdog_data *wdog_dd = + (struct msm_watchdog_data *)arg; + unsigned long delay_time = 0; + struct sched_param param = {.sched_priority = MAX_RT_PRIO-1}; + + sched_setscheduler(current, SCHED_FIFO, ¶m); + while (!kthread_should_stop()) { + while (wait_for_completion_interruptible( + &wdog_dd->pet_complete) != 0) + ; + INIT_COMPLETION(wdog_dd->pet_complete); + if (enable) { + delay_time = msecs_to_jiffies(wdog_dd->pet_time); + if (wdog_dd->do_ipi_ping) + ping_other_cpus(wdog_dd); + pet_watchdog(wdog_dd); + } + /* Check again before scheduling * + * Could have been changed on other cpu */ + mod_timer(&wdog_dd->pet_timer, jiffies + delay_time); } - /* Check again before scheduling * - * Could have been changed on other cpu */ - if (enable) - queue_delayed_work(wdog_wq, - &wdog_dd->dogwork_struct, delay_time); + return 0; } static int wdog_cpu_pm_notify(struct notifier_block *self, @@ -380,7 +372,6 @@ static struct notifier_block wdog_cpu_pm_nb = { static int msm_watchdog_remove(struct platform_device *pdev) { - struct wdog_disable_work_data work_data; struct msm_watchdog_data *wdog_dd = (struct msm_watchdog_data *)platform_get_drvdata(pdev); @@ -389,18 +380,15 @@ static int msm_watchdog_remove(struct platform_device *pdev) mutex_lock(&wdog_dd->disable_lock); if (enable) { - work_data.wdog_dd = wdog_dd; - init_completion(&work_data.complete); - INIT_WORK_ONSTACK(&work_data.work, wdog_disable_work); - queue_work(wdog_wq, &work_data.work); - wait_for_completion(&work_data.complete); + wdog_disable(wdog_dd); } mutex_unlock(&wdog_dd->disable_lock); device_remove_file(wdog_dd->dev, &dev_attr_disable); if (wdog_dd->irq_ppi) free_percpu(wdog_dd->wdog_cpu_dd); printk(KERN_INFO "MSM Watchdog Exit - Deactivated\n"); - destroy_workqueue(wdog_wq); + del_timer_sync(&wdog_dd->pet_timer); + kthread_stop(wdog_dd->watchdog_task); kfree(wdog_dd); return 0; } @@ -560,11 +548,8 @@ out0: } -static void init_watchdog_work(struct work_struct *work) +static void init_watchdog_data(struct msm_watchdog_data *wdog_dd) { - struct msm_watchdog_data *wdog_dd = container_of(work, - struct msm_watchdog_data, - init_dogwork_struct); unsigned long delay_time; uint32_t val; int error; @@ -614,8 +599,14 @@ static void init_watchdog_work(struct work_struct *work) atomic_notifier_chain_register(&panic_notifier_list, &wdog_dd->panic_blk); mutex_init(&wdog_dd->disable_lock); - queue_delayed_work(wdog_wq, &wdog_dd->dogwork_struct, - delay_time); + init_completion(&wdog_dd->pet_complete); + wake_up_process(wdog_dd->watchdog_task); + init_timer(&wdog_dd->pet_timer); + wdog_dd->pet_timer.data = (unsigned long)wdog_dd; + wdog_dd->pet_timer.function = pet_task_wakeup; + wdog_dd->pet_timer.expires = jiffies + delay_time; + add_timer(&wdog_dd->pet_timer); + val = BIT(EN); if (wdog_dd->wakeup_irq_enable) val |= BIT(UNMASKED_INT_EN); @@ -725,12 +716,6 @@ static int msm_watchdog_probe(struct platform_device *pdev) int ret; struct msm_watchdog_data *wdog_dd; - wdog_wq = alloc_workqueue("wdog", WQ_HIGHPRI, 0); - if (!wdog_wq) { - pr_err("Failed to allocate watchdog workqueue\n"); - return -EIO; - } - if (!pdev->dev.of_node || !enable) return -ENODEV; wdog_dd = kzalloc(sizeof(struct msm_watchdog_data), GFP_KERNEL); @@ -746,13 +731,16 @@ static int msm_watchdog_probe(struct platform_device *pdev) msm_wdog_get_cpu_ctx(pdev, &wdog_dd->cpu_ctx_addr, &wdog_dd->cpu_ctx_size_percpu); cpumask_clear(&wdog_dd->alive_mask); - INIT_WORK(&wdog_dd->init_dogwork_struct, init_watchdog_work); - INIT_DELAYED_WORK(&wdog_dd->dogwork_struct, pet_watchdog_work); + wdog_dd->watchdog_task = kthread_create(watchdog_kthread, wdog_dd, + "msm_watchdog"); + if (IS_ERR(wdog_dd->watchdog_task)) { + ret = PTR_ERR(wdog_dd->watchdog_task); + goto err; + } + init_watchdog_data(wdog_dd); g_wdog_dd = wdog_dd; - queue_work(wdog_wq, &wdog_dd->init_dogwork_struct); return 0; err: - destroy_workqueue(wdog_wq); kzfree(wdog_dd); return ret; } diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 1b64f1aa93b..625f0003ca9 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1,9 +1,9 @@ /* - * drivers/gpu/ion/ion.c + * drivers/staging/android/ion/ion.c * * Copyright (C) 2011 Google, Inc. - * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -696,7 +696,7 @@ static void user_ion_free_nolock(struct ion_client *client, WARN(1, "%s: invalid handle passed to free.\n", __func__); return; } - if (!handle->user_ref_count > 0) { + if (handle->user_ref_count == 0) { WARN(1, "%s: User does not have access!\n", __func__); return; } @@ -2010,10 +2010,11 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) up_write(&dev->lock); } -int ion_walk_heaps(struct ion_client *client, int heap_id, void *data, +int ion_walk_heaps(struct ion_client *client, int heap_id, + enum ion_heap_type type, void *data, int (*f)(struct ion_heap *heap, void *data)) { - int ret_val = -EINVAL; + int ret_val = 0; struct ion_heap *heap; struct ion_device *dev = client->dev; /* @@ -2022,7 +2023,8 @@ int ion_walk_heaps(struct ion_client *client, int heap_id, void *data, */ down_write(&dev->lock); plist_for_each_entry(heap, &dev->heaps, node) { - if (ION_HEAP(heap->id) != heap_id) + if (ION_HEAP(heap->id) != heap_id || + type != heap->type) continue; ret_val = f(heap, data); break; diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 343bbd81dbd..231936c63ab 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -90,6 +90,9 @@ static int ion_carveout_heap_allocate(struct ion_heap *heap, unsigned long size, unsigned long align, unsigned long flags) { + if (align > PAGE_SIZE) + return -EINVAL; + buffer->priv_phys = ion_carveout_allocate(heap, size, align); return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0; } diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 0f0e2879560..371b8a7ad5d 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -1,8 +1,8 @@ /* - * drivers/gpu/ion/ion_priv.h + * drivers/staging/android/ion/ion_priv.h * * Copyright (C) 2011 Google, Inc. - * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -441,7 +441,8 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, void ion_pages_sync_for_device(struct device *dev, struct page *page, size_t size, enum dma_data_direction dir); -int ion_walk_heaps(struct ion_client *client, int heap_id, void *data, +int ion_walk_heaps(struct ion_client *client, int heap_id, + enum ion_heap_type type, void *data, int (*f)(struct ion_heap *heap, void *data)); struct ion_handle *ion_handle_get_by_id(struct ion_client *client, diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index af7802d28bf..7a4a8020d12 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -124,6 +124,10 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap, if (!info) return NULL; + info = kmalloc(sizeof(struct page_info), GFP_KERNEL); + if (!info) + return NULL; + for (i = 0; i < num_orders; i++) { if (size < order_to_size(orders[i])) continue; diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index c79bcfc6359..fd67158512a 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -756,16 +756,28 @@ long msm_ion_custom_ioctl(struct ion_client *client, } case ION_IOC_PREFETCH: { - ion_walk_heaps(client, data.prefetch_data.heap_id, + int ret; + + ret = ion_walk_heaps(client, data.prefetch_data.heap_id, + ION_HEAP_TYPE_SECURE_DMA, (void *)data.prefetch_data.len, ion_secure_cma_prefetch); + + if (ret) + return ret; break; } case ION_IOC_DRAIN: { - ion_walk_heaps(client, data.prefetch_data.heap_id, + int ret; + + ret = ion_walk_heaps(client, data.prefetch_data.heap_id, + ION_HEAP_TYPE_SECURE_DMA, (void *)data.prefetch_data.len, ion_secure_cma_drain_pool); + + if (ret) + return ret; break; } diff --git a/drivers/staging/android/oneshot_sync.c b/drivers/staging/android/oneshot_sync.c index 317720ade3a..6a56ee9d6b0 100644 --- a/drivers/staging/android/oneshot_sync.c +++ b/drivers/staging/android/oneshot_sync.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014,2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 0ae406a4750..2aba2f75fb8 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -2557,15 +2557,13 @@ static int __init comedi_init(void) comedi_class->dev_attrs = comedi_dev_attrs; - /* XXX requires /proc interface */ - comedi_proc_init(); - /* create devices files for legacy/manual use */ for (i = 0; i < comedi_num_legacy_minors; i++) { struct comedi_device *dev; dev = comedi_alloc_board_minor(NULL); if (IS_ERR(dev)) { comedi_cleanup_board_minors(); + class_destroy(comedi_class); cdev_del(&comedi_cdev); unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS); @@ -2576,6 +2574,9 @@ static int __init comedi_init(void) } } + /* XXX requires /proc interface */ + comedi_proc_init(); + return 0; } module_init(comedi_init); diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index 0d3356d4b7d..3c0b16fe172 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -477,7 +477,7 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev, long m) { struct ad2s1210_state *st = iio_priv(indio_dev); - bool negative; + u16 negative; int ret = 0; u16 pos; s16 vel; diff --git a/drivers/staging/prima/Android.mk b/drivers/staging/prima/Android.mk index 37dc852a7f8..de0c7354aea 100644 --- a/drivers/staging/prima/Android.mk +++ b/drivers/staging/prima/Android.mk @@ -10,7 +10,7 @@ WLAN_SELECT := CONFIG_PRIMA_WLAN=m endif # Build/Package options for 8916, 8974, 8226, 8610, 8909, 8952, 8937, 8953 targets -ifneq (,$(filter msm8916 msm8974 msm8226 msm8610 msm8909 msm8952 msm8937 msm8953 msm8953,$(TARGET_BOARD_PLATFORM))) +ifneq (,$(filter msm8916 msm8974 msm8226 msm8610 msm8909 msm8952 msm8937 msm8953 titanium,$(TARGET_BOARD_PLATFORM))) WLAN_CHIPSET := pronto WLAN_SELECT := CONFIG_PRONTO_WLAN=m endif @@ -20,8 +20,22 @@ ifneq ($(WLAN_CHIPSET),) LOCAL_PATH := $(call my-dir) -# This makefile is only for DLKM +ifeq ($(TARGET_SUPPORTS_WEARABLES),true) +ifneq ($(findstring device,$(LOCAL_PATH)),) + WLAN_DLKM := 1 +else + WLAN_DLKM := 0 +endif # findstring device +else ifneq ($(findstring vendor,$(LOCAL_PATH)),) + WLAN_DLKM := 1 +else + WLAN_DLKM := 0 +endif # findstring vendor +endif # TARGET_SUPPORTS_WEARABLES + +# This makefile is only for DLKM +ifeq ($(WLAN_DLKM),1) # Determine if we are Proprietary or Open Source ifneq ($(findstring opensource,$(LOCAL_PATH)),) @@ -33,13 +47,21 @@ endif ifeq ($(WLAN_PROPRIETARY),1) WLAN_BLD_DIR := vendor/qcom/proprietary/wlan else +ifneq ($(TARGET_SUPPORTS_WEARABLES),true) WLAN_BLD_DIR := vendor/qcom/opensource/wlan +else + WLAN_BLD_DIR := device/qcom/msm8909w/opensource/wlan +endif endif # DLKM_DIR was moved for JELLY_BEAN (PLATFORM_SDK 16) ifeq (1,$(filter 1,$(shell echo "$$(( $(PLATFORM_SDK_VERSION) >= 16 ))" ))) +ifneq ($(TARGET_SUPPORTS_WEARABLES),true) DLKM_DIR := $(TOP)/device/qcom/common/dlkm else + DLKM_DIR := $(BOARD_DLKM_DIR) +endif +else DLKM_DIR := build/dlkm endif @@ -111,15 +133,24 @@ LOCAL_MODULE := $(WLAN_CHIPSET)_wlan.ko LOCAL_MODULE_KBUILD_NAME := wlan.ko LOCAL_MODULE_TAGS := debug LOCAL_MODULE_DEBUG_ENABLE := true +ifeq ($(PRODUCT_VENDOR_MOVE_ENABLED), true) +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/$(WLAN_CHIPSET) +else LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/modules/$(WLAN_CHIPSET) +endif # PRODUCT_VENDOR_MOVE_ENABLED include $(DLKM_DIR)/AndroidKernelModule.mk ########################################################### #Create symbolic link +ifeq ($(PRODUCT_VENDOR_MOVE_ENABLED), true) +$(shell mkdir -p $(TARGET_OUT_VENDOR)/lib/modules; \ + ln -sf /$(TARGET_COPY_OUT_VENDOR)/lib/modules/$(WLAN_CHIPSET)/$(WLAN_CHIPSET)_wlan.ko \ + $(TARGET_OUT_VENDOR)/lib/modules/wlan.ko) +else $(shell mkdir -p $(TARGET_OUT)/lib/modules; \ ln -sf /system/lib/modules/$(WLAN_CHIPSET)/$(WLAN_CHIPSET)_wlan.ko \ $(TARGET_OUT)/lib/modules/wlan.ko) - +endif # PRODUCT_VENDOR_MOVE_ENABLED endif # DLKM check endif # supported target check diff --git a/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h b/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h index 2bc3b6aba15..764384e14f8 100644 --- a/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h +++ b/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -142,6 +142,10 @@ typedef struct #define QCSAP_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+1) #define QCSAP_IOCTL_COMMIT (SIOCIWFIRSTPRIV+2) +#define QCSAP_IOCTL_SET_CHAR_GET_NONE (SIOCIWFIRSTPRIV + 3) +#define WE_WOWL_ADD_PTRN 1 +#define WE_WOWL_DEL_PTRN 2 + #define QCSAP_IOCTL_GET_STAWPAIE (SIOCIWFIRSTPRIV+4) #define QCSAP_IOCTL_STOPBSS (SIOCIWFIRSTPRIV+6) @@ -173,6 +177,9 @@ typedef struct #define QCSAP_IOCTL_SET_TRAFFIC_MONITOR (SIOCIWFIRSTPRIV+24) #define QCSAP_IOCTL_AP_STATS (SIOCIWFIRSTPRIV+25) // get routines should be odd numbered +#define QCSAP_IOCTL_PRIV_SET_NONE_GET_THREE_INT (SIOCIWFIRSTPRIV+27) +#define QCSAP_IOCTL_GET_TSF 1 + #define MAX_VAR_ARGS 7 #define QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED (SIOCIWFIRSTPRIV + 31) @@ -186,7 +193,9 @@ enum { QCSAP_PARAM_SET_MC_RATE = 10, QCSAP_PARAM_SET_AUTO_CHANNEL = 11, QCSAP_PARAM_GET_FRAME_LOGS = 12, - QCSAP_PARAM_SET_PROXIMITY = 13 + QCSAP_PARAM_SET_PROXIMITY = 13, + QCSAP_PARAM_SET_WOWL = 14, + QCSAP_PARAM_CAP_TSF = 15 }; int iw_softap_get_channel_list(struct net_device *dev, diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h index 81947302e55..01620346d23 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -31,6 +31,8 @@ #if !defined( HDD_CONNECTION_H__ ) #define HDD_CONNECTION_H__ #include <wlan_hdd_mib.h> +#include <net/cfg80211.h> +#include <linux/ieee80211.h> #define HDD_MAX_NUM_IBSS_STA ( 32 ) #ifdef FEATURE_WLAN_TDLS #define HDD_MAX_NUM_TDLS_STA ( 8 ) @@ -47,6 +49,57 @@ /* Timeout in ms for peer info request commpletion */ #define IBSS_PEER_INFO_REQ_TIMOEUT 1000 #endif + +/** + * struct hdd_conn_flag - connection flags + * @ht_present: ht element present or not + * @vht_present: vht element present or not + * @hs20_present: hs20 element present or not + */ +struct hdd_conn_flag { + uint8_t ht_present:1; + uint8_t vht_present:1; + uint8_t hs20_present:1; + uint8_t ht_op_present:1; + uint8_t vht_op_present:1; + uint8_t reserved:3; +}; + +/*defines for tx_BF_cap_info */ +#define TX_BF_CAP_INFO_TX_BF 0x00000001 +#define TX_BF_CAP_INFO_RX_STAG_RED_SOUNDING 0x00000002 +#define TX_BF_CAP_INFO_TX_STAG_RED_SOUNDING 0x00000004 +#define TX_BF_CAP_INFO_RX_ZFL 0x00000008 +#define TX_BF_CAP_INFO_TX_ZFL 0x00000010 +#define TX_BF_CAP_INFO_IMP_TX_BF 0x00000020 +#define TX_BF_CAP_INFO_CALIBRATION 0x000000c0 +#define TX_BF_CAP_INFO_CALIBRATION_SHIFT 6 +#define TX_BF_CAP_INFO_EXP_CSIT_BF 0x00000100 +#define TX_BF_CAP_INFO_EXP_UNCOMP_STEER_MAT 0x00000200 +#define TX_BF_CAP_INFO_EXP_BF_CSI_FB 0x00001c00 +#define TX_BF_CAP_INFO_EXP_BF_CSI_FB_SHIFT 10 +#define TX_BF_CAP_INFO_EXP_UNCMP_STEER_MAT 0x0000e000 +#define TX_BF_CAP_INFO_EXP_UNCMP_STEER_MAT_SHIFT 13 +#define TX_BF_CAP_INFO_EXP_CMP_STEER_MAT_FB 0x00070000 +#define TX_BF_CAP_INFO_EXP_CMP_STEER_MAT_FB_SHIFT 16 +#define TX_BF_CAP_INFO_CSI_NUM_BF_ANT 0x00180000 +#define TX_BF_CAP_INFO_CSI_NUM_BF_ANT_SHIFT 18 +#define TX_BF_CAP_INFO_UNCOMP_STEER_MAT_BF_ANT 0x00600000 +#define TX_BF_CAP_INFO_UNCOMP_STEER_MAT_BF_ANT_SHIFT 20 +#define TX_BF_CAP_INFO_COMP_STEER_MAT_BF_ANT 0x01800000 +#define TX_BF_CAP_INFO_COMP_STEER_MAT_BF_ANT_SHIFT 22 +#define TX_BF_CAP_INFO_RSVD 0xfe000000 + +/* defines for antenna selection info */ +#define ANTENNA_SEL_INFO 0x01 +#define ANTENNA_SEL_INFO_EXP_CSI_FB_TX 0x02 +#define ANTENNA_SEL_INFO_ANT_ID_FB_TX 0x04 +#define ANTENNA_SEL_INFO_EXP_CSI_FB 0x08 +#define ANTENNA_SEL_INFO_ANT_ID_FB 0x10 +#define ANTENNA_SEL_INFO_RX_AS 0x20 +#define ANTENNA_SEL_INFO_TX_SOUNDING_PPDU 0x40 +#define ANTENNA_SEL_INFO_RSVD 0x80 + typedef enum { /** Not associated in Infra or participating in an IBSS / Ad-hoc network.*/ @@ -112,7 +165,42 @@ typedef struct connection_info_s tANI_U32 dot11Mode; uint32_t rate_flags; - + + /** channel frequency */ + uint32_t freq; + + /** txrate structure holds nss & datarate info */ + struct rate_info txrate; + + /** noise information */ + int8_t noise; + + /** ht capabilities info */ + struct ieee80211_ht_cap ht_caps; + + /** vht capabilities info */ + struct ieee80211_vht_cap vht_caps; + + /** passpoint/hs20 info */ + tDot11fIEhs20vendor_ie hs20vendor_ie; + + /** conn info params is present or not */ + struct hdd_conn_flag conn_flag; + + /** ht operation info */ + struct ieee80211_ht_operation ht_operation; + + /** ht operation info */ + struct ieee80211_vht_operation vht_operation; + + /** roaming counter */ + uint32_t roam_count; + + /** rssi info */ + int8_t signal; + + /** assoc fail reason */ + int32_t assoc_status_code; }connection_info_t; /*Forward declaration of Adapter*/ typedef struct hdd_adapter_s hdd_adapter_t; @@ -135,6 +223,9 @@ v_BOOL_t hdd_connGetConnectedBssType( hdd_station_ctx_t *pHddCtx, int hdd_SetGENIEToCsr( hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType ); int hdd_set_csr_auth_type( hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType ); + +void hdd_assoc_registerFwdEapolCB(void *pContext); + VOS_STATUS hdd_roamRegisterTDLSSTA( hdd_adapter_t *pAdapter, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)) const tANI_U8 *peerMac, diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h index 45921187e88..d08c9fcc97b 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h @@ -47,9 +47,20 @@ #include <vos_types.h> #include <csrApi.h> +#ifdef DHCP_SERVER_OFFLOAD +#define IPADDR_NUM_ENTRIES (4) +#define IPADDR_STRING_LENGTH (16) +#define DHCP_START_POOL_ADDRESS 100 +#endif /* DHCP_SERVER_OFFLOAD */ + //Number of items that can be configured #define MAX_CFG_INI_ITEMS 512 +#ifdef SAP_AUTH_OFFLOAD +/* 802.11 pre-share key length */ +#define WLAN_PSK_STRING_LENGTH (64) +#endif /* SAP_AUTH_OFFLOAD */ + // Defines for all of the things we read from the configuration (registry). #define CFG_RTS_THRESHOLD_NAME "RTSThreshold" @@ -355,6 +366,11 @@ typedef enum #define CFG_CHANNEL_BONDING_MODE_MAX WNI_CFG_CHANNEL_BONDING_MODE_STAMAX #define CFG_CHANNEL_BONDING_MODE_DEFAULT WNI_CFG_CHANNEL_BONDING_MODE_STADEF +#define CFG_OVERRIDE_HT40_20_24GHZ_NAME "override_ht20_40_24g" +#define CFG_OVERRIDE_HT40_20_24GHZ_MIN 0 +#define CFG_OVERRIDE_HT40_20_24GHZ_MAX 1 +#define CFG_OVERRIDE_HT40_20_24GHZ_DEFAULT 0 + #define CFG_CHANNEL_BONDING_MODE_5GHZ_NAME "gChannelBondingMode5GHz" #define CFG_CHANNEL_BONDING_MODE_MIN WNI_CFG_CHANNEL_BONDING_MODE_STAMIN #define CFG_CHANNEL_BONDING_MODE_MAX WNI_CFG_CHANNEL_BONDING_MODE_STAMAX @@ -1433,6 +1449,16 @@ typedef enum #define CFG_NEIGHBOR_INITIAL_FORCED_ROAM_TO_5GH_ENABLE_MAX (1) #define CFG_NEIGHBOR_INITIAL_FORCED_ROAM_TO_5GH_ENABLE_DEFAULT (0) +/* + * gWeakZoneRssiThresholdForRoam is the minimum threshold value to get + * candidate list from firmware, firmware filters the received candidate with + * this param before sending candidate list to host. + */ +#define CFG_NEIGHBOR_WEAK_ZONE_RSSI_THRESHOLD_FOR_ROAM_NAME "gWeakZoneRssiThresholdForRoam" +#define CFG_NEIGHBOR_WEAK_ZONE_RSSI_THRESHOLD_FOR_ROAM_MIN (40) +#define CFG_NEIGHBOR_WEAK_ZONE_RSSI_THRESHOLD_FOR_ROAM_MAX (100) +#define CFG_NEIGHBOR_WEAK_ZONE_RSSI_THRESHOLD_FOR_ROAM_DEFAULT (80) + #endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ #define CFG_QOS_WMM_BURST_SIZE_DEFN_NAME "burstSizeDefinition" @@ -1545,6 +1571,25 @@ typedef enum #define CFG_ENABLE_DFS_PNO_CHNL_SCAN_MAX ( 1 ) #define CFG_ENABLE_DFS_PNO_CHNL_SCAN_DEFAULT ( 1 ) +/* + * gStaAuthRetriesForCode17 + * It is for an IOT issue. + * When DUT receives MAX_ASSOC_STA_REACHED_STATUS as + * response for Auth frame this ini decides how many + * times DUT has to retry. + * + * This is mainly for an AP where it wants to force + * the Station to connect to its 5G profile session + * (Dual band AP) by rejecting the Auth on 2.4G band. + * But if a station is only 2.4G capable it can try + * 3 times where third time AP will allow the + * station to connect to this AP. + */ +#define CFG_STA_AUTH_RETRIES_FOR_CODE17_NAME "gStaAuthRetriesForCode17" +#define CFG_STA_AUTH_RETRIES_FOR_CODE17_MIN ( 0 ) +#define CFG_STA_AUTH_RETRIES_FOR_CODE17_MAX ( 5 ) +#define CFG_STA_AUTH_RETRIES_FOR_CODE17_DEFAULT ( 0 ) + typedef enum { eHDD_LINK_SPEED_REPORT_ACTUAL = 0, @@ -1656,6 +1701,29 @@ typedef enum #define CFG_ENABLE_TCP_DELACK_MAX (1) #define CFG_ENABLE_TCP_DELACK_DEFAULT (1) +#ifdef SAP_AUTH_OFFLOAD +/* Enable/Disable SAP Authentication offload + * Default: enable + */ +#define CFG_ENABLE_SAP_AUTH_OFL_NAME "gEnableSAPAuthOffload" +#define CFG_ENABLE_SAP_AUTH_OFL_MIN ( 0 ) +#define CFG_ENABLE_SAP_AUTH_OFL_MAX ( 1 ) +#define CFG_ENABLE_SAP_AUTH_OFL_DEFAULT ( 1 ) + +/* SAP Authentication offload Security Type + * 0: None Security + * 1: WPA2-PSK CCMP + */ +#define CFG_SAP_AUTH_OFL_SECURITY_TYPE_NAME "gSAPAuthOffloadSec" +#define CFG_SAP_AUTH_OFL_SECURITY_TYPE_MIN ( 0 ) +#define CFG_SAP_AUTH_OFL_SECURITY_TYPE_MAX ( 1 ) +#define CFG_SAP_AUTH_OFL_SECURITY_TYPE_DEFAULT ( 0 ) + +/* SAP Authentication offload Security Key */ +#define CFG_SAP_AUTH_OFL_KEY_NAME "gSAPAuthOffloadKey" +#define CFG_SAP_AUTH_OFL_KEY_DEFAULT "" +#endif /* SAP_AUTH_OFFLOAD */ + /* In cfg.dat 1=1MBPS, 2=2MBPS, 3=5_5MBPS, 4=11MBPS, 5=6MBPS, 6=9MBPS, * 7=12MBPS, 8=18MBPS, 9=24MBPS. But 6=9MBPS and 8=18MBPS are not basic * 11g rates and should not be set by gDefaultRateIndex24Ghz. So instead @@ -2374,6 +2442,13 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_BTC_STATIC_OPP_WLAN_IDLE_BT_LEN_DEFAULT ( 120000 ) #define CFG_BTC_STATIC_OPP_WLAN_IDLE_BT_LEN_MIN ( 0 ) #define CFG_BTC_STATIC_OPP_WLAN_IDLE_BT_LEN_MAX ( 250000 ) + + +#define CFG_BTC_DISABLE_WLAN_LINK_CRITICAL "gBtcDisableWlanLinkCritical" +#define CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_DEFAULT ( 0 ) +#define CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_MIN ( 0 ) +#define CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_MAX ( 1 ) + /* * Connection related log Enable/Disable. * 0x1 - Enable mgmt pkt logs (no probe req/rsp). @@ -2404,7 +2479,7 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_RA_RATE_LIMIT_INTERVAL_NAME "gRARateLimitInterval" #define CFG_RA_RATE_LIMIT_INTERVAL_DEFAULT (60) #define CFG_RA_RATE_LIMIT_INTERVAL_MIN (0) -#define CFG_RA_RATE_LIMIT_INTERVAL_MAX (60) +#define CFG_RA_RATE_LIMIT_INTERVAL_MAX (3600) #define CFG_ROAMING_DFS_CHANNEL_NAME "gAllowDFSChannelRoam" #define CFG_ROAMING_DFS_CHANNEL_MIN (0) @@ -2708,6 +2783,102 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_DISABLE_BAR_WAKEUP_HOST_MAX 1 #define CFG_DISABLE_BAR_WAKEUP_HOST_DEFAULT 0 +#ifdef DHCP_SERVER_OFFLOAD +/* + * Enable/Disable DHCP Server Offload + * Default: Disable + */ +#define CFG_DHCP_SERVER_OFFLOAD_SUPPORT_NAME "gDHCPServerOffloadEnable" +#define CFG_DHCP_SERVER_OFFLOAD_SUPPORT_MIN ( 0 ) +#define CFG_DHCP_SERVER_OFFLOAD_SUPPORT_MAX ( 1 ) +#define CFG_DHCP_SERVER_OFFLOAD_SUPPORT_DEFAULT ( 1 ) + +/* Max number of DHCP clients to be supported */ +#define CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_NAME "gDHCPMaxNumClients" +#define CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_MIN ( 1 ) +#define CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_MAX ( 4 ) +#define CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_DEFAULT ( 4 ) + +/* Start address of the pool */ +#define CFG_DHCP_SERVER_OFFLOAD_START_LSB_NAME "gDHCPStartLsb" +#define CFG_DHCP_SERVER_OFFLOAD_START_LSB_MIN ( 100 ) +#define CFG_DHCP_SERVER_OFFLOAD_START_LSB_MAX ( 255 ) +#define CFG_DHCP_SERVER_OFFLOAD_START_LSB_DEFAULT ( 100 ) + +/* DHCP Server IP*/ +#define CFG_DHCP_SERVER_IP_NAME "gDHCPServerIP" +#define CFG_DHCP_SERVER_IP_DEFAULT "192.168.43.1" +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +/* + * Enable/Disable multicast DNS Offload + * 0x0 - Disable mDNS (Default) + * 0x1 - Enable mDNS + */ +#define CFG_MDNS_OFFLOAD_SUPPORT_NAME "gMDNSOffloadEnable" +#define CFG_MDNS_OFFLOAD_SUPPORT_MIN ( 0 ) +#define CFG_MDNS_OFFLOAD_SUPPORT_MAX ( 1 ) +#define CFG_MDNS_OFFLOAD_SUPPORT_ENABLE ( 1 ) +#define CFG_MDNS_OFFLOAD_SUPPORT_DEFAULT ( 1 ) + +/* Set FQDN string for mDNS */ +#define CFG_MDNS_FQDN_NAME "gMDNSFqdn" +#define CFG_MDNS_FQDN_DEFAULT "_GoProRemote._tcp.local" + +/* Set UFQDN string for mDNS */ +#define CFG_MDNS_UNIQUE_FQDN_NAME "gMDNSUniqueFqdn" +#define CFG_MDNS_UNIQUE_FQDN_DEFAULT "service._GoProRemote._tcp.local" + +/* Set the response Type A to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_A_NAME "gMDNSResponseTypeA" +#define CFG_MDNS_RESPONSE_TYPE_A_DEFAULT "goprobp-D89685121212.local" + +#define CFG_MDNS_RESPONSE_TYPE_A_IPV4_NAME "gMDNSResponseTypeAIpv4Addr" +#define CFG_MDNS_RESPONSE_TYPE_A_IPV4_MIN ( 1 ) +#define CFG_MDNS_RESPONSE_TYPE_A_IPV4_MAX ( 0xffffffff ) +#define CFG_MDNS_RESPONSE_TYPE_A_IPV4_DEFAULT ( 0xc0a80102 ) + +/* Set the response Type TXT to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_TXT_NAME "gMDNSResponseTypeTXT" +#define CFG_MDNS_RESPONSE_TYPE_TXT_DEFAULT "GoProBP-D89685121212._GoProRemote._tcp.local" + +#define CFG_MDNS_RESPONSE_TYPE_TXT_CNT_NAME "gMDNSResponseTypeTXTContent" +#define CFG_MDNS_RESPONSE_TYPE_TXT_CNT_DEFAULT "Device=HERO 3+-BAWA Model=BAWA Version=HD3.11.02.00 Wifi Version=4.0.36.0 Protocol Version=2" + +/* Set the response Type PTR to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_PTR_NAME "gMDNSResponseTypePTR" +#define CFG_MDNS_RESPONSE_TYPE_PTR_DEFAULT "_GoProRemote._tcp.local" + +#define CFG_MDNS_RESPONSE_TYPE_PTR_DN_NAME "gMDNSResponseTypePTRDomainName" +#define CFG_MDNS_RESPONSE_TYPE_PTR_DN_DEFAULT "GoProBP-D89685121212._GoProRemote._tcp.local" + +/* Set the response Type SRV to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_SRV_NAME "gMDNSResponseTypeSRV" +#define CFG_MDNS_RESPONSE_TYPE_SRV_DEFAULT "GoProBP-D89685121212._GoProRemote._tcp.local" + +/* Set the response Type SRV Priority to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_SRV_PRIORITY_NAME "gMDNSResponseTypeSRVPriority" +#define CFG_MDNS_RESPONSE_TYPE_SRV_PRIORITY_MIN ( 0 ) +#define CFG_MDNS_RESPONSE_TYPE_SRV_PRIORITY_MAX ( 65535 ) +#define CFG_MDNS_RESPONSE_TYPE_SRV_PRIORITY_DEFAULT ( 0 ) + +/* Set the response Type SRV Weight to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_SRV_WEIGHT_NAME "gMDNSResponseTypeSRVWeight" +#define CFG_MDNS_RESPONSE_TYPE_SRV_WEIGHT_MIN ( 0 ) +#define CFG_MDNS_RESPONSE_TYPE_SRV_WEIGHT_MAX ( 65525 ) +#define CFG_MDNS_RESPONSE_TYPE_SRV_WEIGHT_DEFAULT ( 0 ) + +/* Set the response Type SRV Port to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_SRV_PORT_NAME "gMDNSResponseTypeSRVPort" +#define CFG_MDNS_RESPONSE_TYPE_SRV_PORT_MIN ( 0 ) +#define CFG_MDNS_RESPONSE_TYPE_SRV_PORT_MAX ( 65525 ) +#define CFG_MDNS_RESPONSE_TYPE_SRV_PORT_DEFAULT ( 80 ) + +/* Set the response Type SRV Target to mDNS queries */ +#define CFG_MDNS_RESPONSE_TYPE_SRV_TGT_NAME "gMDNSResponseTypeSRVTarget" +#define CFG_MDNS_RESPONSE_TYPE_SRV_TGT_DEFAULT "goprobp-D89685121212.local" +#endif /* MDNS_OFFLOAD */ /* * gExtScanConcMode is used to manage EXT Scan during concurrency @@ -2871,11 +3042,6 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_SAP_PROBE_RESP_OFFLOAD_MAX (1) #define CFG_SAP_PROBE_RESP_OFFLOAD_DEFAULT (1) -#define CFG_SAP_INTERNAL_RESTART_NAME "gEnableSapInternalRestart" -#define CFG_SAP_INTERNAL_RESTART_MIN (0) -#define CFG_SAP_INTERNAL_RESTART_MAX (1) -#define CFG_SAP_INTERNAL_RESTART_DEFAULT (1) - /* * gDisableScanDuringSco is used to disable/enable scan during SCO call * This can be useful to avoid glitches because of EXIT_IMPS invoked by scan @@ -2888,6 +3054,44 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_DISABLE_SCAN_DURING_SCO_MAX (1) #define CFG_DISABLE_SCAN_DURING_SCO_DEFAULT (0) +#define CFG_SAP_INTERNAL_RESTART_NAME "gEnableSapInternalRestart" +#define CFG_SAP_INTERNAL_RESTART_MIN (0) +#define CFG_SAP_INTERNAL_RESTART_MAX (1) +#define CFG_SAP_INTERNAL_RESTART_DEFAULT (1) + +/* + * maximum interval (in seconds) for a + * single scan plan supported by the device. + */ +#define CFG_MAX_SCHED_SCAN_PLAN_INT_NAME "g_max_sched_scan_plan_int" +#define CFG_MAX_SCHED_SCAN_PLAN_INT_MIN (1) +#define CFG_MAX_SCHED_SCAN_PLAN_INT_MAX (7200) +#define CFG_MAX_SCHED_SCAN_PLAN_INT_DEFAULT (3600) + +/* + * maximum number of iterations for a single + * scan plan supported by the device. + */ +#define CFG_MAX_SCHED_SCAN_PLAN_ITRNS_NAME "g_max_sched_scan_plan_itrns" +#define CFG_MAX_SCHED_SCAN_PLAN_ITRNS_MIN (1) +#define CFG_MAX_SCHED_SCAN_PLAN_ITRNS_MAX (100) +#define CFG_MAX_SCHED_SCAN_PLAN_ITRNS_DEFAULT (10) + +/* + * gEnableLFRMBB is used to disable/enable LFR Make before Break + * 1: Enable LFR Make before Break + * 0: Disable LFR Make before Break + */ +#define CFG_ENABLE_LFR_MBB "gEnableLFRMBB" +#define CFG_ENABLE_LFR_MBB_MIN (0) +#define CFG_ENABLE_LFR_MBB_MAX (1) +#define CFG_ENABLE_LFR_MBB_DEFAULT (0) + +/* Value for TRIGGER_NULLFRAME_BEFORE_HB.*/ +#define CFG_TRIGGER_NULLFRAME_BEFORE_HB_NAME "gTriggerNullframeBeforeHb" +#define CFG_TRIGGER_NULLFRAME_BEFORE_HB_MIN (0) +#define CFG_TRIGGER_NULLFRAME_BEFORE_HB_MAX (1) +#define CFG_TRIGGER_NULLFRAME_BEFORE_HB_DEFAULT (0) /*--------------------------------------------------------------------------- Type declarations @@ -2964,6 +3168,7 @@ typedef struct v_U32_t nAutoBmpsTimerValue; eHddDot11Mode dot11Mode; v_U32_t nChannelBondingMode24GHz; + bool override_ht20_40_24g; v_U32_t nChannelBondingMode5GHz; v_U32_t MaxRxAmpduFactor; v_U32_t nBAAgingTimerInterval; @@ -3032,6 +3237,7 @@ typedef struct v_U16_t nNeighborResultsRefreshPeriod; v_U16_t nEmptyScanRefreshPeriod; v_U8_t nNeighborInitialForcedRoamTo5GhEnable; + v_U8_t nWeakZoneRssiThresholdForRoam; #endif //Additional Handoff params @@ -3119,6 +3325,11 @@ typedef struct v_U32_t PERtimerThreshold; v_U32_t PERroamRxPktsThreshold; #endif + +#ifdef WLAN_FEATURE_LFR_MBB + tANI_BOOLEAN enable_lfr_mbb; +#endif + hdd_wmm_classification_t PktClassificationBasis; // DSCP or 802.1Q v_BOOL_t bImplicitQosEnabled; @@ -3419,6 +3630,7 @@ typedef struct v_BOOL_t toggleArpBDRates; v_U32_t btcStaticOppWlanIdleWlanLen; v_U32_t btcStaticOppWlanIdleBtLen; + v_U32_t btc_disable_wlan_link_critical; v_U32_t linkFailTimeout; v_U32_t linkFailTxCnt; v_BOOL_t ignorePeerHTopMode; @@ -3434,6 +3646,28 @@ typedef struct v_U8_t max_chan_for_dwell_time_cfg; v_U16_t tdls_enable_defer_time; v_U8_t boffset_correction_enable; +#ifdef DHCP_SERVER_OFFLOAD + v_BOOL_t enable_dhcp_srv_offload; + v_U32_t dhcp_max_num_clients; + v_U8_t dhcp_srv_ip[IPADDR_STRING_LENGTH]; + v_U8_t dhcp_start_lsb; +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + uint32_t enable_mdns_offload; + uint8_t mdns_fqdn[MAX_MDNS_FQDN_LEN]; + uint8_t mdns_uniquefqdn[MAX_MDNS_FQDN_LEN]; + uint8_t mdns_resp_type_a[MAX_MDNS_RESP_LEN]; + uint32_t mdns_resp_type_a_ipv4; + uint8_t mdns_resp_type_txt[MAX_MDNS_RESP_LEN]; + uint8_t mdns_resp_type_txt_content[MAX_MDNS_RESP_LEN]; + uint8_t mdns_resp_type_ptr[MAX_MDNS_RESP_LEN]; + uint8_t mdns_resp_type_ptr_dname[MAX_MDNS_RESP_LEN]; + uint8_t mdns_resp_type_srv[MAX_MDNS_RESP_LEN]; + uint16_t mdns_resp_type_srv_priority; + uint16_t mdns_resp_type_srv_weight; + uint16_t mdns_resp_type_srv_port; + uint8_t mdns_resp_type_srv_target[MAX_MDNS_RESP_LEN]; +#endif /* MDNS_OFFLOAD */ uint32_t enable_edca_params; uint32_t edca_vo_cwmin; uint32_t edca_vi_cwmin; @@ -3449,8 +3683,17 @@ typedef struct uint32_t edca_be_aifs; v_BOOL_t sendMgmtPktViaWQ5; v_BOOL_t sap_probe_resp_offload; - v_BOOL_t sap_internal_restart; v_BOOL_t disable_scan_during_sco; + v_BOOL_t sap_internal_restart; +#ifdef SAP_AUTH_OFFLOAD + bool enable_sap_auth_offload; + uint32_t sap_auth_offload_sec_type; + uint8_t sap_auth_offload_key[WLAN_PSK_STRING_LENGTH]; +#endif /* SAP_AUTH_OFFLOAD */ + uint32_t max_sched_scan_plan_interval; + uint32_t max_sched_scan_plan_iterations; + uint32_t sta_auth_retries_for_code17; + uint32_t trigger_nullframe_before_hb; } hdd_config_t; /*--------------------------------------------------------------------------- @@ -3464,6 +3707,16 @@ eCsrPhyMode hdd_cfg_xlate_to_csr_phy_mode( eHddDot11Mode dot11Mode ); VOS_STATUS hdd_execute_config_command(hdd_context_t *pHddCtx, char *command); tANI_BOOLEAN hdd_is_okc_mode_enabled(hdd_context_t *pHddCtx); +VOS_STATUS hdd_string_to_u8_array(char *str, tANI_U8 *intArray, tANI_U8 *len, + tANI_U8 intArrayMaxLen, char *seperator); + +#ifdef MDNS_OFFLOAD +int hdd_string_to_string_array(char *data, uint8_t *datalist, + char separator, uint8_t *num_entries, + uint8_t max_entries, + uint8_t max_len_entry); +#endif /* MDNS_OFFLOAD */ + #define VAR_OFFSET( _Struct, _Var ) (offsetof(_Struct, _Var)) #define VAR_SIZE( _Struct, _Var ) (sizeof(((_Struct *)0)->_Var)) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h index 6307b18ccce..ef99dd041de 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -110,6 +110,7 @@ #define NUM_RADIOS 0x1 #endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + typedef struct { u8 element_id; u8 len; @@ -172,6 +173,7 @@ enum qca_nl80211_vendor_subcmds { /* Get Concurrency Matrix */ QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX = 42, + QCA_NL80211_VENDOR_SUBCMD_APFIND = 52, /* Start Wifi Logger */ QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START = 62, @@ -200,12 +202,159 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105, + /* send BSS Information */ + QCA_NL80211_VENDOR_SUBCMD_GET_STATION = 121, + /* Start / Stop the NUD stats collections */ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET = 149, /* Get the NUD stats, represented by the enum qca_attr_nud_stats_get */ QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET = 150, }; +/** + * enum qca_wlan_vendor_attr_get_station - Sub commands used by + * QCA_NL80211_VENDOR_SUBCMD_GET_STATION to get the corresponding + * station information. The information obtained through these + * commands signify the current info in connected state and + * latest cached information during the connected state , if queried + * when in disconnected state. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO: bss info + * @QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON: assoc fail reason + */ +enum qca_wlan_vendor_attr_get_station { + QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO, + QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_GET_STATION_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX = + QCA_WLAN_VENDOR_ATTR_GET_STATION_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_802_11_mode - dot11 mode + * @QCA_WLAN_802_11_MODE_INVALID: Invalid dot11 mode + * @QCA_WLAN_802_11_MODE_11A: mode A + * @QCA_WLAN_802_11_MODE_11B: mode B + * @QCA_WLAN_802_11_MODE_11G: mode G + * @QCA_WLAN_802_11_MODE_11N: mode N + * @QCA_WLAN_802_11_MODE_11AC: mode AC + */ +enum qca_wlan_802_11_mode { + QCA_WLAN_802_11_MODE_INVALID, + QCA_WLAN_802_11_MODE_11A, + QCA_WLAN_802_11_MODE_11B, + QCA_WLAN_802_11_MODE_11G, + QCA_WLAN_802_11_MODE_11N, + QCA_WLAN_802_11_MODE_11AC, +}; + +/** + * enum qca_wlan_auth_type - Authentication key management type + * @QCA_WLAN_AUTH_TYPE_INVALID: Invalid key management type + * @QCA_WLAN_AUTH_TYPE_OPEN: Open key + * @QCA_WLAN_AUTH_TYPE_SHARED: shared key + * @QCA_WLAN_AUTH_TYPE_WPA: wpa key + * @QCA_WLAN_AUTH_TYPE_WPA_PSK: wpa psk key + * @QCA_WLAN_AUTH_TYPE_WPA_NONE: wpa none key + * @QCA_WLAN_AUTH_TYPE_RSN: rsn key + * @QCA_WLAN_AUTH_TYPE_RSN_PSK: rsn psk key + * @QCA_WLAN_AUTH_TYPE_FT: ft key + * @QCA_WLAN_AUTH_TYPE_FT_PSK: ft psk key + * @QCA_WLAN_AUTH_TYPE_SHA256: shared 256 key + * @QCA_WLAN_AUTH_TYPE_SHA256_PSK: shared 256 psk + * @QCA_WLAN_AUTH_TYPE_WAI: wai key + * @QCA_WLAN_AUTH_TYPE_WAI_PSK wai psk key + * @QCA_WLAN_AUTH_TYPE_CCKM_WPA: cckm wpa key + * @QCA_WLAN_AUTH_TYPE_CCKM_RSN: cckm rsn key + */ +enum qca_wlan_auth_type { + QCA_WLAN_AUTH_TYPE_INVALID, + QCA_WLAN_AUTH_TYPE_OPEN, + QCA_WLAN_AUTH_TYPE_SHARED, + QCA_WLAN_AUTH_TYPE_WPA, + QCA_WLAN_AUTH_TYPE_WPA_PSK, + QCA_WLAN_AUTH_TYPE_WPA_NONE, + QCA_WLAN_AUTH_TYPE_RSN, + QCA_WLAN_AUTH_TYPE_RSN_PSK, + QCA_WLAN_AUTH_TYPE_FT, + QCA_WLAN_AUTH_TYPE_FT_PSK, + QCA_WLAN_AUTH_TYPE_SHA256, + QCA_WLAN_AUTH_TYPE_SHA256_PSK, + QCA_WLAN_AUTH_TYPE_WAI, + QCA_WLAN_AUTH_TYPE_WAI_PSK, + QCA_WLAN_AUTH_TYPE_CCKM_WPA, + QCA_WLAN_AUTH_TYPE_CCKM_RSN, + QCA_WLAN_AUTH_TYPE_AUTOSWITCH, +}; + +/** + * enum qca_wlan_vendor_attr_get_station_info - Station Info queried + * through QCA_NL80211_VENDOR_SUBCMD_GET_STATION. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_INVALID: Invalid Attribute + * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR: + * Get the standard NL attributes Nested with this attribute. + * Ex : Query BW , BITRATE32 , NSS , Signal , Noise of the Link - + * NL80211_ATTR_SSID / NL80211_ATTR_SURVEY_INFO (Connected Channel) / + * NL80211_ATTR_STA_INFO + * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_STANDARD_NL80211_ATTR: + * Get the standard NL attributes Nested with this attribute. + * Ex : Query HT/VHT Capability advertized by the AP. + * NL80211_ATTR_VHT_CAPABILITY / NL80211_ATTR_HT_CAPABILITY + * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT: + * Number of successful Roam attempts before a + * disconnect, Unsigned 32 bit value + * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM: + * Authentication Key Management Type used for the connected session. + * Signified by enum qca_wlan_auth_type + * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE: 802.11 Mode of the + * connected Session, signified by enum qca_wlan_802_11_mode + * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION: + * HS20 Indication Element + * @QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_FAIL_REASON: + * Status Code Corresponding to the Association Failure. + * Unsigned 32 bit value. + */ +enum qca_wlan_vendor_attr_get_station_info { + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_STANDARD_NL80211_ATTR, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_FAIL_REASON, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_MAX = + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AFTER_LAST - 1, +}; + +/* define short names for get station info attributes */ +#define LINK_INFO_STANDARD_NL80211_ATTR \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR +#define AP_INFO_STANDARD_NL80211_ATTR \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_STANDARD_NL80211_ATTR +#define INFO_ROAM_COUNT \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT +#define INFO_AKM \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM +#define WLAN802_11_MODE \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE +#define AP_INFO_HS20_INDICATION \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION +#define HT_OPERATION \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION +#define VHT_OPERATION \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION +#define INFO_ASSOC_FAIL_REASON \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_FAIL_REASON + enum qca_nl80211_vendor_subcmds_index { #ifdef FEATURE_WLAN_CH_AVOID QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX, @@ -291,7 +440,7 @@ enum qca_attr_nud_stats_get { QCA_ATTR_NUD_STATS_GET_LAST, QCA_ATTR_NUD_STATS_GET_MAX = QCA_ATTR_NUD_STATS_GET_LAST - 1, -}; + }; enum qca_wlan_vendor_attr { @@ -1162,6 +1311,10 @@ enum qca_wlan_vendor_config { QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_RATE, QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS, + /* 8-bit unsigned value to set the beacon miss threshold in 2.4 GHz */ + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24 = 37, + /* 8-bit unsigned value to set the beacon miss threshold in 5 GHz */ + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_5 = 38, /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = @@ -1508,4 +1661,5 @@ int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, #endif int wlan_hdd_cfg80211_update_apies(hdd_adapter_t *pHostapdAdapter); +int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter); #endif diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_hostapd.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_hostapd.h index ed52105fc37..1c9aec96211 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_hostapd.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_hostapd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -116,8 +116,34 @@ void hdd_restart_softap (hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter); void hdd_hostapd_ch_avoid_cb(void *pAdapter, void *indParam); #endif /* FEATURE_WLAN_CH_AVOID */ int hdd_del_all_sta(hdd_adapter_t *pAdapter); - void hdd_sap_indicate_disconnect_for_sta(hdd_adapter_t *adapter); void hdd_sap_destroy_timers(hdd_adapter_t *adapter); +#ifdef SAP_AUTH_OFFLOAD +bool hdd_set_sap_auth_offload(hdd_adapter_t *pHostapdAdapter, + bool enabled); +#else +static inline bool +hdd_set_sap_auth_offload(hdd_adapter_t *pHostapdAdapter, bool enabled) +{ +} +#endif + +/** + * hdd_check_for_unsafe_ch() - Check the current operating channel with + * unsafe channel list. + * @phostapd_adapter : Pointer to HDD adapter. + * @hdd_ctx: pointer to hdd context. + * + * Check the current operating chennel of SAP with unsafe channel list + * and Restart the SAP on safe channel if currently SAP is + * on unsafe channel. + * + * Return : None + */ +void hdd_check_for_unsafe_ch(hdd_adapter_t *phostapd_adapter, + hdd_context_t *hdd_ctx); +void hdd_force_scc_restart_sap(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, tANI_U8 channelId); + #endif // end #if !defined( WLAN_HDD_HOSTAPD_H ) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h index 91d3e4b507e..4b9c5a7b974 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h @@ -106,11 +106,12 @@ /** Maximum time(ms)to wait for disconnect to complete **/ #define WLAN_WAIT_TIME_DISCONNECT 5000 #define WLAN_WAIT_TIME_STATS 800 -#define WLAN_WAIT_TIME_POWER 800 +#define WLAN_WAIT_TIME_POWER 5000 #define WLAN_WAIT_TIME_COUNTRY 1000 #define WLAN_WAIT_TIME_CHANNEL_UPDATE 600 #define FW_STATE_WAIT_TIME 500 #define FW_STATE_RSP_LEN 100 + /* Amount of time to wait for sme close session callback. This value should be larger than the timeout used by WDI to wait for a response from WCNSS */ @@ -161,6 +162,7 @@ #define hddLog(level, args...) VOS_TRACE( VOS_MODULE_ID_HDD, level, ## args) #define ENTER() VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Enter:%s", __func__) #define EXIT() VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Exit:%s", __func__) +#define ENTER_DEV(dev) VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Enter:%s dev_name: %s", __func__, (dev)->name) #define WLAN_HDD_GET_PRIV_PTR(__dev__) (hdd_adapter_t*)(netdev_priv((__dev__))) @@ -246,6 +248,27 @@ typedef v_U8_t tWlanHddMacAddr[HDD_MAC_ADDR_LEN]; #define WLAN_WAIT_TIME_EXTSCAN 1000 +#define HDD_MAX_STA_COUNT (HAL_NUM_STA) + +#ifdef MDNS_OFFLOAD +#define MDNS_HEADER_LEN 12 +#define MDNS_FQDN_TYPE_GENERAL 0 +#define MDNS_FQDN_TYPE_UNIQUE 1 +#define MAX_NUM_FIELD_DOMAINNAME 6 +#define MAX_LEN_DOMAINNAME_FIELD 64 +#define MAX_MDNS_RESP_TYPE 6 +#define MDNS_TYPE_A 1 +#define MDNS_TYPE_TXT 16 +#define MDNS_TYPE_PTR 12 +#define MDNS_TYPE_PTR_DNAME 13 +#define MDNS_TYPE_SRV 33 +#define MDNS_TYPE_SRV_TARGET 34 +#define MDNS_CLASS 1 +#define MDNS_TTL 5 +#endif /* MDNS_OFFLOAD */ + +#define HDD_MIN_TX_POWER (-100) /* minimum tx power */ +#define HDD_MAX_TX_POWER (+100) /* maximum tx power */ /* * Generic asynchronous request/response support * @@ -394,8 +417,8 @@ typedef enum typedef struct hdd_arp_stats_s { - uint16 tx_arp_req_count; - uint16 rx_arp_rsp_count; + uint16 txCount; + uint16 rxCount; uint16 txDropped; uint16 rxDropped; uint16 rxDelivered; @@ -799,6 +822,7 @@ struct hdd_station_ctx hdd_ibss_peer_info_t ibss_peer_info; v_BOOL_t hdd_ReassocScenario; + v_BOOL_t get_mgmt_log_sent; }; @@ -813,7 +837,82 @@ typedef struct hdd_hostapd_state_s } hdd_hostapd_state_t; +#ifdef DHCP_SERVER_OFFLOAD +typedef struct hdd_dhcp_state_s +{ + VOS_STATUS dhcp_offload_status; + vos_event_t vos_event; +} hdd_dhcp_state_t; +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +typedef struct hdd_mdns_state_s +{ + VOS_STATUS mdns_enable_status; + VOS_STATUS mdns_fqdn_status; + VOS_STATUS mdns_resp_status; + vos_event_t vos_event; +} hdd_mdns_state_t; +#endif /* MDNS_OFFLOAD */ + +#ifdef WLAN_FEATURE_TSF + +#define HDD_TSF_CAP_REQ_TIMEOUT 2000 +#define HDD_TSF_GET_REQ_TIMEOUT 2000 + +/** + * enum hdd_tsf_get_state - status of get tsf action + * + * TSF_RETURN: get tsf + * TSF_STA_NOT_CONNECTED_NO_TSF: sta not connected to ap + * TSF_NOT_RETURNED_BY_FW: fw not returned tsf + * TSF_CURRENT_IN_CAP_STATE: driver in capture state + * TSF_CAPTURE_FAIL: capture fail + * TSF_GET_FAIL: get fail + * TSF_RESET_GPIO_FAIL: GPIO reset fail + * TSF_SAP_NOT_STARTED_NO_TSF SAP not started + */ +enum hdd_tsf_get_state { + TSF_RETURN = 0, + TSF_STA_NOT_CONNECTED_NO_TSF, + TSF_NOT_RETURNED_BY_FW, + TSF_CURRENT_IN_CAP_STATE, + TSF_CAPTURE_FAIL, + TSF_GET_FAIL, + TSF_RESET_GPIO_FAIL, + TSF_SAP_NOT_STARTED_NO_TSF +}; + +/** + * enum hdd_tsf_capture_state - status of capture + * + * TSF_IDLE: idle + * TSF__CAP_STATE: current is in capture state + */ +enum hdd_tsf_capture_state { + TSF_IDLE = 0, + TSF_CAP_STATE +}; + +/** + * struct hdd_tsf_ctx_s - TSF capture ctx + * @tsf_get_state : tsf action enum + * @tsf_capture_state: tsf capture state enum + * @tsf_capture_done_event : Indicate tsf completion + * @tsf_high : Higher 32-bit for 64-bit tsf + * @tsf_lo : Lower 32-bit for 64-bit tsf + * + */ +struct hdd_tsf_ctx_s { + enum hdd_tsf_get_state tsf_get_state; + enum hdd_tsf_capture_state tsf_capture_state; + vos_event_t tsf_capture_done_event; + vos_spin_lock_t tsf_lock; + uint32_t tsf_high; + uint32_t tsf_low; +}; +#endif /* WLAN_FEATURE_TSF */ /* * Per station structure kept in HDD for multiple station support for SoftAP */ @@ -994,6 +1093,8 @@ typedef enum #endif +#define HDD_SCAN_REJECT_RATE_LIMIT 5 + /* * @eHDD_SCAN_REJECT_DEFAULT: default value * @eHDD_CONNECTION_IN_PROGRESS: connection is in progress @@ -1110,6 +1211,9 @@ struct hdd_adapter_s struct completion ibss_peer_info_comp; #endif /* WLAN_FEATURE_RMC */ + /* completion variable for wlan suspend */ + struct completion wlan_suspend_comp_var; + /* Track whether the linkup handling is needed */ v_BOOL_t isLinkUpSvcNeeded; @@ -1148,7 +1252,10 @@ struct hdd_adapter_s #ifdef FEATURE_WLAN_WAPI hdd_wapi_info_t wapi_info; #endif - + + /* Keep track ns offload count */ + v_U8_t ns_slots; + v_S7_t rssi; v_S7_t rssi_on_disconnect; @@ -1249,9 +1356,18 @@ struct hdd_adapter_s /* Currently used antenna Index*/ int antennaIndex; - bool nud_set_arp_stats; - bool con_status; - bool dad; +#ifdef DHCP_SERVER_OFFLOAD + hdd_dhcp_state_t dhcp_status; +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + hdd_mdns_state_t mdns_status; +#endif /* MDNS_OFFLOAD */ + +#ifdef WLAN_FEATURE_TSF + struct hdd_tsf_ctx_s tsf_cap_ctx; +#endif + bool con_status; + bool dad; }; #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station) @@ -1369,6 +1485,7 @@ struct hdd_ll_stats_context { struct hdd_nud_stats_context { struct completion response_event; }; + #ifdef WLAN_FEATURE_EXTSCAN /** * struct hdd_ext_scan_context - hdd ext scan context @@ -1504,6 +1621,8 @@ struct hdd_context_s v_BOOL_t hdd_wlan_suspended; bool rx_wow_dump; + + uint8_t bad_sta[HDD_MAX_STA_COUNT]; spinlock_t filter_lock; @@ -1689,6 +1808,8 @@ struct hdd_context_s scan_reject_states last_scan_reject_reason; v_TIME_t last_scan_reject_timestamp; v_U8_t scan_reject_cnt; + bool is_ap_mode_wow_supported; + bool is_fatal_event_log_sup; uint32_t track_arp_ip; }; @@ -1757,6 +1878,20 @@ typedef enum WLAN_FW_MEM_DUMP_EN = 1<<6, } WLAN_ENABLE_HW_FW_LOG_TYPE; +#ifdef MDNS_OFFLOAD +/* Offload struct */ +struct hdd_mdns_resp_info { + uint8_t num_entries; + uint8_t *data; + uint16_t *offset; +}; + +struct hdd_mdns_resp_matched { + uint8_t num_matched; + uint8_t type; +}; +#endif /* MDNS_OFFLOAD */ + /*--------------------------------------------------------------------------- Function declarations and documenation -------------------------------------------------------------------------*/ @@ -2040,7 +2175,55 @@ void wlan_hdd_defer_scan_init_work(hdd_context_t *pHddCtx, unsigned long delay); int hdd_reassoc(hdd_adapter_t *pAdapter, const tANI_U8 *bssid, const tANI_U8 channel, const handoff_src src); +#ifdef DHCP_SERVER_OFFLOAD +VOS_STATUS wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *hostapd_adapter, + bool re_init); +#endif +#ifdef MDNS_OFFLOAD +bool wlan_hdd_set_mdns_offload(hdd_adapter_t *adapter); +#else +static inline bool wlan_hdd_set_mdns_offload(hdd_adapter_t *adapter) +{ + return FALSE; +} +#endif /* MDNS_OFFLOAD */ void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter); +/** + * hdd_drv_cmd_validate() - Validates for space in hdd driver command + * @command: pointer to input data (its a NULL terminated string) + * @len: length of command name + * + * This function checks for space after command name and if no space + * is found returns error. + * + * Return: 0 for success non-zero for failure + */ +int hdd_drv_cmd_validate(tANI_U8 *command, int len); + +#ifdef WLAN_FEATURE_TSF +void wlan_hdd_tsf_init(hdd_adapter_t *adapter); +int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len); +int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len); +#else +static inline void +wlan_hdd_tsf_init(hdd_adapter_t *adapter) +{ + return; +} + +static inline int +hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len) +{ + return -ENOTSUPP; +} + +static inline int +hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len) +{ + return -ENOTSUPP; +} +#endif +int hdd_dhcp_mdns_offload(hdd_adapter_t *adapter); #endif // end #if !defined( WLAN_HDD_MAIN_H ) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_oemdata.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_oemdata.h index 5b68187dfbe..47522e172ee 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_oemdata.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_oemdata.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -71,6 +71,7 @@ struct iw_oem_data_rsp }; int oem_activate_service(void *pAdapter); +void oem_deactivate_service(void); int iw_get_oem_data_cap(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h index bc58f4ad459..c9731f1d9dc 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h @@ -539,4 +539,6 @@ tdlsConnInfo_t *wlan_hdd_get_conn_info(hdd_context_t *pHddCtx, v_VOID_t wlan_hdd_tdls_initiator_wait_cb(v_PVOID_t userData); +void wlan_hdd_get_tdls_stats(hdd_adapter_t *pAdapter); + #endif // __HDD_TDSL_H diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h index 68f7174b4ba..06c5accb2ff 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -400,4 +400,14 @@ static inline void wlan_hdd_log_eapol(struct sk_buff *skb, } #endif /* FEATURE_WLAN_DIAG_SUPPORT */ +/** + * hdd_rx_fwd_eapol() - forward cached eapol frames + * @vosContext : pointer to vos global context + * @pVosPacket: pointer to vos packet + * + * Return: None + * + */ +void hdd_rx_fwd_eapol(v_VOID_t *vosContext, vos_pkt_t *pVosPacket); + #endif // end #if !defined( WLAN_HDD_TX_RX_H ) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h index fe8bfed2118..1a58dc027fd 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -463,6 +463,6 @@ void* wlan_hdd_change_country_code_callback(void *pAdapter); int hdd_setBand(struct net_device *dev, u8 ui_band); int hdd_setBand_helper(struct net_device *dev, const char *command); VOS_STATUS wlan_hdd_get_frame_logs(hdd_adapter_t *pAdapter, v_U8_t flag); -int wlan_hdd_set_proximity(int set_value); +int wlan_hdd_set_proximity(int set_value, tHalHandle hal); #endif // __WEXT_IW_H__ diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c index b7c935de763..6a962d4f373 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -266,6 +266,487 @@ static inline void hdd_connSaveConnectedBssType( hdd_station_ctx_t *pHddStaCtx, } +/** + * hdd_copy_vht_caps()- copy vht caps info from roam info to + * hdd station context. + * @hdd_sta_ctx: pointer to hdd station context + * @roam_info: pointer to roam info + * + * Return: None + */ +static void hdd_copy_ht_caps(hdd_station_ctx_t *hdd_sta_ctx, + tCsrRoamInfo *roam_info) +{ + tDot11fIEHTCaps *roam_ht_cap = &roam_info->ht_caps; + struct ieee80211_ht_cap *hdd_ht_cap = &hdd_sta_ctx->conn_info.ht_caps; + uint32_t i, temp_ht_cap; + + vos_mem_zero(hdd_ht_cap, sizeof(struct ieee80211_ht_cap)); + + if (roam_ht_cap->advCodingCap) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_LDPC_CODING; + if (roam_ht_cap->supportedChannelWidthSet) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; + temp_ht_cap = roam_ht_cap->mimoPowerSave & + (IEEE80211_HT_CAP_SM_PS >> IEEE80211_HT_CAP_SM_PS_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->cap_info |= + temp_ht_cap << IEEE80211_HT_CAP_SM_PS_SHIFT; + if (roam_ht_cap->greenField) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_GRN_FLD; + if (roam_ht_cap->shortGI20MHz) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_SGI_20; + if (roam_ht_cap->shortGI40MHz) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_SGI_40; + if (roam_ht_cap->txSTBC) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_TX_STBC; + temp_ht_cap = roam_ht_cap->rxSTBC & (IEEE80211_HT_CAP_RX_STBC >> + IEEE80211_HT_CAP_RX_STBC_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->cap_info |= + temp_ht_cap << IEEE80211_HT_CAP_RX_STBC_SHIFT; + if (roam_ht_cap->delayedBA) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_DELAY_BA; + if (roam_ht_cap->maximalAMSDUsize) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_MAX_AMSDU; + if (roam_ht_cap->dsssCckMode40MHz) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_DSSSCCK40; + if (roam_ht_cap->psmp) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_RESERVED; + if (roam_ht_cap->stbcControlFrame) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_40MHZ_INTOLERANT; + if (roam_ht_cap->lsigTXOPProtection) + hdd_ht_cap->cap_info |= IEEE80211_HT_CAP_LSIG_TXOP_PROT; + + + /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ + if (roam_ht_cap->maxRxAMPDUFactor) + hdd_ht_cap->ampdu_params_info |= + IEEE80211_HT_AMPDU_PARM_FACTOR; + temp_ht_cap = roam_ht_cap->mpduDensity & + (IEEE80211_HT_AMPDU_PARM_DENSITY >> + IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->ampdu_params_info |= + temp_ht_cap << IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT; + + /* 802.11n HT extended capabilities masks */ + if (roam_ht_cap->pco) + hdd_ht_cap->extended_ht_cap_info |= + IEEE80211_HT_EXT_CAP_PCO; + temp_ht_cap = roam_ht_cap->transitionTime & + (IEEE80211_HT_EXT_CAP_PCO_TIME >> + IEEE80211_HT_EXT_CAP_PCO_TIME_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->extended_ht_cap_info |= + temp_ht_cap << IEEE80211_HT_EXT_CAP_PCO_TIME_SHIFT; + temp_ht_cap = roam_ht_cap->mcsFeedback & + (IEEE80211_HT_EXT_CAP_MCS_FB >> IEEE80211_HT_EXT_CAP_MCS_FB_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->extended_ht_cap_info |= + temp_ht_cap << IEEE80211_HT_EXT_CAP_MCS_FB_SHIFT; + + /* tx_bf_cap_info capabilities */ + if (roam_ht_cap->txBF) + hdd_ht_cap->tx_BF_cap_info |= TX_BF_CAP_INFO_TX_BF; + if (roam_ht_cap->rxStaggeredSounding) + hdd_ht_cap->tx_BF_cap_info |= + TX_BF_CAP_INFO_RX_STAG_RED_SOUNDING; + if (roam_ht_cap->txStaggeredSounding) + hdd_ht_cap->tx_BF_cap_info |= + TX_BF_CAP_INFO_TX_STAG_RED_SOUNDING; + if (roam_ht_cap->rxZLF) + hdd_ht_cap->tx_BF_cap_info |= TX_BF_CAP_INFO_RX_ZFL; + if (roam_ht_cap->txZLF) + hdd_ht_cap->tx_BF_cap_info |= TX_BF_CAP_INFO_TX_ZFL; + if (roam_ht_cap->implicitTxBF) + hdd_ht_cap->tx_BF_cap_info |= TX_BF_CAP_INFO_IMP_TX_BF; + temp_ht_cap = roam_ht_cap->calibration & + (TX_BF_CAP_INFO_CALIBRATION >> TX_BF_CAP_INFO_CALIBRATION_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->tx_BF_cap_info |= + temp_ht_cap << TX_BF_CAP_INFO_CALIBRATION_SHIFT; + if (roam_ht_cap->explicitCSITxBF) + hdd_ht_cap->tx_BF_cap_info |= TX_BF_CAP_INFO_EXP_CSIT_BF; + if (roam_ht_cap->explicitUncompressedSteeringMatrix) + hdd_ht_cap->tx_BF_cap_info |= + TX_BF_CAP_INFO_EXP_UNCOMP_STEER_MAT; + temp_ht_cap = roam_ht_cap->explicitBFCSIFeedback & + (TX_BF_CAP_INFO_EXP_BF_CSI_FB >> + TX_BF_CAP_INFO_EXP_BF_CSI_FB_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->tx_BF_cap_info |= + temp_ht_cap << TX_BF_CAP_INFO_EXP_BF_CSI_FB_SHIFT; + temp_ht_cap = + roam_ht_cap->explicitUncompressedSteeringMatrixFeedback & + (TX_BF_CAP_INFO_EXP_UNCMP_STEER_MAT >> + TX_BF_CAP_INFO_EXP_UNCMP_STEER_MAT_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->tx_BF_cap_info |= + temp_ht_cap << + TX_BF_CAP_INFO_EXP_UNCMP_STEER_MAT_SHIFT; + temp_ht_cap = + roam_ht_cap->explicitCompressedSteeringMatrixFeedback & + (TX_BF_CAP_INFO_EXP_CMP_STEER_MAT_FB >> + TX_BF_CAP_INFO_EXP_CMP_STEER_MAT_FB_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->tx_BF_cap_info |= + temp_ht_cap << + TX_BF_CAP_INFO_EXP_CMP_STEER_MAT_FB_SHIFT; + temp_ht_cap = roam_ht_cap->csiNumBFAntennae & + (TX_BF_CAP_INFO_CSI_NUM_BF_ANT >> + TX_BF_CAP_INFO_CSI_NUM_BF_ANT_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->tx_BF_cap_info |= + temp_ht_cap << TX_BF_CAP_INFO_CSI_NUM_BF_ANT_SHIFT; + temp_ht_cap = roam_ht_cap->uncompressedSteeringMatrixBFAntennae & + (TX_BF_CAP_INFO_UNCOMP_STEER_MAT_BF_ANT >> + TX_BF_CAP_INFO_UNCOMP_STEER_MAT_BF_ANT_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->tx_BF_cap_info |= + temp_ht_cap << + TX_BF_CAP_INFO_UNCOMP_STEER_MAT_BF_ANT_SHIFT; + temp_ht_cap = roam_ht_cap->compressedSteeringMatrixBFAntennae & + (TX_BF_CAP_INFO_COMP_STEER_MAT_BF_ANT >> + TX_BF_CAP_INFO_COMP_STEER_MAT_BF_ANT_SHIFT); + if (temp_ht_cap) + hdd_ht_cap->tx_BF_cap_info |= + temp_ht_cap << + TX_BF_CAP_INFO_COMP_STEER_MAT_BF_ANT_SHIFT; + + /* antenna selection */ + if (roam_ht_cap->antennaSelection) + hdd_ht_cap->antenna_selection_info |= ANTENNA_SEL_INFO; + if (roam_ht_cap->explicitCSIFeedbackTx) + hdd_ht_cap->antenna_selection_info |= + ANTENNA_SEL_INFO_EXP_CSI_FB_TX; + if (roam_ht_cap->antennaIndicesFeedbackTx) + hdd_ht_cap->antenna_selection_info |= + ANTENNA_SEL_INFO_ANT_ID_FB_TX; + if (roam_ht_cap->explicitCSIFeedback) + hdd_ht_cap->antenna_selection_info |= + ANTENNA_SEL_INFO_EXP_CSI_FB; + if (roam_ht_cap->antennaIndicesFeedback) + hdd_ht_cap->antenna_selection_info |= + ANTENNA_SEL_INFO_ANT_ID_FB; + if (roam_ht_cap->rxAS) + hdd_ht_cap->antenna_selection_info |= + ANTENNA_SEL_INFO_RX_AS; + if (roam_ht_cap->txSoundingPPDUs) + hdd_ht_cap->antenna_selection_info |= + ANTENNA_SEL_INFO_TX_SOUNDING_PPDU; + + /* mcs data rate */ + for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; ++i) + hdd_ht_cap->mcs.rx_mask[i] = + roam_ht_cap->supportedMCSSet[i]; + hdd_ht_cap->mcs.rx_highest = + ((short) (roam_ht_cap->supportedMCSSet[11]) << 8) | + ((short) (roam_ht_cap->supportedMCSSet[10])); + hdd_ht_cap->mcs.tx_params = + roam_ht_cap->supportedMCSSet[12]; +} + + +#define VHT_CAP_MAX_MPDU_LENGTH_MASK 0x00000003 +#define VHT_CAP_SUPP_CHAN_WIDTH_MASK_SHIFT 2 +#define VHT_CAP_RXSTBC_MASK_SHIFT 8 +#define VHT_CAP_BEAMFORMEE_STS_SHIFT 13 +#define VHT_CAP_BEAMFORMEE_STS_MASK \ + (0x0000e000 >> VHT_CAP_BEAMFORMEE_STS_SHIFT) +#define VHT_CAP_SOUNDING_DIMENSIONS_SHIFT 16 +#define VHT_CAP_SOUNDING_DIMENSIONS_MASK \ + (0x00070000 >> VHT_CAP_SOUNDING_DIMENSIONS_SHIFT) +#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK_SHIFT 23 +#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \ + (0x03800000 >> VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK_SHIFT) +#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB_SHIFT 26 + +/** + * hdd_copy_ht_caps()- copy ht caps info from roam info to + * hdd station context. + * @hdd_sta_ctx: pointer to hdd station context + * @roam_info: pointer to roam info + * + * Return: None + */ +static void hdd_copy_vht_caps(hdd_station_ctx_t *hdd_sta_ctx, + tCsrRoamInfo *roam_info) +{ + tDot11fIEVHTCaps *roam_vht_cap = &roam_info->vht_caps; + struct ieee80211_vht_cap *hdd_vht_cap = + &hdd_sta_ctx->conn_info.vht_caps; + uint32_t temp_vht_cap; + + vos_mem_zero(hdd_vht_cap, sizeof(struct ieee80211_vht_cap)); + + temp_vht_cap = roam_vht_cap->maxMPDULen & VHT_CAP_MAX_MPDU_LENGTH_MASK; + hdd_vht_cap->vht_cap_info |= temp_vht_cap; + temp_vht_cap = roam_vht_cap->supportedChannelWidthSet & + (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK >> + VHT_CAP_SUPP_CHAN_WIDTH_MASK_SHIFT); + if (temp_vht_cap) + if (roam_vht_cap->supportedChannelWidthSet & + (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ >> + VHT_CAP_SUPP_CHAN_WIDTH_MASK_SHIFT)) + hdd_vht_cap->vht_cap_info |= + temp_vht_cap << + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; + if (roam_vht_cap->supportedChannelWidthSet & + (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ >> + VHT_CAP_SUPP_CHAN_WIDTH_MASK_SHIFT)) + hdd_vht_cap->vht_cap_info |= + temp_vht_cap << + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + if (roam_vht_cap->ldpcCodingCap) + hdd_vht_cap->vht_cap_info |= IEEE80211_VHT_CAP_RXLDPC; + if (roam_vht_cap->shortGI80MHz) + hdd_vht_cap->vht_cap_info |= IEEE80211_VHT_CAP_SHORT_GI_80; + if (roam_vht_cap->shortGI160and80plus80MHz) + hdd_vht_cap->vht_cap_info |= IEEE80211_VHT_CAP_SHORT_GI_160; + if (roam_vht_cap->txSTBC) + hdd_vht_cap->vht_cap_info |= IEEE80211_VHT_CAP_TXSTBC; + temp_vht_cap = roam_vht_cap->rxSTBC & (IEEE80211_VHT_CAP_RXSTBC_MASK >> + VHT_CAP_RXSTBC_MASK_SHIFT); + if (temp_vht_cap) + hdd_vht_cap->vht_cap_info |= + temp_vht_cap << VHT_CAP_RXSTBC_MASK_SHIFT; + if (roam_vht_cap->suBeamFormerCap) + hdd_vht_cap->vht_cap_info |= + IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; + if (roam_vht_cap->suBeamformeeCap) + hdd_vht_cap->vht_cap_info |= + IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; + temp_vht_cap = roam_vht_cap->csnofBeamformerAntSup & + (VHT_CAP_BEAMFORMEE_STS_MASK); + if (temp_vht_cap) + hdd_vht_cap->vht_cap_info |= + temp_vht_cap << VHT_CAP_BEAMFORMEE_STS_SHIFT; + temp_vht_cap = roam_vht_cap->numSoundingDim & + (VHT_CAP_SOUNDING_DIMENSIONS_MASK); + if (temp_vht_cap) + hdd_vht_cap->vht_cap_info |= + temp_vht_cap << VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; + if (roam_vht_cap->muBeamformerCap) + hdd_vht_cap->vht_cap_info |= + IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; + if (roam_vht_cap->muBeamformeeCap) + hdd_vht_cap->vht_cap_info |= + IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; + if (roam_vht_cap->vhtTXOPPS) + hdd_vht_cap->vht_cap_info |= + IEEE80211_VHT_CAP_VHT_TXOP_PS; + if (roam_vht_cap->htcVHTCap) + hdd_vht_cap->vht_cap_info |= + IEEE80211_VHT_CAP_HTC_VHT; + temp_vht_cap = roam_vht_cap->maxAMPDULenExp & + (VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK); + if (temp_vht_cap) + hdd_vht_cap->vht_cap_info |= + temp_vht_cap << + VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK_SHIFT; + temp_vht_cap = roam_vht_cap->vhtLinkAdaptCap & + (IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB >> + VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB_SHIFT); + if (temp_vht_cap) + hdd_vht_cap->vht_cap_info |= temp_vht_cap << + VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB_SHIFT; + if (roam_vht_cap->rxAntPattern) + hdd_vht_cap->vht_cap_info |= + IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN; + if (roam_vht_cap->txAntPattern) + hdd_vht_cap->vht_cap_info |= + IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; + hdd_vht_cap->supp_mcs.rx_mcs_map = roam_vht_cap->rxMCSMap; + hdd_vht_cap->supp_mcs.rx_highest = + ((uint16_t)roam_vht_cap->rxHighSupDataRate); + hdd_vht_cap->supp_mcs.tx_mcs_map = roam_vht_cap->txMCSMap; + hdd_vht_cap->supp_mcs.tx_highest = + ((uint16_t)roam_vht_cap->txSupDataRate); +} + +/* ht param */ +#define HT_PARAM_CONTROLLED_ACCESS_ONLY 0x10 +#define HT_PARAM_SERVICE_INT_GRAN 0xe0 +#define HT_PARAM_SERVICE_INT_GRAN_SHIFT 5 + +/* operatinon mode */ +#define HT_OP_MODE_TX_BURST_LIMIT 0x0008 + +/* stbc_param */ +#define HT_STBC_PARAM_MCS 0x007f + +/** + * hdd_copy_ht_operation()- copy HT operation element from roam info to + * hdd station context. + * @hdd_sta_ctx: pointer to hdd station context + * @roam_info: pointer to roam info + * + * Return: None + */ +static void hdd_copy_ht_operation(hdd_station_ctx_t *hdd_sta_ctx, + tCsrRoamInfo *roam_info) +{ + tDot11fIEHTInfo *roam_ht_ops = &roam_info->ht_operation; + struct ieee80211_ht_operation *hdd_ht_ops = + &hdd_sta_ctx->conn_info.ht_operation; + uint32_t i, temp_ht_ops; + + vos_mem_zero(hdd_ht_ops, sizeof(struct ieee80211_ht_operation)); + + hdd_ht_ops->primary_chan = roam_ht_ops->primaryChannel; + + /* HT_PARAMS */ + temp_ht_ops = roam_ht_ops->secondaryChannelOffset & + IEEE80211_HT_PARAM_CHA_SEC_OFFSET; + if (temp_ht_ops) + hdd_ht_ops->ht_param |= temp_ht_ops; + else + hdd_ht_ops->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; + if (roam_ht_ops->recommendedTxWidthSet) + hdd_ht_ops->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; + if (roam_ht_ops->rifsMode) + hdd_ht_ops->ht_param |= IEEE80211_HT_PARAM_RIFS_MODE; + if (roam_ht_ops->controlledAccessOnly) + hdd_ht_ops->ht_param |= HT_PARAM_CONTROLLED_ACCESS_ONLY; + temp_ht_ops = roam_ht_ops->serviceIntervalGranularity & + (HT_PARAM_SERVICE_INT_GRAN >> HT_PARAM_SERVICE_INT_GRAN_SHIFT); + if (temp_ht_ops) + hdd_ht_ops->ht_param |= temp_ht_ops << + HT_PARAM_SERVICE_INT_GRAN_SHIFT; + + /* operation mode */ + temp_ht_ops = roam_ht_ops->opMode & + IEEE80211_HT_OP_MODE_PROTECTION; + switch (temp_ht_ops) { + case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER: + hdd_ht_ops->operation_mode |= + IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER; + break; + case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: + hdd_ht_ops->operation_mode |= + IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; + break; + case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: + hdd_ht_ops->operation_mode |= + IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; + break; + case IEEE80211_HT_OP_MODE_PROTECTION_NONE: + default: + hdd_ht_ops->operation_mode |= + IEEE80211_HT_OP_MODE_PROTECTION_NONE; + } + if (roam_ht_ops->nonGFDevicesPresent) + hdd_ht_ops->operation_mode |= + IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT; + if (roam_ht_ops->transmitBurstLimit) + hdd_ht_ops->operation_mode |= + HT_OP_MODE_TX_BURST_LIMIT; + if (roam_ht_ops->obssNonHTStaPresent) + hdd_ht_ops->operation_mode |= + IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT; + + /* stbc_param */ + temp_ht_ops = roam_ht_ops->basicSTBCMCS & + HT_STBC_PARAM_MCS; + if (temp_ht_ops) + hdd_ht_ops->stbc_param |= temp_ht_ops; + if (roam_ht_ops->dualCTSProtection) + hdd_ht_ops->stbc_param |= + IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT; + if (roam_ht_ops->secondaryBeacon) + hdd_ht_ops->stbc_param |= + IEEE80211_HT_STBC_PARAM_STBC_BEACON; + if (roam_ht_ops->lsigTXOPProtectionFullSupport) + hdd_ht_ops->stbc_param |= + IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT; + if (roam_ht_ops->pcoActive) + hdd_ht_ops->stbc_param |= + IEEE80211_HT_STBC_PARAM_PCO_ACTIVE; + if (roam_ht_ops->pcoPhase) + hdd_ht_ops->stbc_param |= + IEEE80211_HT_STBC_PARAM_PCO_PHASE; + + /* basic MCs set */ + for (i = 0; i < 16; ++i) + hdd_ht_ops->basic_set[i] = + roam_ht_ops->basicMCSSet[i]; +} + +/** + * hdd_copy_vht_operation()- copy VHT operations element from roam info to + * hdd station context. + * @hdd_sta_ctx: pointer to hdd station context + * @roam_info: pointer to roam info + * + * Return: None + */ +static void hdd_copy_vht_operation(hdd_station_ctx_t *hdd_sta_ctx, + tCsrRoamInfo *roam_info) +{ + tDot11fIEVHTOperation *roam_vht_ops = &roam_info->vht_operation; + struct ieee80211_vht_operation *hdd_vht_ops = + &hdd_sta_ctx->conn_info.vht_operation; + + vos_mem_zero(hdd_vht_ops, sizeof(struct ieee80211_vht_operation)); + + hdd_vht_ops->chan_width = roam_vht_ops->chanWidth; + hdd_vht_ops->center_freq_seg1_idx = roam_vht_ops->chanCenterFreqSeg1; + hdd_vht_ops->center_freq_seg2_idx = roam_vht_ops->chanCenterFreqSeg2; + hdd_vht_ops->basic_mcs_set = roam_vht_ops->basicMCSSet; +} + + +/** + * hdd_save_bss_info() - save connection info in hdd sta ctx + * @adapter: Pointer to adapter + * @roam_info: pointer to roam info + * + * Return: None + */ +static void hdd_save_bss_info(hdd_adapter_t *adapter, + tCsrRoamInfo *roam_info) +{ + hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + hdd_sta_ctx->conn_info.freq = vos_chan_to_freq( + hdd_sta_ctx->conn_info.operationChannel); + if (roam_info->vht_caps.present) { + hdd_sta_ctx->conn_info.conn_flag.vht_present = true; + hdd_copy_vht_caps(hdd_sta_ctx, roam_info); + } else { + hdd_sta_ctx->conn_info.conn_flag.vht_present = false; + } + if (roam_info->ht_caps.present) { + hdd_sta_ctx->conn_info.conn_flag.ht_present = true; + hdd_copy_ht_caps(hdd_sta_ctx, roam_info); + } else { + hdd_sta_ctx->conn_info.conn_flag.ht_present = false; + } + if (roam_info->reassoc) + hdd_sta_ctx->conn_info.roam_count++; + if (roam_info->hs20vendor_ie.present) { + hdd_sta_ctx->conn_info.conn_flag.hs20_present = true; + vos_mem_copy(&hdd_sta_ctx->conn_info.hs20vendor_ie, + &roam_info->hs20vendor_ie, + sizeof(roam_info->hs20vendor_ie)); + } else { + hdd_sta_ctx->conn_info.conn_flag.hs20_present = false; + } + if (roam_info->ht_operation.present) { + hdd_sta_ctx->conn_info.conn_flag.ht_op_present = true; + hdd_copy_ht_operation(hdd_sta_ctx, roam_info); + } else { + hdd_sta_ctx->conn_info.conn_flag.ht_op_present = false; + } + if (roam_info->vht_operation.present) { + hdd_sta_ctx->conn_info.conn_flag.vht_op_present = true; + hdd_copy_vht_operation(hdd_sta_ctx, roam_info); + } else { + hdd_sta_ctx->conn_info.conn_flag.vht_op_present = false; + } +} + void hdd_connSaveConnectInfo( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, eCsrRoamBssType eBssType ) { hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); @@ -329,6 +810,7 @@ void hdd_connSaveConnectInfo( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, pHddStaCtx->conn_info.rate_flags = pRoamInfo->maxRateFlags; } + hdd_save_bss_info(pAdapter, pRoamInfo); } // save the connected BssType @@ -982,6 +1464,53 @@ static VOS_STATUS hdd_roamDeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId return( vosStatus ); } +/** + * hdd_print_bss_info() - print bss info + * @hdd_sta_ctx: pointer to hdd station context + * + * Return: None + */ +void hdd_print_bss_info(hdd_station_ctx_t *hdd_sta_ctx) +{ + uint32_t *cap_info; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"WIFI DATA LOGGER"); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"channel: %d", + hdd_sta_ctx->conn_info.freq); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"dot11mode: %d", + hdd_sta_ctx->conn_info.dot11Mode); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"AKM: %d", + hdd_sta_ctx->conn_info.authType); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"ssid: %.*s", + hdd_sta_ctx->conn_info.SSID.SSID.length, + hdd_sta_ctx->conn_info.SSID.SSID.ssId); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"roam count: %d", + hdd_sta_ctx->conn_info.roam_count); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"ant_info: %d", + hdd_sta_ctx->conn_info.txrate.nss); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"datarate legacy %d", + hdd_sta_ctx->conn_info.txrate.legacy); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"datarate mcs: %d", + hdd_sta_ctx->conn_info.txrate.mcs); + if (hdd_sta_ctx->conn_info.conn_flag.ht_present) { + cap_info = (uint32_t *)&hdd_sta_ctx->conn_info.ht_caps; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"ht caps: %x", + *cap_info); + } + if (hdd_sta_ctx->conn_info.conn_flag.vht_present) { + cap_info = (uint32_t *)&hdd_sta_ctx->conn_info.vht_caps; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"vht caps: %x", + *cap_info); + } + if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"hs20 info: %x", + hdd_sta_ctx->conn_info.hs20vendor_ie.release_num); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"signal: %d", + hdd_sta_ctx->conn_info.signal); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"noise: %d", + hdd_sta_ctx->conn_info.noise); +} + static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, tANI_U32 roamId, eRoamCmdStatus roamStatus, @@ -1285,6 +1814,7 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * //Unblock anyone waiting for disconnect to complete complete(&pAdapter->disconnect_comp_var); + hdd_print_bss_info(pHddStaCtx); return( status ); } @@ -1976,12 +2506,11 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs "wlan: connection failed with " MAC_ADDRESS_STR " result:%d and Status:%d", MAC_ADDR_ARRAY(pWextState->req_bssId), roamResult, roamStatus); - - if (( eCSR_ROAM_ASSOCIATION_FAILURE == roamStatus) || - ((roamResult != eCSR_ROAM_RESULT_ASSOCIATED) && - (eCSR_ROAM_ASSOCIATION_COMPLETION == roamStatus))) + if (!pHddStaCtx->get_mgmt_log_sent) { + pHddStaCtx->get_mgmt_log_sent = TRUE; wlan_hdd_get_frame_logs(pAdapter, WLAN_HDD_GET_FRAME_LOG_CMD_SEND_AND_CLEAR); + } if ((eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE == roamResult) || (pRoamInfo && @@ -2055,20 +2584,23 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs wlan_hdd_tdls_reenable(pHddCtx); } - if (pRoamInfo) + if (pRoamInfo) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: send connect failure to nl80211:" " for bssid " MAC_ADDRESS_STR " result:%d and Status:%d reasonCode %d" , __func__, MAC_ADDR_ARRAY(pRoamInfo->bssid), roamResult, roamStatus, pRoamInfo->reasonCode); - else + pHddStaCtx->conn_info.assoc_status_code = + pRoamInfo->statusCode; + } else { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed:" " for bssid " MAC_ADDRESS_STR " result:%d and Status:%d" , __func__, MAC_ADDR_ARRAY(pWextState->req_bssId), roamResult, roamStatus); + } /* inform association failure event to nl80211 */ if ( eCSR_ROAM_RESULT_ASSOC_FAIL_CON_CHANNEL == roamResult ) @@ -2131,6 +2663,10 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs "and STA channel is %d", pHostapdAdapter->sessionCtx.ap.operatingChannel, (int)pRoamInfo->pBssDesc->channelId); hdd_hostapd_stop(pHostapdAdapter->dev); + if (pHddCtx->cfg_ini->enable_sap_auth_offload) + hdd_force_scc_restart_sap(pHostapdAdapter, + pHddCtx, (int)pRoamInfo->pBssDesc->channelId); + } } } @@ -4097,6 +4633,19 @@ int hdd_set_csr_auth_type ( hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType) return 0; } +/** + * hdd_rx_fwd_eapol() - forward cached eapol frames + * @vosContext : pointer to vos global context + * @pVosPacket: pointer to vos packet + * + * Return: None + * + */ +void hdd_assoc_registerFwdEapolCB(void *pContext) +{ + WLANTL_RegisterFwdEapol(pContext, hdd_rx_fwd_eapol); +} + /**--------------------------------------------------------------------------- \brief __iw_set_essid() - @@ -4121,7 +4670,6 @@ int __iw_set_essid(struct net_device *dev, hdd_context_t *pHddCtx; v_U32_t roamId; tCsrRoamProfile *pRoamProfile; - eMib_dot11DesiredBssType connectedBssType; eCsrAuthType RSNAuthType; tHalHandle hHal; hdd_station_ctx_t *pHddStaCtx; @@ -4171,25 +4719,14 @@ int __iw_set_essid(struct net_device *dev, if( SIR_MAC_MAX_SSID_LENGTH < wrqu->essid.length ) return -EINVAL; pRoamProfile = &pWextState->roamProfile; - if (pRoamProfile) - { - if ( hdd_connGetConnectedBssType( pHddStaCtx, &connectedBssType ) || - ( eMib_dot11DesiredBssType_independent == pHddStaCtx->conn_info.connDot11DesiredBssType )) - { - VOS_STATUS vosStatus; - // need to issue a disconnect to CSR. - INIT_COMPLETION(pAdapter->disconnect_comp_var); - vosStatus = sme_RoamDisconnect( hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED ); - - if(VOS_STATUS_SUCCESS == vosStatus) - wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, - msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); - } - } - /** wpa_supplicant 0.8.x, wext driver uses */ - else + + /*Try disconnecting if already in connected state*/ + status = wlan_hdd_try_disconnect(pAdapter); + if (0 > status) { - return -EINVAL; + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing" + " connection")); + return -EALREADY; } /** wpa_supplicant 0.8.x, wext driver uses */ /** when cfg80211 defined, wpa_supplicant wext driver uses diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c index 89270a3ce4a..7272ed0d912 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c @@ -487,6 +487,13 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_CHANNEL_BONDING_MODE_MIN, CFG_CHANNEL_BONDING_MODE_MAX), + REG_VARIABLE(CFG_OVERRIDE_HT40_20_24GHZ_NAME, WLAN_PARAM_Integer, + hdd_config_t, override_ht20_40_24g, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OVERRIDE_HT40_20_24GHZ_DEFAULT, + CFG_OVERRIDE_HT40_20_24GHZ_MIN, + CFG_OVERRIDE_HT40_20_24GHZ_MAX), + REG_VARIABLE( CFG_CHANNEL_BONDING_MODE_5GHZ_NAME, WLAN_PARAM_Integer, hdd_config_t, nChannelBondingMode5GHz, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK, @@ -1955,6 +1962,14 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_NEIGHBOR_INITIAL_FORCED_ROAM_TO_5GH_ENABLE_MIN, CFG_NEIGHBOR_INITIAL_FORCED_ROAM_TO_5GH_ENABLE_MAX), + REG_VARIABLE(CFG_NEIGHBOR_WEAK_ZONE_RSSI_THRESHOLD_FOR_ROAM_NAME, + WLAN_PARAM_Integer, + hdd_config_t, nWeakZoneRssiThresholdForRoam, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NEIGHBOR_WEAK_ZONE_RSSI_THRESHOLD_FOR_ROAM_DEFAULT, + CFG_NEIGHBOR_WEAK_ZONE_RSSI_THRESHOLD_FOR_ROAM_MIN, + CFG_NEIGHBOR_WEAK_ZONE_RSSI_THRESHOLD_FOR_ROAM_MAX), + #endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ REG_VARIABLE( CFG_QOS_WMM_BURST_SIZE_DEFN_NAME , WLAN_PARAM_Integer, @@ -2227,13 +2242,6 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_BCN_EARLY_TERM_WAKE_MIN, CFG_BCN_EARLY_TERM_WAKE_MAX ), - REG_VARIABLE( CFG_AP_DATA_AVAIL_POLL_PERIOD_NAME, WLAN_PARAM_Integer, - hdd_config_t, apDataAvailPollPeriodInMs, - VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, - CFG_AP_DATA_AVAIL_POLL_PERIOD_DEFAULT, - CFG_AP_DATA_AVAIL_POLL_PERIOD_MIN, - CFG_AP_DATA_AVAIL_POLL_PERIOD_MAX ), - REG_VARIABLE( CFG_ENABLE_CLOSE_LOOP_NAME, WLAN_PARAM_Integer, hdd_config_t, enableCloseLoop, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -2884,6 +2892,15 @@ REG_VARIABLE( CFG_EXTSCAN_ENABLE, WLAN_PARAM_Integer, CFG_PER_ROAM_BAD_RSSI_MAX), #endif +#ifdef WLAN_FEATURE_LFR_MBB + REG_VARIABLE(CFG_ENABLE_LFR_MBB, WLAN_PARAM_Integer, + hdd_config_t, enable_lfr_mbb, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_LFR_MBB_DEFAULT, + CFG_ENABLE_LFR_MBB_MIN, + CFG_ENABLE_LFR_MBB_MAX ), +#endif + REG_VARIABLE( CFG_ENABLE_ADAPT_RX_DRAIN_NAME, WLAN_PARAM_Integer, hdd_config_t, fEnableAdaptRxDrain, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK , @@ -3497,6 +3514,13 @@ REG_VARIABLE( CFG_EXTSCAN_ENABLE, WLAN_PARAM_Integer, CFG_BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN_MIN, CFG_BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN_MAX ), + REG_VARIABLE( CFG_BTC_DISABLE_WLAN_LINK_CRITICAL , WLAN_PARAM_Integer, + hdd_config_t, btc_disable_wlan_link_critical, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_DEFAULT, + CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_MIN, + CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_MAX ), + REG_VARIABLE( CFG_BTC_STATIC_OPP_WLAN_IDLE_BT_LEN , WLAN_PARAM_Integer, hdd_config_t, btcStaticOppWlanIdleBtLen, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -3624,6 +3648,7 @@ REG_VARIABLE( CFG_EXTSCAN_ENABLE, WLAN_PARAM_Integer, CFG_SAR_BOFFSET_SET_CORRECTION_MIN, CFG_SAR_BOFFSET_SET_CORRECTION_MAX), + REG_VARIABLE(CFG_ENABLE_EDCA_INI_NAME, WLAN_PARAM_Integer, hdd_config_t, enable_edca_params, VAR_FLAGS_OPTIONAL | @@ -3755,6 +3780,162 @@ REG_VARIABLE( CFG_EXTSCAN_ENABLE, WLAN_PARAM_Integer, CFG_DISABLE_SCAN_DURING_SCO_DEFAULT, CFG_DISABLE_SCAN_DURING_SCO_MIN, CFG_DISABLE_SCAN_DURING_SCO_MAX ), +#ifdef SAP_AUTH_OFFLOAD + REG_VARIABLE(CFG_ENABLE_SAP_AUTH_OFL_NAME, WLAN_PARAM_Integer, + hdd_config_t, enable_sap_auth_offload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SAP_AUTH_OFL_DEFAULT, + CFG_ENABLE_SAP_AUTH_OFL_MIN, + CFG_ENABLE_SAP_AUTH_OFL_MAX ), + + REG_VARIABLE(CFG_SAP_AUTH_OFL_SECURITY_TYPE_NAME, WLAN_PARAM_Integer, + hdd_config_t, sap_auth_offload_sec_type, + VAR_FLAGS_OPTIONAL | CFG_SAP_AUTH_OFL_SECURITY_TYPE_DEFAULT, + CFG_SAP_AUTH_OFL_SECURITY_TYPE_DEFAULT, + CFG_SAP_AUTH_OFL_SECURITY_TYPE_MIN, + CFG_SAP_AUTH_OFL_SECURITY_TYPE_MAX ), + + REG_VARIABLE_STRING(CFG_SAP_AUTH_OFL_KEY_NAME, WLAN_PARAM_String, + hdd_config_t, sap_auth_offload_key, + VAR_FLAGS_OPTIONAL, + (void *) CFG_SAP_AUTH_OFL_KEY_DEFAULT ), +#endif +#ifdef DHCP_SERVER_OFFLOAD + REG_VARIABLE(CFG_DHCP_SERVER_OFFLOAD_SUPPORT_NAME, WLAN_PARAM_Integer, + hdd_config_t, enable_dhcp_srv_offload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DHCP_SERVER_OFFLOAD_SUPPORT_DEFAULT, + CFG_DHCP_SERVER_OFFLOAD_SUPPORT_MIN, + CFG_DHCP_SERVER_OFFLOAD_SUPPORT_MAX), + + REG_VARIABLE(CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_NAME, WLAN_PARAM_Integer, + hdd_config_t, dhcp_max_num_clients, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_DEFAULT, + CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_MIN, + CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_MAX), + + REG_VARIABLE_STRING(CFG_DHCP_SERVER_IP_NAME, WLAN_PARAM_String, + hdd_config_t, dhcp_srv_ip, + VAR_FLAGS_OPTIONAL, + (void *) CFG_DHCP_SERVER_IP_DEFAULT), + + REG_VARIABLE(CFG_DHCP_SERVER_OFFLOAD_START_LSB_NAME, WLAN_PARAM_Integer, + hdd_config_t, dhcp_start_lsb, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DHCP_SERVER_OFFLOAD_START_LSB_DEFAULT, + CFG_DHCP_SERVER_OFFLOAD_START_LSB_MIN, + CFG_DHCP_SERVER_OFFLOAD_START_LSB_MAX), +#endif /* DHCP_SERVER_OFFLOAD */ + REG_VARIABLE(CFG_MAX_SCHED_SCAN_PLAN_INT_NAME, WLAN_PARAM_Integer, + hdd_config_t, max_sched_scan_plan_interval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_SCHED_SCAN_PLAN_INT_DEFAULT, + CFG_MAX_SCHED_SCAN_PLAN_INT_MIN, + CFG_MAX_SCHED_SCAN_PLAN_INT_MAX), + + REG_VARIABLE(CFG_MAX_SCHED_SCAN_PLAN_ITRNS_NAME, WLAN_PARAM_Integer, + hdd_config_t, max_sched_scan_plan_iterations, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_SCHED_SCAN_PLAN_ITRNS_DEFAULT, + CFG_MAX_SCHED_SCAN_PLAN_ITRNS_MIN, + CFG_MAX_SCHED_SCAN_PLAN_ITRNS_MAX), + +#ifdef MDNS_OFFLOAD + REG_VARIABLE( CFG_MDNS_OFFLOAD_SUPPORT_NAME, WLAN_PARAM_Integer, + hdd_config_t, enable_mdns_offload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MDNS_OFFLOAD_SUPPORT_DEFAULT, + CFG_MDNS_OFFLOAD_SUPPORT_MIN, + CFG_MDNS_OFFLOAD_SUPPORT_MAX ), + + REG_VARIABLE_STRING( CFG_MDNS_FQDN_NAME, WLAN_PARAM_String, + hdd_config_t, mdns_fqdn, + VAR_FLAGS_OPTIONAL, + (void *) CFG_MDNS_FQDN_DEFAULT ), + + REG_VARIABLE_STRING( CFG_MDNS_UNIQUE_FQDN_NAME, WLAN_PARAM_String, + hdd_config_t, mdns_uniquefqdn, + VAR_FLAGS_OPTIONAL, + (void *) CFG_MDNS_UNIQUE_FQDN_DEFAULT ), + + REG_VARIABLE_STRING( CFG_MDNS_RESPONSE_TYPE_A_NAME, WLAN_PARAM_String, + hdd_config_t, mdns_resp_type_a, + VAR_FLAGS_OPTIONAL, + (void *) CFG_MDNS_RESPONSE_TYPE_A_DEFAULT ), + + REG_VARIABLE( CFG_MDNS_RESPONSE_TYPE_A_IPV4_NAME, WLAN_PARAM_HexInteger, + hdd_config_t, mdns_resp_type_a_ipv4, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MDNS_RESPONSE_TYPE_A_IPV4_DEFAULT, + CFG_MDNS_RESPONSE_TYPE_A_IPV4_MIN, + CFG_MDNS_RESPONSE_TYPE_A_IPV4_MAX ), + + REG_VARIABLE_STRING( CFG_MDNS_RESPONSE_TYPE_TXT_NAME, WLAN_PARAM_String, + hdd_config_t, mdns_resp_type_txt, + VAR_FLAGS_OPTIONAL, + (void *) CFG_MDNS_RESPONSE_TYPE_TXT_DEFAULT ), + + REG_VARIABLE_STRING( CFG_MDNS_RESPONSE_TYPE_TXT_CNT_NAME, WLAN_PARAM_String, + hdd_config_t, mdns_resp_type_txt_content, + VAR_FLAGS_OPTIONAL, + (void *) CFG_MDNS_RESPONSE_TYPE_TXT_CNT_DEFAULT ), + + REG_VARIABLE_STRING( CFG_MDNS_RESPONSE_TYPE_PTR_NAME, WLAN_PARAM_String, + hdd_config_t, mdns_resp_type_ptr, + VAR_FLAGS_OPTIONAL, + (void *) CFG_MDNS_RESPONSE_TYPE_PTR_DEFAULT ), + + REG_VARIABLE_STRING( CFG_MDNS_RESPONSE_TYPE_PTR_DN_NAME, WLAN_PARAM_String, + hdd_config_t, mdns_resp_type_ptr_dname, + VAR_FLAGS_OPTIONAL, + (void *) CFG_MDNS_RESPONSE_TYPE_PTR_DN_DEFAULT ), + + REG_VARIABLE_STRING( CFG_MDNS_RESPONSE_TYPE_SRV_NAME, WLAN_PARAM_String, + hdd_config_t, mdns_resp_type_srv, + VAR_FLAGS_OPTIONAL, + (void *) CFG_MDNS_RESPONSE_TYPE_SRV_DEFAULT ), + + REG_VARIABLE( CFG_MDNS_RESPONSE_TYPE_SRV_PRIORITY_NAME, WLAN_PARAM_Integer, + hdd_config_t, mdns_resp_type_srv_priority, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MDNS_RESPONSE_TYPE_SRV_PRIORITY_DEFAULT, + CFG_MDNS_RESPONSE_TYPE_SRV_PRIORITY_MIN, + CFG_MDNS_RESPONSE_TYPE_SRV_PRIORITY_MAX ), + + REG_VARIABLE( CFG_MDNS_RESPONSE_TYPE_SRV_WEIGHT_NAME, WLAN_PARAM_Integer, + hdd_config_t, mdns_resp_type_srv_weight, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MDNS_RESPONSE_TYPE_SRV_WEIGHT_DEFAULT, + CFG_MDNS_RESPONSE_TYPE_SRV_WEIGHT_MIN, + CFG_MDNS_RESPONSE_TYPE_SRV_WEIGHT_MAX ), + + REG_VARIABLE( CFG_MDNS_RESPONSE_TYPE_SRV_PORT_NAME, WLAN_PARAM_Integer, + hdd_config_t, mdns_resp_type_srv_port, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MDNS_RESPONSE_TYPE_SRV_PORT_DEFAULT, + CFG_MDNS_RESPONSE_TYPE_SRV_PORT_MIN, + CFG_MDNS_RESPONSE_TYPE_SRV_PORT_MAX ), + + REG_VARIABLE_STRING( CFG_MDNS_RESPONSE_TYPE_SRV_TGT_NAME, WLAN_PARAM_String, + hdd_config_t, mdns_resp_type_srv_target, + VAR_FLAGS_OPTIONAL, + (void *) CFG_MDNS_RESPONSE_TYPE_SRV_TGT_DEFAULT ), +#endif /* MDNS_OFFLOAD */ + + REG_VARIABLE( CFG_STA_AUTH_RETRIES_FOR_CODE17_NAME, WLAN_PARAM_Integer, + hdd_config_t, sta_auth_retries_for_code17, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_STA_AUTH_RETRIES_FOR_CODE17_DEFAULT, + CFG_STA_AUTH_RETRIES_FOR_CODE17_MIN, + CFG_STA_AUTH_RETRIES_FOR_CODE17_MAX ), + + REG_VARIABLE( CFG_TRIGGER_NULLFRAME_BEFORE_HB_NAME, WLAN_PARAM_Integer, + hdd_config_t, trigger_nullframe_before_hb, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TRIGGER_NULLFRAME_BEFORE_HB_DEFAULT, + CFG_TRIGGER_NULLFRAME_BEFORE_HB_MIN, + CFG_TRIGGER_NULLFRAME_BEFORE_HB_MAX ), }; /* @@ -4016,6 +4197,8 @@ static void print_hdd_cfg(hdd_context_t *pHddCtx) VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gApAutoChannelSelection] value = [%u]",pHddCtx->cfg_ini->apAutoChannelSelection); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ChannelBondingMode] Value = [%u]",pHddCtx->cfg_ini->nChannelBondingMode24GHz); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [%s] Value = [%u] ", + CFG_OVERRIDE_HT40_20_24GHZ_NAME, pHddCtx->cfg_ini->override_ht20_40_24g); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ChannelBondingMode] Value = [%u]",pHddCtx->cfg_ini->nChannelBondingMode5GHz); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [dot11Mode] Value = [%u]",pHddCtx->cfg_ini->dot11Mode); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [WmmMode] Value = [%u] ",pHddCtx->cfg_ini->WmmMode); @@ -4102,6 +4285,7 @@ static void print_hdd_cfg(hdd_context_t *pHddCtx) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborScanResultsRefreshPeriod] Value = [%u] ",pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nEmptyScanRefreshPeriod] Value = [%u] ",pHddCtx->cfg_ini->nEmptyScanRefreshPeriod); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nNeighborInitialForcedRoamTo5GhEnable] Value = [%u] ",pHddCtx->cfg_ini->nNeighborInitialForcedRoamTo5GhEnable); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [nWeakZoneRssiThresholdForRoam] Value = [%u] ",pHddCtx->cfg_ini->nWeakZoneRssiThresholdForRoam); #endif VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [burstSizeDefinition] Value = [0x%x] ",pHddCtx->cfg_ini->burstSizeDefinition); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [tsInfoAckPolicy] Value = [0x%x] ",pHddCtx->cfg_ini->tsInfoAckPolicy); @@ -4125,7 +4309,6 @@ static void print_hdd_cfg(hdd_context_t *pHddCtx) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [maxListenInterval] Value = [%u] ",pHddCtx->cfg_ini->nTeleBcnMaxListenInterval); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [maxLiNumIdleBeacons] Value = [%u] ",pHddCtx->cfg_ini->nTeleBcnMaxLiNumIdleBeacons); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [bcnEarlyTermWakeInterval] Value = [%u] ",pHddCtx->cfg_ini->bcnEarlyTermWakeInterval); - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gApDataAvailPollInterVal] Value = [%u] ",pHddCtx->cfg_ini->apDataAvailPollPeriodInMs); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableBypass11d] Value = [%u] ",pHddCtx->cfg_ini->enableBypass11d); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableDFSChnlScan] Value = [%u] ",pHddCtx->cfg_ini->enableDFSChnlScan); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableDFSPnoChnlScan] Value = [%u] ",pHddCtx->cfg_ini->enableDFSPnoChnlScan); @@ -4292,6 +4475,66 @@ static void print_hdd_cfg(hdd_context_t *pHddCtx) "Name = [gPERRoamCCAEnabled] Value = [%u] ", pHddCtx->cfg_ini->isPERRoamCCAEnabled); +#ifdef DHCP_SERVER_OFFLOAD + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gDHCPServerOffloadEnable] Value = [%u]", + pHddCtx->cfg_ini->enable_dhcp_srv_offload); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gDHCPMaxNumClients] Value = [%u]", + pHddCtx->cfg_ini->dhcp_max_num_clients); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gDHCPServerIP] Value = [%s]", + pHddCtx->cfg_ini->dhcp_srv_ip); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gDHCPStartLsb] Value = [%u]", + pHddCtx->cfg_ini->dhcp_start_lsb); +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSOffloadEnable] Value = [%u]", + pHddCtx->cfg_ini->enable_mdns_offload); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSFqdn] Value = [%s]", + pHddCtx->cfg_ini->mdns_fqdn); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSUniqueFqdn] Value = [%s]", + pHddCtx->cfg_ini->mdns_uniquefqdn); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSResponseTypeA] Value = [%s]", + pHddCtx->cfg_ini->mdns_resp_type_a); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSResponseTypeAIpv4Addr] Value = [%u]", + pHddCtx->cfg_ini->mdns_resp_type_a_ipv4); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSResponseTypeTXT] Value = [%s]", + pHddCtx->cfg_ini->mdns_resp_type_txt); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSResponseTypeTXTContent] Value = [%s]", + pHddCtx->cfg_ini->mdns_resp_type_txt_content); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSResponseTypePTR] Value = [%s]", + pHddCtx->cfg_ini->mdns_resp_type_ptr); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSResponseTypePTRDomainName] Value = [%s]", + pHddCtx->cfg_ini->mdns_resp_type_ptr_dname); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSResponseTypeSRV] Value = [%s]", + pHddCtx->cfg_ini->mdns_resp_type_srv); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSResponseTypeSRVPriority] Value = [%u]", + pHddCtx->cfg_ini->mdns_resp_type_srv_priority); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSResponseTypeSRVWeight] Value = [%u]", + pHddCtx->cfg_ini->mdns_resp_type_srv_weight); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSResponseTypeSRVPort] Value = [%u]", + pHddCtx->cfg_ini->mdns_resp_type_srv_port); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gMDNSResponseTypeSRVTarget] Value = [%s]", + pHddCtx->cfg_ini->mdns_resp_type_srv_target); +#endif /* MDNS_OFFLOAD */ + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gPERRoamFullScanThreshold] Value = [%u] ", pHddCtx->cfg_ini->PERRoamFullScanThreshold); @@ -4319,11 +4562,30 @@ static void print_hdd_cfg(hdd_context_t *pHddCtx) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gDisableScanDuringSco] Value = [%u] ", pHddCtx->cfg_ini->disable_scan_during_sco); - +#endif +#ifdef SAP_AUTH_OFFLOAD + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableSAPAuthOffload] Value = [%u] ", + pHddCtx->cfg_ini->enable_sap_auth_offload); #endif VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableSapInternalRestart] Value = [%u] ", pHddCtx->cfg_ini->sap_internal_restart); + +#ifdef WLAN_FEATURE_LFR_MBB + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [gEnableLFRMBB] Value = [%u] ", + pHddCtx->cfg_ini->enable_lfr_mbb); +#endif + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [sta_auth_retries_for_code17] Value = [%u] ", + pHddCtx->cfg_ini->sta_auth_retries_for_code17); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, + "Name = [%s] Value = [%u] ", + CFG_TRIGGER_NULLFRAME_BEFORE_HB_NAME, + pHddCtx->cfg_ini->trigger_nullframe_before_hb); } @@ -4844,8 +5106,9 @@ static void hdd_set_power_save_config(hdd_context_t *pHddCtx, tSmeConfigParams * } -#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING -static VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 *len, tANI_U8 intArrayMaxLen ) +VOS_STATUS hdd_string_to_u8_array(char *str, tANI_U8 *intArray, + tANI_U8 *len, tANI_U8 intArrayMaxLen, + char *seperator) { char *s = str; @@ -4862,10 +5125,12 @@ static VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 //Any other return value means error. Ignore it. if( sscanf(s, "%d", &val ) == 1 ) { + if (val > 255 || val < 0) + return VOS_STATUS_E_FAILURE; intArray[*len] = (tANI_U8) val; *len += 1; } - s = strpbrk( s, "," ); + s = strpbrk( s, seperator); if( s ) s++; } @@ -4873,8 +5138,58 @@ static VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 return VOS_STATUS_SUCCESS; } -#endif +#ifdef MDNS_OFFLOAD +int hdd_string_to_string_array(char *data, uint8_t *datalist, + char separator, uint8_t *num_entries, + uint8_t max_entries, + uint8_t max_len_entry) +{ + uint8_t num = 0; + char *str = NULL; + char *temp_str = NULL; + char *field; + uint16_t len = 0; + + if ((data == NULL) || ( datalist == NULL) || (num_entries == NULL)) + return VOS_STATUS_E_INVAL; + + str = vos_mem_malloc(strlen((char *)data)); + if (!str) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s str allocation failed",__func__); + return -ENOMEM; + } + vos_mem_copy(str, data, strlen((char *)data)); + temp_str = str; + /* parse the string */ + while (str && ('\0' != *str) && (num < max_entries)) { + field = str; + while (str && ('\0' != *str) && (separator != *str)) + str++; + if ('\0' == *str) { + /* reach the end of string */ + if ('\0' != *field) { + strlcpy((char *)(datalist + + (num * max_len_entry)), + field, max_len_entry); + num++; + } + break; + } + /* replace separator with NULL to terminate the data */ + *str++ = '\0'; + len = (char *)str - (char *)field; + strlcpy((char *)(datalist + (num * max_len_entry)), + field, len); + num++; + } + *num_entries = num; + vos_mem_free(temp_str); + + return 0; +} +#endif /* MDNS_OFFLOAD */ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) { @@ -5282,13 +5597,6 @@ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) hddLog(LOGE,"Failure: Could not pass on WNI_CFG_HEART_BEAT_THRESHOLD configuration info to CCM" ); } - if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD, pConfig->apDataAvailPollPeriodInMs, - NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) - { - fStatus = FALSE; - hddLog(LOGE,"Failure: Could not pass on WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD configuration info to CCM" ); - } - if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_CLOSE_LOOP, pConfig->enableCloseLoop, NULL, eANI_BOOLEAN_FALSE) ==eHAL_STATUS_FAILURE) @@ -5865,6 +6173,14 @@ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) hddLog(LOGE, "Could not pass on WNI_CFG_BTC_STATIC_OPP_WLAN_IDLE_BT_LEN "); } + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL, + pConfig->btc_disable_wlan_link_critical, NULL, + eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL"); + } + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LINK_FAIL_TIMEOUT, pConfig->linkFailTimeout, NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) @@ -5917,6 +6233,22 @@ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) fStatus = FALSE; hddLog(LOGE, "Could not pass on WNI_CFG_DISABLE_BAR_WAKE_UP_HOST to CCM"); } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_SAR_BOFFSET_SET_CORRECTION, + pConfig->boffset_correction_enable, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_SAR_BOFFSET_SET_CORRECTION to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_DISABLE_SCAN_DURING_SCO, + pConfig->disable_scan_during_sco, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_DISABLE_SCAN_DURING_SCO to CCM"); + } if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_CONC_BMISS, pConfig->enable_conc_bmiss, NULL, eANI_BOOLEAN_FALSE) ==eHAL_STATUS_FAILURE) @@ -5932,22 +6264,14 @@ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) hddLog(LOGE, "Could not pass on WNI_CFG_ENABLE_UNITS_BWAIT to CCM"); } - if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_SAR_BOFFSET_SET_CORRECTION, - pConfig->boffset_correction_enable, - NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) - { - fStatus = FALSE; - hddLog(LOGE, "Could not pass on WNI_CFG_SAR_BOFFSET_SET_CORRECTION to CCM"); - } - - if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_DISABLE_SCAN_DURING_SCO, - pConfig->disable_scan_during_sco, - NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB, + pConfig->trigger_nullframe_before_hb, NULL, + eANI_BOOLEAN_FALSE) + ==eHAL_STATUS_FAILURE) { fStatus = FALSE; - hddLog(LOGE, "Could not pass on WNI_CFG_DISABLE_SCAN_DURING_SCO to CCM"); + hddLog(LOGE, "Couldn't pass WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB to CCM"); } - return fStatus; } @@ -6162,6 +6486,11 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig->csrConfig.bFastRoamInConIniFeatureEnabled = 0; } #endif + +#ifdef WLAN_FEATURE_LFR_MBB + smeConfig->csrConfig.enable_lfr_mbb = pConfig->enable_lfr_mbb; +#endif + #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING smeConfig->csrConfig.neighborRoamConfig.nNeighborReassocRssiThreshold = pConfig->nNeighborReassocRssiThreshold; smeConfig->csrConfig.neighborRoamConfig.nNeighborLookupRssiThreshold = pConfig->nNeighborLookupRssiThreshold; @@ -6179,10 +6508,12 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig->csrConfig.neighborRoamConfig.nNeighborInitialForcedRoamTo5GhEnable = pConfig->nNeighborInitialForcedRoamTo5GhEnable; } + smeConfig->csrConfig.neighborRoamConfig.nWeakZoneRssiThresholdForRoam = + pConfig->nWeakZoneRssiThresholdForRoam; hdd_string_to_u8_array( pConfig->neighborScanChanList, smeConfig->csrConfig.neighborRoamConfig.neighborScanChanList.channelList, &smeConfig->csrConfig.neighborRoamConfig.neighborScanChanList.numChannels, - WNI_CFG_VALID_CHANNEL_LIST_LEN ); + WNI_CFG_VALID_CHANNEL_LIST_LEN, "," ); #endif smeConfig->csrConfig.addTSWhenACMIsOff = pConfig->AddTSWhenACMIsOff; @@ -6260,6 +6591,8 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig->csrConfig.edca_be_aifs = pHddCtx->cfg_ini->edca_be_aifs; + smeConfig->csrConfig.sta_auth_retries_for_code17 = + pHddCtx->cfg_ini->sta_auth_retries_for_code17; sme_set_mgmt_frm_via_wq5((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->sendMgmtPktViaWQ5); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c index 4eda9428042..c9c56e849a3 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -183,6 +183,10 @@ #define MAC_ADDR_SPOOFING_FW_ENABLE_HOST_DISABLE 2 #define MAC_ADDR_SPOOFING_DEFER_INTERVAL 10 //in ms +/* + * max_sched_scan_plans defined to 10 + */ +#define MAX_SCHED_SCAN_PLANS 10 static const u32 hdd_cipher_suites[] = { @@ -776,6 +780,538 @@ inline void wlan_hdd_cfg80211_nan_init(hdd_context_t *pHddCtx) sme_NanRegisterCallback(pHddCtx->hHal, wlan_hdd_cfg80211_nan_callback); } +/* + * define short names for the global vendor params + * used by __wlan_hdd_cfg80211_get_station_cmd() + */ +#define STATION_INVALID \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID +#define STATION_INFO \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO +#define STATION_ASSOC_FAIL_REASON \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON +#define STATION_MAX \ + QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + +static const struct nla_policy +hdd_get_station_policy[STATION_MAX + 1] = { + [STATION_INFO] = {.type = NLA_FLAG}, + [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG}, +}; + +/** + * hdd_get_station_assoc_fail() - Handle get station assoc fail + * @hdd_ctx: HDD context within host driver + * @wdev: wireless device + * + * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL. + * Validate cmd attributes and send the station info to upper layers. + * + * Return: Success(0) or reason code for failure + */ +static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter) +{ + struct sk_buff *skb = NULL; + uint32_t nl_buf_len; + hdd_station_ctx_t *hdd_sta_ctx; + + nl_buf_len = NLMSG_HDRLEN; + nl_buf_len += sizeof(uint32_t); + skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len); + + if (!skb) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"cfg80211_vendor_cmd_alloc_reply_skb failed"); + return -ENOMEM; + } + + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON, + hdd_sta_ctx->conn_info.assoc_status_code)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + return cfg80211_vendor_cmd_reply(skb); +fail: + if (skb) + kfree_skb(skb); + return -EINVAL; +} + +/** + * hdd_map_auth_type() - transform auth type specific to + * vendor command + * @auth_type: csr auth type + * + * Return: Success(0) or reason code for failure + */ +static int hdd_convert_auth_type(uint32_t auth_type) +{ + uint32_t ret_val; + + switch (auth_type) { + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + ret_val = QCA_WLAN_AUTH_TYPE_OPEN; + break; + case eCSR_AUTH_TYPE_SHARED_KEY: + ret_val = QCA_WLAN_AUTH_TYPE_SHARED; + break; + case eCSR_AUTH_TYPE_WPA: + ret_val = QCA_WLAN_AUTH_TYPE_WPA; + break; + case eCSR_AUTH_TYPE_WPA_PSK: + ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK; + break; + case eCSR_AUTH_TYPE_AUTOSWITCH: + ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH; + break; + case eCSR_AUTH_TYPE_WPA_NONE: + ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE; + break; + case eCSR_AUTH_TYPE_RSN: + ret_val = QCA_WLAN_AUTH_TYPE_RSN; + break; + case eCSR_AUTH_TYPE_RSN_PSK: + ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK; + break; + case eCSR_AUTH_TYPE_FT_RSN: + ret_val = QCA_WLAN_AUTH_TYPE_FT; + break; + case eCSR_AUTH_TYPE_FT_RSN_PSK: + ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK; + break; + case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE: + ret_val = QCA_WLAN_AUTH_TYPE_WAI; + break; + case eCSR_AUTH_TYPE_WAPI_WAI_PSK: + ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK; + break; +#ifdef FEATURE_WLAN_ESE + case eCSR_AUTH_TYPE_CCKM_WPA: + ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA; + break; + case eCSR_AUTH_TYPE_CCKM_RSN: + ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN; + break; +#endif + case eCSR_AUTH_TYPE_RSN_PSK_SHA256: + ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK; + break; + case eCSR_AUTH_TYPE_RSN_8021X_SHA256: + ret_val = QCA_WLAN_AUTH_TYPE_SHA256; + break; + case eCSR_NUM_OF_SUPPORT_AUTH_TYPE: + case eCSR_AUTH_TYPE_FAILED: + case eCSR_AUTH_TYPE_NONE: + default: + ret_val = QCA_WLAN_AUTH_TYPE_INVALID; + break; + } + return ret_val; +} + +/** + * hdd_map_dot_11_mode() - transform dot11mode type specific to + * vendor command + * @dot11mode: dot11mode + * + * Return: Success(0) or reason code for failure + */ +static int hdd_convert_dot11mode(uint32_t dot11mode) +{ + uint32_t ret_val; + + switch (dot11mode) { + case eCSR_CFG_DOT11_MODE_11A: + ret_val = QCA_WLAN_802_11_MODE_11A; + break; + case eCSR_CFG_DOT11_MODE_11B: + ret_val = QCA_WLAN_802_11_MODE_11B; + break; + case eCSR_CFG_DOT11_MODE_11G: + ret_val = QCA_WLAN_802_11_MODE_11G; + break; + case eCSR_CFG_DOT11_MODE_11N: + ret_val = QCA_WLAN_802_11_MODE_11N; + break; + case eCSR_CFG_DOT11_MODE_11AC: + ret_val = QCA_WLAN_802_11_MODE_11AC; + break; + case eCSR_CFG_DOT11_MODE_AUTO: + case eCSR_CFG_DOT11_MODE_ABG: + default: + ret_val = QCA_WLAN_802_11_MODE_INVALID; + } + return ret_val; +} + +/** + * hdd_add_tx_bitrate() - add tx bitrate attribute + * @skb: pointer to sk buff + * @hdd_sta_ctx: pointer to hdd station context + * @idx: attribute index + * + * Return: Success(0) or reason code for failure + */ +static int32_t hdd_add_tx_bitrate(struct sk_buff *skb, + hdd_station_ctx_t *hdd_sta_ctx, + int idx) +{ + struct nlattr *nla_attr; + uint32_t bitrate, bitrate_compat; + + nla_attr = nla_nest_start(skb, idx); + if (!nla_attr) + goto fail; + /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ + bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate); + + /* report 16-bit bitrate only if we can */ + bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0; + if (bitrate > 0 && + nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + if (bitrate_compat > 0 && + nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS, + hdd_sta_ctx->conn_info.txrate.nss)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + nla_nest_end(skb, nla_attr); + return 0; +fail: + return -EINVAL; +} + +/** + * hdd_add_sta_info() - add station info attribute + * @skb: pointer to sk buff + * @hdd_sta_ctx: pointer to hdd station context + * @idx: attribute index + * + * Return: Success(0) or reason code for failure + */ +static int32_t hdd_add_sta_info(struct sk_buff *skb, + hdd_station_ctx_t *hdd_sta_ctx, int idx) +{ + struct nlattr *nla_attr; + + nla_attr = nla_nest_start(skb, idx); + if (!nla_attr) + goto fail; + if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL, + (hdd_sta_ctx->conn_info.signal + 100))) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE)) + goto fail; + nla_nest_end(skb, nla_attr); + return 0; +fail: + return -EINVAL; +} + +/** + * hdd_add_survey_info() - add survey info attribute + * @skb: pointer to sk buff + * @hdd_sta_ctx: pointer to hdd station context + * @idx: attribute index + * + * Return: Success(0) or reason code for failure + */ +static int32_t hdd_add_survey_info(struct sk_buff *skb, + hdd_station_ctx_t *hdd_sta_ctx, + int idx) +{ + struct nlattr *nla_attr; + + nla_attr = nla_nest_start(skb, idx); + if (!nla_attr) + goto fail; + if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY, + hdd_sta_ctx->conn_info.freq) || + nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE, + (hdd_sta_ctx->conn_info.noise + 100))) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + nla_nest_end(skb, nla_attr); + return 0; +fail: + return -EINVAL; +} + +/** + * hdd_add_link_standard_info() - add link info attribute + * @skb: pointer to sk buff + * @hdd_sta_ctx: pointer to hdd station context + * @idx: attribute index + * + * Return: Success(0) or reason code for failure + */ +static int32_t +hdd_add_link_standard_info(struct sk_buff *skb, + hdd_station_ctx_t *hdd_sta_ctx, int idx) +{ + struct nlattr *nla_attr; + + nla_attr = nla_nest_start(skb, idx); + if (!nla_attr) + goto fail; + if (nla_put(skb, + NL80211_ATTR_SSID, + hdd_sta_ctx->conn_info.SSID.SSID.length, + hdd_sta_ctx->conn_info.SSID.SSID.ssId)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO)) + goto fail; + if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO)) + goto fail; + nla_nest_end(skb, nla_attr); + return 0; +fail: + return -EINVAL; +} + +/** + * hdd_add_ap_standard_info() - add ap info attribute + * @skb: pointer to sk buff + * @hdd_sta_ctx: pointer to hdd station context + * @idx: attribute index + * + * Return: Success(0) or reason code for failure + */ +static int32_t +hdd_add_ap_standard_info(struct sk_buff *skb, + hdd_station_ctx_t *hdd_sta_ctx, int idx) +{ + struct nlattr *nla_attr; + + nla_attr = nla_nest_start(skb, idx); + if (!nla_attr) + goto fail; + if (hdd_sta_ctx->conn_info.conn_flag.vht_present) + if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY, + sizeof(hdd_sta_ctx->conn_info.vht_caps), + &hdd_sta_ctx->conn_info.vht_caps)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + if (hdd_sta_ctx->conn_info.conn_flag.ht_present) + if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY, + sizeof(hdd_sta_ctx->conn_info.ht_caps), + &hdd_sta_ctx->conn_info.ht_caps)) { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + nla_nest_end(skb, nla_attr); + return 0; +fail: + return -EINVAL; +} + +/** + * hdd_get_station_info() - send BSS information to supplicant + * @hdd_ctx: pointer to hdd context + * @adapter: pointer to adapter + * + * Return: 0 if success else error status + */ +static int hdd_get_station_info(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter) +{ + struct sk_buff *skb = NULL; + uint8_t *tmp_hs20 = NULL; + uint32_t nl_buf_len; + hdd_station_ctx_t *hdd_sta_ctx; + + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + nl_buf_len = NLMSG_HDRLEN; + nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) + + sizeof(hdd_sta_ctx->conn_info.freq) + + sizeof(hdd_sta_ctx->conn_info.noise) + + sizeof(hdd_sta_ctx->conn_info.signal) + + (sizeof(uint32_t) * 2) + + sizeof(hdd_sta_ctx->conn_info.txrate.nss) + + sizeof(hdd_sta_ctx->conn_info.roam_count) + + sizeof(hdd_sta_ctx->conn_info.authType) + + sizeof(hdd_sta_ctx->conn_info.dot11Mode); + if (hdd_sta_ctx->conn_info.conn_flag.vht_present) + nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps); + if (hdd_sta_ctx->conn_info.conn_flag.ht_present) + nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps); + if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) { + tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie); + nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - + 1); + } + if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present) + nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation); + if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present) + nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation); + + + skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len); + if (!skb) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: %d cfg80211_vendor_cmd_alloc_reply_skb failed", + __func__, __LINE__); + return -ENOMEM; + } + + if (hdd_add_link_standard_info(skb, hdd_sta_ctx, + LINK_INFO_STANDARD_NL80211_ATTR)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + if (hdd_add_ap_standard_info(skb, hdd_sta_ctx, + AP_INFO_STANDARD_NL80211_ATTR)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + if (nla_put_u32(skb, INFO_ROAM_COUNT, + hdd_sta_ctx->conn_info.roam_count) || + nla_put_u32(skb, INFO_AKM, + hdd_convert_auth_type( + hdd_sta_ctx->conn_info.authType)) || + nla_put_u32(skb, WLAN802_11_MODE, + hdd_convert_dot11mode( + hdd_sta_ctx->conn_info.dot11Mode))) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present) + if (nla_put(skb, HT_OPERATION, + (sizeof(hdd_sta_ctx->conn_info.ht_operation)), + &hdd_sta_ctx->conn_info.ht_operation)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present) + if (nla_put(skb, VHT_OPERATION, + (sizeof(hdd_sta_ctx->conn_info.vht_operation)), + &hdd_sta_ctx->conn_info.vht_operation)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) + if (nla_put(skb, AP_INFO_HS20_INDICATION, + (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1), + tmp_hs20 + 1)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"put fail"); + goto fail; + } + + return cfg80211_vendor_cmd_reply(skb); +fail: + if (skb) + kfree_skb(skb); + return -EINVAL; +} + +/** + * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd + * @wiphy: corestack handler + * @wdev: wireless device + * @data: data + * @data_len: data length + * + * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION. + * Validate cmd attributes and send the station info to upper layers. + * + * Return: Success(0) or reason code for failure + */ +static int32_t +__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct net_device *dev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1]; + int32_t status; + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"Enter"); + if (VOS_FTM_MODE == hdd_get_conparam()) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"Command not allowed in FTM mode"); + status = -EPERM; + goto out; + } + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) + goto out; + + + status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX, + data, data_len, NULL); + if (status) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"Invalid ATTR"); + goto out; + } + + /* Parse and fetch Command Type*/ + if (tb[STATION_INFO]) { + status = hdd_get_station_info(hdd_ctx, adapter); + } else if (tb[STATION_ASSOC_FAIL_REASON]) { + status = hdd_get_station_assoc_fail(hdd_ctx, adapter); + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"get station info cmd type failed"); + status = -EINVAL; + goto out; + } + EXIT(); +out: + return status; +} + +/** + * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd + * @wiphy: corestack handler + * @wdev: wireless device + * @data: data + * @data_len: data length + * + * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION. + * Validate cmd attributes and send the station info to upper layers. + * + * Return: Success(0) or reason code for failure + */ +static int32_t +hdd_cfg80211_get_station_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} + +/* + * undef short names defined for get station command + * used by __wlan_hdd_cfg80211_get_station_cmd() + */ +#undef STATION_INVALID +#undef STATION_INFO +#undef STATION_ASSOC_FAIL_REASON +#undef STATION_MAX #ifdef WLAN_FEATURE_LINK_LAYER_STATS @@ -1733,7 +2269,7 @@ static int __wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy, if ( (TRUE != pHddCtx->cfg_ini->fEnableLLStats) || (TRUE != sme_IsFeatureSupportedByFW(LINK_LAYER_STATS_MEAS))) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_WARN, FL("Link Layer Statistics not supported by Firmware")); return -EINVAL; } @@ -2155,6 +2691,8 @@ wlan_hdd_extscan_config_policy { .type = NLA_U32 }, [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS] = + { .type = NLA_U32 }, [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL] = { .type = NLA_U32 }, [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME] = { .type = NLA_U32 }, @@ -3804,13 +4342,20 @@ static int hdd_extscan_start_fill_bucket_channel_spec( int rem1, rem2; eHalStatus status; tANI_U8 bktIndex, j, numChannels; + uint32_t expected_buckets; tANI_U32 chanList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; tANI_U32 passive_max_chn_time, active_max_chn_time; + expected_buckets = pReqMsg->numBuckets; bktIndex = 0; nla_for_each_nested(buckets, tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) { + if (bktIndex >= expected_buckets) { + hddLog(LOGW, FL("ignoring excess buckets")); + break; + } + if (nla_parse(bucket, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, nla_data(buckets), nla_len(buckets), @@ -6723,6 +7268,10 @@ static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy, return cfg80211_vendor_cmd_reply(reply_skb); } +#define BEACON_MISS_THRESH_2_4 \ + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24 +#define BEACON_MISS_THRESH_5_0 \ + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_5 #define PARAM_WIFICONFIG_MAX QCA_WLAN_VENDOR_ATTR_CONFIG_MAX #define PARAM_MODULATED_DTIM QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM #define PARAM_STATS_AVG_FACTOR QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR @@ -6758,12 +7307,16 @@ static int __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, tModifyRoamParamsReqParams modifyRoamParamsReq; eHalStatus status; int ret_val; + uint8_t hb_thresh_val; + static const struct nla_policy policy[PARAM_WIFICONFIG_MAX + 1] = { [PARAM_STATS_AVG_FACTOR] = { .type = NLA_U16 }, [PARAM_MODULATED_DTIM] = { .type = NLA_U32 }, [PARAM_GUARD_TIME] = { .type = NLA_U32}, [PARAM_BCNMISS_PENALTY_PARAM_COUNT] = { .type = NLA_U32}, + [BEACON_MISS_THRESH_2_4] = { .type = NLA_U8 }, + [BEACON_MISS_THRESH_5_0] = { .type = NLA_U8 }, }; ENTER(); @@ -6886,6 +7439,50 @@ static int __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, } + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24]) { + hb_thresh_val = nla_get_u8( + tb[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24]); + + hddLog(LOG1, "WLAN set heartbeat threshold for 2.4Ghz %d", + hb_thresh_val); + ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal, + WNI_CFG_HEART_BEAT_THRESHOLD, hb_thresh_val, + NULL, eANI_BOOLEAN_FALSE); + + status = sme_update_hb_threshold( + (WLAN_HDD_GET_CTX(pAdapter))->hHal, + WNI_CFG_HEART_BEAT_THRESHOLD, + hb_thresh_val, eCSR_BAND_24); + if (eHAL_STATUS_SUCCESS != status) { + hddLog(LOGE, "WLAN set heartbeat threshold FAILED %d", status); + vos_mem_free(pReq); + pReq = NULL; + return -EPERM; + } + } + + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_5]) { + hb_thresh_val = nla_get_u8( + tb[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_5]); + + hddLog(LOG1, "WLAN set heartbeat threshold for 5Ghz %d", + hb_thresh_val); + ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal, + WNI_CFG_HEART_BEAT_THRESHOLD, hb_thresh_val, + NULL, eANI_BOOLEAN_FALSE); + + status = sme_update_hb_threshold( + (WLAN_HDD_GET_CTX(pAdapter))->hHal, + WNI_CFG_HEART_BEAT_THRESHOLD, + hb_thresh_val, eCSR_BAND_5G); + if (eHAL_STATUS_SUCCESS != status) { + hddLog(LOGE, "WLAN set heartbeat threshold FAILED %d", status); + vos_mem_free(pReq); + pReq = NULL; + return -EPERM; + } + } + EXIT(); return ret_val; } @@ -6939,24 +7536,6 @@ qca_wlan_vendor_set_nud_stats[STATS_SET_MAX +1] = }; /** - * hdd_test_con_alive() - check connection alive - * @adapter: pointer to adapter - * - * Return: true if SME command is sent of false otherwise - */ -static bool hdd_test_con_alive(hdd_adapter_t *adapter) -{ - hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); - - if (eHAL_STATUS_SUCCESS != sme_test_con_alive(hdd_ctx->hHal)) { - hddLog(LOGE, FL("could not send ADDBA")); - return false; - } - - return true; -} - -/** * hdd_set_nud_stats_cb() - hdd callback api to get status * @data: pointer to adapter * @rsp: status @@ -6974,8 +7553,6 @@ static void hdd_set_nud_stats_cb(void *data, VOS_STATUS rsp) if (VOS_STATUS_SUCCESS == rsp) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s success received STATS_SET_START", __func__); - if (adapter->nud_set_arp_stats) - hdd_test_con_alive(adapter); } else { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s STATS_SET_START Failed!!", __func__); @@ -7036,18 +7613,15 @@ static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy, return -EINVAL; } arp_stats_params.flag = true; - adapter->nud_set_arp_stats = true; arp_stats_params.ip_addr = nla_get_u32(tb[STATS_GW_IPV4]); } else { arp_stats_params.flag = false; - adapter->nud_set_arp_stats = false; } - if (!arp_stats_params.flag) { + if (arp_stats_params.flag) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s STATS_SET_START Cleared!!", __func__); - hdd_ctx->track_arp_ip = 0; - vos_mem_zero(&adapter->hdd_stats.hddArpStats, sizeof(adapter->hdd_stats.hddArpStats)); - } + vos_mem_zero(&adapter->hdd_stats.hddArpStats, + sizeof(adapter->hdd_stats.hddArpStats)); arp_stats_params.pkt_type = 1; // ARP packet type @@ -7152,65 +7726,6 @@ qca_wlan_vendor_get_nud_stats[STATS_GET_MAX +1] = [AP_LINK_DAD] = {.type = NLA_FLAG }, }; -/** - * hdd_con_alive_cb() - Call back to get the connection status - * @context: pointer to adapter - * - * Return: None - */ -static void hdd_con_alive_cb(void *context, bool status) -{ - hdd_adapter_t *adapter = (hdd_adapter_t *)context; - adapter->con_status = status; -} - -/** - * hdd_get_con_alive() - get the connection status - * @adapter: pointer to adapter - * - * Return: true if SME command is sent of false otherwise - */ -static bool hdd_get_con_alive(hdd_adapter_t *adapter) -{ - hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); - getConStatusParams conStatusParams; - - conStatusParams.rsp_cb_fn = hdd_con_alive_cb; - conStatusParams.data_ctx = adapter; - - if (eHAL_STATUS_SUCCESS != sme_get_con_alive(hdd_ctx->hHal, - &conStatusParams)) - { - hddLog(LOGE, FL("could not get connection status")); - return false; - } - - return true; -} - -/** - * hdd_con_test_DELBA() - delete the BA session - * @adapter: pointer to adapter - * - * Return: true if SME command is sent of false otherwise - */ -static bool hdd_con_test_DELBA(hdd_adapter_t *adapter) -{ - hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); - hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; - uint8_t sta_id = pHddStaCtx->conn_info.staId[0]; - - ENTER(); - - if (eHAL_STATUS_SUCCESS != sme_test_con_delba((hdd_ctx->hHal), sta_id, - adapter->sessionId)) { - hddLog(LOGE, FL("could not send DELBA ")); - return false; - } - - return true; -} - static void hdd_get_nud_stats_cb(void *data, rsp_stats *rsp) { @@ -7265,8 +7780,6 @@ static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy, if (0 != err) return err; - hdd_get_con_alive(adapter); - arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE; arp_stats_params.get_rsp_cb_fn = hdd_get_nud_stats_cb; arp_stats_params.data_ctx = adapter; @@ -7309,7 +7822,7 @@ static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy, } if (nla_put_u16(skb, COUNT_FROM_NETDEV, - adapter->hdd_stats.hddArpStats.tx_arp_req_count) || + adapter->hdd_stats.hddArpStats.txCount) || nla_put_u16(skb, COUNT_TO_LOWER_MAC, adapter->hdd_stats.hddArpStats.tx_host_fw_sent) || nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC, @@ -7319,7 +7832,7 @@ static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy, nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC, adapter->hdd_stats.hddArpStats.rx_fw_cnt) || nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC, - adapter->hdd_stats.hddArpStats.rx_arp_rsp_count) || + adapter->hdd_stats.hddArpStats.rxCount) || nla_put_u16(skb, RSP_COUNT_TO_NETDEV, adapter->hdd_stats.hddArpStats.rxDelivered) || nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP, @@ -7328,15 +7841,11 @@ static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy, kfree_skb(skb); return -EINVAL; } - if (adapter->con_status) { + if (adapter->con_status) nla_put_flag(skb, AP_LINK_ACTIVE); - adapter->con_status = false; - hdd_con_test_DELBA(adapter); - } if (adapter->dad) nla_put_flag(skb, AP_LINK_DAD); - hdd_ctx->track_arp_ip = 0; cfg80211_vendor_cmd_reply(skb); return err; } @@ -7366,6 +7875,76 @@ static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy, #undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE #undef QCA_ATTR_NUD_STATS_GET_MAX + + +#ifdef WLAN_FEATURE_APFIND +/** + * __wlan_hdd_cfg80211_apfind_cmd() - set configuration to firmware + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: pointer to apfind configuration data. + * @data_len: the length in byte of apfind data. + * + * This is called when wlan driver needs to send APFIND configurations to + * firmware. + * + * Return: An error code or 0 on success. + */ +static int __wlan_hdd_cfg80211_apfind_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct sme_ap_find_request_req apfind_req; + VOS_STATUS status; + int ret_val; + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + + ENTER(); + + ret_val = wlan_hdd_validate_context(hdd_ctx); + if (ret_val) + return ret_val; + + if (VOS_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EPERM; + } + + apfind_req.request_data_len = data_len; + apfind_req.request_data = data; + + status = sme_apfind_set_cmd(&apfind_req); + if (VOS_STATUS_SUCCESS != status) { + ret_val = -EIO; + } + return ret_val; +} + +/** + * wlan_hdd_cfg80211_apfind_cmd() - set configuration to firmware + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: pointer to apfind configuration data. + * @data_len: the length in byte of apfind data. + * + * This is called when wlan driver needs to send APFIND configurations to + * firmware. + * + * Return: An error code or 0 on success. + */ +static int wlan_hdd_cfg80211_apfind_cmd(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_apfind_cmd(wiphy, wdev, data, data_len); + vos_ssr_unprotect(__func__); + + return ret; +} +#endif /* WLAN_FEATURE_APFIND */ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { { @@ -7596,6 +8175,15 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wlan_hdd_cfg80211_wifi_configuration_set }, +#ifdef WLAN_FEATURE_APFIND + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_APFIND, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_apfind_cmd + }, +#endif /* WLAN_FEATURE_APFIND */ { .info.vendor_id = QCA_NL80211_VENDOR_ID, .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET, @@ -7612,6 +8200,14 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wlan_hdd_cfg80211_get_nud_stats }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = hdd_cfg80211_get_station_cmd + }, }; /* vendor specific events */ @@ -7709,7 +8305,7 @@ struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = }, - { + [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = { .vendor_id = QCA_NL80211_VENDOR_ID, .subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN }, @@ -7758,6 +8354,33 @@ struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size) return wiphy; } +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,4,0)) || \ + defined (CFG80211_MULTI_SCAN_PLAN_BACKPORT) +/** + * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy + * @wiphy: pointer to wiphy + * @config: pointer to config + * + * Return: None + */ +static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy, + hdd_config_t *config) +{ + wiphy->max_sched_scan_plans = MAX_SCHED_SCAN_PLANS; + if (config->max_sched_scan_plan_interval) + wiphy->max_sched_scan_plan_interval = + config->max_sched_scan_plan_interval; + if (config->max_sched_scan_plan_iterations) + wiphy->max_sched_scan_plan_iterations = + config->max_sched_scan_plan_iterations; +} +#else +static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy, + hdd_config_t *config) +{ +} +#endif + /* * FUNCTION: wlan_hdd_cfg80211_update_band * This function is called from the supplicant through a @@ -8049,6 +8672,8 @@ int wlan_hdd_cfg80211_init(struct device *dev, wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events; wiphy->n_vendor_events = ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events); + hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg); + EXIT(); return 0; } @@ -8570,7 +9195,7 @@ static void wlan_hdd_add_hostapd_conf_vsie(hdd_adapter_t* pHostapdAdapter, elem_id, elem_len, left); return; } - if (IE_EID_VENDOR == elem_id) + if ((IE_EID_VENDOR == elem_id) && (elem_len >= WPS_OUI_TYPE_SIZE)) { /* skipping the VSIE's which we don't want to include or * it will be included by existing code @@ -9105,6 +9730,118 @@ static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, return ret; } +#ifdef DHCP_SERVER_OFFLOAD +void hdd_dhcp_server_offload_done(void *fw_dhcp_srv_offload_cb_context, + VOS_STATUS status) +{ + hdd_adapter_t* adapter = (hdd_adapter_t*)fw_dhcp_srv_offload_cb_context; + + ENTER(); + + if (NULL == adapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: adapter is NULL",__func__); + return; + } + + adapter->dhcp_status.dhcp_offload_status = status; + vos_event_set(&adapter->dhcp_status.vos_event); + return; +} + +/** + * wlan_hdd_set_dhcp_server_offload() - set dhcp server offload + * @hostapd_adapter: pointer to hostapd adapter. + * @re_init: flag set if api called post ssr + * + * Return: None + */ +VOS_STATUS wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *hostapd_adapter, + bool re_init) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter); + sir_dhcp_srv_offload_info dhcp_srv_info; + tANI_U8 num_entries = 0; + tANI_U8 srv_ip[IPADDR_NUM_ENTRIES]; + tANI_U8 num; + tANI_U32 temp; + VOS_STATUS ret; + + ENTER(); + + if (!re_init) { + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return VOS_STATUS_E_INVAL; + } + + /* Prepare the request to send to SME */ + dhcp_srv_info = vos_mem_malloc(sizeof(*dhcp_srv_info)); + if (NULL == dhcp_srv_info) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: could not allocate tDhcpSrvOffloadInfo!", __func__); + return VOS_STATUS_E_NOMEM; + } + + vos_mem_zero(dhcp_srv_info, sizeof(*dhcp_srv_info)); + + dhcp_srv_info->bssidx = hostapd_adapter->sessionId; + dhcp_srv_info->dhcp_srv_offload_enabled = TRUE; + dhcp_srv_info->dhcp_client_num = hdd_ctx->cfg_ini->dhcp_max_num_clients; + dhcp_srv_info->start_lsb = hdd_ctx->cfg_ini->dhcp_start_lsb; + dhcp_srv_info->dhcp_offload_callback = hdd_dhcp_server_offload_done; + dhcp_srv_info->dhcp_server_offload_cb_context = hostapd_adapter; + + hdd_string_to_u8_array(hdd_ctx->cfg_ini->dhcp_srv_ip, + srv_ip, + &num_entries, + IPADDR_NUM_ENTRIES, "."); + if (num_entries != IPADDR_NUM_ENTRIES) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: incorrect IP address (%s) assigned for DHCP server!", + __func__, hdd_ctx->cfg_ini->dhcp_srv_ip); + vos_mem_free(dhcp_srv_info); + return VOS_STATUS_E_FAILURE; + } + + if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: invalid IP address (%s)! It could NOT be multicast IP address!", + __func__, hdd_ctx->cfg_ini->dhcp_srv_ip); + vos_mem_free(dhcp_srv_info); + return VOS_STATUS_E_FAILURE; + } + + if (srv_ip[IPADDR_NUM_ENTRIES-1] >= DHCP_START_POOL_ADDRESS) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: invalid IP address (%s)! The last field must be less than 100!", + __func__, hdd_ctx->cfg_ini->dhcp_srv_ip); + vos_mem_free(dhcp_srv_info); + return VOS_STATUS_E_FAILURE; + } + + for (num = 0; num < num_entries; num++) { + temp = srv_ip[num]; + dhcp_srv_info->dhcp_srv_ip |= (temp << (8 * num)); + } + + if (eHAL_STATUS_SUCCESS != + sme_set_dhcp_srv_offload(hdd_ctx->hHal, dhcp_srv_info)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_set_dhcp_srv_offload fail!", __func__); + vos_mem_free(dhcp_srv_info); + return VOS_STATUS_E_FAILURE; + } + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: enable DHCP Server offload successfully!", __func__); + + vos_mem_free(dhcp_srv_info); + return 0; +} +#endif /* DHCP_SERVER_OFFLOAD */ + #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, struct beacon_parameters *params) @@ -9142,6 +9879,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, ENTER(); + wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx); iniConfig = pHddCtx->cfg_ini; pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); @@ -9239,6 +9977,19 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, pConfig->privacy = (pMgmt_frame->u.beacon.capab_info & WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE; +#ifdef SAP_AUTH_OFFLOAD + /* In case of sap offload, hostapd.conf is configuted with open mode and + * security is configured from ini file. Due to open mode in hostapd.conf + * privacy bit is set to false which will result in not sending, + * data packets as encrypted. + * If enable_sap_auth_offload is enabled in ini and + * sap_auth_offload_sec_type is type of WPA2-PSK, + * driver will set privacy bit to 1. + */ + if (pHddCtx->cfg_ini->enable_sap_auth_offload && + pHddCtx->cfg_ini->sap_auth_offload_sec_type) + pConfig->privacy = VOS_TRUE; +#endif (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy; @@ -9594,10 +10345,108 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, } set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); + if (WLANSAP_get_sessionId(pVosContext, &pHostapdAdapter->sessionId) != + VOS_STATUS_SUCCESS) + { + hddLog(LOGE,FL("Fail to get Softap sessionID")); + VOS_ASSERT(0); + } /* Initialize WMM configuation */ hdd_wmm_init(pHostapdAdapter); wlan_hdd_incr_active_session(pHddCtx, pHostapdAdapter->device_mode); +#ifdef DHCP_SERVER_OFFLOAD + /* set dhcp server offload */ + if (iniConfig->enable_dhcp_srv_offload && + sme_IsFeatureSupportedByFW(SAP_OFFLOADS)) { + vos_event_reset(&pHostapdAdapter->dhcp_status.vos_event); + status = wlan_hdd_set_dhcp_server_offload(pHostapdAdapter, false); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("HDD DHCP Server Offload Failed!!")); + vos_event_reset(&pHostapdState->vosEvent); + if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) { + status = vos_wait_single_event(&pHostapdState->vosEvent, + 10000); + if (!VOS_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("SAP Stop Failed")); + ret = -EINVAL; + goto error; + } + } + } + status = vos_wait_single_event(&pHostapdAdapter->dhcp_status.vos_event, 2000); + if (!VOS_IS_STATUS_SUCCESS(status) || pHostapdAdapter->dhcp_status.dhcp_offload_status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("ERROR: DHCP HDD vos wait for single_event failed!! %d"), + pHostapdAdapter->dhcp_status.dhcp_offload_status); + vos_event_reset(&pHostapdState->vosEvent); + if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) { + status = vos_wait_single_event(&pHostapdState->vosEvent, + 10000); + if (!VOS_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("SAP Stop Failed")); + ret = -EINVAL; + goto error; + } + } + } +#ifdef MDNS_OFFLOAD + if (iniConfig->enable_mdns_offload) { + vos_event_reset(&pHostapdAdapter->mdns_status.vos_event); + status = wlan_hdd_set_mdns_offload(pHostapdAdapter); + if (VOS_IS_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("HDD MDNS Server Offload Failed!!")); + vos_event_reset(&pHostapdState->vosEvent); + if (VOS_STATUS_SUCCESS == + WLANSAP_StopBss(pHddCtx->pvosContext)) { + status = vos_wait_single_event(&pHostapdState->vosEvent, + 10000); + if (!VOS_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("SAP Stop Failed")); + ret = -EINVAL; + goto error; + } + } + } + status = vos_wait_single_event(&pHostapdAdapter-> + mdns_status.vos_event, 2000); + if (!VOS_IS_STATUS_SUCCESS(status) || + pHostapdAdapter->mdns_status.mdns_enable_status || + pHostapdAdapter->mdns_status.mdns_fqdn_status || + pHostapdAdapter->mdns_status.mdns_resp_status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("MDNS HDD vos wait for single_event failed!! enable %d fqdn %d resp %d"), + pHostapdAdapter->mdns_status.mdns_enable_status, + pHostapdAdapter->mdns_status.mdns_fqdn_status, + pHostapdAdapter->mdns_status.mdns_resp_status); + vos_event_reset(&pHostapdState->vosEvent); + if (VOS_STATUS_SUCCESS == + WLANSAP_StopBss(pHddCtx->pvosContext)) { + status = vos_wait_single_event(&pHostapdState->vosEvent, + 10000); + if (!VOS_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("SAP Stop Failed")); + ret = -EINVAL; + goto error; + } + } + } + } +#endif /* MDNS_OFFLOAD */ + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + ("DHCP Disabled ini %d, FW %d"), + iniConfig->enable_dhcp_srv_offload, + sme_IsFeatureSupportedByFW(SAP_OFFLOADS)); + } +#endif /* DHCP_SERVER_OFFLOAD */ + #ifdef WLAN_FEATURE_P2P_DEBUG if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO) { @@ -9615,6 +10464,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, } } #endif + /* Check and restart SAP if it is on Unsafe channel */ + hdd_check_for_unsafe_ch(pHostapdAdapter, pHddCtx); pHostapdState->bCommit = TRUE; EXIT(); @@ -11911,6 +12762,10 @@ static int __wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy, { if ( (eCSR_ENCRYPT_TYPE_TKIP != pHddStaCtx->conn_info.ucEncryptionType) && +#ifdef FEATURE_WLAN_WAPI + (eCSR_ENCRYPT_TYPE_WPI != + pHddStaCtx->conn_info.ucEncryptionType) && +#endif (eCSR_ENCRYPT_TYPE_AES != pHddStaCtx->conn_info.ucEncryptionType) ) @@ -12617,9 +13472,11 @@ VOS_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t * pAdapter, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) static inline bool wlan_hdd_cfg80211_validate_scan_req(struct cfg80211_scan_request - *scan_req) + *scan_req, hdd_context_t + *hdd_ctx) { - if (!scan_req || !scan_req->wiphy) { + if (!scan_req || !scan_req->wiphy || + scan_req->wiphy != hdd_ctx->wiphy) { hddLog(VOS_TRACE_LEVEL_ERROR, "Invalid scan request"); return false; } @@ -12632,9 +13489,11 @@ static inline bool wlan_hdd_cfg80211_validate_scan_req(struct #else static inline bool wlan_hdd_cfg80211_validate_scan_req(struct cfg80211_scan_request - *scan_req) + *scan_req, hdd_context_t + *hdd_ctx) { - if (!scan_req || !scan_req->wiphy) { + if (!scan_req || !scan_req->wiphy || + scan_req->wiphy != hdd_ctx->wiphy) { hddLog(VOS_TRACE_LEVEL_ERROR, "Invalid scan request"); return false; } @@ -12642,7 +13501,7 @@ static inline bool wlan_hdd_cfg80211_validate_scan_req(struct } #endif - +#define NET_DEV_IS_IFF_UP(pAdapter) (pAdapter->dev->flags & IFF_UP) /* * FUNCTION: hdd_cfg80211_scan_done_callback * scanning callback function, called after finishing scan @@ -12658,9 +13517,6 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, struct cfg80211_scan_request *req = NULL; int ret = 0; bool aborted = false; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) - bool iface_down = false; -#endif long waitRet = 0; tANI_U8 i; hdd_context_t *pHddCtx; @@ -12679,10 +13535,9 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) - if (!(pAdapter->dev->flags & IFF_UP)) + if (!NET_DEV_IS_IFF_UP(pAdapter)) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("Interface is down")); - iface_down = true; } #endif pScanInfo = &pHddCtx->scan_info; @@ -12722,7 +13577,7 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) - if (!iface_down) + if (NET_DEV_IS_IFF_UP(pAdapter)) #endif { ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy, @@ -12764,11 +13619,11 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, /* Scan is no longer pending */ pScanInfo->mScanPending = VOS_FALSE; - if (!wlan_hdd_cfg80211_validate_scan_req(req)) + if (!wlan_hdd_cfg80211_validate_scan_req(req, pHddCtx)) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) hddLog(VOS_TRACE_LEVEL_ERROR, FL("interface state %s"), - iface_down ? "up" : "down"); + NET_DEV_IS_IFF_UP(pAdapter) ? "up" : "down"); #endif if (pAdapter->dev) { @@ -12810,7 +13665,8 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) - if (!iface_down) + if (NET_DEV_IS_IFF_UP(pAdapter) && + wlan_hdd_cfg80211_validate_scan_req(req, pHddCtx)) #endif cfg80211_scan_done(req, aborted); @@ -12837,7 +13693,7 @@ allow_suspend: hdd_prevent_suspend_timeout(1000, WIFI_POWER_EVENT_WAKELOCK_SCAN); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) - if (!iface_down) + if (NET_DEV_IS_IFF_UP(pAdapter)) #endif #ifdef FEATURE_WLAN_TDLS wlan_hdd_tdls_scan_done_callback(pAdapter); @@ -12880,7 +13736,7 @@ v_BOOL_t hdd_isConnectionInProgress(hdd_context_t *pHddCtx, v_U8_t *session_id, (eConnectionState_Connecting == (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(LOG1, "%s: %p(%d) Connection is in progress", __func__, WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId); if (session_id && reason) @@ -12893,7 +13749,7 @@ v_BOOL_t hdd_isConnectionInProgress(hdd_context_t *pHddCtx, v_U8_t *session_id, if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && smeNeighborMiddleOfRoaming(WLAN_HDD_GET_HAL_CTX(pAdapter))) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(LOG1, "%s: %p(%d) Reassociation is in progress", __func__, WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId); if (session_id && reason) @@ -12912,7 +13768,7 @@ v_BOOL_t hdd_isConnectionInProgress(hdd_context_t *pHddCtx, v_U8_t *session_id, (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated)) { staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]); - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(LOG1, "%s: client " MAC_ADDRESS_STR " is in the middle of WPS/EAPOL exchange.", __func__, MAC_ADDR_ARRAY(staMac)); @@ -12942,7 +13798,7 @@ v_BOOL_t hdd_isConnectionInProgress(hdd_context_t *pHddCtx, v_U8_t *session_id, { staMac = (v_U8_t *) &(pSapCtx->aStaInfo[staId].macAddrSTA.bytes[0]); - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(LOG1, "%s: client " MAC_ADDRESS_STR " of SoftAP/P2P-GO is in the " "middle of WPS/EAPOL exchange.", __func__, MAC_ADDR_ARRAY(staMac)); @@ -13117,30 +13973,33 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy, } if (hdd_isConnectionInProgress(pHddCtx, &curr_session_id, &curr_reason)) { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("Scan not allowed")); + + if (!(pHddCtx->scan_reject_cnt % HDD_SCAN_REJECT_RATE_LIMIT)) + hddLog(LOGE, FL("Scan not allowed Session %d reason %d"), + curr_session_id, curr_reason); if (pHddCtx->last_scan_reject_session_id != curr_session_id || pHddCtx->last_scan_reject_reason != curr_reason || !pHddCtx->last_scan_reject_timestamp) { pHddCtx->last_scan_reject_session_id = curr_session_id; pHddCtx->last_scan_reject_reason = curr_reason; - pHddCtx->last_scan_reject_timestamp = jiffies_to_msecs(jiffies); + pHddCtx->last_scan_reject_timestamp = + jiffies_to_msecs(jiffies) + SCAN_REJECT_THRESHOLD_TIME; pHddCtx->scan_reject_cnt = 0; } else { pHddCtx->scan_reject_cnt++; - hddLog(LOGE, FL("Reject cnt %d time delta %lu ms"), pHddCtx->scan_reject_cnt, - (jiffies_to_msecs(jiffies) - - pHddCtx->last_scan_reject_timestamp)); - if ((pHddCtx->scan_reject_cnt >= SCAN_REJECT_THRESHOLD) && - (jiffies_to_msecs(jiffies) - - pHddCtx->last_scan_reject_timestamp) >= - SCAN_REJECT_THRESHOLD_TIME) + vos_system_time_after(jiffies_to_msecs(jiffies), + pHddCtx->last_scan_reject_timestamp)) { + hddLog(LOGE, FL("Session %d reason %d reject cnt %d threshold time has elapsed? %d"), + curr_session_id, curr_reason, pHddCtx->scan_reject_cnt, + vos_system_time_after(jiffies_to_msecs(jiffies), + pHddCtx->last_scan_reject_timestamp)); pHddCtx->last_scan_reject_timestamp = 0; pHddCtx->scan_reject_cnt = 0; if (pHddCtx->cfg_ini->enableFatalEvent) @@ -13605,6 +14464,7 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, int status = 0; hdd_wext_state_t *pWextState; hdd_context_t *pHddCtx; + hdd_station_ctx_t *hdd_sta_ctx; v_U32_t roamId; tCsrRoamProfile *pRoamProfile; eCsrAuthType RSNAuthType; @@ -13613,6 +14473,7 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); status = wlan_hdd_validate_context(pHddCtx); if (status) @@ -13626,12 +14487,15 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, return -EINVAL; } + wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx); + pRoamProfile = &pWextState->roamProfile; if (pRoamProfile) { hdd_station_ctx_t *pHddStaCtx; pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + pHddStaCtx->get_mgmt_log_sent = FALSE; wlan_hdd_get_frame_logs(pAdapter, WLAN_HDD_GET_FRAME_LOG_CMD_CLEAR); @@ -13883,8 +14747,12 @@ static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter, hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); ENTER(); /* Should be in ieee802_11_defs.h */ +#ifndef WLAN_AKM_SUITE_8021X_SHA256 #define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05 +#endif +#ifndef WLAN_AKM_SUITE_PSK_SHA256 #define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06 +#endif /*set key mgmt type*/ switch(key_mgmt) { @@ -14600,7 +15468,7 @@ int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter, * This function is used to disconnect from previous * connection */ -static int wlan_hdd_try_disconnect( hdd_adapter_t *pAdapter ) +int wlan_hdd_try_disconnect( hdd_adapter_t *pAdapter ) { long ret = 0; int status, result = 0; @@ -14712,6 +15580,51 @@ static int wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter, } #endif +/** + * wlan_hdd_check_ht20_ht40_ind() - check if Supplicant has indicated to + * connect in HT20 mode + * @hdd_ctx: hdd context + * @adapter: Pointer to the HDD adapter + * @req: Pointer to the structure cfg_connect_params receieved from user space + * + * This function will check if supplicant has indicated to to connect in HT20 + * mode. this is currently applicable only for 2.4Ghz mode only. + * if feature is enabled and supplicant indicate HT20 set + * force_24ghz_in_ht20 to true to force 2.4Ghz in HT20 else set it to false. + * + * Return: void + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) +static void wlan_hdd_check_ht20_ht40_ind(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + struct cfg80211_connect_params *req) +{ + hdd_wext_state_t *wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter); + tCsrRoamProfile *roam_profile; + + roam_profile = &wext_state->roamProfile; + roam_profile->force_24ghz_in_ht20 = false; + if (hdd_ctx->cfg_ini->override_ht20_40_24g && + !(req->ht_capa.cap_info & + IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + roam_profile->force_24ghz_in_ht20 = true; + + hddLog(LOG1, FL("req->ht_capa.cap_info %x override_ht20_40_24g %d"), + req->ht_capa.cap_info, hdd_ctx->cfg_ini->override_ht20_40_24g); +} +#else +static inline void wlan_hdd_check_ht20_ht40_ind(hdd_context_t *hdd_ctx, + hdd_adapter_t *adapter, + struct cfg80211_connect_params *req) +{ + hdd_wext_state_t *wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter); + tCsrRoamProfile *roam_profile; + + roam_profile = &wext_state->roamProfile; + roam_profile->force_24ghz_in_ht20 = false; +} +#endif + /* * FUNCTION: __wlan_hdd_cfg80211_connect * This function is used to start the association process @@ -14828,6 +15741,8 @@ static int __wlan_hdd_cfg80211_connect( struct wiphy *wiphy, if (0 != status) hddLog(VOS_TRACE_LEVEL_ERROR, FL("scan abort failed")); + wlan_hdd_check_ht20_ht40_ind(pHddCtx, pAdapter, req); + status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid, req->ssid_len, req->bssid, bssid_hint, channel); @@ -14875,6 +15790,7 @@ int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason ) hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); long ret; + eConnectionState prev_conn_state; ENTER(); @@ -14895,6 +15811,8 @@ int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason ) * Calls hdd_DisConnectHandler. */ + prev_conn_state = pHddStaCtx->conn_info.connState; + spin_lock_bh(&pAdapter->lock_for_active_session); if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) { @@ -14921,7 +15839,21 @@ int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason ) /*issue disconnect*/ status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, reason); - if(eHAL_STATUS_CMD_NOT_QUEUED == status) + if((eHAL_STATUS_CMD_NOT_QUEUED == status) && + prev_conn_state != eConnectionState_Connecting) + { + hddLog(LOG1, + FL("status = %d, already disconnected"), status); + result = 0; + goto disconnected; + } + /* + * Wait here instead of returning directly, this will block the next + * connect command and allow processing of the scan for ssid and + * the previous connect command in CSR. Else we might hit some + * race conditions leading to SME and HDD out of sync. + */ + else if(eHAL_STATUS_CMD_NOT_QUEUED == status) { hddLog(LOG1, FL("Already disconnected or connect was in sme/roam pending list and removed by disconnect")); @@ -15076,7 +16008,10 @@ static int __wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, } } #endif - hddLog(LOG1, FL("Disconnecting with reasoncode:%u"), reasonCode); + + hddLog(LOG1, FL("Disconnecting with reasoncode:%u connState %d"), + reasonCode, + pHddStaCtx->conn_info.connState); status = wlan_hdd_disconnect(pAdapter, reasonCode); if ( 0 != status ) { @@ -15391,6 +16326,7 @@ static int __wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy, tCsrRoamProfile *pRoamProfile; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); int status; + eHalStatus hal_status; #ifdef WLAN_FEATURE_RMC tANI_U8 addIE[WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN] = {0}; #endif @@ -15463,8 +16399,23 @@ static int __wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy, /* Issue Disconnect request */ INIT_COMPLETION(pAdapter->disconnect_comp_var); - sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, - eCSR_DISCONNECT_REASON_IBSS_LEAVE); + hal_status = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_IBSS_LEAVE); + if (!HAL_STATUS_SUCCESS(hal_status)) { + hddLog(LOGE, + FL("sme_RoamDisconnect failed hal_status(%d)"), + hal_status); + return -EAGAIN; + } + status = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!status) { + hddLog(LOGE, + FL("wait on disconnect_comp_var failed")); + return -ETIMEDOUT; + } EXIT(); return 0; @@ -15787,6 +16738,63 @@ static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, return ret; } +/* + * wlan_hdd_fill_summary_stats() - populate station_info summary stats + * @stats: summary stats to use as a source + * @info: kernel station_info struct to use as a destination + * + * Return: None + */ +static void wlan_hdd_fill_summary_stats(tCsrSummaryStatsInfo *stats, + struct station_info *info) +{ + int i; + + info->rx_packets = stats->rx_frm_cnt; + info->tx_packets = 0; + info->tx_retries = 0; + info->tx_failed = 0; + + for (i = 0; i < 4; ++i) { + info->tx_packets += stats->tx_frm_cnt[i]; + info->tx_retries += stats->multiple_retry_cnt[i]; + info->tx_failed += stats->fail_cnt[i]; + } + + info->filled |= STATION_INFO_TX_PACKETS | + STATION_INFO_TX_RETRIES | + STATION_INFO_TX_FAILED | + STATION_INFO_RX_PACKETS; +} + +/** + * wlan_hdd_get_sap_stats() - get aggregate SAP stats + * @adapter: sap adapter to get stats for + * @info: kernel station_info struct to populate + * + * Fetch the vdev-level aggregate stats for the given SAP adapter. This is to + * support "station dump" and "station get" for SAP vdevs, even though they + * aren't technically stations. + * + * Return: errno + */ +static int +wlan_hdd_get_sap_stats(hdd_adapter_t *adapter, struct station_info *info) +{ + VOS_STATUS status; + + status = wlan_hdd_get_station_stats(adapter); + if (!VOS_IS_STATUS_SUCCESS(status)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "Failed to get SAP stats; status:%d", status); + return 0; + } + + wlan_hdd_fill_summary_stats(&adapter->hdd_stats.summary_stat, info); + + return 0; +} + static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)) const u8* mac, @@ -15810,6 +16818,7 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET]; tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET; tANI_U16 maxRate = 0; + int8_t snr = 0; tANI_U16 myRate; tANI_U16 currentRate = 0; tANI_U8 maxSpeedMCS = 0; @@ -15826,6 +16835,15 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic ENTER(); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + { + return status; + } + + if (pAdapter->device_mode == WLAN_HDD_SOFTAP) + return wlan_hdd_get_sap_stats(pAdapter, sinfo); + if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) || (0 == ssidlen)) { @@ -15844,16 +16862,13 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic return 0; } - status = wlan_hdd_validate_context(pHddCtx); - if (0 != status) - { - return status; - } - wlan_hdd_get_station_stats(pAdapter); rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags; wlan_hdd_get_rssi(pAdapter, &sinfo->signal); + wlan_hdd_get_snr(pAdapter, &snr); + pHddStaCtx->conn_info.signal = sinfo->signal; + pHddStaCtx->conn_info.noise = pHddStaCtx->conn_info.signal - snr; sinfo->filled |= STATION_INFO_SIGNAL; /*overwrite rate_flags if MAX link-speed need to be reported*/ @@ -16242,6 +17257,8 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_devic sinfo->rx_packets = pAdapter->hdd_stats.summary_stat.rx_frm_cnt; sinfo->filled |= STATION_INFO_RX_PACKETS; + vos_mem_copy(&pHddStaCtx->conn_info.txrate, + &sinfo->txrate, sizeof(sinfo->txrate)); if (rate_flags & eHAL_TX_RATE_LEGACY) hddLog(LOG1, FL("Reporting RSSI:%d legacy rate %d pkt cnt tx %d rx %d"), sinfo->signal, sinfo->txrate.legacy, sinfo->tx_packets, @@ -16453,6 +17470,12 @@ static int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, FL("psapCtx is NULL")); return -ENOENT; } + if (pHddCtx->cfg_ini->enable_sap_auth_offload) + { + VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, + "Change reason code to eSIR_MAC_DISASSOC_LEAVING_BSS_REASON in sap auth offload"); + pDelStaParams->reason_code = eSIR_MAC_DISASSOC_LEAVING_BSS_REASON; + } if (vos_is_macaddr_broadcast((v_MACADDR_t *)pDelStaParams->peerMacAddr)) { v_U16_t i; @@ -16962,11 +17985,19 @@ static eHalStatus wlan_hdd_is_pno_allowed(hdd_adapter_t *pAdapter) hdd_station_ctx_t *pStaCtx; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); int status = 0; + + if (WLAN_HDD_INFRA_STATION != pAdapter->device_mode) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: PNO is allowed only in STA interface", __func__); + return eHAL_STATUS_FAILURE; + } + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); /* The current firmware design does not allow PNO during any - * active sessions. Hence, determine the active sessions - * and return a failure. + * active sessions. PNO is allowed only in case when sap session + * is present and sapo auth offload feature enabled in firmare. */ while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status)) { @@ -16977,7 +18008,8 @@ static eHalStatus wlan_hdd_is_pno_allowed(hdd_adapter_t *pAdapter) && (eConnectionState_NotConnected != pStaCtx->conn_info.connState)) || (WLAN_HDD_P2P_CLIENT == pTempAdapter->device_mode) || (WLAN_HDD_P2P_GO == pTempAdapter->device_mode) - || (WLAN_HDD_SOFTAP == pTempAdapter->device_mode) + || (WLAN_HDD_SOFTAP == pTempAdapter->device_mode && + !pHddCtx->cfg_ini->enable_sap_auth_offload) || (WLAN_HDD_TM_LEVEL_4 == pHddCtx->tmInfo.currentTmLevel) ) { @@ -17021,6 +18053,69 @@ void hdd_cfg80211_sched_scan_start_status_cb(void *callbackContext, VOS_STATUS s EXIT(); } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)) || \ + defined (CFG80211_MULTI_SCAN_PLAN_BACKPORT) +/** + * hdd_config_sched_scan_plan() - configures the sched scan plans + * from the framework. + * @pno_req: pointer to PNO scan request + * @request: pointer to scan request from framework + * + * Return: None + */ +static void hdd_config_sched_scan_plan(tpSirPNOScanReq pno_req, + struct cfg80211_sched_scan_request *request, + hdd_context_t *hdd_ctx) +{ + v_U32_t i = 0; + + pno_req->scanTimers.ucScanTimersCount = request->n_scan_plans; + for (i = 0; i < request->n_scan_plans; i++) + { + pno_req->scanTimers.aTimerValues[i].uTimerRepeat = + request->scan_plans[i].iterations; + pno_req->scanTimers.aTimerValues[i].uTimerValue = + request->scan_plans[i].interval; + } +} +#else +static void hdd_config_sched_scan_plan(tpSirPNOScanReq pno_req, + struct cfg80211_sched_scan_request *request, + hdd_context_t *hdd_ctx) +{ + v_U32_t i, temp_int; + /* Driver gets only one time interval which is hardcoded in + * supplicant for 10000ms. Taking power consumption into account 6 + * timers will be used, Timervalue is increased exponentially + * i.e 10,20,40, 80,160,320 secs. And number of scan cycle for each + * timer is configurable through INI param gPNOScanTimerRepeatValue. + * If it is set to 0 only one timer will be used and PNO scan cycle + * will be repeated after each interval specified by supplicant + * till PNO is disabled. + */ + if (0 == hdd_ctx->cfg_ini->configPNOScanTimerRepeatValue) + pno_req->scanTimers.ucScanTimersCount = + HDD_PNO_SCAN_TIMERS_SET_ONE; + else + pno_req->scanTimers.ucScanTimersCount = + HDD_PNO_SCAN_TIMERS_SET_MULTIPLE; + + temp_int = (request->interval)/1000; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Base scan interval = %d PNOScanTimerRepeatValue = %d", + temp_int, hdd_ctx->cfg_ini->configPNOScanTimerRepeatValue); + for ( i = 0; i < pno_req->scanTimers.ucScanTimersCount; i++) + { + pno_req->scanTimers.aTimerValues[i].uTimerRepeat = + hdd_ctx->cfg_ini->configPNOScanTimerRepeatValue; + pno_req->scanTimers.aTimerValues[i].uTimerValue = temp_int; + temp_int *= 2; + } + //Repeat last timer until pno disabled. + pno_req->scanTimers.aTimerValues[i-1].uTimerRepeat = 0; +} +#endif + /* * FUNCTION: __wlan_hdd_cfg80211_sched_scan_start * Function to enable PNO @@ -17032,7 +18127,7 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, tSirPNOScanReq pnoRequest = {0}; hdd_context_t *pHddCtx; tHalHandle hHal; - v_U32_t i, indx, num_ch, tempInterval, j; + v_U32_t i, indx, num_ch, j; u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN; @@ -17069,7 +18164,6 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_SCHED_SCAN_START, pAdapter->sessionId, pAdapter->device_mode)); - sme_ScanFlushResult(hHal, pAdapter->sessionId); ret = wlan_hdd_scan_abort(pAdapter); if (ret < 0) { @@ -17276,34 +18370,7 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, pnoRequest.us5GProbeTemplateLen); } - /* Driver gets only one time interval which is hardcoded in - * supplicant for 10000ms. Taking power consumption into account 6 timers - * will be used, Timervalue is increased exponentially i.e 10,20,40, - * 80,160,320 secs. And number of scan cycle for each timer - * is configurable through INI param gPNOScanTimerRepeatValue. - * If it is set to 0 only one timer will be used and PNO scan cycle - * will be repeated after each interval specified by supplicant - * till PNO is disabled. - */ - if (0 == pHddCtx->cfg_ini->configPNOScanTimerRepeatValue) - pnoRequest.scanTimers.ucScanTimersCount = HDD_PNO_SCAN_TIMERS_SET_ONE; - else - pnoRequest.scanTimers.ucScanTimersCount = - HDD_PNO_SCAN_TIMERS_SET_MULTIPLE; - - tempInterval = (request->interval)/1000; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Base scan interval = %d PNOScanTimerRepeatValue = %d", - tempInterval, pHddCtx->cfg_ini->configPNOScanTimerRepeatValue); - for ( i = 0; i < pnoRequest.scanTimers.ucScanTimersCount; i++) - { - pnoRequest.scanTimers.aTimerValues[i].uTimerRepeat = - pHddCtx->cfg_ini->configPNOScanTimerRepeatValue; - pnoRequest.scanTimers.aTimerValues[i].uTimerValue = tempInterval; - tempInterval *= 2; - } - //Repeat last timer until pno disabled. - pnoRequest.scanTimers.aTimerValues[i-1].uTimerRepeat = 0; + hdd_config_sched_scan_plan(&pnoRequest, request, pHddCtx); pnoRequest.modePNO = SIR_PNO_MODE_IMMEDIATE; @@ -19249,6 +20316,7 @@ static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len return -EINVAL; } + vos_mem_zero(hb_params, sizeof(tSirLPHBReq)); vos_mem_copy(hb_params, buf, buf_len); smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal), hb_params, @@ -19288,6 +20356,7 @@ static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, } #endif /* CONFIG_NL80211_TESTMODE */ +extern void hdd_set_wlan_suspend_mode(bool suspend); static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, int idx, struct survey_info *survey) @@ -19434,6 +20503,14 @@ int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_RESUME_WLAN, NO_SESSION, pHddCtx->isWiphySuspended)); + + if (pHddCtx->is_ap_mode_wow_supported) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Resume SoftAP", __func__); + hdd_set_wlan_suspend_mode(false); + } + spin_lock(&pHddCtx->schedScan_lock); pHddCtx->isWiphySuspended = FALSE; if (TRUE != pHddCtx->isSchedScanUpdatePending) @@ -19518,6 +20595,12 @@ int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, return ret; } + if (pHddCtx->is_ap_mode_wow_supported) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Suspend SoftAP", __func__); + hdd_set_wlan_suspend_mode(true); + } + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN, diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c index 275eeaf6d3e..d715393414b 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -162,6 +162,10 @@ static int wlan_suspend(hdd_context_t* pHddCtx) if ((vos_timer_get_system_time() - pHddCtx->last_suspend_success) >= WLAN_POWER_COLLAPSE_FAIL_THRESHOLD) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("Current time: %lu Last suspend fail time: %lu continuous fail count: %d"), + vos_timer_get_system_time(), pHddCtx->last_suspend_success, + pHddCtx->continuous_suspend_fail_cnt); pHddCtx->last_suspend_success = 0; vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL, WLAN_LOG_INDICATOR_HOST_DRIVER, diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c index 57596797597..c14890ccb2e 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -98,7 +98,7 @@ static eHalStatus g_full_pwr_status; static eHalStatus g_standby_status; extern VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx); -extern void hdd_wlan_initial_scan(hdd_context_t *pHddCtx); +extern void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter); extern struct notifier_block hdd_netdev_notifier; extern tVOS_CON_MODE hdd_get_conparam ( void ); @@ -489,7 +489,7 @@ VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE; //Trigger the initial scan - hdd_wlan_initial_scan(pHddCtx); + hdd_wlan_initial_scan(pAdapter); return VOS_STATUS_SUCCESS; @@ -643,12 +643,16 @@ void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) } if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || + ((WLAN_HDD_SOFTAP == pAdapter->device_mode) && + (pHddCtx->is_ap_mode_wow_supported))) { if (fenable) { - if (eConnectionState_Associated == - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) + if (((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && + (eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) + || (WLAN_HDD_SOFTAP == pAdapter->device_mode)) { if ((pHddCtx->cfg_ini->fhostArpOffload)) { @@ -871,6 +875,8 @@ void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable) i++; } } + /* store actual slots being used */ + pAdapter->ns_slots = i; read_unlock_bh(&in6_dev->lock); vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest)); @@ -975,7 +981,7 @@ void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable) hdd_wlan_offload_event(SIR_IPV6_NS_OFFLOAD, SIR_OFFLOAD_DISABLE); - for (i = 0; i < slot_index; i++) + for (i = 0; i < pAdapter->ns_slots; i++) { hddLog(VOS_TRACE_LEVEL_INFO, FL("Disable Slot= %d"), i); offLoadRequest.nsOffloadInfo.slotIdx = i; @@ -987,6 +993,7 @@ void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable) " %d Slot"), i); } } + pAdapter->ns_slots = 0; } end: while (slot > 0 && selfIPv6Addr[--slot]) @@ -1468,6 +1475,26 @@ void hdd_mc_addr_list_cfg_config(hdd_context_t* pHddCtx, bool action) } } +/** + * hdd_suspend_ind_callback: This API will set completion event for suspend + * @pAdapter: hdd_adapter_t + * @status: suspend status + * + * Return: none + */ +static void hdd_suspend_ind_callback(void *context, VOS_STATUS status) +{ + hdd_adapter_t *adapter = (hdd_adapter_t *)context; + if (NULL == adapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: HDD adapter is NULL",__func__); + return; + } + hddLog(VOS_TRACE_LEVEL_INFO, FL("suspend status %d"), status); + complete(&adapter->wlan_suspend_comp_var); +} + static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx, hdd_adapter_t *pAdapter) { @@ -1513,6 +1540,8 @@ static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx, wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter; + wlanSuspendParam->wlan_sus_callback = hdd_suspend_ind_callback; + wlanSuspendParam->context = pAdapter; /* mc add list cfg item configuration in fwr */ hdd_mc_addr_list_cfg_config(pHddCtx, true); @@ -1589,7 +1618,7 @@ void hdd_suspend_wlan(void) { hdd_context_t *pHddCtx = NULL; v_CONTEXT_t pVosContext = NULL; - + long ret; VOS_STATUS status; hdd_adapter_t *pAdapter = NULL; hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; @@ -1673,9 +1702,17 @@ void hdd_suspend_wlan(void) } #endif + INIT_COMPLETION(pAdapter->wlan_suspend_comp_var); /*Suspend notification sent down to driver*/ hdd_conf_suspend_ind(pHddCtx, pAdapter); - + ret = wait_for_completion_interruptible_timeout( + &pAdapter->wlan_suspend_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR)); + if (0 >= ret) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s:wait on suspend failed %ld", + __func__, ret); + } status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); pAdapterNode = pNext; } @@ -1946,6 +1983,8 @@ void hdd_resume_wlan(void) hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; VOS_STATUS status; v_CONTEXT_t pVosContext = NULL; + tPmcState pmc_state; + hdd_adapter_t *first_adapter = NULL; hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__); @@ -1980,6 +2019,26 @@ void hdd_resume_wlan(void) pHddCtx->hdd_wlan_suspended = FALSE; hdd_wlan_suspend_resume_event(HDD_WLAN_EARLY_RESUME); + + /* Get first valid adapter for disable/enable bmps purpose */ + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + first_adapter = pAdapterNode->pAdapter; + if (first_adapter != NULL) + break; + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + pmc_state = pmcGetPmcState(pHddCtx->hHal); + if (BMPS == pmc_state && first_adapter) + { + /* put the device into full power */ + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Disaling bmps during resume", __func__); + wlan_hdd_enter_bmps(first_adapter, DRIVER_POWER_MODE_ACTIVE); + } + /*loop through all adapters. Concurrency */ status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); @@ -2027,14 +2086,8 @@ void hdd_resume_wlan(void) "Switch to DTIM%d",powerRequest.uListenInterval); sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE); - if (BMPS == pmcGetPmcState(pHddCtx->hHal)) + if (BMPS == pmc_state) { - /* put the device into full power */ - wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE); - - /* put the device back into BMPS */ - wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO); - pHddCtx->hdd_ignore_dtim_enabled = FALSE; } } @@ -2044,6 +2097,15 @@ void hdd_resume_wlan(void) pAdapterNode = pNext; } + if (BMPS == pmc_state && first_adapter) + { + /* put the device into full power */ + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Enable bmps during resume", __func__); + /* put the device back into BMPS */ + wlan_hdd_enter_bmps(first_adapter, DRIVER_POWER_MODE_AUTO); + } + #ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY) { @@ -2128,6 +2190,30 @@ static void hdd_ssr_timer_start(int msec) ssr_timer_started = true; } +#ifdef FEATURE_WLAN_DIAG_SUPPORT +/** + * hdd_wlan_ssr_shutdown_event()- send ssr shutdown state + * + * This Function send send ssr shutdown state diag event + * + * Return: void. + */ +static void hdd_wlan_ssr_shutdown_event(void) +{ + WLAN_VOS_DIAG_EVENT_DEF(ssr_shutdown, + struct host_event_wlan_ssr_shutdown); + vos_mem_zero(&ssr_shutdown, sizeof(ssr_shutdown)); + ssr_shutdown.status = SSR_SUB_SYSTEM_SHUTDOWN; + WLAN_VOS_DIAG_EVENT_REPORT(&ssr_shutdown, + EVENT_WLAN_SSR_SHUTDOWN_SUBSYSTEM); +} +#else +static inline void hdd_wlan_ssr_shutdown_event(void) +{ + +}; +#endif + /* the HDD interface to WLAN driver shutdown, * the primary shutdown function in SSR */ @@ -2164,7 +2250,6 @@ VOS_STATUS hdd_wlan_shutdown(void) { vos_timer_stop(&pHddCtx->tx_rx_trafficTmr); } - vos_flush_delayed_work(&pHddCtx->spoof_mac_addr_work); vos_flush_work(&pHddCtx->sap_start_work); hdd_reset_all_adapters(pHddCtx); @@ -2313,11 +2398,81 @@ VOS_STATUS hdd_wlan_shutdown(void) hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock", __func__); } + hdd_wlan_ssr_shutdown_event(); hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete" ,__func__); return VOS_STATUS_SUCCESS; } +int hdd_dhcp_mdns_offload(hdd_adapter_t *adapter) +{ + hdd_config_t *config; + int status = VOS_STATUS_SUCCESS; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + config = hdd_ctx->cfg_ini; + if (NULL == config) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("cfg_ini is NULL!!")); + return -EINVAL; + } +#ifdef DHCP_SERVER_OFFLOAD + /* set dhcp server offload */ + if (config->enable_dhcp_srv_offload && + sme_IsFeatureSupportedByFW(SAP_OFFLOADS)) { + vos_event_reset(&adapter->dhcp_status.vos_event); + status = wlan_hdd_set_dhcp_server_offload(adapter, true); + if (!VOS_IS_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("HDD DHCP Server Offload Failed!!")); + return -EINVAL; + } + status = vos_wait_single_event(&adapter->dhcp_status.vos_event, 2000); + if (!VOS_IS_STATUS_SUCCESS(status) || + adapter->dhcp_status.dhcp_offload_status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("ERROR: DHCP HDD vos wait for single_event failed!! %d"), + adapter->dhcp_status.dhcp_offload_status); + return -EINVAL; + } +#ifdef MDNS_OFFLOAD + if (config->enable_mdns_offload) { + vos_event_reset(&adapter->mdns_status.vos_event); + status = wlan_hdd_set_mdns_offload(adapter); + if (VOS_IS_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("HDD MDNS Server Offload Failed!!")); + return -EINVAL; + } + status = vos_wait_single_event(&adapter-> + mdns_status.vos_event, 2000); + if (!VOS_IS_STATUS_SUCCESS(status) || + adapter->mdns_status.mdns_enable_status || + adapter->mdns_status.mdns_fqdn_status || + adapter->mdns_status.mdns_resp_status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("MDNS HDD vos wait for single_event failed!! enable %d fqdn %d resp %d"), + adapter->mdns_status.mdns_enable_status, + adapter->mdns_status.mdns_fqdn_status, + adapter->mdns_status.mdns_resp_status); + return -EINVAL; + } + } +#endif /* MDNS_OFFLOAD */ + } else { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + ("DHCP Disabled ini %d, FW %d"), + config->enable_dhcp_srv_offload, + sme_IsFeatureSupportedByFW(SAP_OFFLOADS)); + } +#endif /* DHCP_SERVER_OFFLOAD */ + return status; +} + /** * hdd_ssr_restart_sap() - restart sap on SSR * @hdd_ctx: hdd context @@ -2329,6 +2484,7 @@ static void hdd_ssr_restart_sap(hdd_context_t *hdd_ctx) VOS_STATUS status; hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; hdd_adapter_t *adapter; + hdd_hostapd_state_t *hostapd_state; ENTER(); @@ -2337,8 +2493,29 @@ static void hdd_ssr_restart_sap(hdd_context_t *hdd_ctx) adapter = adapter_node->pAdapter; if (adapter && adapter->device_mode == WLAN_HDD_SOFTAP) { if (test_bit(SOFTAP_INIT_DONE, &adapter->event_flags)) { + hostapd_state = + WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter); hddLog(VOS_TRACE_LEVEL_INFO, FL("Restart prev SAP session")); wlan_hdd_start_sap(adapter); + if (!VOS_IS_STATUS_SUCCESS( + hdd_dhcp_mdns_offload(adapter))) { + vos_event_reset( + &hostapd_state->vosEvent); + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("DHCP/MDNS offload Failed!!")); + if (VOS_STATUS_SUCCESS == + WLANSAP_StopBss( + hdd_ctx->pvosContext)) { + status = vos_wait_single_event( + &hostapd_state->vosEvent + , 10000); + if (!VOS_IS_STATUS_SUCCESS( + status)) { + hddLog(LOGE, FL("SAP Stop Failed")); + return; + } + } + } } } status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); @@ -2348,6 +2525,29 @@ static void hdd_ssr_restart_sap(hdd_context_t *hdd_ctx) EXIT(); } +#ifdef FEATURE_WLAN_DIAG_SUPPORT +/** +* hdd_wlan_ssr_reinit_event()- send ssr reinit state +* +* This Function send send ssr reinit state diag event +* +* Return: void. +*/ +static void hdd_wlan_ssr_reinit_event(void) +{ + WLAN_VOS_DIAG_EVENT_DEF(ssr_reinit, struct host_event_wlan_ssr_reinit); + vos_mem_zero(&ssr_reinit, sizeof(ssr_reinit)); + ssr_reinit.status = SSR_SUB_SYSTEM_REINIT; + WLAN_VOS_DIAG_EVENT_REPORT(&ssr_reinit, + EVENT_WLAN_SSR_REINIT_SUBSYSTEM); +} +#else +static inline void hdd_wlan_ssr_reinit_event(void) +{ + +} +#endif + /* the HDD interface to WLAN driver re-init. * This is called to initialize/start WLAN driver after a shutdown. */ @@ -2646,6 +2846,7 @@ err_re_init: return -EPERM; success: + hdd_wlan_ssr_reinit_event(); /* Trigger replay of BTC events */ send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c index ffe7cbae158..f318f1fadd9 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c @@ -79,6 +79,8 @@ #include "wlan_hdd_p2p.h" #include "cfgApi.h" #include "wniCfg.h" +#include <wlan_hdd_wowl.h> +#include "wlan_hdd_hostapd.h" #ifdef FEATURE_WLAN_CH_AVOID #include "wcnss_wlan.h" @@ -408,6 +410,11 @@ static int hdd_hostapd_driver_command(hdd_adapter_t *pAdapter, hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); tANI_U8 filterType = 0; tANI_U8 *value; + + ret = hdd_drv_cmd_validate(command, 8); + if (ret) + goto exit; + value = command + 9; /* Convert the value from ascii to integer */ @@ -448,6 +455,10 @@ static int hdd_hostapd_driver_command(hdd_adapter_t *pAdapter, } else if (strncasecmp(command, "DISABLE_CA_EVENT", 16) == 0) { + ret = hdd_drv_cmd_validate(command, 16); + if (ret) + goto exit; + ret = hdd_enable_disable_ca_event(pHddCtx, command, 16); } @@ -785,6 +796,54 @@ static int hdd_stop_bss_link(hdd_adapter_t *pHostapdAdapter,v_PVOID_t usrDataFor return (status == VOS_STATUS_SUCCESS) ? 0 : -EBUSY; } +#ifdef SAP_AUTH_OFFLOAD +bool hdd_set_sap_auth_offload(hdd_adapter_t *pHostapdAdapter, + bool enabled) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + struct tSirSapOffloadInfo sap_offload_info; + + vos_mem_copy( &sap_offload_info.macAddr, + pHostapdAdapter->macAddressCurrent.bytes, VOS_MAC_ADDR_SIZE); + + sap_offload_info.sap_auth_offload_enable = enabled; + sap_offload_info.sap_auth_offload_sec_type = + pHddCtx->cfg_ini->sap_auth_offload_sec_type; + sap_offload_info.key_len = + strlen(pHddCtx->cfg_ini->sap_auth_offload_key); + + if (sap_offload_info.sap_auth_offload_enable && + sap_offload_info.sap_auth_offload_sec_type) + { + if (sap_offload_info.key_len < 8 || + sap_offload_info.key_len > WLAN_PSK_STRING_LENGTH) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: invalid key length(%d) of WPA security!", __func__, + sap_offload_info.key_len); + return false; + } + } + if (sap_offload_info.key_len) + { + vos_mem_copy(sap_offload_info.key, + pHddCtx->cfg_ini->sap_auth_offload_key, + sap_offload_info.key_len); + } + if (eHAL_STATUS_SUCCESS != + sme_set_sap_auth_offload(pHddCtx->hHal, &sap_offload_info)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_set_sap_auth_offload fail!", __func__); + return false; + } + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: sme_set_sap_auth_offload successfully!", __func__); + return true; +} +#endif + VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCallback) { hdd_adapter_t *pHostapdAdapter; @@ -1004,8 +1063,12 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa { bAuthRequired = FALSE; } - - if (bAuthRequired || bWPSState == eANI_BOOLEAN_TRUE ) + /* fAuthRequiredshould should be false for sap offload */ + if ((bAuthRequired || bWPSState) +#ifdef SAP_AUTH_OFFLOAD + && !cfg_param->enable_sap_auth_offload +#endif + ) { vos_status = hdd_softap_RegisterSTA( pHostapdAdapter, TRUE, @@ -1553,6 +1616,43 @@ static void hdd_unsafe_channel_restart_sap(hdd_adapter_t *adapter, return; } +void hdd_check_for_unsafe_ch(hdd_adapter_t *phostapd_adapter, + hdd_context_t *hdd_ctxt) +{ + v_U16_t channelLoop; + v_U16_t unsafeChannelCount = 0; + v_U16_t unsafeChannelList[NUM_20MHZ_RF_CHANNELS]; + + /* Get unsafe channel list */ + vos_get_wlan_unsafe_channel(unsafeChannelList, sizeof(unsafeChannelList), + &unsafeChannelCount); + for (channelLoop = 0; channelLoop < unsafeChannelCount; channelLoop++) + { + if ((unsafeChannelList[channelLoop] == + phostapd_adapter->sessionCtx.ap.operatingChannel)) { + if ((AUTO_CHANNEL_SELECT == + phostapd_adapter->sessionCtx.ap.sapConfig.channel) + && (WLAN_HDD_SOFTAP == phostapd_adapter->device_mode)) { + /* + * current operating channel is un-safe channel + * restart driver + */ + hdd_unsafe_channel_restart_sap(phostapd_adapter, hdd_ctxt); + /* + * On LE, this event is handled by wlan-services to + * restart SAP. On android, this event would be + * ignored. + */ + wlan_hdd_send_svc_nlink_msg(WLAN_SVC_SAP_RESTART_IND, + NULL, 0); + } + break; + } + } + return; +} + + /**--------------------------------------------------------------------------- @@ -1717,28 +1817,9 @@ void hdd_hostapd_ch_avoid_cb "%s : Current operation channel %d", __func__, pHostapdAdapter->sessionCtx.ap.operatingChannel); - for (channelLoop = 0; channelLoop < unsafeChannelCount; channelLoop++) - { - if ((unsafeChannelList[channelLoop] == - pHostapdAdapter->sessionCtx.ap.operatingChannel)) - { - if ((AUTO_CHANNEL_SELECT == - pHostapdAdapter->sessionCtx.ap.sapConfig.channel) - && (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)) - { - /* current operating channel is un-safe channel - * restart driver */ - hdd_unsafe_channel_restart_sap(pHostapdAdapter, hddCtxt); - /* On LE, this event is handled by wlan-services to - * restart SAP. On android, this event would be - * ignored. - */ - wlan_hdd_send_svc_nlink_msg(WLAN_SVC_SAP_RESTART_IND, - NULL, 0); - } - return; - } - } + /* Check and Restart the SAP if it is on unsafe channel */ + hdd_check_for_unsafe_ch(pHostapdAdapter, hddCtxt); + } #ifdef WLAN_FEATURE_AP_HT40_24G @@ -1873,6 +1954,7 @@ static __iw_softap_setparam(struct net_device *dev, int set_value = value[1]; eHalStatus status; int ret = 0; /* success */ + int enable_pattrn_byte_match, enable_magic_pkt; v_CONTEXT_t pVosContext; ENTER(); @@ -2026,7 +2108,44 @@ static __iw_softap_setparam(struct net_device *dev, } case QCSAP_PARAM_SET_PROXIMITY: { - ret = wlan_hdd_set_proximity(set_value); + ret = wlan_hdd_set_proximity(set_value, hHal); + break; + } + case QCSAP_PARAM_SET_WOWL: + { + if (!pHddCtx->is_ap_mode_wow_supported) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Not supported",__func__); + return -ENOTSUPP; + } + switch (set_value) + { + case 0x00: + hdd_exit_wowl(pHostapdAdapter, eWOWL_EXIT_USER); + break; + case 0x01: + case 0x02: + case 0x03: + enable_magic_pkt = (set_value & 0x01) ? 1 : 0; + enable_pattrn_byte_match = (set_value & 0x02) ? 1 : 0; + hddLog(LOGE, "magic packet ? = %s pattern byte matching ? = %s", + (enable_magic_pkt ? "YES":"NO"), + (enable_pattrn_byte_match ? "YES":"NO")); + hdd_enter_wowl(pHostapdAdapter, enable_magic_pkt, + enable_pattrn_byte_match); + break; + default: + hddLog(LOGE, "Invalid arg %d in WE_WOWL IOCTL", set_value); + ret = -EINVAL; + break; + } + break; + } + case QCSAP_PARAM_CAP_TSF: + { + ret = hdd_capture_tsf(pHostapdAdapter, + (uint32_t *)&set_value, 1); break; } default: @@ -2187,6 +2306,112 @@ static iw_softap_getparam(struct net_device *dev, return ret; } + +int +static __iw_softap_setchar_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int sub_cmd; + int ret = 0; /* success */ + char *pBuffer = NULL; + hdd_adapter_t *pAdapter; + hdd_context_t *pHddCtx; + struct iw_point s_priv_data; + + ENTER(); + + if (!capable(CAP_NET_ADMIN)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("permission check failed")); + return -EPERM; + } + + pAdapter = (netdev_priv(dev)); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + if (0 != ret) + { + return ret; + } + + if (!pHddCtx->is_ap_mode_wow_supported) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Not supported",__func__); + return -ENOTSUPP; + } + + /* helper function to get iwreq_data with compat handling. */ + if (hdd_priv_get_data(&s_priv_data, wrqu)) + { + return -EINVAL; + } + + /* make sure all params are correctly passed to function */ + if ((NULL == s_priv_data.pointer) || (0 == s_priv_data.length)) + { + return -EINVAL; + } + + sub_cmd = s_priv_data.flags; + + /* ODD number is used for set, copy data using copy_from_user */ + pBuffer = mem_alloc_copy_from_user_helper(s_priv_data.pointer, + s_priv_data.length); + if (NULL == pBuffer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "mem_alloc_copy_from_user_helper fail"); + return -ENOMEM; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received length %d", __func__, s_priv_data.length); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received data %s", __func__, pBuffer); + + switch(sub_cmd) + { + case WE_WOWL_ADD_PTRN: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "ADD_PTRN"); + ret = hdd_add_wowl_ptrn(pAdapter, pBuffer); + if (!ret) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Failed to add pattern :%d", ret); + break; + case WE_WOWL_DEL_PTRN: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "DEL_PTRN"); + ret = hdd_del_wowl_ptrn(pAdapter, pBuffer); + if (!ret) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Failed to del pattern :%d", ret); + break; + default: + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "ioctl not supported in SOFTAP"); + ret = -EINVAL; + break; + } + + kfree(pBuffer); + return ret; +} + +int +static iw_softap_setchar_getnone(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_setchar_getnone(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + /* Usage: BLACK_LIST = 0 WHITE_LIST = 1 @@ -3029,6 +3254,60 @@ static iw_softap_ap_stats(struct net_device *dev, return ret; } +/** + * __iw_softap_get_three() - return three value to upper layer. + * + * @dev: pointer of net_device of this wireless card + * @info: meta data about Request sent + * @wrqu: include request info + * @extra: buf used for in/out + * + * Return: execute result + */ +static int __iw_softap_get_three(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + uint32_t *value = (uint32_t *)extra; + uint32_t sub_cmd = value[0]; + int ret = 0; /* success */ + + hdd_adapter_t *padapter = WLAN_HDD_GET_PRIV_PTR(dev); + + switch (sub_cmd) { + case QCSAP_IOCTL_GET_TSF: + ret = hdd_indicate_tsf(padapter, value, 3); + break; + default: + hddLog(LOGE, FL("Invalid getparam command %d"), sub_cmd); + break; + } + return ret; +} + + +/** + * iw_softap_get_three() - return three value to upper layer. + * + * @dev: pointer of net_device of this wireless card + * @info: meta data about Request sent + * @wrqu: include request info + * @extra: buf used for in/Output + * + * Return: execute result + */ +static int iw_softap_get_three(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_softap_get_three(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} static int __iw_softap_set_channel_range(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -4495,6 +4774,10 @@ static const struct iw_priv_args hostapd_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setMcRate" }, { QCSAP_PARAM_SET_PROXIMITY, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setProximity" }, + { QCSAP_PARAM_CAP_TSF, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "cap_tsf" }, + { QCSAP_PARAM_SET_WOWL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wowl" }, { QCSAP_IOCTL_GETPARAM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam" }, @@ -4528,6 +4811,14 @@ static const struct iw_priv_args hostapd_private_args[] = { IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 6 , 0, "disassoc_sta" }, { QCSAP_IOCTL_AP_STATS, 0, IW_PRIV_TYPE_CHAR | QCSAP_MAX_WSC_IE, "ap_stats" }, + /* handlers for main ioctl */ + { QCSAP_IOCTL_PRIV_SET_NONE_GET_THREE_INT, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, "" }, +#ifdef WLAN_FEATURE_TSF + { QCSAP_IOCTL_GET_TSF, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + "get_tsf" }, +#endif { QCSAP_IOCTL_GET_STATS, 0, IW_PRIV_TYPE_CHAR | QCSAP_MAX_STR_LEN, "getStats"}, { QCSAP_IOCTL_CLR_STATS, 0, 0, "clearStats" }, @@ -4606,11 +4897,29 @@ static const struct iw_priv_args hostapd_private_args[] = { IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1, 0, "setTrafficMon" }, + /* handlers for main ioctl */ + { QCSAP_IOCTL_SET_CHAR_GET_NONE, + IW_PRIV_TYPE_CHAR| 512, + 0, + "" }, + + /* handlers for sub-ioctl */ + { WE_WOWL_ADD_PTRN, + IW_PRIV_TYPE_CHAR| 512, + 0, + "wowlAddPtrn" }, + + { WE_WOWL_DEL_PTRN, + IW_PRIV_TYPE_CHAR| 512, + 0, + "wowlDelPtrn" }, }; static const iw_handler hostapd_private[] = { [QCSAP_IOCTL_SETPARAM - SIOCIWFIRSTPRIV] = iw_softap_setparam, //set priv ioctl - [QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam, //get priv ioctl + [QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam, //get priv ioctl + [QCSAP_IOCTL_SET_CHAR_GET_NONE - SIOCIWFIRSTPRIV] = + iw_softap_setchar_getnone, [QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie, //get station genIE [QCSAP_IOCTL_STOPBSS - SIOCIWFIRSTPRIV] = iw_softap_stopbss, // stop bss [QCSAP_IOCTL_VERSION - SIOCIWFIRSTPRIV] = iw_softap_version, // get driver version @@ -4619,6 +4928,7 @@ static const iw_handler hostapd_private[] = { [QCSAP_IOCTL_ASSOC_STA_MACADDR - SIOCIWFIRSTPRIV] = iw_softap_getassoc_stamacaddr, [QCSAP_IOCTL_DISASSOC_STA - SIOCIWFIRSTPRIV] = iw_softap_disassoc_sta, [QCSAP_IOCTL_AP_STATS - SIOCIWFIRSTPRIV] = iw_softap_ap_stats, + [QCSAP_IOCTL_PRIV_SET_NONE_GET_THREE_INT - SIOCIWFIRSTPRIV] = iw_softap_get_three, [QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_three_ints_getnone, [QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_var_ints_getnone, [QCSAP_IOCTL_SET_CHANNEL_RANGE - SIOCIWFIRSTPRIV] = iw_softap_set_channel_range, @@ -4681,6 +4991,12 @@ void hdd_set_ap_ops( struct net_device *pWlanHostapdDev ) VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter, bool re_init) { hdd_hostapd_state_t * phostapdBuf; +#ifdef DHCP_SERVER_OFFLOAD + hdd_dhcp_state_t *dhcp_status; +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + hdd_mdns_state_t *mdns_status; +#endif /* MDNS_OFFLOAD */ struct net_device *dev = pAdapter->dev; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); VOS_STATUS status; @@ -4697,8 +5013,27 @@ VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter, bool re_init) } ENTER(); - // Allocate the Wireless Extensions state structure + +#ifdef SAP_AUTH_OFFLOAD + if (pHddCtx->cfg_ini->enable_sap_auth_offload) + { + if (!hdd_set_sap_auth_offload(pAdapter, TRUE)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("SAP AUTH OFFLOAD is not enabled successfully, Don't start SAP")); + return VOS_STATUS_E_FAILURE; + } + } +#endif + + // Allocate the Wireless Extensions state structure phostapdBuf = WLAN_HDD_GET_HOSTAP_STATE_PTR( pAdapter ); +#ifdef DHCP_SERVER_OFFLOAD + dhcp_status = &pAdapter->dhcp_status; +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + mdns_status = &pAdapter->mdns_status; +#endif /* MDNS_OFFLOAD */ spin_lock_init(&pAdapter->sta_hash_lock); pAdapter->is_sta_id_hash_initialized = VOS_FALSE; @@ -4720,7 +5055,13 @@ VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter, bool re_init) // Zero the memory. This zeros the profile structure. memset(phostapdBuf, 0,sizeof(hdd_hostapd_state_t)); - +#ifdef DHCP_SERVER_OFFLOAD + memset(dhcp_status, 0,sizeof(*dhcp_status)); +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + memset(mdns_status, 0,sizeof(*mdns_status)); +#endif /* MDNS_OFFLOAD */ + // Set up the pointer to the Wireless Extensions state structure // NOP status = hdd_set_hostapd(pAdapter); @@ -4735,7 +5076,21 @@ VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter, bool re_init) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: Hostapd HDD vos event init failed!!")); return status; } - +#ifdef DHCP_SERVER_OFFLOAD + status = vos_event_init(&dhcp_status->vos_event); + if (!VOS_IS_STATUS_SUCCESS(status)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: Hostapd HDD vos event init failed!!")); + return status; + } +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + status = vos_event_init(&mdns_status->vos_event); + if (!VOS_IS_STATUS_SUCCESS(status)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("Hostapd HDD vos event init failed!!")); + return status; + } +#endif /* MDNS_OFFLOAD */ sema_init(&(WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->semWpsPBCOverlapInd, 1); @@ -5009,3 +5364,41 @@ void hdd_sap_destroy_timers(hdd_adapter_t *adapter) FL("Failed to Destroy HT20/40 timer")); } + +/** + * hdd_force_scc_restart_sap - restart sap to forcer SCC + * @adapter: hdd ap adapter + * + * hdd_force_scc_restart_sap will choose station channel and will + * schedule work to restart the sap. + * + * Return - none + */ +void hdd_force_scc_restart_sap(hdd_adapter_t *adapter, + hdd_context_t *hdd_ctx, tANI_U8 channelId) +{ + if (!(adapter && (WLAN_HDD_SOFTAP == adapter->device_mode))) { + return; + } + + hddLog(LOG1, FL("Current operation channel %d"), + adapter->sessionCtx.ap.operatingChannel); + hddLog(LOG1, FL("STA channel is %d"), + channelId); + + vos_flush_work( + &hdd_ctx->sap_start_work); + + hddLog(LOGE, + FL("Restarting SAP for force SCC ")); + + adapter->sessionCtx.ap.sapConfig.channel = channelId; + + if (hdd_ctx->cfg_ini->sap_internal_restart) { + netif_tx_disable(adapter->dev); + schedule_work(&hdd_ctx->sap_start_work); + } else { + hdd_hostapd_stop(adapter->dev); + } + return; +} diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c index 668b61948f4..6dc22da0ec2 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c @@ -758,11 +758,6 @@ void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code) /*New country doesn't support DFS */ sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0); } - else - { - /*New country Supports DFS as well resetting value back from .ini*/ - sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan); - } } @@ -799,7 +794,7 @@ static int hdd_parse_setrmcenable_command(tANI_U8 *pValue, tANI_U8 *pRmcEnable) /* getting the first argument which enables or disables RMC * for input IP v4 address*/ - sscanf(inPtr, "%32s ", buf); + sscanf(inPtr, "%31s ", buf); v = kstrtos32(buf, 10, &tempInt); if ( v < 0) { @@ -848,7 +843,7 @@ static int hdd_parse_setrmcactionperiod_command(tANI_U8 *pValue, /* getting the first argument which enables or disables RMC * for input IP v4 address*/ - sscanf(inPtr, "%32s ", buf); + sscanf(inPtr, "%31s ", buf); v = kstrtos32(buf, 10, &tempInt); if ( v < 0) { @@ -906,7 +901,7 @@ static int hdd_parse_setrmcrate_command(tANI_U8 *pValue, /* * getting the first argument which sets multicast rate. */ - sscanf(inPtr, "%32s ", buf); + sscanf(inPtr, "%31s ", buf); v = kstrtos32(buf, 10, &tempInt); if ( v < 0) { @@ -2593,16 +2588,23 @@ hdd_parse_reassoc_v1(hdd_adapter_t *pAdapter, const char *command) * @pAdapter: Adapter upon which the command was received * @command: command that was received, ASCII command followed * by binary data + * @total_len: Total length of the command received * * Return: 0 for success non-zero for failure */ static int -hdd_parse_reassoc_v2(hdd_adapter_t *pAdapter, const char *command) +hdd_parse_reassoc_v2(hdd_adapter_t *pAdapter, const char *command, + int total_len) { struct android_wifi_reassoc_params params; tSirMacAddr bssid; int ret; + if (total_len < sizeof(params) + 8) { + hddLog(LOGE, FL("Invalid command length")); + return -EINVAL; + } + /* The params are located after "REASSOC " */ memcpy(¶ms, command + 8, sizeof(params)); @@ -2626,11 +2628,12 @@ hdd_parse_reassoc_v2(hdd_adapter_t *pAdapter, const char *command) * * @pAdapter: Adapter upon which the command was received * @command: command that was received + * @total_len: Total length of the command received * * Return: 0 for success non-zero for failure */ static int -hdd_parse_reassoc(hdd_adapter_t *pAdapter, const char *command) +hdd_parse_reassoc(hdd_adapter_t *pAdapter, const char *command, int total_len) { int ret; @@ -2648,10 +2651,16 @@ hdd_parse_reassoc(hdd_adapter_t *pAdapter, const char *command) * 1111111111222222 * 01234567890123456789012345 */ + + if (total_len < 26) { + hddLog(LOGE, FL("Invalid command (total_len=%d)"), total_len); + return -EINVAL; + } + if (command[25]) ret = hdd_parse_reassoc_v1(pAdapter, command); else - ret = hdd_parse_reassoc_v2(pAdapter, command); + ret = hdd_parse_reassoc_v2(pAdapter, command, total_len); return ret; } @@ -2759,6 +2768,55 @@ void hdd_FWStatisCB( VOS_STATUS status, return; } +/* + *hdd_parse_setmaxtxpower_command() - HDD Parse MAXTXPOWER command + *@pValue Pointer to MAXTXPOWER command + *@pTxPower Pointer to tx power + * + *This function parses the MAXTXPOWER command passed in the format + * MAXTXPOWER<space>X(Tx power in dbm) + * For example input commands: + * 1) MAXTXPOWER -8 -> This is translated into set max TX power to -8 dbm + * 2) MAXTXPOWER -23 -> This is translated into set max TX power to -23 dbm + * + *return - 0 for success non-zero for failure + */ +static int hdd_parse_setmaxtxpower_command(unsigned char *pValue, int *pTxPower) +{ + unsigned char *inPtr = pValue; + int tempInt; + int v = 0; + *pTxPower = 0; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + /* no argument after the command */ + if (NULL == inPtr) + return -EINVAL; + /* no space after the command */ + else if (SPACE_ASCII_VALUE != *inPtr) + return -EINVAL; + + /* removing empty spaces */ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; + + /* no argument followed by spaces */ + if ('\0' == *inPtr) + return 0; + + v = kstrtos32(inPtr, 10, &tempInt); + + /* Range checking for passed parameter */ + if ((tempInt < HDD_MIN_TX_POWER) || (tempInt > HDD_MAX_TX_POWER)) + return -EINVAL; + + *pTxPower = tempInt; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "SETMAXTXPOWER: %d", *pTxPower); + + return 0; +} + static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len) { int ret = 0; @@ -2809,6 +2867,14 @@ static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, return ret; } +int hdd_drv_cmd_validate(tANI_U8 *command, int len) +{ + if (command[len] != ' ') + return -EINVAL; + + return 0; +} + static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command) { tHalHandle hHal; @@ -2831,6 +2897,9 @@ static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command) if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 ) { + if (hdd_drv_cmd_validate(command, 23)) + return -EINVAL; + value = value + 24; temp = kstrtou32(value, 10, &val); if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN || @@ -2847,6 +2916,9 @@ static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command) } else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0) { + if (hdd_drv_cmd_validate(command, 23)) + return -EINVAL; + value = value + 24; temp = kstrtou32(value, 10, &val); if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN || @@ -2863,6 +2935,9 @@ static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command) } else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0) { + if (hdd_drv_cmd_validate(command, 24)) + return -EINVAL; + value = value + 25; temp = kstrtou32(value, 10, &val); if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN || @@ -2879,6 +2954,9 @@ static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command) } else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0) { + if (hdd_drv_cmd_validate(command, 24)) + return -EINVAL; + value = value + 25; temp = kstrtou32(value, 10, &val); if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN || @@ -2895,6 +2973,9 @@ static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command) } else if (strncmp(command, "SETDWELLTIME", 12) == 0) { + if (hdd_drv_cmd_validate(command, 12)) + return -EINVAL; + value = value + 13; temp = kstrtou32(value, 10, &val); if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN || @@ -3204,6 +3285,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, { tANI_U8 *ptr = command ; + ret = hdd_drv_cmd_validate(command, 7); + if (ret) + goto exit; + /* Change band request received */ /* First 8 bytes will have "SETBAND " and @@ -3222,12 +3307,22 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, else if(strncmp(command, "SETWMMPS", 8) == 0) { tANI_U8 *ptr = command; + + ret = hdd_drv_cmd_validate(command, 8); + if (ret) + goto exit; + ret = hdd_wmmps_helper(pAdapter, ptr); } else if(strncmp(command, "TDLSSCAN", 8) == 0) { tANI_U8 *ptr = command; + + ret = hdd_drv_cmd_validate(command, 8); + if (ret) + goto exit; + ret = hdd_set_tdls_scan_type(pAdapter, ptr); } @@ -3235,6 +3330,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, { char *country_code; + ret = hdd_drv_cmd_validate(command, 7); + if (ret) + goto exit; + country_code = command + 8; INIT_COMPLETION(pAdapter->change_country_code); @@ -3281,7 +3380,13 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, else if(strncmp(command, "SETSUSPENDMODE", 14) == 0) { int suspend = 0; - tANI_U8 *ptr = (tANI_U8*)command + 15; + tANI_U8 *ptr; + + ret = hdd_drv_cmd_validate(command, 14); + if (ret) + goto exit; + + ptr = (tANI_U8*)command + 15; suspend = *ptr - '0'; MTRACE(vos_trace(VOS_MODULE_ID_HDD, @@ -3297,6 +3402,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT; eHalStatus status = eHAL_STATUS_SUCCESS; + ret = hdd_drv_cmd_validate(command, 14); + if (ret) + goto exit; + /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */ value = value + 15; @@ -3375,6 +3484,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 roamScanPeriod = 0; tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT; + ret = hdd_drv_cmd_validate(command, 17); + if (ret) + goto exit; + /* input refresh period is in terms of seconds */ /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */ value = value + 18; @@ -3442,6 +3555,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 roamScanRefreshPeriod = 0; tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT; + ret = hdd_drv_cmd_validate(command, 24); + if (ret) + goto exit; + /* input refresh period is in terms of seconds */ /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */ value = value + 25; @@ -3505,6 +3622,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT; + ret = hdd_drv_cmd_validate(command, SIZE_OF_SETROAMMODE); + if (ret) + goto exit; + /* Move pointer to ahead of SETROAMMODE<delimiter> */ value = value + SIZE_OF_SETROAMMODE + 1; @@ -3582,6 +3703,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT; + ret = hdd_drv_cmd_validate(command, 12); + if (ret) + goto exit; + /* Move pointer to ahead of SETROAMDELTA<delimiter> */ value = value + 13; /* Convert the value from ascii to integer */ @@ -3830,6 +3955,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT; + ret = hdd_drv_cmd_validate(command, 25); + if (ret) + goto exit; + /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */ value = value + 26; /* Convert the value from ascii to integer */ @@ -4014,6 +4143,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT; + ret = hdd_drv_cmd_validate(command, 18); + if (ret) + goto exit; + /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */ value = value + 19; /* Convert the value from ascii to integer */ @@ -4071,6 +4204,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT; + ret = hdd_drv_cmd_validate(command, 15); + if (ret) + goto exit; + /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */ value = value + 16; /* Convert the value from ascii to integer */ @@ -4128,6 +4265,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT; + ret = hdd_drv_cmd_validate(command, 16); + if (ret) + goto exit; + /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */ value = value + 17; /* Convert the value from ascii to integer */ @@ -4184,6 +4325,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT; + ret = hdd_drv_cmd_validate(command, 14); + if (ret) + goto exit; + /* Move pointer to ahead of SETSCANNPROBES<delimiter> */ value = value + 15; /* Convert the value from ascii to integer */ @@ -4238,6 +4383,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT; + ret = hdd_drv_cmd_validate(command, 19); + if (ret) + goto exit; + /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */ /* input value is in units of msec */ value = value + 20; @@ -4292,7 +4441,11 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, } else if (strncmp(command, "REASSOC", 7) == 0) { - ret = hdd_parse_reassoc(pAdapter, command); + ret = hdd_drv_cmd_validate(command, 7); + if (ret) + goto exit; + + ret = hdd_parse_reassoc(pAdapter, command, priv_data.total_len); if (!ret) goto exit; } @@ -4301,6 +4454,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT; + ret = hdd_drv_cmd_validate(command, 10); + if (ret) + goto exit; + /* Move pointer to ahead of SETWESMODE<delimiter> */ value = value + 11; /* Convert the value from ascii to integer */ @@ -4356,6 +4513,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT; + ret = hdd_drv_cmd_validate(command, 11); + if (ret) + goto exit; + /* Move pointer to ahead of SETFASTROAM<delimiter> */ value = value + 12; /* Convert the value from ascii to integer */ @@ -4397,6 +4558,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT; + ret = hdd_drv_cmd_validate(command, 17); + if (ret) + goto exit; + /* Move pointer to ahead of SETFASTROAM<delimiter> */ value = value + 18; /* Convert the value from ascii to integer */ @@ -4436,6 +4601,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U8 dfsScanMode = DFS_CHNL_SCAN_ENABLED_NORMAL; + ret = hdd_drv_cmd_validate(command, 14); + if (ret) + goto exit; + /* Move pointer to ahead of SETDFSSCANMODE<delimiter> */ value = value + 15; /* Convert the value from ascii to integer */ @@ -4499,6 +4668,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT; + ret = hdd_drv_cmd_validate(command, 10); + if (ret) + goto exit; + /* Check if the features OKC/ESE/11R are supported simultaneously, then this operation is not permitted (return FAILURE) */ if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) && @@ -4550,6 +4723,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_BOOLEAN roamScanControl = 0; + ret = hdd_drv_cmd_validate(command, 18); + if (ret) + goto exit; + /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */ value = value + 19; /* Convert the value from ascii to integer */ @@ -4583,6 +4760,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 *value = command; tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT; + ret = hdd_drv_cmd_validate(command, 10); + if (ret) + goto exit; + /* Check if the features OKC/ESE/11R are supported simultaneously, then this operation is not permitted (return FAILURE) */ if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) && @@ -4652,6 +4833,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tANI_U8 filterType = 0; tANI_U8 *value = command; + ret = hdd_drv_cmd_validate(command, 21); + if (ret) + goto exit; + /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */ value = value + 22; @@ -4684,6 +4869,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, char *dhcpPhase; int ret; + ret = hdd_drv_cmd_validate(command, 10); + if (ret) + goto exit; + dhcpPhase = command + 11; if ('1' == *dhcpPhase) { @@ -4750,6 +4939,11 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, { tANI_U8 filterType = 0; tANI_U8 *value; + + ret = hdd_drv_cmd_validate(command, 8); + if (ret) + goto exit; + value = command + 9; /* Convert the value from ascii to integer */ @@ -4795,6 +4989,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tSirRateUpdateInd *rateUpdate; eHalStatus status; + ret = hdd_drv_cmd_validate(command, 9); + if (ret) + goto exit; + /* Only valid for SAP mode */ if (WLAN_HDD_SOFTAP != pAdapter->device_mode) { @@ -4838,6 +5036,41 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, goto exit; } } + else if (strncmp(command, "MAXTXPOWER", 10) == 0) + { + int status; + int txPower; + eHalStatus smeStatus; + tANI_U8 *value = command; + tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + + status = hdd_parse_setmaxtxpower_command(value, &txPower); + if (status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid MAXTXPOWER command "); + ret = -EINVAL; + goto exit; + } + + hddLog(VOS_TRACE_LEVEL_INFO, "max tx power %d selfMac: " + MAC_ADDRESS_STR " bssId: " MAC_ADDRESS_STR " ", + txPower, MAC_ADDR_ARRAY(selfMac), + MAC_ADDR_ARRAY(bssid)); + smeStatus = sme_SetMaxTxPower((tHalHandle)(pHddCtx->hHal), + bssid, selfMac, txPower) ; + if( smeStatus != eHAL_STATUS_SUCCESS ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Set max tx power failed", + __func__); + ret = -EINVAL; + goto exit; + } + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set max tx power success", + __func__); + } #ifdef FEATURE_WLAN_BATCH_SCAN else if (strncmp(command, "WLS_BATCHING", 12) == 0) { @@ -5587,6 +5820,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, tAniTrafStrmMetrics tsmMetrics; pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + ret = hdd_drv_cmd_validate(command, 11); + if (ret) + goto exit; + /* if not associated, return error */ if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { @@ -5796,6 +6033,11 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) { tANI_U8 *value = command; int set_value; + + ret = hdd_drv_cmd_validate(command, 26); + if (ret) + goto exit; + /* Move pointer to ahead of TDLSOFFCH*/ value += 26; if (!(sscanf(value, "%d", &set_value))) { @@ -5818,6 +6060,11 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) { tANI_U8 *value = command; int set_value; + + ret = hdd_drv_cmd_validate(command, 18); + if (ret) + goto exit; + /* Move pointer to ahead of tdlsoffchnmode*/ value += 18; ret = sscanf(value, "%d", &set_value); @@ -5839,6 +6086,11 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) { tANI_U8 *value = command; int set_value; + + ret = hdd_drv_cmd_validate(command, 14); + if (ret) + goto exit; + /* Move pointer to ahead of TDLSOFFCH*/ value += 14; ret = sscanf(value, "%d", &set_value); @@ -5869,8 +6121,13 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, fwStatsContext_t fwStatsCtx; tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp); tANI_U8 *ptr = command; - int stats = *(ptr + 11) - '0'; + int stats; + ret = hdd_drv_cmd_validate(command, 10); + if (ret) + goto exit; + + stats = *(ptr + 11) - '0'; hddLog(VOS_TRACE_LEVEL_INFO, FL("stats = %d "),stats); if (!IS_FEATURE_FW_STATS_ENABLE) { @@ -5964,6 +6221,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, } else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0) { + ret = hdd_drv_cmd_validate(command, 15); + if (ret) + goto exit; + /* * this command wld be called by user-space when it detects WLAN * ON after airplane mode is set. When APM is set, WLAN turns off. @@ -5977,6 +6238,10 @@ static int hdd_driver_command(hdd_adapter_t *pAdapter, } else if (strncasecmp(command, "DISABLE_CA_EVENT", 16) == 0) { + ret = hdd_drv_cmd_validate(command, 16); + if (ret) + goto exit; + ret = hdd_enable_disable_ca_event(pHddCtx, command, 16); } else { @@ -8828,13 +9093,14 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, if(VOS_STATUS_SUCCESS == status) { wlan_hdd_set_concurrency_mode(pHddCtx, session_type); - //Initialize the WoWL service if(!hdd_init_wowl(pAdapter)) { hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__); goto err_free_netdev; } + //Initialize the TSF capture data + wlan_hdd_tsf_init(pAdapter); } return pAdapter; @@ -8970,6 +9236,18 @@ void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter) } } +VOS_STATUS hdd_cleanup_ap_events(hdd_adapter_t *adapter) +{ +#ifdef DHCP_SERVER_OFFLOAD + vos_event_destroy(&adapter->dhcp_status.vos_event); +#endif +#ifdef MDNS_OFFLOAD + vos_event_destroy(&adapter->mdns_status.vos_event); +#endif + return VOS_STATUS_SUCCESS; +} + + VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, const v_BOOL_t bCloseSession ) { @@ -9014,6 +9292,13 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, if( hdd_connIsConnected(pstation) || (pstation->conn_info.connState == eConnectionState_Connecting) ) { + /* + * Indicate sme of disconnect so that in progress connection + * or preauth can be aborted. + */ + sme_abortConnection(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId); + INIT_COMPLETION(pAdapter->disconnect_comp_var); if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS) halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, @@ -9140,6 +9425,7 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, } //Any softap specific cleanup here... + hdd_cleanup_ap_events(pAdapter); if (pAdapter->device_mode == WLAN_HDD_P2P_GO) { while (pAdapter->is_roc_inprogress) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, @@ -9160,6 +9446,10 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, vos_flush_delayed_work(&pAdapter->roc_work); } +#ifdef SAP_AUTH_OFFLOAD + if (pHddCtx->cfg_ini->enable_sap_auth_offload) + hdd_set_sap_auth_offload(pAdapter, FALSE); +#endif mutex_lock(&pHddCtx->sap_lock); if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags)) { @@ -9297,6 +9587,18 @@ static void wlan_hdd_restart_sap(hdd_adapter_t *ap_adapter) set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); wlan_hdd_incr_active_session(pHddCtx, ap_adapter->device_mode); pHostapdState->bCommit = TRUE; + if (!VOS_IS_STATUS_SUCCESS(hdd_dhcp_mdns_offload(ap_adapter))) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("DHCP/MDNS offload Failed!!")); + vos_event_reset(&pHostapdState->vosEvent); + if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) { + vos_status = vos_wait_single_event(&pHostapdState->vosEvent, + 10000); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGE, FL("SAP Stop Failed")); + goto end; + } + } + } } end: mutex_unlock(&pHddCtx->sap_lock); @@ -9336,6 +9638,8 @@ static void __hdd_sap_restart_handle(struct work_struct *work) wlan_hdd_restart_sap(sap_adapter); hdd_change_ch_avoidance_status(hdd_ctx, false); } + if (hdd_ctx->cfg_ini->enable_sap_auth_offload) + wlan_hdd_restart_sap(sap_adapter); } /** @@ -11900,14 +12204,11 @@ int hdd_wlan_startup(struct device *dev ) /* * cfg80211: Initialization ... */ - if (VOS_FTM_MODE != hdd_get_conparam()) + if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini)) { - if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini)) - { - hddLog(VOS_TRACE_LEVEL_FATAL, - "%s: wlan_hdd_cfg80211_init return failure", __func__); - goto err_config; - } + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: wlan_hdd_cfg80211_init return failure", __func__); + goto err_config; } // Update VOS trace levels based upon the cfg.ini @@ -12453,7 +12754,7 @@ int hdd_wlan_startup(struct device *dev ) { hddLog(VOS_TRACE_LEVEL_FATAL, "%s: oem_activate_service failed", __func__); - goto err_reg_netdev; + goto err_btc_activate_service; } #endif @@ -12462,7 +12763,7 @@ int hdd_wlan_startup(struct device *dev ) if(ptt_sock_activate_svc(pHddCtx) != 0) { hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__); - goto err_reg_netdev; + goto err_oem_activate_service; } #endif @@ -12470,7 +12771,7 @@ int hdd_wlan_startup(struct device *dev ) if (hdd_open_cesium_nl_sock() < 0) { hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_open_cesium_nl_sock failed", __func__); - goto err_reg_netdev; + goto err_ptt_sock_activate_svc; } #endif @@ -12485,7 +12786,7 @@ int hdd_wlan_startup(struct device *dev ) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc" " failed", __func__); - goto err_reg_netdev; + goto err_open_cesium_nl_sock; } //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for //EAPOL and DHCP @@ -12511,6 +12812,13 @@ int hdd_wlan_startup(struct device *dev ) #endif +#ifdef SAP_AUTH_OFFLOAD + if (!sme_IsFeatureSupportedByFW(SAP_OFFLOADS)) + { + hddLog(VOS_TRACE_LEVEL_INFO, FL(" SAP AUTH OFFLOAD not supp by FW")); + pHddCtx->cfg_ini->enable_sap_auth_offload = 0; + } +#endif if (vos_is_multicast_logging()) wlan_logging_set_log_level(); @@ -12571,7 +12879,7 @@ int hdd_wlan_startup(struct device *dev ) vos_wdthread_init_timer_work(vos_process_wd_timer); /* Initialize the timer to detect thread stuck issues */ vos_thread_stuck_timer_init( - &((VosContextType*)pVosContext)->vosWatchdog); + &((VosContextType*)pVosContext)->vosWatchdog); } //Register the traffic monitor timer now @@ -12618,6 +12926,8 @@ int hdd_wlan_startup(struct device *dev ) } #endif + vos_mem_set((uint8_t *)&pHddCtx->bad_sta, HDD_MAX_STA_COUNT, 0); + // Register IPv4 notifier to notify if any change in IP // So that we can reconfigure the offload parameters pHddCtx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed; @@ -12634,8 +12944,36 @@ int hdd_wlan_startup(struct device *dev ) memdump_init(); hdd_dp_util_send_rps_ind(pHddCtx); + pHddCtx->is_ap_mode_wow_supported = + sme_IsFeatureSupportedByFW(SAP_MODE_WOW); + + pHddCtx->is_fatal_event_log_sup = + sme_IsFeatureSupportedByFW(FATAL_EVENT_LOGGING); + hddLog(VOS_TRACE_LEVEL_INFO, FL("FATAL_EVENT_LOGGING: %d"), + pHddCtx->is_fatal_event_log_sup); + + hdd_assoc_registerFwdEapolCB(pVosContext); + goto success; +err_open_cesium_nl_sock: +#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE + hdd_close_cesium_nl_sock(); +#endif + +err_ptt_sock_activate_svc: +#ifdef PTT_SOCK_SVC_ENABLE + ptt_sock_deactivate_svc(pHddCtx); +#endif + +err_oem_activate_service: +#ifdef FEATURE_OEM_DATA_SUPPORT + oem_deactivate_service(); +#endif + +err_btc_activate_service: + btc_deactivate_service(); + err_reg_netdev: unregister_netdevice_notifier(&hdd_netdev_notifier); @@ -12764,11 +13102,11 @@ static int hdd_driver_init( void) #ifdef HAVE_WCNSS_CAL_DOWNLOAD /* wait until WCNSS driver downloads NV */ - while (!wcnss_device_ready() && 5 >= ++max_retries) { + while (!wcnss_device_ready() && 10 >= ++max_retries) { msleep(1000); } - if (max_retries >= 5) { + if (max_retries >= 10) { hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__); vos_wake_lock_destroy(&wlan_wake_lock); #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE @@ -13380,9 +13718,13 @@ v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx) return TRUE; } hddLog( LOGE, "%s: do not allow APPS power collapse-" - "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d", - __func__, pmcState, scanRspPending, inMiddleOfRoaming ); - return FALSE; + "pmcState = %d scanRspPending = %d " + "inMiddleOfRoaming = %d connected = %d", + __func__, pmcState, scanRspPending, + inMiddleOfRoaming, hdd_connIsConnected( + WLAN_HDD_GET_STATION_CTX_PTR( pAdapter ))); + wlan_hdd_get_tdls_stats(pAdapter); + return FALSE; } } status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); @@ -13996,7 +14338,7 @@ int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter) */ if (abortScanStatus == eSIR_ABORT_ACTIVE_SCAN_LIST_NOT_EMPTY) { - status = wait_for_completion_interruptible_timeout( + status = wait_for_completion_timeout( &pScanInfo->abortscan_event_var, msecs_to_jiffies(5000)); if (0 >= status) @@ -14843,10 +15185,1464 @@ void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter) init_completion(&pAdapter->hdd_set_batch_scan_req_var); init_completion(&pAdapter->hdd_get_batch_scan_req_var); #endif + init_completion(&pAdapter->wlan_suspend_comp_var); return; } +#ifdef MDNS_OFFLOAD + +/** + * hdd_mdns_enable_offload_done() - mdns enable offload response api + * @padapter: holds adapter + * @status: response status + * + * Return - None + */ +void hdd_mdns_enable_offload_done(void *padapter, VOS_STATUS status) +{ + hdd_adapter_t* adapter = (hdd_adapter_t*) padapter; + + ENTER(); + + if (NULL == adapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: adapter is NULL",__func__); + return; + } + + adapter->mdns_status.mdns_enable_status = status; + vos_event_set(&adapter->mdns_status.vos_event); + return; +} + +/** + * hdd_mdns_fqdn_offload_done() - mdns fqdn offload response api + * @padapter: holds adapter + * @status: responce status + * + * Return - None + */ +void hdd_mdns_fqdn_offload_done(void *padapter, VOS_STATUS status) +{ + hdd_adapter_t* adapter = (hdd_adapter_t*) padapter; + + ENTER(); + + if (NULL == adapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: adapter is NULL",__func__); + return; + } + + adapter->mdns_status.mdns_fqdn_status = status; + return; +} + +/** + * hdd_mdns_resp_offload_done() - mdns resp offload response api + * @padapter: holds adapter + * @status: responce status + * + * Return - None + */ +void hdd_mdns_resp_offload_done(void *padapter, VOS_STATUS status) +{ + hdd_adapter_t* adapter = (hdd_adapter_t*) padapter; + + ENTER(); + + if (NULL == adapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: adapter is NULL",__func__); + return; + } + + adapter->mdns_status.mdns_resp_status = status; + return; +} + +/** + * wlan_hdd_mdns_process_response_dname() - Process mDNS domain name + * @response: Pointer to a struct hdd_mdns_resp_info + * @resp_info: Pointer to a struct tSirMDNSResponseInfo + * + * This function will pack the whole domain name without compression. It will + * add the leading len for each field and add zero length octet to terminate + * the domain name. + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +static bool +wlan_hdd_mdns_process_response_dname(struct hdd_mdns_resp_info *response, + sir_mdns_resp_info resp_info) +{ + uint8_t num; + uint16_t idx; + uint8_t len = 0; + + if ((response == NULL) || (response->data == NULL) || + (response->offset == NULL)) { + hddLog(LOGE, FL("Either data or offset in response is NULL!")); + return FALSE; + } + + if ((resp_info == NULL) || + (resp_info->resp_len >= MAX_MDNS_RESP_LEN)) { + hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN); + return FALSE; + } + + for (num = 0; num < response->num_entries; num++) { + response->offset[num] = + resp_info->resp_len + MDNS_HEADER_LEN; + idx = num * MAX_LEN_DOMAINNAME_FIELD; + len = strlen((char *)&response->data[idx]); + if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) { + hddLog(LOGE, FL("resp_len exceeds %d!"), + MAX_MDNS_RESP_LEN); + return FALSE; + } + resp_info->resp_data[resp_info->resp_len] = len; + resp_info->resp_len++; + vos_mem_copy(&resp_info->resp_data[resp_info->resp_len], + &response->data[idx], len); + resp_info->resp_len += len; + } + + /* The domain name terminates with the zero length octet */ + if (num == response->num_entries) { + if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) { + hddLog(LOGE, FL("resp_len exceeds %d!"), + MAX_MDNS_RESP_LEN); + return FALSE; + } + resp_info->resp_data[resp_info->resp_len] = 0; + resp_info->resp_len++; + } + + return TRUE; +} + +/** + * wlan_hdd_mdns_format_response_u16() - Form uint16_t response data + * @value: The uint16_t value is formed to the struct tSirMDNSResponseInfo + * @resp_info: Pointer to a struct tSirMDNSResponseInfo + * + * Return: None + */ +static void wlan_hdd_mdns_format_response_u16(uint16_t value, + sir_mdns_resp_info resp_info) +{ + uint8_t val_u8; + + if ((resp_info == NULL) || (resp_info->resp_data == NULL)) + return; + val_u8 = (value & 0xff00) >> 8; + resp_info->resp_data[resp_info->resp_len++] = val_u8; + val_u8 = value & 0xff; + resp_info->resp_data[resp_info->resp_len++] = val_u8; +} + +/** + * wlan_hdd_mdns_format_response_u32() - Form uint32_t response data + * @value: The uint32_t value is formed to the struct tSirMDNSResponseInfo + * @resp_info: Pointer to a struct tSirMDNSResponseInfo + * + * Return: None + */ +static void wlan_hdd_mdns_format_response_u32(uint32_t value, + sir_mdns_resp_info resp_info) +{ + uint8_t val_u8; + + if ((resp_info == NULL) || (resp_info->resp_data == NULL)) + return; + val_u8 = (value & 0xff000000) >> 24; + resp_info->resp_data[resp_info->resp_len++] = val_u8; + val_u8 = (value & 0xff0000) >> 16; + resp_info->resp_data[resp_info->resp_len++] = val_u8; + val_u8 = (value & 0xff00) >> 8; + resp_info->resp_data[resp_info->resp_len++] = val_u8; + val_u8 = value & 0xff; + resp_info->resp_data[resp_info->resp_len++] = val_u8; +} + +/** + * wlan_hdd_mdns_process_response_misc() - Process misc info in mDNS response + * @resp_type: Response type for mDNS + * @resp_info: Pointer to a struct tSirMDNSResponseInfo + * + * This function will pack the response type, class and TTL (Time To Live). + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +static bool wlan_hdd_mdns_process_response_misc(uint16_t resp_type, + sir_mdns_resp_info resp_info) +{ + uint16_t len; + + if (resp_info == NULL) { + hddLog(LOGE, FL("resp_info is NULL!")); + return FALSE; + } + + len = resp_info->resp_len + (2 * sizeof(uint16_t) + sizeof(uint32_t)); + if (len >= MAX_MDNS_RESP_LEN) { + hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN); + return FALSE; + } + + /* Fill Type, Class, TTL */ + wlan_hdd_mdns_format_response_u16(resp_type, resp_info); + wlan_hdd_mdns_format_response_u16(MDNS_CLASS, resp_info); + wlan_hdd_mdns_format_response_u32(MDNS_TTL, resp_info); + + return TRUE; +} + +/** + * wlan_hdd_mdns_compress_data() - Compress the domain name in mDNS response + * @resp_info: Pointer to a struct tSirMDNSResponseInfo + * @response_dst: The response which domain name is compressed. + * @response_src: The response which domain name is matched with response_dst. + * Its offset is used for data compression. + * @num_matched: The number of matched entries between response_dst and + * response_src + * + * This function will form the different fields of domain name in response_dst + * if any. Then use the offset of the matched domain name in response_src to + * compress the matched domain name. + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +static bool +wlan_hdd_mdns_compress_data(sir_mdns_resp_info resp_info, + struct hdd_mdns_resp_info *response_dst, + struct hdd_mdns_resp_info *response_src, + uint8_t num_matched) +{ + uint8_t num, num_diff; + uint16_t value, idx; + uint8_t len = 0; + + if ((response_src == NULL) || (response_dst == NULL) || + (resp_info == NULL)) { + hddLog(LOGE, FL("response info is NULL!")); + return FALSE; + } + + if (response_dst->num_entries < num_matched) { + hddLog(LOGE, FL("num_entries is less than num_matched!")); + return FALSE; + } + + if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) { + hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN); + return FALSE; + } + + num_diff = response_dst->num_entries - num_matched; + if ((num_diff > 0) && (response_dst->data == NULL)) { + hddLog(LOGE, FL("response_dst->data is NULL!")); + return FALSE; + } + + /* + * Handle the unmatched string at the beginning + * Store the length of octets and the octets + */ + for (num = 0; num < num_diff; num++) { + response_dst->offset[num] = + resp_info->resp_len + MDNS_HEADER_LEN; + idx = num * MAX_LEN_DOMAINNAME_FIELD; + len = strlen((char *)&response_dst->data[idx]); + if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) { + hddLog(LOGE, FL("resp_len exceeds %d!"), + MAX_MDNS_RESP_LEN); + return FALSE; + } + resp_info->resp_data[resp_info->resp_len] = len; + resp_info->resp_len++; + vos_mem_copy(&resp_info->resp_data[resp_info->resp_len], + &response_dst->data[idx], len); + resp_info->resp_len += len; + } + /* + * Handle the matched string from the end + * Just keep the offset and mask the leading two bit + */ + if (response_src->num_entries >= num_matched) { + num_diff = response_src->num_entries - num_matched; + value = response_src->offset[num_diff]; + if (value > 0) { + value |= 0xc000; + if ((resp_info->resp_len + sizeof(uint16_t)) >= + MAX_MDNS_RESP_LEN) { + hddLog(LOGE, FL("resp_len exceeds %d!"), + MAX_MDNS_RESP_LEN); + return FALSE; + } + wlan_hdd_mdns_format_response_u16(value, resp_info); + return TRUE; + } + } + return FALSE; +} + +/** + * wlan_hdd_mdns_reset_response() - Reset the response info + * @response: The response which info is reset. + * + * Return: None + */ +static void wlan_hdd_mdns_reset_response(struct hdd_mdns_resp_info *response) +{ + if (response == NULL) + return; + response->num_entries = 0; + response->data = NULL; + response->offset = NULL; +} + +/** + * wlan_hdd_mdns_init_response() - Initialize the response info + * @response: The response which info is initiatized. + * @resp_dname: The domain name string which might be tokenized. + * + * This function will allocate the memory for both response->data and + * response->offset. Besides, it will also tokenize the domain name to some + * entries and fill response->num_entries with the num of entries. + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +static bool wlan_hdd_mdns_init_response(struct hdd_mdns_resp_info *response, + uint8_t *resp_dname, char separator) +{ + uint16_t size; + + if ((resp_dname == NULL) || (response == NULL)) { + hddLog(LOGE, FL("resp_dname or response is NULL!")); + return FALSE; + } + + size = MAX_NUM_FIELD_DOMAINNAME * MAX_LEN_DOMAINNAME_FIELD; + response->data = vos_mem_malloc(size); + if (response->data) { + vos_mem_zero(response->data, size); + if (VOS_STATUS_SUCCESS != + hdd_string_to_string_array((char *)resp_dname, + response->data, + separator, + &response->num_entries, + MAX_NUM_FIELD_DOMAINNAME, + MAX_LEN_DOMAINNAME_FIELD)) { + hddLog(LOGE, FL("hdd_string_to_string_array fail!")); + goto err_init_resp; + } + + if ((response->num_entries > 0) && + (strlen((char *)&response->data[0]) > 0)) { + size = sizeof(uint16_t) * response->num_entries; + response->offset = vos_mem_malloc(size); + if (response->offset) { + vos_mem_zero(response->offset, size); + return TRUE; + } + } + } + +err_init_resp: + if (response->data) + vos_mem_free(response->data); + wlan_hdd_mdns_reset_response(response); + return FALSE; +} + +/** + * wlan_hdd_mdns_find_entries_from_end() - Find the matched entries + * @response1: The response info is used to be compared. + * @response2: The response info is used to be compared. + * + * This function will find the matched entries from the end. + * + * Return: Return the number of the matched entries. + */ +static uint8_t +wlan_hdd_mdns_find_entries_from_end(struct hdd_mdns_resp_info *response1, + struct hdd_mdns_resp_info *response2) +{ + uint8_t min, len1, i; + uint16_t num1, num2; + uint8_t num_matched = 0; + + min = VOS_MIN(response1->num_entries, response2->num_entries); + + for (i = 1; i <= min; i++) { + num1 = (response1->num_entries - i); + num1 *= MAX_LEN_DOMAINNAME_FIELD; + num2 = (response2->num_entries - i); + num2 *= MAX_LEN_DOMAINNAME_FIELD; + len1 = strlen((char *)&response1->data[num1]); + + if ((len1 == 0) || + (len1 != strlen((char *)&response2->data[num2]))) + break; + if (memcmp(&response1->data[num1], + &response2->data[num2], len1)) + break; + else + num_matched++; + } + + return num_matched; +} + +/** + * wlan_hdd_mdns_find_max() - Find the maximum number of the matched entries + * @matchedlist: Pointer to the array of struct hdd_mdns_resp_matched + * @numlist: The number of the elements in the array matchedlist. + * + * Find the max number of the matched entries among the array matchedlist. + * + * Return: None + */ +static void wlan_hdd_mdns_find_max(struct hdd_mdns_resp_matched *matchedlist, + uint8_t numlist) +{ + int j; + struct hdd_mdns_resp_matched tmp; + + /* At least two values are used for sorting */ + if ((numlist < 2) || (matchedlist == NULL)) { + hddLog(LOGE, FL("At least two values are used for sorting!")); + return; + } + + for (j = 0; j < numlist-1; j++) { + if (matchedlist[j].num_matched > + matchedlist[j+1].num_matched) { + vos_mem_copy(&tmp, &matchedlist[j], + sizeof(struct hdd_mdns_resp_matched)); + vos_mem_copy(&matchedlist[j], &matchedlist[j+1], + sizeof(struct hdd_mdns_resp_matched)); + vos_mem_copy(&matchedlist[j+1], &tmp, + sizeof(struct hdd_mdns_resp_matched)); + } + } +} + +/** + * wlan_hdd_mdns_pack_response_type_a() - Pack Type A response + * @ini_config: Pointer to the struct hdd_config_t + * @resp_info: Pointer to the struct tSirMDNSResponseInfo + * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A + * + * Type A response include QName, response type, class, TTL and Ipv4. + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +static bool +wlan_hdd_mdns_pack_response_type_a(hdd_config_t *ini_config, + sir_mdns_resp_info resp_info, + struct hdd_mdns_resp_info *resptype_a) +{ + uint16_t value; + uint32_t len; + + ENTER(); + if ((ini_config == NULL) || (resp_info == NULL) || + (resptype_a == NULL)) { + hddLog(LOGE, FL("ini_config or response info is NULL!")); + return FALSE; + } + + /* No Type A response */ + if (strlen((char *)ini_config->mdns_resp_type_a) <= 0) + return TRUE; + + /* Wrong response is assigned, just ignore this response */ + if (!wlan_hdd_mdns_init_response(resptype_a, + ini_config->mdns_resp_type_a, '.')) + return TRUE; + + /* Process response domain name */ + if (!wlan_hdd_mdns_process_response_dname(resptype_a, resp_info)) { + hddLog(LOGE, FL("Fail to process mDNS response (%d)!"), + MDNS_TYPE_A); + return FALSE; + } + + /* Process response Type, Class, TTL */ + if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_A, resp_info)) { + hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"), + MDNS_TYPE_A); + return FALSE; + } + + /* Process response RDLength, RData */ + len = sizeof(uint16_t) + sizeof(uint32_t); + len += resp_info->resp_len; + if (len >= MAX_MDNS_RESP_LEN) { + hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN); + return FALSE; + } + value = sizeof(uint32_t); + wlan_hdd_mdns_format_response_u16(value, resp_info); + wlan_hdd_mdns_format_response_u32(ini_config->mdns_resp_type_a_ipv4, + resp_info); + + EXIT(); + return TRUE; +} + +/** + * wlan_hdd_mdns_pack_response_type_txt() - Pack Type Txt response + * @ini_config: Pointer to the struct hdd_config_t + * @resp_info: Pointer to the struct tSirMDNSResponseInfo + * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type txt + * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A + * + * Type Txt response include QName, response type, class, TTL and text content. + * Also, it will find the matched QName from resptype_A and compress the data. + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +static bool +wlan_hdd_mdns_pack_response_type_txt(hdd_config_t *ini_config, + sir_mdns_resp_info resp_info, + struct hdd_mdns_resp_info *resptype_txt, + struct hdd_mdns_resp_info *resptype_a) +{ + uint8_t num_matched; + uint8_t num; + uint16_t idx; + uint16_t value = 0; + uint32_t len; + uint32_t total_len; + bool status; + struct hdd_mdns_resp_info resptype_content; + + ENTER(); + + if ((ini_config == NULL) || (resp_info == NULL) || + (resptype_txt == NULL)) { + hddLog(LOGE, FL("ini_config or response info is NULL!")); + return FALSE; + } + + /* No Type Txt response */ + if (strlen((char *)ini_config->mdns_resp_type_txt) <= 0) + return TRUE; + + /* Wrong response is assigned, just ignore this response */ + if (!wlan_hdd_mdns_init_response(resptype_txt, + ini_config->mdns_resp_type_txt, '.')) + return TRUE; + + /* + * For data compression + * Check if any strings are matched with Type A response + */ + if (resptype_a && (resptype_a->num_entries > 0)) { + num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_txt, + resptype_a); + if (num_matched > 0) { + if (!wlan_hdd_mdns_compress_data(resp_info, + resptype_txt, resptype_a, num_matched)) { + hddLog(LOGE, FL("Fail to compress mDNS " + "response (%d)!"), MDNS_TYPE_TXT); + return FALSE; + } + } else { + /* + * num_matched is zero. Error! + * At least ".local" is needed. + */ + hddLog(LOGE, FL("No matched string! Fail to pack mDNS " + "response (%d)!"), MDNS_TYPE_TXT); + return FALSE; + } + } else { + /* no TypeA response, so show the whole data */ + if (!wlan_hdd_mdns_process_response_dname(resptype_txt, + resp_info)) { + hddLog(LOGE, FL("Fail to process mDNS response (%d)!"), + MDNS_TYPE_TXT); + return FALSE; + } + } + + /* Process response Type, Class, TTL */ + if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_TXT, resp_info)) { + hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"), + MDNS_TYPE_TXT); + return FALSE; + } + + /* + * Process response RDLength, RData. + * TypeTxt RData include len. + */ + status = wlan_hdd_mdns_init_response(&resptype_content, + ini_config->mdns_resp_type_txt_content, + '/'); + if (status == FALSE) { + hddLog(LOGE, FL("wlan_hdd_mdns_init_response FAIL")); + return FALSE; + } + + for (num = 0; num < resptype_content.num_entries; num++) { + idx = num * MAX_LEN_DOMAINNAME_FIELD; + value += strlen((char *)&resptype_content.data[idx]); + } + + /* content len is uint16_t */ + total_len = sizeof(uint16_t); + total_len += resp_info->resp_len + value + + resptype_content.num_entries; + + if (total_len >= MAX_MDNS_RESP_LEN) { + hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN); + return FALSE; + } + wlan_hdd_mdns_format_response_u16(value + resptype_content.num_entries, + resp_info); + + for (num = 0; num < resptype_content.num_entries; num++) { + idx = num * MAX_LEN_DOMAINNAME_FIELD; + len = strlen((char *)&resptype_content.data[idx]); + resp_info->resp_data[resp_info->resp_len] = len; + resp_info->resp_len++; + + vos_mem_copy(&resp_info->resp_data[resp_info->resp_len], + &resptype_content.data[idx], len); + + resp_info->resp_len += len; + hddLog(LOG1, FL("index = %d, len = %d, str = %s"), + num, len, &resptype_content.data[idx]); + } + + EXIT(); + return TRUE; +} + +/** + * wlan_hdd_mdns_pack_response_type_ptr_dname() - Pack Type PTR domain name + * @ini_config: Pointer to the struct hdd_config_t + * @resp_info: Pointer to the struct tSirMDNSResponseInfo + * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr + * domain name + * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr + * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt + * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A + * + * The Type Ptr response include Type PTR domain name in its data field. + * Also, it will find the matched QName from the existing resptype_ptr, + * resptype_txt, resptype_a and then compress the data. + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +static bool +wlan_hdd_mdns_pack_response_type_ptr_dname(hdd_config_t *ini_config, + sir_mdns_resp_info resp_info, + struct hdd_mdns_resp_info *resptype_ptr_dn, + struct hdd_mdns_resp_info *resptype_ptr, + struct hdd_mdns_resp_info *resptype_txt, + struct hdd_mdns_resp_info *resptype_a) +{ + uint8_t num_matched, numlist, size; + struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1]; + struct hdd_mdns_resp_info *resp; + + if ((ini_config == NULL) || (resp_info == NULL) || + (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) { + hddLog(LOGE, FL("ini_config or response info is NULL!")); + return FALSE; + } + + /* No Type Ptr domain name response */ + if (strlen((char *)ini_config->mdns_resp_type_ptr_dname) <= 0) + return TRUE; + + /* Wrong response is assigned, just ignore this response */ + if (!wlan_hdd_mdns_init_response(resptype_ptr_dn, + ini_config->mdns_resp_type_ptr_dname, '.')) + return TRUE; + + /* + * For data compression + * Check if any strings are matched with previous + * response. + */ + numlist = 0; + size = (MAX_MDNS_RESP_TYPE-1); + size *= sizeof(struct hdd_mdns_resp_matched); + vos_mem_zero(matchedlist, size); + num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr_dn, + resptype_ptr); + if (num_matched > 0) { + matchedlist[numlist].num_matched = num_matched; + matchedlist[numlist].type = MDNS_TYPE_PTR; + numlist++; + } + if (resptype_txt && (resptype_txt->num_entries > 0)) { + num_matched = wlan_hdd_mdns_find_entries_from_end( + resptype_ptr_dn, resptype_txt); + if (num_matched > 0) { + matchedlist[numlist].num_matched = num_matched; + matchedlist[numlist].type = MDNS_TYPE_TXT; + numlist++; + } + } + if (resptype_a && (resptype_a->num_entries > 0)) { + num_matched = wlan_hdd_mdns_find_entries_from_end( + resptype_ptr_dn,resptype_a); + if (num_matched > 0) { + matchedlist[numlist].num_matched = num_matched; + matchedlist[numlist].type = MDNS_TYPE_A; + numlist++; + } + } + if (numlist > 0) { + if (numlist > 1) + wlan_hdd_mdns_find_max(matchedlist, numlist); + resp = NULL; + switch (matchedlist[numlist-1].type) { + case MDNS_TYPE_A: + resp = resptype_a; + break; + case MDNS_TYPE_TXT: + resp = resptype_txt; + break; + case MDNS_TYPE_PTR: + resp = resptype_ptr; + break; + default: + hddLog(LOGE, FL("Fail to compress mDNS response " + "(%d)!"), MDNS_TYPE_PTR_DNAME); + return FALSE; + } + num_matched = matchedlist[numlist-1].num_matched; + if (!wlan_hdd_mdns_compress_data(resp_info, resptype_ptr_dn, + resp, num_matched)) { + hddLog(LOGE, FL("Fail to compress mDNS response " + "(%d)!"), MDNS_TYPE_PTR_DNAME); + return FALSE; + } + } else { + /* num = 0 -> no matched string */ + if (!wlan_hdd_mdns_process_response_dname(resptype_ptr_dn, + resp_info)) { + hddLog(LOGE, FL("Fail to process mDNS response (%d)!"), + MDNS_TYPE_PTR_DNAME); + return FALSE; + } + } + + return TRUE; +} + +/** + * wlan_hdd_mdns_pack_response_type_ptr() - Pack Type PTR response + * @ini_config: Pointer to the struct hdd_config_t + * @resp_info: Pointer to the struct tSirMDNSResponseInfo + * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr + * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr + * domain name + * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt + * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A + * + * The Type Ptr response include QName, response type, class, TTL and + * Type PTR domain name. Also, it will find the matched QName from the + * existing resptype_txt, resptype_a and then compress the data. + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +static bool +wlan_hdd_mdns_pack_response_type_ptr(hdd_config_t *ini_config, + sir_mdns_resp_info resp_info, + struct hdd_mdns_resp_info *resptype_ptr, + struct hdd_mdns_resp_info *resptype_ptr_dn, + struct hdd_mdns_resp_info *resptype_txt, + struct hdd_mdns_resp_info *resptype_a) +{ + uint8_t num_matched, num_matched1; + uint16_t value; + uint8_t val_u8; + uint32_t offset_data_len, len; + + ENTER(); + if ((ini_config == NULL) || (resp_info == NULL) || + (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) { + hddLog(LOGE, FL("ini_config or response info is NULL!")); + return FALSE; + } + + /* No Type Ptr response */ + if (strlen((char *)ini_config->mdns_resp_type_ptr) <= 0) + return TRUE; + + /* Wrong response is assigned, just ignore this response */ + if (!wlan_hdd_mdns_init_response(resptype_ptr, + ini_config->mdns_resp_type_ptr, '.')) + return TRUE; + + /* + * For data compression + * Check if any strings are matched with Type A response + */ + num_matched = 0; + num_matched1 = 0; + if (resptype_a && (resptype_a->num_entries > 0)) { + num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr, + resptype_a); + } + if (resptype_txt && (resptype_txt->num_entries > 0)) { + num_matched1 = wlan_hdd_mdns_find_entries_from_end( + resptype_ptr, resptype_txt); + } + if ((num_matched != num_matched1) || + ((num_matched > 0) && (num_matched1 > 0))) { + if (num_matched >= num_matched1) { + if (!wlan_hdd_mdns_compress_data(resp_info, + resptype_ptr, resptype_a, num_matched)) { + hddLog(LOGE, FL("Fail to compress mDNS " + "response (%d)!"), MDNS_TYPE_PTR); + return FALSE; + } + } else { + /* num_matched is less than num_matched1 */ + if (!wlan_hdd_mdns_compress_data(resp_info, + resptype_ptr, resptype_txt, num_matched1)) { + hddLog(LOGE, FL("Fail to compress mDNS " + "response (%d)!"), MDNS_TYPE_PTR); + return FALSE; + } + } + } else { + /* + * Both num_matched and num_matched1 are zero. + * no TypeA & TypeTxt + */ + if (!wlan_hdd_mdns_process_response_dname(resptype_ptr, + resp_info)) { + hddLog(LOGE, FL("Fail to process mDNS response (%d)!"), + MDNS_TYPE_PTR); + return FALSE; + } + } + + /* Process response Type, Class, TTL */ + if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_PTR, resp_info)) { + hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"), + MDNS_TYPE_PTR); + return FALSE; + } + + /* + * Process response RDLength, RData (Ptr domain name) + * Save the offset of RData length + */ + offset_data_len = resp_info->resp_len; + resp_info->resp_len += sizeof(uint16_t); + + if (!wlan_hdd_mdns_pack_response_type_ptr_dname(ini_config, resp_info, + resptype_ptr_dn, resptype_ptr, + resptype_txt, resptype_a)) { + return FALSE; + } + /* Set the RData length */ + len = offset_data_len + sizeof(uint16_t); + if ((resptype_ptr_dn->num_entries > 0) && + (resp_info->resp_len > len)) { + value = resp_info->resp_len - len; + val_u8 = (value & 0xff00) >> 8; + resp_info->resp_data[offset_data_len] = val_u8; + val_u8 = value & 0xff; + resp_info->resp_data[offset_data_len+1] = val_u8; + } else { + hddLog(LOGE, FL("Fail to process mDNS response (%d)!"), + MDNS_TYPE_PTR); + return FALSE; + } + + EXIT(); + return TRUE; +} + +/** + * wlan_hdd_mdns_pack_response_type_srv_target()- Pack Type Service Target + * @ini_config: Pointer to the struct hdd_config_t + * @resp_info: Pointer to the struct tSirMDNSResponseInfo + * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv + * target + * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv + * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr + * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr + * domain name + * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt + * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A + * + * The Type service target is one of the data field in the Type SRV response. + * Also, it will find the matched QName from the existing resptype_srv, + * resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and then compress + * the data. + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +static bool +wlan_hdd_mdns_pack_response_type_srv_target(hdd_config_t *ini_config, + sir_mdns_resp_info resp_info, + struct hdd_mdns_resp_info *resptype_srv_tgt, + struct hdd_mdns_resp_info *resptype_srv, + struct hdd_mdns_resp_info *resptype_ptr, + struct hdd_mdns_resp_info *resptype_ptr_dn, + struct hdd_mdns_resp_info *resptype_txt, + struct hdd_mdns_resp_info *resptype_a) +{ + uint8_t num_matched, num, size; + struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1]; + struct hdd_mdns_resp_info *resp; + + if ((ini_config == NULL) || (resp_info == NULL) || + (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) { + hddLog(LOGE, FL("ini_config or response info is NULL!")); + return FALSE; + } + + /* No Type Srv Target response */ + if (strlen((char *)ini_config->mdns_resp_type_srv_target) <= 0) + return TRUE; + + /* Wrong response is assigned, just ignore this response */ + if (!wlan_hdd_mdns_init_response(resptype_srv_tgt, + ini_config->mdns_resp_type_srv_target, '.')) + return TRUE; + + /* + * For data compression + * Check if any strings are matched with previous response. + */ + num = 0; + size = (MAX_MDNS_RESP_TYPE-1); + size *= sizeof(struct hdd_mdns_resp_matched); + vos_mem_zero(matchedlist, size); + num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv_tgt, + resptype_srv); + if (num_matched > 0) { + matchedlist[num].num_matched = num_matched; + matchedlist[num].type = MDNS_TYPE_SRV; + num++; + } + if (resptype_ptr && (resptype_ptr->num_entries > 0)) { + if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) { + num_matched = wlan_hdd_mdns_find_entries_from_end( + resptype_srv_tgt, resptype_ptr_dn); + if (num_matched > 0) { + matchedlist[num].num_matched = num_matched; + matchedlist[num].type = MDNS_TYPE_PTR_DNAME; + num++; + } + } + num_matched = wlan_hdd_mdns_find_entries_from_end( + resptype_srv_tgt, resptype_ptr); + if (num_matched > 0) { + matchedlist[num].num_matched = num_matched; + matchedlist[num].type = MDNS_TYPE_PTR; + num++; + } + } + if (resptype_txt && (resptype_txt->num_entries > 0)) { + num_matched = wlan_hdd_mdns_find_entries_from_end( + resptype_srv_tgt, resptype_txt); + if (num_matched > 0) { + matchedlist[num].num_matched = num_matched; + matchedlist[num].type = MDNS_TYPE_TXT; + num++; + } + } + if (resptype_a && (resptype_a->num_entries > 0)) { + num_matched = wlan_hdd_mdns_find_entries_from_end( + resptype_srv_tgt, resptype_a); + if (num_matched > 0) { + matchedlist[num].num_matched = num_matched; + matchedlist[num].type = MDNS_TYPE_A; + num++; + } + } + if (num > 0) { + if (num > 1) + wlan_hdd_mdns_find_max(matchedlist, num); + resp = NULL; + switch (matchedlist[num-1].type) { + case MDNS_TYPE_A: + resp = resptype_a; + break; + case MDNS_TYPE_TXT: + resp = resptype_txt; + break; + case MDNS_TYPE_PTR: + resp = resptype_ptr; + break; + case MDNS_TYPE_PTR_DNAME: + resp = resptype_ptr_dn; + break; + case MDNS_TYPE_SRV: + resp = resptype_srv; + break; + default: + hddLog(LOGE, FL("Fail to compress mDNS response " + "(%d)!"), MDNS_TYPE_SRV_TARGET); + return FALSE; + } + num_matched = matchedlist[num-1].num_matched; + if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv_tgt, + resp, num_matched)) { + hddLog(LOGE, FL("Fail to compress mDNS response " + "(%d)!"), MDNS_TYPE_SRV_TARGET); + return FALSE; + } + } else { + /* num = 0 -> no matched string */ + if (!wlan_hdd_mdns_process_response_dname(resptype_srv_tgt, + resp_info)) { + hddLog(LOGE, FL("Fail to process mDNS response (%d)!"), + MDNS_TYPE_SRV_TARGET); + return FALSE; + } + } + + return TRUE; +} + +/** + * wlan_hdd_mdns_pack_response_type_srv()- Pack Type Service response + * @ini_config: Pointer to the struct hdd_config_t + * @resp_info: Pointer to the struct tSirMDNSResponseInfo + * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv + * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv + * target + * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr + * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr + * domain name + * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt + * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A + * + * The Type SRV (Service) response include QName, response type, class, TTL + * and four kinds of data fields. Also, it will find the matched QName from + * the existing resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and + * then compress the data. + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +static bool +wlan_hdd_mdns_pack_response_type_srv(hdd_config_t *ini_config, + sir_mdns_resp_info resp_info, + struct hdd_mdns_resp_info *resptype_srv, + struct hdd_mdns_resp_info *resptype_srv_tgt, + struct hdd_mdns_resp_info *resptype_ptr, + struct hdd_mdns_resp_info *resptype_ptr_dn, + struct hdd_mdns_resp_info *resptype_txt, + struct hdd_mdns_resp_info *resptype_a) +{ + uint8_t num_matched, num, size; + uint16_t value; + uint8_t val_u8; + uint32_t offset_data_len, len; + struct hdd_mdns_resp_info *resp; + struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1]; + + ENTER(); + + if ((ini_config == NULL) || (resp_info == NULL) || + (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) { + hddLog(LOGE, FL("ini_config or response info is NULL!")); + return FALSE; + } + + /* No Type Srv response */ + if (strlen((char *)ini_config->mdns_resp_type_srv) <= 0) + return TRUE; + + /* Wrong response is assigned, just ignore this response */ + if (!wlan_hdd_mdns_init_response(resptype_srv, + ini_config->mdns_resp_type_srv, '.')) + return TRUE; + + /* + * For data compression + * Check if any strings are matched with Type A response + */ + num = 0; + size = (MAX_MDNS_RESP_TYPE-1); + size *= sizeof(struct hdd_mdns_resp_matched); + vos_mem_zero(matchedlist, size); + if (resptype_ptr && (resptype_ptr->num_entries > 0)) { + if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) { + num_matched = wlan_hdd_mdns_find_entries_from_end( + resptype_srv, + resptype_ptr_dn); + if (num_matched > 0) { + matchedlist[num].num_matched = num_matched; + matchedlist[num].type = MDNS_TYPE_PTR_DNAME; + num++; + } + } + num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv, + resptype_ptr); + if (num_matched > 0) { + matchedlist[num].num_matched = num_matched; + matchedlist[num].type = MDNS_TYPE_PTR; + num++; + } + } + if (resptype_txt && (resptype_txt->num_entries > 0)) { + num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv, + resptype_txt); + if (num_matched > 0) { + matchedlist[num].num_matched =num_matched; + matchedlist[num].type = MDNS_TYPE_TXT; + num++; + } + } + if (resptype_a && (resptype_a->num_entries > 0)) { + num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv, + resptype_a); + if (num_matched > 0) { + matchedlist[num].num_matched = num_matched; + matchedlist[num].type = MDNS_TYPE_A; + num++; + } + } + if (num > 0) { + if (num > 1) + wlan_hdd_mdns_find_max(matchedlist, num); + resp = NULL; + switch (matchedlist[num-1].type) { + case MDNS_TYPE_A: + resp = resptype_a; + break; + case MDNS_TYPE_TXT: + resp = resptype_txt; + break; + case MDNS_TYPE_PTR: + resp = resptype_ptr; + break; + case MDNS_TYPE_PTR_DNAME: + resp = resptype_ptr_dn; + break; + default: + hddLog(LOGE, FL("Fail to compress mDNS response " + "(%d)!"), MDNS_TYPE_SRV); + return FALSE; + } + num_matched = matchedlist[num-1].num_matched; + if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv, + resp, num_matched)) { + hddLog(LOGE, FL("Fail to compress mDNS response " + "(%d)!"), MDNS_TYPE_SRV); + return FALSE; + } + } else { + /* num = 0 -> no matched string */ + if (!wlan_hdd_mdns_process_response_dname(resptype_srv, + resp_info)) { + hddLog(LOGE, FL("Fail to process mDNS response (%d)!"), + MDNS_TYPE_SRV); + return FALSE; + } + } + + /* Process response Type, Class, TTL */ + if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_SRV, resp_info)) { + hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"), + MDNS_TYPE_SRV); + return FALSE; + } + + /* + * Process response RDLength, RData (Srv target name) + * Save the offset of RData length + */ + offset_data_len = resp_info->resp_len; + resp_info->resp_len += sizeof(uint16_t); + + len = resp_info->resp_len + (3 * sizeof(uint16_t)); + if (len >= MAX_MDNS_RESP_LEN) { + hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN); + return FALSE; + } + + /* set Srv Priority */ + value = ini_config->mdns_resp_type_srv_priority; + wlan_hdd_mdns_format_response_u16(value, resp_info); + /* set Srv Weight */ + value = ini_config->mdns_resp_type_srv_weight; + wlan_hdd_mdns_format_response_u16(value, resp_info); + /* set Srv Port */ + value = ini_config->mdns_resp_type_srv_port; + wlan_hdd_mdns_format_response_u16(value, resp_info); + + if (!wlan_hdd_mdns_pack_response_type_srv_target(ini_config, resp_info, + resptype_srv_tgt, resptype_srv, + resptype_ptr, resptype_ptr_dn, + resptype_txt, resptype_a)) { + return FALSE; + } + /* Set the RData length */ + len = offset_data_len + sizeof(uint16_t); + if ((resptype_srv_tgt->num_entries > 0) && + (resp_info->resp_len > len)) { + value = resp_info->resp_len - len; + val_u8 = (value & 0xff00) >> 8; + resp_info->resp_data[offset_data_len] = val_u8; + val_u8 = value & 0xff; + resp_info->resp_data[offset_data_len+1] = val_u8; + } else { + hddLog(LOGE, FL("Fail to process mDNS response (%d)!"), + MDNS_TYPE_SRV); + return FALSE; + } + + EXIT(); + return TRUE; +} + +/** + * wlan_hdd_mdns_free_mem() - Free the allocated memory + * @response: Pointer to the struct hdd_mdns_resp_info + * + * Return: None + */ +static void wlan_hdd_mdns_free_mem(struct hdd_mdns_resp_info *response) +{ + if (response && response->data) + vos_mem_free(response->data); + if (response && response->offset) + vos_mem_free(response->offset); +} + +/** + * wlan_hdd_mdns_pack_response() - Pack mDNS response + * @ini_config: Pointer to the struct hdd_config_t + * @resp_info: Pointer to the struct tSirMDNSResponseInfo + * + * This function will pack four types of responses (Type A, Type Txt, Type Ptr + * and Type Service). Each response contains QName, response type, class, TTL + * and data fields. + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +static bool wlan_hdd_mdns_pack_response(hdd_config_t *ini_config, + sir_mdns_resp_info resp_info) +{ + struct hdd_mdns_resp_info resptype_a, resptype_txt; + struct hdd_mdns_resp_info resptype_ptr, resptype_ptr_dn; + struct hdd_mdns_resp_info resptype_srv, resptype_srv_tgt; + uint32_t num_res_records = 0; + bool status = FALSE; + + ENTER(); + + wlan_hdd_mdns_reset_response(&resptype_a); + wlan_hdd_mdns_reset_response(&resptype_txt); + wlan_hdd_mdns_reset_response(&resptype_ptr); + wlan_hdd_mdns_reset_response(&resptype_ptr_dn); + wlan_hdd_mdns_reset_response(&resptype_srv); + wlan_hdd_mdns_reset_response(&resptype_srv_tgt); + + resp_info->resp_len = 0; + + /* Process Type A response */ + if (!wlan_hdd_mdns_pack_response_type_a(ini_config, resp_info, + &resptype_a)) + goto err_resptype_a; + + if ((resptype_a.num_entries > 0) && + (strlen((char *)&resptype_a.data[0]) > 0)) + num_res_records++; + + /* Process Type TXT response */ + if (!wlan_hdd_mdns_pack_response_type_txt(ini_config, resp_info, + &resptype_txt, &resptype_a)) + goto err_resptype_txt; + + if ((resptype_txt.num_entries > 0) && + (strlen((char *)&resptype_txt.data[0]) > 0)) + num_res_records++; + + /* Process Type PTR response */ + if (!wlan_hdd_mdns_pack_response_type_ptr(ini_config, resp_info, + &resptype_ptr, &resptype_ptr_dn, + &resptype_txt, &resptype_a)) + goto err_resptype_ptr; + + if ((resptype_ptr.num_entries > 0) && + (strlen((char *)&resptype_ptr.data[0]) > 0)) + num_res_records++; + + /* Process Type SRV response */ + if (!wlan_hdd_mdns_pack_response_type_srv(ini_config, resp_info, + &resptype_srv, &resptype_srv_tgt, + &resptype_ptr, &resptype_ptr_dn, + &resptype_txt, &resptype_a)) + goto err_resptype_srv; + + if ((resptype_srv.num_entries > 0) && + (strlen((char *)&resptype_srv.data[0]) > 0)) + num_res_records++; + + resp_info->resourceRecord_count = num_res_records; + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Pack mDNS response data successfully!", __func__); + status = TRUE; + +err_resptype_srv: + wlan_hdd_mdns_free_mem(&resptype_srv); + wlan_hdd_mdns_free_mem(&resptype_srv_tgt); + +err_resptype_ptr: + wlan_hdd_mdns_free_mem(&resptype_ptr); + wlan_hdd_mdns_free_mem(&resptype_ptr_dn); + +err_resptype_txt: + wlan_hdd_mdns_free_mem(&resptype_txt); + +err_resptype_a: + wlan_hdd_mdns_free_mem(&resptype_a); + + EXIT(); + return status; +} + +/** + * wlan_hdd_set_mdns_offload() - Enable mDNS offload + * @hostapd_adapter: Pointer to the struct hdd_adapter_t + * + * This function will set FQDN/unique FQDN (full qualified domain name) + * and the mDNS response. Then send them to SME. + * + * Return: Return boolean. TRUE for success, FALSE for fail. + */ +bool wlan_hdd_set_mdns_offload(hdd_adapter_t *hostapd_adapter) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter); + sir_mdns_offload_info mdns_offload_info; + sir_mdns_fqdn_info mdns_fqdn_info; + sir_mdns_resp_info mdns_resp_info; + uint32_t fqdn_len, ufqdn_len; + + ENTER(); + + /* 1. Prepare the MDNS fqdn request to send to SME */ + fqdn_len = strlen(hdd_ctx->cfg_ini->mdns_fqdn); + ufqdn_len = strlen(hdd_ctx->cfg_ini->mdns_uniquefqdn); + if ((fqdn_len == 0) && (ufqdn_len == 0)) { + hddLog(LOGE, FL("No mDNS FQDN or UFQDN is assigned fqdn_len %d," + "ufqdn_len %d!"), fqdn_len, ufqdn_len); + return FALSE; + } + + mdns_fqdn_info = vos_mem_malloc(sizeof(*mdns_fqdn_info)); + if (NULL == mdns_fqdn_info) { + hddLog(LOGE, FL("could not allocate tSirMDNSFqdnInfo!")); + return FALSE; + } + /* MDNS fqdn request */ + if (fqdn_len > 0) { + vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info)); + mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId; + mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_GENERAL; + mdns_fqdn_info->fqdn_len = fqdn_len; + mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done; + mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter; + vos_mem_copy(mdns_fqdn_info->fqdn_data, + hdd_ctx->cfg_ini->mdns_fqdn, + mdns_fqdn_info->fqdn_len); + + if (eHAL_STATUS_SUCCESS != + sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) { + hddLog(LOGE, FL("sme_set_mdns_fqdn fail!")); + vos_mem_free(mdns_fqdn_info); + return FALSE; + } + } + /* MDNS unique fqdn request */ + if (ufqdn_len > 0) { + vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info)); + mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId; + mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_UNIQUE; + mdns_fqdn_info->fqdn_len = ufqdn_len; + mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done; + mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter; + vos_mem_copy(mdns_fqdn_info->fqdn_data, + hdd_ctx->cfg_ini->mdns_uniquefqdn, + mdns_fqdn_info->fqdn_len); + if (eHAL_STATUS_SUCCESS != + sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) { + hddLog(LOGE, FL("sme_set_mdns_fqdn fail!")); + vos_mem_free(mdns_fqdn_info); + return FALSE; + } + } + vos_mem_free(mdns_fqdn_info); + + /* 2. Prepare the MDNS response request to send to SME */ + mdns_resp_info = vos_mem_malloc(sizeof(*mdns_resp_info)); + if (NULL == mdns_resp_info) { + hddLog(LOGE, FL("could not allocate tSirMDNSResponseInfo!")); + return FALSE; + } + + vos_mem_zero(mdns_resp_info, sizeof(*mdns_resp_info)); + mdns_resp_info->bss_idx = hostapd_adapter->sessionId; + mdns_resp_info->mdns_resp_callback = hdd_mdns_resp_offload_done; + mdns_resp_info->mdns_resp_cb_context = hostapd_adapter; + if (!wlan_hdd_mdns_pack_response(hdd_ctx->cfg_ini, mdns_resp_info)) { + hddLog(LOGE, FL("wlan_hdd_pack_mdns_response fail!")); + vos_mem_free(mdns_resp_info); + return FALSE; + } + if (eHAL_STATUS_SUCCESS != + sme_set_mdns_resp(hdd_ctx->hHal, mdns_resp_info)) { + hddLog(LOGE, FL("sme_set_mdns_resp fail!")); + vos_mem_free(mdns_resp_info); + return FALSE; + } + vos_mem_free(mdns_resp_info); + + /* 3. Prepare the MDNS Enable request to send to SME */ + mdns_offload_info = vos_mem_malloc(sizeof(*mdns_offload_info)); + if (NULL == mdns_offload_info) { + hddLog(LOGE, FL("could not allocate tSirMDNSOffloadInfo!")); + return FALSE; + } + + vos_mem_zero(mdns_offload_info, sizeof(*mdns_offload_info)); + + mdns_offload_info->bss_idx = hostapd_adapter->sessionId; + mdns_offload_info->enable = hdd_ctx->cfg_ini->enable_mdns_offload; + mdns_offload_info->mdns_enable_callback = hdd_mdns_enable_offload_done; + mdns_offload_info->mdns_enable_cb_context = hostapd_adapter; + if (eHAL_STATUS_SUCCESS != + sme_set_mdns_offload(hdd_ctx->hHal, mdns_offload_info)) { + hddLog(LOGE, FL("sme_set_mdns_offload fail!")); + vos_mem_free(mdns_offload_info); + return FALSE; + } + + vos_mem_free(mdns_offload_info); + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: enable mDNS offload successfully!", __func__); + return TRUE; +} + + +#endif /* MDNS_OFFLOAD */ /** * wlan_hdd_start_sap() - This function starts bss of SAP. @@ -14911,6 +16707,314 @@ end: return; } +#ifdef WLAN_FEATURE_TSF + +/** + * hdd_tsf_cb() - handle tsf request callback + * + * @pcb_cxt: pointer to the hdd_contex + * @ptsf: pointer to struct stsf + * + * Based on the request sent . + * + * Return: Describe the execute result of this routine + */ +static int hdd_tsf_cb(void *pcb_ctx, struct stsf *ptsf) +{ + hdd_context_t *hddctx; + int status; + hdd_adapter_t* adapter = (hdd_adapter_t*)pcb_ctx; + + if (pcb_ctx == NULL || ptsf == NULL) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("HDD context is not valid")); + return -EINVAL; + } + + hddctx = (hdd_context_t *)pcb_ctx; + status = wlan_hdd_validate_context(hddctx); + if (0 != status) + return -EINVAL; + + if (NULL == adapter) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("failed to find adapter")); + return -EINVAL; + } + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("tsf cb handle event, device_mode is %d"), + adapter->device_mode); + + /* copy the return value to hdd_tsf_ctx in adapter*/ + if (ptsf->tsf_req_status) { + + vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock); + adapter->tsf_cap_ctx.tsf_get_state = TSF_NOT_RETURNED_BY_FW; + adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE; + vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event); + vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock); + + hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf req failure :%d"), + ptsf->tsf_req_status); + return ptsf->tsf_req_status; + } + /* If this is a get request.Store the tsf values in adapter. */ + if (!ptsf->set_tsf_req) { + vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock); + adapter->tsf_cap_ctx.tsf_low = ptsf->tsf_low; + adapter->tsf_cap_ctx.tsf_high = ptsf->tsf_high; + adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN; + adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE; + vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock); + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"), + adapter->sessionId, ptsf->tsf_low, ptsf->tsf_high); + } + else { + vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock); + adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE; + adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE; + vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock); + } + vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock); + vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event); + vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock); + + /* free allocated mem */ + vos_mem_free(ptsf); + + return 0; +} + +/** + * hdd_capture_tsf() - capture tsf + * + * @adapter: pointer to adapter + * @buf: pointer to upper layer buf + * @len : the length of buf + * + * This function returns tsf value to uplayer. + * + * Return: Describe the execute result of this routine + */ +int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len) +{ + int ret = 0; + hdd_station_ctx_t *hdd_sta_ctx; + hdd_context_t *hdd_ctx; + tSirCapTsfParams cap_tsf_params; + VOS_STATUS status; + + if (adapter == NULL || buf == NULL) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invalid pointer")); + return -EINVAL; + } + if (len != 1) + return -EINVAL; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invalid hdd ctx")); + return -EINVAL; + } + if (adapter->device_mode == WLAN_HDD_INFRA_STATION || + adapter->device_mode == WLAN_HDD_P2P_CLIENT) { + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (hdd_sta_ctx->conn_info.connState != + eConnectionState_Associated) { + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("failed to cap tsf, not connect with ap")); + buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF; + return ret; + } + } + if ((adapter->device_mode == WLAN_HDD_SOFTAP || + adapter->device_mode == WLAN_HDD_P2P_GO) && + !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Soft AP / P2p GO not beaconing")); + buf[0] = TSF_SAP_NOT_STARTED_NO_TSF; + return ret; + } + if (adapter->tsf_cap_ctx.tsf_capture_state == TSF_CAP_STATE) { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("current in capture state, pls reset")); + buf[0] = TSF_CURRENT_IN_CAP_STATE; + } else { + hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd")); + buf[0] = TSF_RETURN; + cap_tsf_params.session_id = adapter->sessionId; + cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb; + cap_tsf_params.tsf_rsp_cb_ctx = adapter; + + vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock); + adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE; + adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE; + vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock); + + ret = sme_capture_tsf_req(hdd_ctx->hHal, cap_tsf_params); + + if (ret != VOS_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail")); + buf[0] = TSF_CAPTURE_FAIL; + vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock); + adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE; + vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock); + return -EINVAL; + } + /* wait till we get a response from fw */ + status = vos_wait_single_event(&adapter->tsf_cap_ctx. + tsf_capture_done_event, + HDD_TSF_CAP_REQ_TIMEOUT); + + if (!VOS_IS_STATUS_SUCCESS(status)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("capture tsf vos wait for single_event failed!! %d"), + adapter->tsf_cap_ctx.tsf_get_state); + + vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock); + adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE; + vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock); + + return -EINVAL; + } + } + buf[0] = TSF_RETURN; + hddLog(VOS_TRACE_LEVEL_INFO, + FL("ioctl return cap tsf cmd, ret = %d"), ret); + return ret; +} + +/** + * hdd_indicate_tsf() - return tsf to uplayer + * + * @adapter: pointer to adapter + * @buf: pointer to uplayer buf + * @len : the length of buf + * + * This function returns tsf value to uplayer. + * + * Return: Describe the execute result of this routine + */ +int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len) +{ + int ret = 0; + hdd_station_ctx_t *hdd_sta_ctx; + hdd_context_t *hdd_ctx; + tSirCapTsfParams cap_tsf_params; + VOS_STATUS status; + + if (adapter == NULL || buf == NULL) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invalid pointer")); + return -EINVAL; + } + if (len != 3) + return -EINVAL; + + buf [1] = 0; + buf [2] = 0; + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + if (wlan_hdd_validate_context(hdd_ctx)) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("invalid hdd ctx")); + return -EINVAL; + } + if (adapter->device_mode == WLAN_HDD_INFRA_STATION || + adapter->device_mode == WLAN_HDD_P2P_CLIENT) { + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (hdd_sta_ctx->conn_info.connState != + eConnectionState_Associated) { + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("failed to cap tsf, not connect with ap")); + buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF; + return ret; + } + } + if ((adapter->device_mode == WLAN_HDD_SOFTAP || + adapter->device_mode == WLAN_HDD_P2P_GO) && + !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Soft AP / P2p GO not beaconing")); + buf[0] = TSF_SAP_NOT_STARTED_NO_TSF; + return ret; + } + + if (adapter->tsf_cap_ctx.tsf_capture_state != TSF_CAP_STATE || + adapter->tsf_cap_ctx.tsf_get_state != TSF_CURRENT_IN_CAP_STATE ) { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Not in capture state,Enter capture state first")); + buf[0] = TSF_GET_FAIL; + } else { + hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd")); + cap_tsf_params.session_id = adapter->sessionId; + cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb; + cap_tsf_params.tsf_rsp_cb_ctx = adapter; + + ret = sme_get_tsf_req(hdd_ctx->hHal, cap_tsf_params); + + if (ret != VOS_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail")); + buf[0] = TSF_CAPTURE_FAIL; + vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock); + adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE; + vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock); + return -EINVAL; + } + /* wait till we get a response from fw */ + status = vos_wait_single_event(&adapter->tsf_cap_ctx. + tsf_capture_done_event, + HDD_TSF_GET_REQ_TIMEOUT); + + if (!VOS_IS_STATUS_SUCCESS(status)) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + ("capture tsf vos wait for single_event failed!! %d"), + status); + + vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock); + adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE; + vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock); + return status; + } + buf[1] = adapter->tsf_cap_ctx.tsf_low; + buf[2] = adapter->tsf_cap_ctx.tsf_high; + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"), + buf[0], buf[1], buf[2]); + } + hddLog(VOS_TRACE_LEVEL_INFO, + FL("ioctl return cap tsf cmd, ret = %d"), ret); + return ret; +} + +void wlan_hdd_tsf_init(hdd_adapter_t *adapter) +{ + + if (adapter == NULL) { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("TSF init on a null adapter!")); + return; + } + + adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN; + adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE; + vos_event_init(&adapter->tsf_cap_ctx.tsf_capture_done_event); + vos_spin_lock_init(&adapter->tsf_cap_ctx.tsf_lock); + adapter->tsf_cap_ctx.tsf_high = 0; + adapter->tsf_cap_ctx.tsf_low = 0; +} + +#endif + //Register the module init/exit functions module_init(hdd_module_init); module_exit(hdd_module_exit); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_oemdata.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_oemdata.c index 9bc83726bef..df015ac40a5 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_oemdata.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_oemdata.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -992,5 +992,20 @@ int oem_activate_service(void *pAdapter) return 0; } +/**--------------------------------------------------------------------------- + + \brief oem_deactivate_service() - Deactivate oem message handler + + This function unregisters a handler to receive netlink message from + an OEM application process. + + \return - none + --------------------------------------------------------------------------*/ +void oem_deactivate_service() +{ + /* unregister the msg handler for msgs addressed to WLAN_NL_MSG_OEM */ + nl_srv_unregister(WLAN_NL_MSG_OEM, __oem_msg_callback); +} + #endif diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c index d2225a4f2a6..feef357215b 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c @@ -132,10 +132,14 @@ static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter, tANI_U8* pbFrames, tANI_U8 frameType ); -static v_BOOL_t wlan_hdd_is_type_p2p_action( const u8 *buf ) +static v_BOOL_t wlan_hdd_is_type_p2p_action( const u8 *buf, uint32_t len ) { const u8 *ouiPtr; + if (len < WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET + 1) { + return VOS_FALSE; + } + if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] != WLAN_HDD_PUBLIC_ACTION_FRAME ) { return VOS_FALSE; @@ -160,11 +164,11 @@ static v_BOOL_t wlan_hdd_is_type_p2p_action( const u8 *buf ) return VOS_TRUE; } -static bool hdd_p2p_is_action_type_rsp( const u8 *buf ) +static bool hdd_p2p_is_action_type_rsp( const u8 *buf, uint32_t len ) { tActionFrmType actionFrmType; - if ( wlan_hdd_is_type_p2p_action(buf) ) + if ( wlan_hdd_is_type_p2p_action(buf, len) ) { actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET]; if ( actionFrmType != WLAN_HDD_INVITATION_REQ && @@ -1274,17 +1278,27 @@ int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev, hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); - tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]); - tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]); + tANI_U8 type; + tANI_U8 subType; tActionFrmType actionFrmType = WLAN_HDD_ACTION_FRM_TYPE_MAX; bool noack = 0; int status; + uint32_t mgmt_hdr_len = sizeof(struct ieee80211_hdr_3addr); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) uint8_t home_ch = 0; #endif ENTER(); + + if (len < mgmt_hdr_len + 1) { + hddLog(VOS_TRACE_LEVEL_ERROR,"Invalid Length"); + return -EINVAL; + } + + type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]); + subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]); + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_ACTION, pAdapter->sessionId, pAdapter->device_mode )); @@ -1301,7 +1315,8 @@ int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev, if ((type == SIR_MAC_MGMT_FRAME) && (subType == SIR_MAC_MGMT_ACTION) && - wlan_hdd_is_type_p2p_action(&buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET])) + wlan_hdd_is_type_p2p_action( + &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET], len - mgmt_hdr_len)) { actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET]; #ifdef WLAN_FEATURE_P2P_DEBUG @@ -1600,7 +1615,9 @@ bypass_lock: if ((type == SIR_MAC_MGMT_FRAME) && (subType == SIR_MAC_MGMT_ACTION) && - (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)) + wlan_hdd_is_type_p2p_action( + &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET], + len - mgmt_hdr_len)) { actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET]; hddLog(LOG1, "Tx Action Frame %u.", actionFrmType); @@ -2461,7 +2478,9 @@ void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, /* Get pAdapter from Destination mac address of the frame */ if ((type == SIR_MAC_MGMT_FRAME) && - (subType != SIR_MAC_MGMT_PROBE_REQ)) + (subType != SIR_MAC_MGMT_PROBE_REQ) && + !vos_is_macaddr_broadcast( + (v_MACADDR_t *)&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET])) { pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter), &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]); @@ -2710,17 +2729,17 @@ void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, //Indicate Frame Over Normal Interface hddLog( LOG1, FL("Indicate Frame over NL80211 Interface")); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)) - cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0, pbFrames, + cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, rxRssi * 100, pbFrames, nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED); #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)) - cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0, pbFrames, + cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, rxRssi * 100, pbFrames, nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC); #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) - cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0, + cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, rxRssi * 100, pbFrames, nFrameLength, GFP_ATOMIC ); #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) - cfg80211_rx_mgmt( pAdapter->dev, freq, 0, + cfg80211_rx_mgmt( pAdapter->dev, freq, rxRssi * 100, pbFrames, nFrameLength, GFP_ATOMIC ); #else diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c index 5a3f1de674b..2cb3b89887b 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -453,6 +453,23 @@ int __hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) // checked. Over-limit packets will be dropped. spin_lock_bh(&pSapCtx->aStaInfo[STAId].wmm_tx_queue[ac].lock); hdd_list_size(&pSapCtx->aStaInfo[STAId].wmm_tx_queue[ac], &pktListSize); + + if (pHddCtx->bad_sta[STAId]) { + hdd_list_node_t *anchor = NULL; + skb_list_node_t *pktNode = NULL; + struct sk_buff *fskb = NULL; + if(pktListSize >= (pAdapter->aTxQueueLimit[ac])/2) { + hdd_list_remove_front(&pSapCtx->aStaInfo[STAId].wmm_tx_queue[ac], + &anchor); + pktNode = list_entry(anchor, skb_list_node_t, anchor); + fskb = pktNode->skb; + kfree_skb(fskb); + pktListSize--; + ++pAdapter->stats.tx_dropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; + } + } + if(pktListSize >= pAdapter->aTxQueueLimit[ac]) { VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN, @@ -740,7 +757,8 @@ void __hdd_softap_tx_timeout(struct net_device *dev) hdd_context_t *pHddCtx; VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR, - "%s: Transmission timeout occurred", __func__); + "%s: Transmission timeout occurred jiffies %lu dev->trans_start %lu", + __func__, jiffies, dev->trans_start); if ( NULL == pAdapter ) { @@ -993,6 +1011,9 @@ static VOS_STATUS hdd_softap_flush_tx_queues_sta( hdd_adapter_t *pAdapter, v_U8_ spin_unlock_bh(&pSapCtx->aStaInfo[STAId].wmm_tx_queue[i].lock); } + VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO, + "%s: flushed the TX queues of sta:%d", __func__, STAId); + return VOS_STATUS_SUCCESS; } @@ -1631,7 +1652,7 @@ VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext, vos_pkt_t* pVosPacket; vos_pkt_t* pNextVosPacket; hdd_context_t *pHddCtx = NULL; - v_U8_t proto_type; + v_U8_t proto_type = 0; //Sanity check on inputs if ( ( NULL == vosContext ) || diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c index 460ffe5637f..d17995429c2 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c @@ -3644,4 +3644,42 @@ void wlan_hdd_start_stop_tdls_source_timer(hdd_context_t *pHddCtx, return; } +void wlan_hdd_get_tdls_stats(hdd_adapter_t *pAdapter) +{ + hdd_context_t *pHddCtx = NULL; + tdlsCtx_t *pHddTdlsCtx = NULL; + tANI_U16 numConnectedTdlsPeers = 0; + tANI_U16 numDiscoverySentCnt = 0; + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + ENTER(); + if (0 != (wlan_hdd_validate_context(pHddCtx))) + { + return; + } + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + + mutex_lock(&pHddCtx->tdls_lock); + if (NULL == pHddTdlsCtx) + { + mutex_unlock(&pHddCtx->tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + FL("pHddTdlsCtx points to NULL")); + return; + } + numConnectedTdlsPeers = pHddCtx->connected_peer_count; + numDiscoverySentCnt = pHddTdlsCtx->discovery_sent_cnt; + mutex_unlock(&pHddCtx->tdls_lock); + + hddLog( LOGE, "%s: TDLS Mode: %d TDLS connected peer count %d" + " DiscoverySentCnt=%d", __func__, pHddCtx->tdls_mode, + numConnectedTdlsPeers, numDiscoverySentCnt); + EXIT(); + + return; +} + + /*EXT TDLS*/ diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c index 00ba6f40a13..b0a8c420133 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -840,11 +840,9 @@ int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (arp_pkt) { - if (pHddCtx->track_arp_ip && vos_check_arp_req_target_ip(skb, false)) { - ++pAdapter->hdd_stats.hddArpStats.tx_arp_req_count; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s :ARP packet received form net_dev", __func__); - } + ++pAdapter->hdd_stats.hddArpStats.txCount; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s :ARP packet received form net_dev", __func__); } //Get TL Q index corresponding to Qdisc queue index/AC. @@ -933,6 +931,24 @@ int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } } + + if (pHddCtx->bad_sta[STAId]) { + hdd_list_node_t *anchor = NULL; + skb_list_node_t *pktNode = NULL; + struct sk_buff *fskb = NULL; + + if (pAdapter->wmm_tx_queue[qid].count >= + pAdapter->wmm_tx_queue[qid].max_size / 2) { + hdd_list_remove_front(&pAdapter->wmm_tx_queue[qid], + &anchor); + pktNode = list_entry(anchor, skb_list_node_t, anchor); + fskb = pktNode->skb; + kfree_skb(fskb); + ++pAdapter->stats.tx_dropped; + ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; + } + } + //If we have already reached the max queue size, disable the TX queue if ( pAdapter->wmm_tx_queue[qid].count == pAdapter->wmm_tx_queue[qid].max_size) { @@ -2676,9 +2692,8 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, struct sk_buff *skb = NULL; vos_pkt_t* pVosPacket; vos_pkt_t* pNextVosPacket; - v_U8_t proto_type; + v_U8_t proto_type = 0; v_BOOL_t arp_pkt; - bool track_arp_resp = false; //Sanity check on inputs if ( ( NULL == vosContext ) || @@ -2811,12 +2826,9 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, if (arp_pkt) { - if (pHddCtx->track_arp_ip && vos_check_arp_rsp_src_ip(skb, false)) { - ++pAdapter->hdd_stats.hddArpStats.rx_arp_rsp_count; - track_arp_resp = true; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s :STA RX ARP received",__func__); - } + ++pAdapter->hdd_stats.hddArpStats.rxCount; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s :STA RX ARP received",__func__); } if (pHddCtx->rx_wow_dump) { @@ -2844,7 +2856,12 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, pAdapter->stats.rx_bytes += skb->len; if (arp_pkt) - pAdapter->dad |= hdd_is_duplicate_ip_arp(skb); + { + pAdapter->dad = hdd_is_duplicate_ip_arp(skb); + if(pAdapter->dad) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s :Duplicate IP detected",__func__); + } #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION, @@ -2864,11 +2881,9 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, if (arp_pkt) { - if (track_arp_resp) { - ++pAdapter->hdd_stats.hddArpStats.rxDelivered; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "STA RX ARP packet Delivered to net stack"); - } + ++pAdapter->hdd_stats.hddArpStats.rxDelivered; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "STA RX ARP packet Delivered to net stack"); } ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered; @@ -3040,6 +3055,74 @@ void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx) return; } +/** + * hdd_rx_fwd_eapol() - forward cached eapol frames + * @vosContext : pointer to vos global context + * @pVosPacket: pointer to vos packet + * + * Return: None + * + */ +void hdd_rx_fwd_eapol(v_VOID_t *vosContext, vos_pkt_t *pVosPacket) +{ + hdd_context_t *pHddCtx = NULL; + hdd_adapter_t * pAdapter; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + struct sk_buff *skb = NULL; + uint8_t proto_type; + uint8_t status; + + if ((NULL == vosContext) || (NULL == pVosPacket)) + { + VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: Null global context", __func__); + return; + } + + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vosContext); + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: HDD adapter context is Null", __func__); + return; + } + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && 0 == status ) + { + pAdapter = pAdapterNode->pAdapter; + + if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) + break; + + status = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR, + "%s: No adapter", __func__); + return; + } + + vos_pkt_get_os_packet(pVosPacket, (v_VOID_t **)&skb, VOS_FALSE); + proto_type = vos_pkt_get_proto_type(skb, + pHddCtx->cfg_ini->gEnableDebugLog); + if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "STA RX EAPOL"); + } + + skb->dev = pAdapter->dev; + skb->protocol = eth_type_trans(skb, skb->dev); + skb->ip_summed = CHECKSUM_NONE; + + netif_rx_ni(skb); +} + #ifdef FEATURE_WLAN_DIAG_SUPPORT /* * wlan_hdd_get_eapol_params() - Function to extract EAPOL params diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c index 5cadb459d21..fbd52e7ef7d 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c @@ -174,6 +174,9 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #define WE_SET_MONITOR_STATE 22 #define WE_SET_PKT_STATS_ENABLE_DISABLE 23 #define WE_SET_PROXIMITY_ENABLE 24 +#define WE_CAP_TSF 25 +#define WE_SET_MODULATED_DTIM 26 +#define WLAN_SET_DYNNAMIC_AGGREGATION 27 /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_NONE_GET_INT (SIOCIWFIRSTPRIV + 1) @@ -295,7 +298,8 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, /* (SIOCIWFIRSTPRIV + 10) is currently unused */ /* (SIOCIWFIRSTPRIV + 12) is currently unused */ /* (SIOCIWFIRSTPRIV + 14) is currently unused */ -/* (SIOCIWFIRSTPRIV + 15) is currently unused */ +#define WLAN_PRIV_SET_NONE_GET_THREE_INT (SIOCIWFIRSTPRIV + 15) +#define WE_GET_TSF 1 #ifdef FEATURE_OEM_DATA_SUPPORT /* Private ioctls for setting the measurement configuration */ @@ -387,6 +391,9 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #define TX_PWR_MAX 22 #define TX_PWR_DEF 50 +/* Dynamic Aggregation */ +#define DISABLE_AGGREGATION 0 +#define ENABLE_AGGREGATION 1 /* * When supplicant sends SETBAND ioctl it queries for channels from * cfg80211 layer by sending itself EVENT_CHANNEL_LIST_CHANGED command. @@ -1107,6 +1114,8 @@ VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) spin_unlock(&hdd_context_lock); *rssi_value = pAdapter->rssi; + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: RSSI = %d", __func__, *rssi_value); return VOS_STATUS_SUCCESS; } @@ -1635,7 +1644,7 @@ v_U8_t* wlan_hdd_get_vendor_oui_ie_ptr(v_U8_t *oui, v_U8_t oui_size, v_U8_t *ie, eid,elem_len,left); return NULL; } - if (elem_id == eid) + if ((elem_id == eid) && (elem_len >= oui_size)) { if(memcmp( &ptr[2], oui, oui_size)==0) return ptr; @@ -3584,10 +3593,12 @@ static void hdd_get_station_statisticsCB(void *pStats, void *pContext) VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) { - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_station_ctx_t *pHddStaCtx; + hdd_ap_ctx_t *sap_ctx; eHalStatus hstatus; long lrc; struct statsContext context; + tANI_U8 sta_id; if (NULL == pAdapter) { @@ -3595,6 +3606,14 @@ VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) return VOS_STATUS_SUCCESS; } + if (pAdapter->device_mode == WLAN_HDD_SOFTAP) { + sap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); + sta_id = sap_ctx->uBCStaId; + } else { + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + sta_id = pHddStaCtx->conn_info.staId[0]; + } + /* we are connected prepare our callback context */ init_completion(&context.completion); @@ -3610,7 +3629,7 @@ VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter) hdd_get_station_statisticsCB, 0, // not periodic FALSE, //non-cached results - pHddStaCtx->conn_info.staId[0], + sta_id, &context); if (eHAL_STATUS_SUCCESS != hstatus) { @@ -3808,6 +3827,7 @@ static int iw_get_rssi(struct net_device *dev, (note that it is not NUL-terminated) */ memcpy(cmd, pHddStaCtx->conn_info.SSID.SSID.ssId, ssidlen ); + wlan_hdd_get_station_stats(pAdapter); vosStatus = wlan_hdd_get_rssi(pAdapter, &s7Rssi); if (VOS_STATUS_SUCCESS == vosStatus) @@ -5572,7 +5592,7 @@ static int iw_set_mlme(struct net_device *dev, return ret; } -int wlan_hdd_set_proximity(int set_value) +int wlan_hdd_set_proximity(int set_value, tHalHandle hal) { sHwCalValues hwCalValues; uint16 hwCalTxPower; @@ -5593,12 +5613,14 @@ int wlan_hdd_set_proximity(int set_value) txPwr = (int8)(hwCalTxPower & 0x00FF); txPwr = txPwr/10; - if (txPwr < TX_PWR_MIN) + if (txPwr == 0) + txPwr = TX_PWR_DEF; + else if (txPwr < TX_PWR_MIN) txPwr = TX_PWR_MIN; - if (txPwr > TX_PWR_MAX) + else if (txPwr > TX_PWR_MAX) txPwr = TX_PWR_MAX; - if (sme_SetMaxTxPowerPerBand(eCSR_BAND_24, txPwr) != + if (sme_SetMaxTxPowerPerBand(eCSR_BAND_24, txPwr, hal) != eHAL_STATUS_SUCCESS) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("Setting tx power failed for 2.4GHz band %d"), txPwr); @@ -5607,12 +5629,14 @@ int wlan_hdd_set_proximity(int set_value) txPwr = (int8)((hwCalTxPower >> 8) & 0x00FF); txPwr /= 10; - if (txPwr < TX_PWR_MIN) + if (txPwr == 0) + txPwr = TX_PWR_DEF; + else if (txPwr < TX_PWR_MIN) txPwr = TX_PWR_MIN; - if (txPwr > TX_PWR_MAX) + else if (txPwr > TX_PWR_MAX) txPwr = TX_PWR_MAX; - if (sme_SetMaxTxPowerPerBand(eCSR_BAND_5G, txPwr) != + if (sme_SetMaxTxPowerPerBand(eCSR_BAND_5G, txPwr, hal) != eHAL_STATUS_SUCCESS) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("setting tx power failed for 5GHz band %d"), txPwr); @@ -5620,14 +5644,14 @@ int wlan_hdd_set_proximity(int set_value) } } else if(FALSE == set_value) { - if (sme_SetMaxTxPowerPerBand(eCSR_BAND_24, txPwr) != + if (sme_SetMaxTxPowerPerBand(eCSR_BAND_24, txPwr, hal) != eHAL_STATUS_SUCCESS) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("Setting tx power failed for 2.4GHz band %d"), txPwr); return -EIO; } - if (sme_SetMaxTxPowerPerBand(eCSR_BAND_5G, txPwr) != + if (sme_SetMaxTxPowerPerBand(eCSR_BAND_5G, txPwr, hal) != eHAL_STATUS_SUCCESS) { hddLog(VOS_TRACE_LEVEL_ERROR, FL("setting tx power failed for 5GHz band %d"), txPwr); @@ -5640,6 +5664,42 @@ int wlan_hdd_set_proximity(int set_value) return eHAL_STATUS_SUCCESS; } + +static int hdd_set_dynamic_aggregation(int value, hdd_adapter_t *adapter) +{ + int ret = 0; + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); + tDelBaParams del_session; + + del_session.session_id = adapter->sessionId; + hddLog(LOG1, FL("WLAN_SET_DYNNAMIC_AGGREGATION: %d"), value); + + if ((value == DISABLE_AGGREGATION) || (value == ENABLE_AGGREGATION)) + { + ret = ccmCfgSetInt(hal, WNI_CFG_ENABLE_TX_RX_AGGREGATION, + value,NULL, eANI_BOOLEAN_FALSE); + if (ret != eHAL_STATUS_SUCCESS) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("failed to set ini parameter, WNI_CFG_ENABLE_TX_RX_AGGREGATION")); + return -EIO; + } + + } else { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Invalid command input")); + return -EINVAL; + } + ret = sme_del_sta_ba_session_req(hal, del_session); + if (ret != VOS_STATUS_SUCCESS) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("send ba session req fail")); + return -EINVAL; + } + + EXIT(); + return ret; +} + /* set param sub-ioctls */ static int __iw_setint_getnone(struct net_device *dev, struct iw_request_info *info, @@ -5994,10 +6054,13 @@ static int __iw_setint_getnone(struct net_device *dev, } case WE_SET_MAX_TX_POWER_2_4: { + if (NULL == hHal) + return -EINVAL; + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Setting maximum tx power %d dBm for 2.4 GHz band", __func__, set_value); - if (sme_SetMaxTxPowerPerBand(eCSR_BAND_24, set_value) != + if (sme_SetMaxTxPowerPerBand(eCSR_BAND_24, set_value, hHal) != eHAL_STATUS_SUCCESS) { hddLog(VOS_TRACE_LEVEL_ERROR, @@ -6010,10 +6073,13 @@ static int __iw_setint_getnone(struct net_device *dev, } case WE_SET_MAX_TX_POWER_5_0: { + if (NULL == hHal) + return -EINVAL; + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Setting maximum tx power %d dBm for 5.0 GHz band", __func__, set_value); - if (sme_SetMaxTxPowerPerBand(eCSR_BAND_5G, set_value) != + if (sme_SetMaxTxPowerPerBand(eCSR_BAND_5G, set_value, hHal) != eHAL_STATUS_SUCCESS) { hddLog(VOS_TRACE_LEVEL_ERROR, @@ -6317,7 +6383,38 @@ static int __iw_setint_getnone(struct net_device *dev, } case WE_SET_PROXIMITY_ENABLE: { - ret = wlan_hdd_set_proximity(set_value); + if (NULL == hHal) + return -EINVAL; + + ret = wlan_hdd_set_proximity(set_value, hHal); + break; + } + case WE_CAP_TSF: + { + if (NULL == hHal) + return -EINVAL; + + ret = hdd_capture_tsf(pAdapter, (uint32_t *)&set_value, 1); + break; + } + case WE_SET_MODULATED_DTIM: + { + if ((set_value < CFG_ENABLE_MODULATED_DTIM_MIN) || + (set_value > CFG_ENABLE_MODULATED_DTIM_MAX)) { + hddLog(LOGE, FL("Invalid value %d in gEnableModuleDTIM"), + set_value); + return -EINVAL; + } else { + ret = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini-> + enableModulatedDTIM = set_value; + } + } + case WLAN_SET_DYNNAMIC_AGGREGATION: + { + if (NULL == hHal) + return -EINVAL; + + ret = hdd_set_dynamic_aggregation(set_value, pAdapter); break; } default: @@ -7020,10 +7117,10 @@ static int __iw_get_char_setnone(struct net_device *dev, pResetStats->totalFWHearbeatFailures, pResetStats->totalUnknownExceptions, - parpStats->tx_arp_req_count, + parpStats->txCount, parpStats->txDropped, - parpStats->rx_arp_rsp_count, + parpStats->rxCount, parpStats->rxDropped, parpStats->rxDelivered, parpStats->rxRefused, @@ -8480,6 +8577,62 @@ static int iw_get_tspec(struct net_device *dev, return ret; } +/** + * __iw_setnone_get_threeint() - return three value to up layer. + * + * @dev: pointer of net_device of this wireless card + * @info: meta data about Request sent + * @wrqu: include request info + * @extra: buf used for in/Output + * + * Return: execute result + */ +static int __iw_setnone_get_threeint(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret = 0; /* success */ + uint32_t *value = (int *)extra; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + + hddLog(VOS_TRACE_LEVEL_INFO, FL("param = %d"), value[0]); + + switch (value[0]) { + case WE_GET_TSF: + ret = hdd_indicate_tsf(adapter, value, 3); + break; + default: + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Invalid IOCTL get_value command %d"), + value[0]); + break; + } + return ret; +} + +/** + * iw_setnone_get_threeint() - return three value to up layer. + * + * @dev: pointer of net_device of this wireless card + * @info: meta data about Request sent + * @wrqu: include request info + * @extra: buf used for in/Output + * + * Return: execute result + */ +static int iw_setnone_get_threeint(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + vos_ssr_protect(__func__); + ret = __iw_setnone_get_threeint(dev, info, wrqu, extra); + vos_ssr_unprotect(__func__); + + return ret; +} + #ifdef WLAN_FEATURE_VOWIFI_11R // // @@ -10909,7 +11062,6 @@ int iw_set_tdlsoffchannelmode(hdd_adapter_t *pAdapter, int offchanmode) } #endif - // Define the Wireless Extensions to the Linux Network Device structure // A number of these routines are NULL (meaning they are not implemented.) @@ -10984,6 +11136,8 @@ static const iw_handler we_private[] = { [WLAN_PRIV_ADD_TSPEC - SIOCIWFIRSTPRIV] = iw_add_tspec, [WLAN_PRIV_DEL_TSPEC - SIOCIWFIRSTPRIV] = iw_del_tspec, [WLAN_PRIV_GET_TSPEC - SIOCIWFIRSTPRIV] = iw_get_tspec, + [WLAN_PRIV_SET_NONE_GET_THREE_INT - SIOCIWFIRSTPRIV] = + iw_setnone_get_threeint, #ifdef FEATURE_OEM_DATA_SUPPORT [WLAN_PRIV_SET_OEM_DATA_REQ - SIOCIWFIRSTPRIV] = iw_set_oem_data_req, //oem data req Specifc [WLAN_PRIV_GET_OEM_DATA_RSP - SIOCIWFIRSTPRIV] = iw_get_oem_data_rsp, //oem data req Specifc @@ -11146,6 +11300,20 @@ static const struct iw_priv_args we_private_args[] = { { WE_SET_PROXIMITY_ENABLE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setProximity" }, + +#ifdef WLAN_FEATURE_TSF + { WE_CAP_TSF, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "cap_tsf" }, +#endif + { WE_SET_MODULATED_DTIM, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "setModDTIM" }, + { + WLAN_SET_DYNNAMIC_AGGREGATION, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "setAggregation" }, + /* handlers for main ioctl */ { WLAN_PRIV_SET_NONE_GET_INT, 0, @@ -11502,7 +11670,17 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getTspec" }, - + /* handlers for main ioctl */ + { WLAN_PRIV_SET_NONE_GET_THREE_INT, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + "" }, +#ifdef WLAN_FEATURE_TSF + { WE_GET_TSF, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + "get_tsf" }, +#endif #ifdef FEATURE_OEM_DATA_SUPPORT /* handlers for main ioctl - OEM DATA */ { @@ -11577,6 +11755,10 @@ static const struct iw_priv_args we_private_args[] = { WLAN_GET_LINK_SPEED, IW_PRIV_TYPE_CHAR | 18, IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" }, + { + WLAN_PRIV_SET_FTIES, + IW_PRIV_TYPE_CHAR | MAX_FTIE_SIZE, + 0, "set_ft_ies"}, }; diff --git a/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h b/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h index 6c4d59bea0b..5257cfb6981 100644 --- a/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h +++ b/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h @@ -44,12 +44,6 @@ #ifndef _ANIGLOBAL_H #define _ANIGLOBAL_H -// Take care to avoid redefinition of this type, if it is -// already defined in "halWmmApi.h" -#if !defined(_HALMAC_WMM_API_H) -typedef struct sAniSirGlobal *tpAniSirGlobal; -#endif - #include "halTypes.h" #include "sirCommon.h" #include "aniSystemDefs.h" @@ -230,6 +224,11 @@ typedef struct sLimTimers TX_TIMER gLimFTPreAuthRspTimer; #endif +#ifdef WLAN_FEATURE_LFR_MBB + TX_TIMER glim_pre_auth_mbb_rsp_timer; + TX_TIMER glim_reassoc_mbb_rsp_timer; +#endif + #ifdef FEATURE_WLAN_ESE TX_TIMER gLimEseTsmTimer; #endif @@ -260,12 +259,6 @@ typedef struct { v_TIME_t failed_timestamp[MAX_TIDS]; } tLimStaBAInfo; -typedef struct { - bool tx_aggr; - uint8_t sta_id; - uint8_t tid; -} t_test_status_bainfo; - typedef struct sAniSirLim { ////////////////////////////////////// TIMER RELATED START /////////////////////////////////////////// @@ -920,7 +913,6 @@ tLimMlmOemDataRsp *gpLimMlmOemDataRsp; tANI_U32 txBdToken; tANI_U32 EnableTdls2040BSSCoexIE; tLimStaBAInfo staBaInfo[WLAN_MAX_STA_COUNT]; - t_test_status_bainfo test_status_bainfo; } tAniSirLim, *tpAniSirLim; typedef struct sLimMgmtFrameRegistration @@ -948,6 +940,14 @@ typedef struct sFTContext } tftContext, *tpFTContext; #endif +typedef struct assoc_rsp_tx_context +{ + vos_list_node_t node; + tANI_U8 psessionID; + tANI_U16 staId; + tANI_U32 txBdToken; +} assoc_rsp_tx_context; + //Check if this definition can actually move here even for Volans. In that case //this featurization can be removed. /** ------------------------------------------------------------------------- * @@ -1052,7 +1052,7 @@ typedef struct sAniSirGlobal #if defined WLAN_FEATURE_VOWIFI_11R tftContext ft; #endif - + vos_list_t assoc_rsp_completion_list; tANI_U32 gCurrentLogSize; tANI_U32 menuCurrent; /* logDump specific */ @@ -1093,7 +1093,12 @@ typedef struct sAniSirGlobal v_U32_t PERroamTimeout; v_U32_t currentBssScore; #endif +#ifdef SAP_AUTH_OFFLOAD + bool sap_auth_offload; + uint32_t sap_auth_offload_sec_type; +#endif /* SAP_AUTH_OFFLOAD */ bool max_power_cmd_pending; + uint32_t sta_auth_retries_for_code17; } tAniSirGlobal; #ifdef FEATURE_WLAN_TDLS diff --git a/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h b/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h index d49b49462d9..07a6af758a8 100644 --- a/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h +++ b/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h @@ -44,8 +44,8 @@ BRIEF DESCRIPTION: #define QWLAN_VERSION_PATCH 11 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 66 +#define QWLAN_VERSION_BUILD 85 -#define QWLAN_VERSIONSTR "3.0.11.66" +#define QWLAN_VERSIONSTR "3.0.11.85" #endif /* QWLAN_VERSION_H */ diff --git a/drivers/staging/prima/CORE/MAC/inc/sirApi.h b/drivers/staging/prima/CORE/MAC/inc/sirApi.h index f1d59c42b08..de0f9cc7ebb 100644 --- a/drivers/staging/prima/CORE/MAC/inc/sirApi.h +++ b/drivers/staging/prima/CORE/MAC/inc/sirApi.h @@ -41,10 +41,18 @@ #ifndef __SIR_API_H #define __SIR_API_H +/* Take care to avoid redefinition of this type, if it is */ +/* already defined in "halWmmApi.h" */ +#if !defined(_HALMAC_WMM_API_H) +typedef struct sAniSirGlobal *tpAniSirGlobal; +#endif + + #include "sirTypes.h" #include "sirMacProtDef.h" #include "aniSystemDefs.h" #include "sirParams.h" +#include <dot11f.h> #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) #include "eseGlobal.h" @@ -756,6 +764,13 @@ typedef struct sSirSmeStartBssRsp tSirBssDescription bssDescription;//Peer BSS description } tSirSmeStartBssRsp, *tpSirSmeStartBssRsp; +#ifdef WLAN_FEATURE_APFIND +struct hal_apfind_request +{ + tANI_U16 request_data_len; + tANI_U8 request_data[]; +}; +#endif typedef struct sSirChannelList { @@ -1110,6 +1125,7 @@ typedef struct sSirSmeJoinReq tAniBool spectrumMgtIndicator; tSirMacPowerCapInfo powerCap; tSirSupChnl supportedChannels; + bool force_24ghz_in_ht20; tSirBssDescription bssDescription; } tSirSmeJoinReq, *tpSirSmeJoinReq; @@ -1149,6 +1165,12 @@ typedef struct sSirSmeJoinRsp /*to report MAX link-speed populate rate-flags from ASSOC RSP frame*/ tANI_U32 maxRateFlags; + tDot11fIEHTCaps ht_caps; + tDot11fIEVHTCaps vht_caps; + tDot11fIEHTInfo ht_operation; + tDot11fIEVHTOperation vht_operation; + tDot11fIEhs20vendor_ie hs20vendor_ie; + tANI_U8 frames[ 1 ]; } tSirSmeJoinRsp, *tpSirSmeJoinRsp; @@ -2928,10 +2950,11 @@ typedef struct sSmeDelBAPeerInd // Message Type tANI_U16 mesgType; + tSirMacAddr bssId;//BSSID + // Message Length tANI_U16 mesgLen; - tSirMacAddr bssId;//BSSID // Station Index tANI_U16 staIdx; @@ -3751,9 +3774,13 @@ typedef struct sSirNoAParam tANI_U8 psSelection; }tSirNoAParam, *tpSirNoAParam; +typedef void(*wlan_suspend_req_cb)(void *ptr, VOS_STATUS status); + typedef struct sSirWlanSuspendParam { tANI_U8 configuredMcstBcstFilterSetting; + wlan_suspend_req_cb wlan_sus_callback; + void *context; }tSirWlanSuspendParam,*tpSirWlanSuspendParam; typedef struct sSirWlanResumeParam @@ -3834,11 +3861,17 @@ typedef struct { void *data_ctx; } getArpStatsParams, *pgetArpStatsParams; + typedef void(*FWLoggingInitReqCb)(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp); typedef void ( *tGetFrameLogCallback) (void *pContext); typedef void(*RssiMonitorReqCb)(void *rssiMonitorCbContext, VOS_STATUS status); typedef void(*pktFilterReqCb)(void *data, tANI_U32 status); - +typedef void(*dhcp_offload_req_cb)(void *rssiMonitorCbContext, + VOS_STATUS status); +typedef void(*mdns_enable_req_cb)(void *mdns_enable_cb_context, + VOS_STATUS status); +typedef void(*mdns_fqdn_req_cb)(void *mdns_fqdn_cb_context, VOS_STATUS status); +typedef void(*mdns_resp_req_cb)(void *mdns_resp_cb_context, VOS_STATUS status); typedef struct sAniGetFrameLogReq { @@ -4100,6 +4133,7 @@ typedef struct sSirRoamOffloadScanReq tANI_U8 p5GProbeTemplate[SIR_ROAM_SCAN_MAX_PB_REQ_SIZE]; tANI_U8 nProbes; tANI_U16 HomeAwayTime; + tANI_U8 WeakZoneRssiThresholdForRoam; tSirRoamNetworkType ConnectedNetwork; tSirMobilityDomainInfo MDID; } tSirRoamOffloadScanReq, *tpSirRoamOffloadScanReq; @@ -5612,6 +5646,65 @@ typedef PACKED_PRE struct PACKED_POST tSirWifiScanResult bssHotlist[1]; } tSirEXTScanHotlistMatch, *tpSirEXTScanHotlistMatch; +#ifdef DHCP_SERVER_OFFLOAD +/** + * sir_dhcp_srv_offload_info_t - dhcp server offload info + * @bssidx: bss index + * @dhcp_srv_offload_enabled: enable or disable + * @dhcp_client_num: number of clients supported + * @dhcp_srv_ip: server ip address + * @start_lsb: lsb of start address of dhcp pool + */ +typedef struct +{ + tANI_U8 bssidx; + tANI_U32 dhcp_srv_offload_enabled; + tANI_U32 dhcp_client_num; + tANI_U32 dhcp_srv_ip; + tANI_U32 start_lsb; + dhcp_offload_req_cb dhcp_offload_callback; + void *dhcp_server_offload_cb_context; +} sir_dhcp_srv_offload_info_t, *sir_dhcp_srv_offload_info; +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +#define MAX_MDNS_FQDN_LEN 64 +#define MAX_MDNS_RESP_LEN 512 + +typedef struct +{ + tANI_U8 bss_idx; + tANI_U32 enable; + mdns_enable_req_cb mdns_enable_callback; + void *mdns_enable_cb_context; +} sir_mdns_offload_info_t, *sir_mdns_offload_info; + +typedef struct +{ + tANI_U8 bss_idx; + tANI_U32 fqdn_type; + tANI_U32 fqdn_len; + tANI_U8 fqdn_data[MAX_MDNS_FQDN_LEN]; + mdns_fqdn_req_cb mdns_fqdn_callback; + void *mdns_fqdn_cb_context; + +} sir_mdns_fqdn_info_t, *sir_mdns_fqdn_info; + +typedef struct +{ + tANI_U8 bss_idx; + tANI_U32 resourceRecord_count; + tANI_U32 resp_len; + tANI_U8 resp_data[MAX_MDNS_RESP_LEN]; + mdns_resp_req_cb mdns_resp_callback; + void *mdns_resp_cb_context; +} sir_mdns_resp_info_t, *sir_mdns_resp_info; + +typedef struct +{ + tANI_U8 bss_idx; +} sir_get_mdns_stats_info_t, *sir_get_mdns_stats_info; +#endif /* MDNS_OFFLOAD */ typedef PACKED_PRE struct PACKED_POST { @@ -6050,11 +6143,188 @@ typedef struct { tANI_U32 value; } tModifyRoamParamsReqParams, * tpModifyRoamParamsReqParams; -typedef void(*hdd_conAliveCb)(void *data, bool status); +#ifdef SAP_AUTH_OFFLOAD +/* 80211 Pre-Share Key length */ +#define SIR_PSK_MAX_LEN 64 +/** + * enum tSirSecurityType - definition for Software AP Auth Offload + * Security Type + * @eSIR_OFFLOAD_NONE: None type security + * @eSIR_OFFLOAD_WPA2PSK_CCMP: WPA2-PSK + */ +enum tSirSecurityType +{ + eSIR_OFFLOAD_NONE, + eSIR_OFFLOAD_WPA2PSK_CCMP, +}; + +/** + * struct tSirSapOffloadInfo - Structure to store sap offload related params. + * @macAddr: Self mac address + * @sap_auth_offload_enable: tell if sap auth offload is enabled or not. + * @sap_auth_offload_sec_type: tells security type + * 0 - none + * 1 - WPA1-PSK + * @key_len: psk key length + * @key: psk key. + */ +struct tSirSapOffloadInfo +{ + tSirMacAddr macAddr; + bool sap_auth_offload_enable; + uint32_t sap_auth_offload_sec_type; + uint32_t key_len; + uint8_t key[SIR_PSK_MAX_LEN]; +}; + +typedef PACKED_PRE struct PACKED_POST +{ + /** staId returned from firmware for each STA association to SAP */ + tANI_U8 staIdx; + /** bssIdx on which the STA is added */ + tANI_U8 bssIdx; + /** DPU desc index of this station */ + tANI_U8 dpuIndex; + /** Bcast DPU index of this station */ + tANI_U8 bcastDpuIndex; + /** Bcast DPU Management index of this station */ + tANI_U8 bcastMgmtDpuIdx; + + tANI_U8 ucUcastSig; + + tANI_U8 ucBcastSig; + + tANI_U8 ucMgmtSig; + /** aid (association id) of this station */ + tANI_U32 assoc_id; + /** peer station's mac addr */ + tSirMacAddr peer_macaddr; + /** length of association request frame */ + tANI_U32 data_len; + /* Following this structure is the byte stream of a whole + * association request frame of length data_len + */ + tANI_U8 bufp[1]; +} tSapOfldAddStaIndMsg, *tpSapOfldAddStaIndMsg; + +typedef enum +{ + SAP_OFL_DEL_STA_FLAG_NONE = 0x00, + SAP_OFL_DEL_STA_FLAG_RECONNECT = 0x01, +} eSapOfldDelStaFlags; + +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U32 staIdx; + /** bssIdx on which the STA is added */ + tANI_U32 bssIdx; + /** aid (association id) of this station */ + tANI_U32 assoc_id; + /** peer station's mac addr */ + tSirMacAddr peer_macaddr; + /** disassociation reason */ + tANI_U32 reason; + /** flags - wmi_sap_ofl_del_sta_flags */ + tANI_U32 flags; +} tSapOfldDelStaIndMsg, *tpSapOfldDelStaIndMsg; + +typedef enum +{ + SAP_OFFLOAD_ADD_STA_IND = 0x00, + SAP_OFFLOAD_DEL_STA_IND = 0x01, +} eSapOfldIndType; + +typedef PACKED_PRE struct PACKED_POST +{ + /* indType will be from eSapOfldIndType */ + tANI_U32 indType; + /* size of this array will be depend on the indication type. + * Indication type can be either ADD_STA_IND or DEL_STA_IND. + * If indication type is ADD_STA_IND, size of this indication + * array will be sizeof(tSapOfldDelStaIndMsg) + * and if indication type is DEL_STA_IND, size of this indication + * arrary will be sizeof(tSapOfldAddStaIndMsg) + */ + tANI_U8 indication[1]; +} tSapOfldInd; + +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U32 num_indications; + /* size of this array will be depend on the number of indications.*/ + tSapOfldInd indications[1]; +}tSapOfldIndications; + +#endif /* SAP_AUTH_OFFLOAD */ + +/** + * struct stsf - the basic stsf structure + * + * @session_id: session id from adapter + * @set_req: set/get request flag. + * @tsf_low: low 32bits of tsf + * @tsf_high: high 32bits of tsf + * + * driver use this struct to store the tsf info + */ +struct stsf { + uint32_t session_id; + bool set_tsf_req; + uint32_t tsf_low; + uint32_t tsf_high; + bool tsf_req_status; +}; + +typedef int(*tsf_rsp_cb)(void *tsf_ctx, struct stsf *pTsf); + +/** + * struct tCapTsfParams - capture tsf request + * @bss_idx: bss index, SAP/STA + * @session_id: adapter session id + * @bssid: bssid for SAP/STA + * @tsf_rsp_cb_func : handler for tsf rsp from fw + * @tsf_rsp_cb_ctx : hdd ctx for tsf rsp handler + */ typedef struct { - hdd_conAliveCb rsp_cb_fn; - void *data_ctx; -}getConStatusParams, *pgetConStatusParams; + tANI_U8 bss_idx; + tANI_U8 session_id; + tSirMacAddr bssid; + tsf_rsp_cb tsf_rsp_cb_func; + void * tsf_rsp_cb_ctx; +}tSirCapTsfParams,*tpSirCapTsfParams; + +#ifdef WLAN_FEATURE_LFR_MBB + +/** + * enum csr_roam_op_code - Operation to be done by the callback. + * @SIR_ROAMING_DEREGISTER_STA: Deregister the old STA after roaming. + * @SIR_STOP_ROAM_OFFLOAD_SCAN : sends RSO stop + * @SIR_PREPARE_REASSOC_REQ: prepares reassoc request + */ +enum csr_roam_op_code { + SIR_ROAMING_DEREGISTER_STA, + SIR_STOP_ROAM_OFFLOAD_SCAN, + SIR_PREPARE_REASSOC_REQ, +}; + +/** + * enum sir_roam_cleanup_type - Type of cleanup needs to be performed. + * @SIR_MBB_DISCONNECTED: Entire CSR cleanup for connected AP + * needs to be performed + * @SIR_MBB_CONNECTED: No need to perform CSR cleanup for connected AP. + */ +enum sir_roam_cleanup_type { + SIR_MBB_DISCONNECTED, + SIR_MBB_CONNECTED, +}; +#endif +/** + * struct tDelBaParams - Del BA Session req + * @session_id: adapter session id + */ +typedef struct { + tANI_U8 session_id; +}tDelBaParams,*ptDelBaParams; #endif /* __SIR_API_H */ diff --git a/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h b/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h index 75c73e44102..52c172a78d7 100644 --- a/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h +++ b/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h @@ -598,8 +598,13 @@ #define SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS 4 #define SIR_MAC_KEY_LENGTH 13 // WEP Maximum key length size #define SIR_MAC_AUTH_CHALLENGE_LENGTH 253 +#define SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH 128 #define SIR_MAC_WEP_IV_LENGTH 4 #define SIR_MAC_WEP_ICV_LENGTH 4 +#define SIR_MAC_CHALLENGE_ID_LEN 2 + +/* 2 bytes each for auth algo number, transaction number and status code */ +#define SIR_MAC_AUTH_FRAME_INFO_LEN 6 /// MAX key length when ULA is used #define SIR_MAC_MAX_KEY_LENGTH 32 diff --git a/drivers/staging/prima/CORE/MAC/inc/wniApi.h b/drivers/staging/prima/CORE/MAC/inc/wniApi.h index bdea77c7c0c..6445286ce06 100644 --- a/drivers/staging/prima/CORE/MAC/inc/wniApi.h +++ b/drivers/staging/prima/CORE/MAC/inc/wniApi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -235,7 +235,6 @@ enum eWniMsgTypes eWNI_SME_PRE_CHANNEL_SWITCH_FULL_POWER, eWNI_SME_GET_SNR_REQ, eWNI_SME_LOST_LINK_PARAMS_IND, - eWNI_SME_DEL_TEST_BA, //General Power Save Messages eWNI_PMC_MSG_TYPES_BEGIN, eWNI_PMC_PWR_SAVE_CFG, @@ -388,6 +387,15 @@ enum eWniMsgTypes eWNI_SME_SET_TDLS_2040_BSSCOEX_REQ, eWNI_SME_DEL_ALL_TDLS_PEERS, eWNI_SME_REGISTER_MGMT_FRAME_CB, + eWNI_SME_CAP_TSF_REQ, + eWNI_SME_GET_TSF_REQ, + +#ifdef WLAN_FEATURE_LFR_MBB + eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ, + eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP, +#endif + + eWNI_SME_DEL_BA_SES_REQ, eWNI_SME_MSG_TYPES_END }; diff --git a/drivers/staging/prima/CORE/MAC/inc/wniCfg.h b/drivers/staging/prima/CORE/MAC/inc/wniCfg.h index a6557506534..4db2054360c 100644 --- a/drivers/staging/prima/CORE/MAC/inc/wniCfg.h +++ b/drivers/staging/prima/CORE/MAC/inc/wniCfg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -394,7 +394,10 @@ enum { WNI_CFG_SAR_BOFFSET_SET_CORRECTION, WNI_CFG_ENABLE_UNITS_BWAIT, WNI_CFG_ENABLE_CONC_BMISS, - WNI_CFG_DISABLE_SCAN_DURING_SCO + WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL, + WNI_CFG_DISABLE_SCAN_DURING_SCO, + WNI_CFG_ENABLE_TX_RX_AGGREGATION, + WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB }; /* @@ -760,7 +763,7 @@ enum { #define WNI_CFG_MAX_NUM_PRE_AUTH_STADEF 64 #define WNI_CFG_HEART_BEAT_THRESHOLD_STAMIN 0 -#define WNI_CFG_HEART_BEAT_THRESHOLD_STAMAX 65535 +#define WNI_CFG_HEART_BEAT_THRESHOLD_STAMAX 256 #define WNI_CFG_HEART_BEAT_THRESHOLD_STADEF 40 #define WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT_STAMIN 10 @@ -1805,7 +1808,7 @@ enum { #define WNI_CFG_RA_FILTER_ENABLE_STADEF 0 #define WNI_CFG_RA_RATE_LIMIT_INTERVAL_STAMIN 0 -#define WNI_CFG_RA_RATE_LIMIT_INTERVAL_STAMAX 60 +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL_STAMAX 3600 #define WNI_CFG_RA_RATE_LIMIT_INTERVAL_STADEF 60 #define WNI_CFG_BTC_FATAL_HID_NSNIFF_BLK_GUIDANCE_STAMIN 0 @@ -1895,6 +1898,10 @@ enum { #define WNI_CFG_BTC_STATIC_OPP_WLAN_IDLE_BT_LEN_MAX 250000 #define WNI_CFG_BTC_STATIC_OPP_WLAN_IDLE_BT_LEN_DEF 40000 +#define WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_MIN 0 +#define WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_MAX 1 +#define WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_DEF 0 + #define WNI_CFG_LINK_FAIL_TIMEOUT_MIN 1000 #define WNI_CFG_LINK_FAIL_TIMEOUT_MAX 60000 #define WNI_CFG_LINK_FAIL_TIMEOUT_DEF 6000 @@ -1931,8 +1938,16 @@ enum { #define WNI_CFG_DISABLE_SCAN_DURING_SCO_MAX 1 #define WNI_CFG_DISABLE_SCAN_DURING_SCO_DEF 0 -#define CFG_PARAM_MAX_NUM 361 -#define CFG_STA_IBUF_MAX_SIZE 295 +#define WNI_CFG_ENABLE_TX_RX_AGGREGATION_MIN 0 +#define WNI_CFG_ENABLE_TX_RX_AGGREGATION_MAX 1 +#define WNI_CFG_ENABLE_TX_RX_AGGREGATION_DEF 1 + +#define WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB_MIN 0 +#define WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB_MAX 1 +#define WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB_DEF 0 + +#define CFG_PARAM_MAX_NUM 364 +#define CFG_STA_IBUF_MAX_SIZE 298 #define CFG_STA_SBUF_MAX_SIZE 3389 #define CFG_STA_MAGIC_DWORD 0xbeefbeef diff --git a/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c b/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c index 9047d3a7a21..b4c260b96b9 100644 --- a/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c +++ b/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c @@ -957,6 +957,17 @@ cfgGetCapabilityInfo(tpAniSirGlobal pMac, tANI_U16 *pCap,tpPESession sessionEntr if(systemRole == eLIM_AP_ROLE) { val = sessionEntry->privacy; +#ifdef SAP_AUTH_OFFLOAD + /* Support SAP Authentication Offload feature, + * If Auth offload security Type is not disabled + * driver need to enable privacy bit in beacon + */ + if (pMac->sap_auth_offload && pMac->sap_auth_offload_sec_type) + { + val = 1; + } +#endif + } else { diff --git a/drivers/staging/prima/CORE/MAC/src/cfg/cfgProcMsg.c b/drivers/staging/prima/CORE/MAC/src/cfg/cfgProcMsg.c index 999bd5976b7..43bcf084824 100644 --- a/drivers/staging/prima/CORE/MAC/src/cfg/cfgProcMsg.c +++ b/drivers/staging/prima/CORE/MAC/src/cfg/cfgProcMsg.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1703,6 +1703,16 @@ tAniSirCgStatic cfgStatic[CFG_PARAM_MAX_NUM] = WNI_CFG_SAR_BOFFSET_SET_CORRECTION_MIN, WNI_CFG_SAR_BOFFSET_SET_CORRECTION_MAX, WNI_CFG_SAR_BOFFSET_SET_CORRECTION_DEFAULT}, + {WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_NTF_HAL, + WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_MIN, + WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_MAX, + WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_DEF}, + {WNI_CFG_DISABLE_SCAN_DURING_SCO, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_NTF_HAL, + WNI_CFG_DISABLE_SCAN_DURING_SCO_MIN, + WNI_CFG_DISABLE_SCAN_DURING_SCO_MAX, + WNI_CFG_DISABLE_SCAN_DURING_SCO_DEF}, {WNI_CFG_ENABLE_CONC_BMISS, CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, WNI_CFG_ENABLE_CONC_BMISS_STAMIN, @@ -1713,11 +1723,16 @@ tAniSirCgStatic cfgStatic[CFG_PARAM_MAX_NUM] = WNI_CFG_ENABLE_UNITS_BWAIT_STAMIN, WNI_CFG_ENABLE_UNITS_BWAIT_STAMAX, WNI_CFG_ENABLE_UNITS_BWAIT_STADEF}, - {WNI_CFG_DISABLE_SCAN_DURING_SCO, - CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_NTF_HAL, - WNI_CFG_DISABLE_SCAN_DURING_SCO_MIN, - WNI_CFG_DISABLE_SCAN_DURING_SCO_MAX, - WNI_CFG_DISABLE_SCAN_DURING_SCO_DEF}, + {WNI_CFG_ENABLE_TX_RX_AGGREGATION, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_ENABLE_TX_RX_AGGREGATION_MIN, + WNI_CFG_ENABLE_TX_RX_AGGREGATION_MAX, + WNI_CFG_ENABLE_TX_RX_AGGREGATION_DEF}, + {WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB_MIN, + WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB_MAX, + WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB_DEF}, }; tAniSirCfgStaticString cfgStaticString[CFG_MAX_STATIC_STRING] = diff --git a/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/dot11f.frms b/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/dot11f.frms index f4e490ac786..3c125e9e9bd 100644 --- a/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/dot11f.frms +++ b/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/dot11f.frms @@ -2047,6 +2047,28 @@ IE ESERadMgmtCap (EID_VENDOR_SPECIFIC) OUI (0x00, 0x40, 0x96, 0x01) } +IE hs20vendor_ie (EID_VENDOR_SPECIFIC) OUI (0x50, 0x6F, 0x9A, 0x10) +{ + /* hotspot_configurations */ + { + dgaf_dis: 1; + hs_id_present: 2; + reserved: 1; + release_num: 4; + } + OPTIONAL UNION hs_id (DISCRIMINATOR hs_id_present) + { + pps_mo (hs_id_present IS 1) + { + pps_mo_id, 2; + } + anqp_domain (hs_id_present IS 2) + { + anqp_domain_id, 2; + } + }; +} + IE ESETrafStrmMet (EID_VENDOR_SPECIFIC) OUI (0x00, 0x40, 0x96, 0x07) { tsid, 1; @@ -3334,6 +3356,7 @@ FRAME Beacon // C.f. Sec. 7.2.3.1 OPTIE OperatingMode; OPTIE WiderBWChanSwitchAnn; OPTIE OBSSScanParameters; + OPTIE hs20vendor_ie; } // End frame Beacon. // Ok, here's the story on Beacon1 & Beacon2. We presumably beacon a lot @@ -3414,6 +3437,7 @@ FRAME Beacon2 OPTIE OperatingMode; OPTIE WiderBWChanSwitchAnn; OPTIE OBSSScanParameters; + OPTIE hs20vendor_ie; } // This frame is just Beacon with its Fixed Fields stripped out. It's handy @@ -3471,6 +3495,7 @@ FRAME BeaconIEs OPTIE OperatingMode; OPTIE WiderBWChanSwitchAnn; OPTIE OBSSScanParameters; + OPTIE hs20vendor_ie; } // End frame BeaconIEs. @@ -3508,6 +3533,7 @@ FRAME AssocRequest // 7.2.3.4 OPTIE ExtCap; OPTIE OperatingMode; OPTIE QosMapSet; + OPTIE hs20vendor_ie; } // End frame AssocRequest. FRAME AssocResponse // 7.2.3.5 @@ -3578,6 +3604,7 @@ FRAME ReAssocRequest // 7.2.3.6 OPTIE ExtCap; OPTIE OperatingMode; OPTIE QosMapSet; + OPTIE hs20vendor_ie; } // End frame ReAssocRequest. FRAME ReAssocResponse // 7.2.3.7 @@ -3676,6 +3703,7 @@ FRAME ProbeResponse // 7.2.3.9 OPTIE VHTExtBssLoad; OPTIE ExtCap; OPTIE OBSSScanParameters; + OPTIE hs20vendor_ie; } // End frame ProbeResponse. FRAME Authentication // 7.2.3.10 diff --git a/drivers/staging/prima/CORE/MAC/src/include/dot11f.h b/drivers/staging/prima/CORE/MAC/src/include/dot11f.h index 50788d8af08..585d2b3151e 100644 --- a/drivers/staging/prima/CORE/MAC/src/include/dot11f.h +++ b/drivers/staging/prima/CORE/MAC/src/include/dot11f.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014, 2016, 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -30,7 +30,7 @@ * * * This file was automatically generated by 'framesc' - * Tue Jul 4 11:19:48 2017 from the following file(s): + * Wed Jul 12 16:02:49 2017 from the following file(s): * * dot11f.frms * @@ -6185,6 +6185,45 @@ tANI_U32 dot11fGetPackedIEWscReassocRes(tpAniSirGlobal, tDot11fIEWscReassocRes*, #ifdef __cplusplus }; /* End extern "C". */ #endif /* C++ */ +// EID 221 (0xdd) {OUI 0x50, 0x6f, 0x9a, 0x10} +typedef struct sDot11fIEhs20vendor_ie { + tANI_U8 present; + tANI_U8 dgaf_dis: 1; + tANI_U8 hs_id_present: 2; + tANI_U8 reserved: 1; + tANI_U8 release_num: 4; + union + { + struct + { + tANI_U16 pps_mo_id; + } pps_mo; /* hs_id_present = 1 */ + struct + { + tANI_U16 anqp_domain_id; + } anqp_domain; /* hs_id_present = 2 */ + } hs_id; +} tDot11fIEhs20vendor_ie; + +#define DOT11F_EID_HS20VENDOR_IE ( 221 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_HS20VENDOR_IE_MIN_LEN ( 5 ) + +#define DOT11F_IE_HS20VENDOR_IE_MAX_LEN ( 7 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIehs20vendor_ie(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEhs20vendor_ie*); + +tANI_U32 dot11fPackIehs20vendor_ie(tpAniSirGlobal, tDot11fIEhs20vendor_ie*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEhs20vendor_ie(tpAniSirGlobal, tDot11fIEhs20vendor_ie*, tANI_U32*); + +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ /************************************************************************ * Frames **********************************************************************/ @@ -6325,6 +6364,7 @@ typedef struct sDot11fAssocRequest{ tDot11fIEExtCap ExtCap; tDot11fIEOperatingMode OperatingMode; tDot11fIEQosMapSet QosMapSet; + tDot11fIEhs20vendor_ie hs20vendor_ie; } tDot11fAssocRequest; #define DOT11F_ASSOCREQUEST ( 5 ) @@ -6465,6 +6505,7 @@ typedef struct sDot11fBeacon{ tDot11fIEOperatingMode OperatingMode; tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEhs20vendor_ie hs20vendor_ie; } tDot11fBeacon; #define DOT11F_BEACON ( 8 ) @@ -6539,6 +6580,7 @@ typedef struct sDot11fBeacon2{ tDot11fIEOperatingMode OperatingMode; tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEhs20vendor_ie hs20vendor_ie; } tDot11fBeacon2; #define DOT11F_BEACON2 ( 10 ) @@ -6601,6 +6643,7 @@ typedef struct sDot11fBeaconIEs{ tDot11fIEOperatingMode OperatingMode; tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEhs20vendor_ie hs20vendor_ie; } tDot11fBeaconIEs; #define DOT11F_BEACONIES ( 11 ) @@ -7217,6 +7260,7 @@ typedef struct sDot11fProbeResponse{ tDot11fIEVHTExtBssLoad VHTExtBssLoad; tDot11fIEExtCap ExtCap; tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEhs20vendor_ie hs20vendor_ie; } tDot11fProbeResponse; #define DOT11F_PROBERESPONSE ( 37 ) @@ -7403,6 +7447,7 @@ typedef struct sDot11fReAssocRequest{ tDot11fIEExtCap ExtCap; tDot11fIEOperatingMode OperatingMode; tDot11fIEQosMapSet QosMapSet; + tDot11fIEhs20vendor_ie hs20vendor_ie; } tDot11fReAssocRequest; #define DOT11F_REASSOCREQUEST ( 44 ) diff --git a/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h b/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h index 3dac65ae0c1..e6e7d98878e 100644 --- a/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h +++ b/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2013, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -320,6 +320,27 @@ typedef struct sCfgTrafficClass { } tCfgTrafficClass; +/** + * struct parsed_ies: Parsed IE's of BSS capability + * @ht_caps: HT caps IE + * @vht_caps: VHT caps IE + * @ht_operation: HT operation IE + * @vht_operation: VHT operation IE + * @hs20vendor_ie: HS2.0 vendor IE + * + * This structure holds the parsed IE of connected BSS + * and this is not the intersection of BSS and STA + * capability. For example, if BSS supports 80 MHz + * and STA connects to BSS in 20 MHz, this structure + * holds 80 MHz as peer capability. + */ +struct parsed_ies { + tDot11fIEHTCaps ht_caps; + tDot11fIEVHTCaps vht_caps; + tDot11fIEHTInfo ht_operation; + tDot11fIEVHTOperation vht_operation; + tDot11fIEhs20vendor_ie hs20vendor_ie; +}; /// STA state node @@ -639,6 +660,13 @@ typedef struct sDphHashNode */ tANI_U8 isDisassocDeauthInProgress; bool sta_deletion_in_progress; + struct parsed_ies parsed_ies; +#ifdef SAP_AUTH_OFFLOAD + tANI_U8 dpuIndex; + tANI_U8 bcastDpuIndex; + tANI_U8 bcastMgmtDpuIdx; + tANI_U8 ucMgmtSig; +#endif struct sDphHashNode *next; diff --git a/drivers/staging/prima/CORE/MAC/src/include/parserApi.h b/drivers/staging/prima/CORE/MAC/src/include/parserApi.h index 8ab00e014d6..fac5c071272 100644 --- a/drivers/staging/prima/CORE/MAC/src/include/parserApi.h +++ b/drivers/staging/prima/CORE/MAC/src/include/parserApi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -149,6 +149,8 @@ typedef struct sSirProbeRespBeacon tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; #endif tDot11fIEOBSSScanParameters OBSSScanParameters; + tDot11fIEhs20vendor_ie hs20vendor_ie; + } tSirProbeRespBeacon, *tpSirProbeRespBeacon; // probe Request structure @@ -220,6 +222,7 @@ typedef struct sSirAssocReq tDot11fIEVHTCaps VHTCaps; tDot11fIEOperatingMode operMode; #endif + tDot11fIEhs20vendor_ie hs20vendor_ie; } tSirAssocReq, *tpSirAssocReq; @@ -960,7 +963,6 @@ void PopulateDot11fAssocRspRates ( tpAniSirGlobal pMac, tDot11fIESuppRates *pSup int FindIELocation( tpAniSirGlobal pMac, tpSirRSNie pRsnIe, tANI_U8 EID); -#endif #ifdef WLAN_FEATURE_11AC tSirRetStatus @@ -995,3 +997,21 @@ tSirRetStatus ValidateAndRectifyIEs(tpAniSirGlobal pMac, tANI_U8 *pMgmtFrame, tANI_U32 nFrameBytes, tANI_U32 *nMissingRsnBytes); +#ifdef SAP_AUTH_OFFLOAD +void +sap_auth_offload_update_rsn_ie(tpAniSirGlobal pmac, + tDot11fIERSNOpaque *pdot11f); +#endif /* SAP_AUTH_OFFLOAD */ + +/** + * sir_copy_hs20_ie() - Update HS 2.0 Information Element. + * @dest: dest HS IE buffer to be updated + * @src: src HS IE buffer + * + * Update HS2.0 IE info from src to dest + * + * Return: void + */ +void sir_copy_hs20_ie(tDot11fIEhs20vendor_ie *dest, + tDot11fIEhs20vendor_ie *src); +#endif /* __PARSE_H__ */ diff --git a/drivers/staging/prima/CORE/MAC/src/include/sirParams.h b/drivers/staging/prima/CORE/MAC/src/include/sirParams.h index 236d5282977..dca671d347e 100644 --- a/drivers/staging/prima/CORE/MAC/src/include/sirParams.h +++ b/drivers/staging/prima/CORE/MAC/src/include/sirParams.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -144,8 +144,18 @@ typedef enum { #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD PER_BASED_ROAMING = 63, #endif + SAP_MODE_WOW = 64, + /* SAP_OFFLOADS flag will be used for + * SAP auth offload, SAP DHCP offload and + * SAP DNS offload. + */ + SAP_OFFLOADS = 65, + SAP_BUFF_ALLOC = 66, +#ifdef WLAN_FEATURE_LFR_MBB + MAKE_BEFORE_BREAK = 67, +#endif NUD_DEBUG = 68, - /*69 reserved for FATAL_EVENT_LOGGING */ + FATAL_EVENT_LOGGING = 69, /*70 reserved for WIFI_DUAL_BAND_ENABLE */ PROBE_RSP_TEMPLATE_VER1 = 71, //MAX_FEATURE_SUPPORTED = 128 @@ -171,6 +181,11 @@ typedef enum eSriLinkState { eSIR_LINK_FINISH_CAL_STATE = 13, eSIR_LINK_LISTEN_STATE = 14, eSIR_LINK_SEND_ACTION_STATE = 15, + +#ifdef WLAN_FEATURE_LFR_MBB + eSIR_LINK_PRE_AUTH_REASSOC_STATE = 17, +#endif + } tSirLinkState; @@ -769,12 +784,33 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_PER_ROAM_SCAN_TRIGGER_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 289) #endif #define SIR_HAL_UPDATE_CFG_INT_PARAM (SIR_HAL_ITC_MSG_TYPES_BEGIN + 290) + +#ifdef SAP_AUTH_OFFLOAD +#define SIR_HAL_SET_SAP_AUTH_OFL (SIR_HAL_ITC_MSG_TYPES_BEGIN + 291) +#define SIR_HAL_SAP_OFL_ADD_STA (SIR_HAL_ITC_MSG_TYPES_BEGIN + 292) +#define SIR_HAL_SAP_OFL_DEL_STA (SIR_HAL_ITC_MSG_TYPES_BEGIN + 293) +#endif +#ifdef DHCP_SERVER_OFFLOAD +#define SIR_HAL_SET_DHCP_SERVER_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 294) +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD +#define SIR_HAL_SET_MDNS_OFFLOAD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 295) +#define SIR_HAL_SET_MDNS_FQDN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 296) +#define SIR_HAL_SET_MDNS_RESPONSE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 297) +#define SIR_HAL_GET_MDNS_STATUS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 298) +#endif /* MDNS_OFFLOAD */ +#ifdef WLAN_FEATURE_APFIND +#define SIR_HAL_APFIND_SET_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 299) +#define SIR_HAL_AP_FIND_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 300) +#endif/* WLAN_FEATURE_APFIND */ + +#define SIR_HAL_CAP_TSF_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 301) +#define SIR_HAL_GET_TSF_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 302) + /* ARP Debug stats */ -#define SIR_HAL_SET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 301) -#define SIR_HAL_GET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 302) +#define SIR_HAL_SET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 303) +#define SIR_HAL_GET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 304) -#define SIR_HAL_TRIGGER_ADD_BA_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 303) -#define SIR_HAL_GET_CON_STATUS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 304) #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) // CFG message types @@ -870,6 +906,11 @@ typedef struct sSirMbMsgP2p #define SIR_LIM_DEAUTH_ACK_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x27) #define SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x28) +#ifdef WLAN_FEATURE_LFR_MBB +#define SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x29) +#define SIR_LIM_REASSOC_MBB_RSP_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x2A) +#endif + #define SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE (SIR_LIM_TIMEOUT_MSG_START + 0x2C) #define SIR_LIM_AUTH_RETRY_TIMEOUT (SIR_LIM_TIMEOUT_MSG_START + 0x2D) diff --git a/drivers/staging/prima/CORE/MAC/src/pe/include/limApi.h b/drivers/staging/prima/CORE/MAC/src/pe/include/limApi.h index 5b869d3f064..88bca93e8de 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/include/limApi.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/include/limApi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2013, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -191,6 +191,9 @@ tSirRetStatus limUpdateGlobalChannelBonding(tpAniSirGlobal pMac, tHalBitVal cbBi void limHandleLowRssiInd(tpAniSirGlobal pMac); void limHandleBmpsStatusInd(tpAniSirGlobal pMac); +#ifdef WLAN_FEATURE_APFIND +void limHandleAPFindInd(tpAniSirGlobal pMac); +#endif void limHandleMissedBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg); tMgmtFrmDropReason limIsPktCandidateForDrop(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U32 subType); boolean limIsDeauthDiassocForDrop(tpAniSirGlobal pMac, diff --git a/drivers/staging/prima/CORE/MAC/src/pe/include/limFT.h b/drivers/staging/prima/CORE/MAC/src/pe/include/limFT.h index d7508495b6c..bf4dd64b408 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/include/limFT.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/include/limFT.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -52,6 +52,7 @@ extern void limFTInit(tpAniSirGlobal pMac); extern int limProcessFTPreAuthReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg); extern void limPerformFTPreAuth(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data, tpPESession psessionEntry); +void limFTSetupAuthSession(tpAniSirGlobal pMac, tpPESession psessionEntry); void limPerformPostFTPreAuth(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data, tpPESession psessionEntry); void limFTResumeLinkCb(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h b/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h index 97625a33021..9e856594c59 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -57,6 +57,7 @@ typedef struct sSirFTPreAuthReq { tANI_U16 messageType; // eWNI_SME_FT_PRE_AUTH_REQ tANI_U16 length; + tANI_U32 dot11mode; tANI_BOOLEAN bPreAuthRspProcessed; /* Track if response is processed for this request We expect only one response per request. */ tANI_U8 preAuthchannelNum; @@ -81,6 +82,10 @@ typedef struct sSirFTPreAuthRsp tANI_U8 ft_ies[MAX_FTIE_SIZE]; tANI_U16 ric_ies_length; tANI_U8 ric_ies[MAX_FTIE_SIZE]; +#ifdef WLAN_FEATURE_LFR_MBB + enum sir_roam_cleanup_type reason; + tCsrRoamInfo *roam_info; +#endif } tSirFTPreAuthRsp, *tpSirFTPreAuthRsp; /*-------------------------------------------------------------------------- diff --git a/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h b/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h index 7c049afc77c..21b75bfb4ba 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -353,6 +353,8 @@ typedef struct sPESession // Added to Support BT-AMP tANI_BOOLEAN isCiscoVendorAP; /* To hold OBSS Scan IE Parameters */ tSirOBSSHT40Param obssHT40ScanParam; + /* HS 2.0 Indication */ + tDot11fIEhs20vendor_ie hs20vendor_ie; /* flag to indicate country code in beacon */ tANI_U8 countryInfoPresent; /* DSCP to UP mapping for HS 2.0 */ @@ -361,6 +363,12 @@ typedef struct sPESession // Added to Support BT-AMP tANI_BOOLEAN is11Gonly; tANI_BOOLEAN addBssfailed; tDot11fIEExtCap ExtCap; + uint32_t sta_auth_retries_for_code17; + tDot11fIEHTCaps ht_caps; + tDot11fIEVHTCaps vht_caps; + tDot11fIEHTInfo ht_operation; + tDot11fIEVHTOperation vht_operation; + bool force_24ghz_in_ht20; }tPESession, *tpPESession; #define LIM_MAX_ACTIVE_SESSIONS 4 @@ -421,6 +429,7 @@ tpPESession peFindSessionByBssid(tpAniSirGlobal pMac, tANI_U8* bssid, tANI_ tpPESession peFindSessionByBssIdx(tpAniSirGlobal pMac, tANI_U8 bssIdx); +tANI_S8 limGetInfraSessionId(tpAniSirGlobal pMac); /*-------------------------------------------------------------------------- @@ -495,10 +504,5 @@ void peDeleteSession(tpAniSirGlobal pMac, tpPESession psessionEntry); \sa --------------------------------------------------------------------------*/ - +int peFindBssIdxFromSmeSessionId(tpAniSirGlobal pMac, tANI_U8 sme_sessionId); #endif //#if !defined( __LIM_SESSION_H ) - - - - - diff --git a/drivers/staging/prima/CORE/MAC/src/pe/include/lim_mbb.h b/drivers/staging/prima/CORE/MAC/src/pe/include/lim_mbb.h new file mode 100644 index 00000000000..770263ef1e0 --- /dev/null +++ b/drivers/staging/prima/CORE/MAC/src/pe/include/lim_mbb.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +void lim_process_preauth_mbb_rsp_timeout(tpAniSirGlobal mac); +void lim_process_pre_auth_reassoc_req(tpAniSirGlobal mac, tpSirMsgQ msg); +void lim_handle_pre_auth_mbb_rsp(tpAniSirGlobal mac, + tSirRetStatus status, tpPESession session_entry); +void lim_process_reassoc_mbb_rsp_timeout(tpAniSirGlobal mac); +void lim_handle_reassoc_mbb_fail(tpAniSirGlobal mac, + tpPESession session_entry); +void lim_handle_reassoc_mbb_success(tpAniSirGlobal mac, + tpPESession session_entry, tpSirAssocRsp assoc_rsp, tpDphHashNode sta_ds); +void lim_process_sta_mlm_del_sta_rsp_mbb(tpAniSirGlobal mac, + tpSirMsgQ lim_msg, tpPESession session_entry); +void lim_process_sta_mlm_del_bss_rsp_mbb(tpAniSirGlobal mac, + tpSirMsgQ lim_msg, tpPESession session_entry); +void lim_process_sta_mlm_add_bss_rsp_mbb(tpAniSirGlobal mac, + tpSirMsgQ limMsgQ,tpPESession session_entry); +void lim_process_sta_mlm_add_sta_rsp_mbb(tpAniSirGlobal mac, + tpSirMsgQ limMsgQ,tpPESession session_entry); +eAniBoolean lim_is_mbb_reassoc_in_progress(tpAniSirGlobal mac, + tpPESession session_entry); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c index f49aa01580f..b21ad3aeef5 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -703,6 +703,18 @@ tSirRetStatus limStart(tpAniSirGlobal pMac) return retCode; } +static void +limInitAssocRspCompletiontionList(tpAniSirGlobal pMac) +{ + vos_list_init(&pMac->assoc_rsp_completion_list); +} + +static void +limDestroyAssocRspCompletiontionList(tpAniSirGlobal pMac) +{ + vos_list_destroy(&pMac->assoc_rsp_completion_list); +} + /** * limInitialize() * @@ -753,6 +765,7 @@ limInitialize(tpAniSirGlobal pMac) // Initializations for maintaining peers in IBSS limIbssInit(pMac); + limInitAssocRspCompletiontionList(pMac); pmmInitialize(pMac); @@ -946,7 +959,7 @@ limCleanup(tpAniSirGlobal pMac) vos_mem_free(pMac->lim.gpLimMlmScanReq); pMac->lim.gpLimMlmScanReq = NULL; } - + limDestroyAssocRspCompletiontionList(pMac); #if 0 if(NULL != pMac->lim.beacon) { @@ -2160,6 +2173,21 @@ void limHandleBmpsStatusInd(tpAniSirGlobal pMac) return; } +#ifdef WLAN_FEATURE_APFIND +void limHandleAPFindInd(tpAniSirGlobal pMac) +{ + tANI_S8 pe_sessionid = -1; + /* Find STA connection session */ + pe_sessionid = limGetInfraSessionId(pMac); + if (pe_sessionid != -1) + limTearDownLinkWithAp(pMac, + pe_sessionid, + eSIR_BEACON_MISSED); + else + limLog(pMac, LOGE, + FL("session id doesn't exist for infra")); +} +#endif /** ----------------------------------------------------------------- \brief limHandleMissedBeaconInd() - handles missed beacon indication @@ -2682,3 +2710,151 @@ eHalStatus pe_ReleaseGlobalLock( tAniSirLim *psPe) } return (status); } +/** + * lim_process_sme_cap_tsf_req()- send cap tsf request to WDA + * Get bss_idx from PE and fill in cap tsf request. + * @pMac:Mac ctx + * @pMsgBuf: message buffer from sme + * Returns success on post to WDA, otherwise failure + */ + +tSirRetStatus lim_process_sme_cap_tsf_req(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf) +{ + tSirCapTsfParams *pMsg = NULL; + tpPESession psessionEntry = NULL; + uint8_t sessionId; + tSirMsgQ msg; + tSirCapTsfParams *cap_tsf_params; + + pMsg = (tSirCapTsfParams*)pMsgBuf; + if (pMsg == NULL) { + limLog(pMac, LOGE, FL("NULL pMsg")); + return eSIR_FAILURE; + } + + psessionEntry = peFindSessionByBssid(pMac, pMsg->bssid, &sessionId); + if (NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("NULL psessionEntry")); + return eSIR_FAILURE; + } + cap_tsf_params = (tSirCapTsfParams *) + vos_mem_malloc(sizeof(*cap_tsf_params)); + if (!cap_tsf_params) { + limLog(pMac, LOGE, FL(" Unable to allocate memory for cap tsf params")); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_copy (cap_tsf_params, pMsg, sizeof(*cap_tsf_params)); + cap_tsf_params->bss_idx = psessionEntry->bssIdx; + + msg.type = WDA_CAP_TSF_REQ; + msg.reserved = 0; + msg.bodyptr = cap_tsf_params; + msg.bodyval = 0; + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + limLog(pMac, LOGE, FL("lim_process_sme_cap_tsf_req failed\n")); + vos_mem_free(cap_tsf_params); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} + +/** + * lim_process_sme_get_tsf_req()- send get tsf request to WDA + * Get bss_idx from PE and fill in cap tsf request. + * @pMac:Mac ctx + * @pMsgBuf: message buffer from sme + * Returns success on post to WDA, otherwise failure + */ +tSirRetStatus lim_process_sme_get_tsf_req(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf) +{ + tSirCapTsfParams *pMsg = NULL; + tpPESession psessionEntry = NULL; + uint8_t sessionId; + tSirMsgQ msg; + tSirCapTsfParams *get_tsf_params; + + pMsg = (tSirCapTsfParams*)pMsgBuf; + if (pMsg == NULL) { + limLog(pMac, LOGE, FL("NULL pMsg")); + return eSIR_FAILURE; + } + + psessionEntry = peFindSessionByBssid(pMac, pMsg->bssid, &sessionId); + if (NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("NULL psessionEntry")); + return eSIR_FAILURE; + } + get_tsf_params = (tSirCapTsfParams *) + vos_mem_malloc(sizeof(*get_tsf_params)); + if (!get_tsf_params) { + limLog(pMac, LOGE, FL(" Unable to allocate memory for cap tsf params")); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_copy (get_tsf_params, pMsg, sizeof(*get_tsf_params)); + get_tsf_params->bss_idx = psessionEntry->bssIdx; + + msg.type = WDA_GET_TSF_REQ; + msg.reserved = 0; + msg.bodyptr = get_tsf_params; + msg.bodyval = 0; + if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) + { + limLog(pMac, LOGE, FL("lim_process_sme_cap_tsf_req failed\n")); + vos_mem_free(get_tsf_params); + return eSIR_FAILURE; + } + + return eSIR_SUCCESS; +} + +/** + * lim_process_sme_del_ba_ses_req()- process del ba req + * @pMac:Mac ctx + * @pMsgBuf: message buffer from sme + * Returns success on taking action based on cfg value, otherwise failure + */ +tSirRetStatus lim_process_sme_del_ba_ses_req(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf) +{ + tDelBaParams *pMsg = NULL; + tpPESession psessionEntry = NULL; + int val; + + pMsg = (tDelBaParams*)pMsgBuf; + if (pMsg == NULL) { + limLog(pMac, LOGE, FL("NULL pMsg")); + return eSIR_FAILURE; + } + + psessionEntry = peFindSessionBySessionId(pMac, pMsg->session_id); + if (NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("NULL psessionEntry")); + return eSIR_FAILURE; + } + + if (wlan_cfgGetInt + (pMac, WNI_CFG_ENABLE_TX_RX_AGGREGATION, &val) != + eSIR_SUCCESS) + { + limLog(pMac, LOGE, + FL( "Unable to get WNI_CFG_ENABLE_TX_RX_AGGREGATION")); + return eSIR_FAILURE; + } + + if (!val) + { + limLog(pMac, LOGW, + FL("user requested to disable all RX BA sessions")); + limDeleteBASessions(pMac, psessionEntry, BA_BOTH_DIRECTIONS, + eSIR_MAC_PEER_TIMEDOUT_REASON); + } + + return eSIR_SUCCESS; +} diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c index 188f2e57868..ed44ecea424 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1011,6 +1011,8 @@ limRejectAssociation(tpAniSirGlobal pMac, tSirMacAddr peerAddr, tANI_U8 subType, tANI_U16 staId, tANI_U8 deleteSta, tSirResultCodes rCode, tpPESession psessionEntry ) { tpDphHashNode pStaDs; + assoc_rsp_tx_context *tx_complete_context = NULL; + vos_list_node_t *pNode= NULL; limLog(pMac, LOG1, FL("Sessionid: %d authType: %d subType: %d " "addPreAuthContext: %d staId: %d deleteSta: %d rCode : %d " @@ -1049,23 +1051,38 @@ limRejectAssociation(tpAniSirGlobal pMac, tSirMacAddr peerAddr, tANI_U8 subType, return; } + vos_list_peek_front(&pMac->assoc_rsp_completion_list, &pNode); + + tx_complete_context = vos_mem_malloc(sizeof(*tx_complete_context)); + if (!tx_complete_context) + { + limLog(pMac, LOGW, + FL("Failed to allocate memory")); + + return; + } + tx_complete_context->psessionID = psessionEntry->peSessionId; + tx_complete_context->staId = staId; + + if (pNode) + vos_list_insert_back(&pMac->assoc_rsp_completion_list, + &tx_complete_context->node); + else + vos_list_insert_front(&pMac->assoc_rsp_completion_list, + &tx_complete_context->node); /** * Polaris has state for this STA. * Trigger cleanup. */ pStaDs->mlmStaContext.cleanupTrigger = eLIM_REASSOC_REJECT; - - // Receive path cleanup - limCleanupRxPath(pMac, pStaDs, psessionEntry); - // Send Re/Association Response with // status code to requesting STA. limSendAssocRspMgmtFrame(pMac, rCode, 0, peerAddr, - subType, 0,psessionEntry); + subType, 0,psessionEntry, tx_complete_context); if ( psessionEntry->parsedAssocReq[pStaDs->assocId] != NULL) { @@ -1085,7 +1102,7 @@ limRejectAssociation(tpAniSirGlobal pMac, tSirMacAddr peerAddr, tANI_U8 subType, eSIR_MAC_MAX_ASSOC_STA_REACHED_STATUS, 1, peerAddr, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); // Log error limLog(pMac, LOGW, FL("received Re/Assoc req when max associated STAs reached from ")); @@ -2421,7 +2438,15 @@ limAddSta( } else #endif - pAddStaParams->staIdx = HAL_STA_INVALID_IDX; +#ifdef SAP_AUTH_OFFLOAD + if (!pMac->sap_auth_offload) + pAddStaParams->staIdx = HAL_STA_INVALID_IDX; + else + pAddStaParams->staIdx = pStaDs->staIndex; +#else + pAddStaParams->staIdx = HAL_STA_INVALID_IDX; +#endif + pAddStaParams->staType = pStaDs->staType; pAddStaParams->updateSta = updateEntry; @@ -2593,11 +2618,30 @@ limAddSta( "p2pCapableSta: %d"), pAddStaParams->htLdpcCapable, pAddStaParams->vhtLdpcCapable, pAddStaParams->p2pCapableSta); +#ifdef SAP_AUTH_OFFLOAD + if (pMac->sap_auth_offload) { + pAddStaParams->dpuIndex = pStaDs->dpuIndex; + pAddStaParams->bcastDpuIndex = pStaDs->bcastDpuIndex; + pAddStaParams->bcastMgmtDpuIdx = pStaDs->bcastMgmtDpuIdx; + pAddStaParams->ucUcastSig = pStaDs->ucUcastSig; + pAddStaParams->ucBcastSig = pStaDs->ucBcastSig; + pAddStaParams->ucMgmtSig = pStaDs->ucMgmtSig; + pAddStaParams->bssIdx = pStaDs->bssId; + } +#endif + //we need to defer the message until we get the response back from HAL. if (pAddStaParams->respReqd) SET_LIM_PROCESS_DEFD_MESGS(pMac, false); - msgQ.type = WDA_ADD_STA_REQ; +#ifdef SAP_AUTH_OFFLOAD + if (pMac->sap_auth_offload && LIM_IS_AP_ROLE(psessionEntry)) + msgQ.type = WDA_SAP_OFL_ADD_STA; + else + msgQ.type = WDA_ADD_STA_REQ; +#else + msgQ.type = WDA_ADD_STA_REQ; +#endif msgQ.reserved = 0; msgQ.bodyptr = pAddStaParams; @@ -2723,7 +2767,14 @@ limDelSta( pDelStaParams->sessionId = psessionEntry->peSessionId; pDelStaParams->status = eHAL_STATUS_SUCCESS; +#ifdef SAP_AUTH_OFFLOAD + if (pMac->sap_auth_offload && LIM_IS_AP_ROLE(psessionEntry)) + msgQ.type = WDA_SAP_OFL_DEL_STA; + else + msgQ.type = WDA_DELETE_STA_REQ; +#else msgQ.type = WDA_DELETE_STA_REQ; +#endif msgQ.reserved = 0; msgQ.bodyptr = pDelStaParams; msgQ.bodyval = 0; @@ -3374,6 +3425,9 @@ limCheckAndAnnounceJoinSuccess(tpAniSirGlobal pMac, mlmJoinCnf.sessionId = psessionEntry->peSessionId; limPostSmeMessage(pMac, LIM_MLM_JOIN_CNF, (tANI_U32 *) &mlmJoinCnf); } // if ((pMac->lim.gLimSystemRole == IBSS.... + + /* Update HS 2.0 Information Element */ + sir_copy_hs20_ie(&psessionEntry->hs20vendor_ie, &pBPR->hs20vendor_ie); } /** diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h index d44afc5abeb..8b4705a8dda 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -188,6 +188,7 @@ void limSendSmeTsmIEInd( tpAniSirGlobal pMac, tpPESession psessionEntry, tANI_U8 tid, tANI_U8 state, tANI_U16 measInterval); #endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ +tANI_U16 __limGetSmeJoinReqSizeForAlloc(tANI_U8 *pBuf); #endif /* __LIM_ASSOC_UTILS_H */ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c index 7a60cac737e..ba78826ae70 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -705,7 +705,6 @@ tpPESession limFillFTSession(tpAniSirGlobal pMac, tPowerdBm localPowerConstraint; tPowerdBm regMax; tSchBeaconStruct *pBeaconStruct; - uint32 selfDot11Mode; ePhyChanBondState cbMode; pBeaconStruct = vos_mem_malloc(sizeof(tSchBeaconStruct)); @@ -750,9 +749,8 @@ tpPESession limFillFTSession(tpAniSirGlobal pMac, vos_mem_copy(pftSessionEntry->ssId.ssId, pBeaconStruct->ssId.ssId, pftSessionEntry->ssId.length); - wlan_cfgGetInt(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode); - limLog(pMac, LOG1, FL("selfDot11Mode %d"),selfDot11Mode ); - pftSessionEntry->dot11mode = selfDot11Mode; + pftSessionEntry->dot11mode = pMac->ft.ftPEContext.pFTPreAuthReq->dot11mode; + limLog(pMac, LOG1, FL("dot11mode %d"), pftSessionEntry->dot11mode); pftSessionEntry->vhtCapability = (IS_DOT11_MODE_VHT(pftSessionEntry->dot11mode) && IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c index 36b7a68a8b1..d60902a0e9d 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -55,6 +55,9 @@ #endif //FEATURE_WLAN_DIAG_SUPPORT #include "limSession.h" #include "limSerDesUtils.h" +#ifdef WLAN_FEATURE_LFR_MBB +#include "lim_mbb.h" +#endif /** @@ -111,6 +114,15 @@ limDeleteStaContext(tpAniSirGlobal pMac, tpSirMsgQ limMsg) return; } +#ifdef WLAN_FEATURE_LFR_MBB + if (lim_is_mbb_reassoc_in_progress(pMac, psessionEntry)) + { + limLog(pMac, LOGE, + FL("Ignore delete sta as LFR MBB in progress")); + return; + } +#endif + switch(pMsg->reasonCode) { case HAL_DEL_STA_REASON_CODE_KEEP_ALIVE: @@ -474,6 +486,15 @@ void limHandleHeartBeatFailure(tpAniSirGlobal pMac,tpPESession psessionEntry) /* Ensure HB Status for the session has been reseted */ psessionEntry->LimHBFailureStatus = eANI_BOOLEAN_FALSE; +#ifdef WLAN_FEATURE_LFR_MBB + if (lim_is_mbb_reassoc_in_progress(pMac, psessionEntry)) + { + limLog(pMac, LOGE, + FL("Ignore Heartbeat failure as LFR MBB in progress")); + return; + } +#endif + if (((psessionEntry->limSystemRole == eLIM_STA_ROLE)|| (psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE))&& (psessionEntry->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE)&& diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c index 5d6ebecea5b..387e32eac8e 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -68,6 +68,10 @@ #endif #include "wlan_qct_wda.h" +#ifdef WLAN_FEATURE_LFR_MBB +#include "lim_mbb.h" +#endif + #define BA_DEFAULT_TX_BUFFER_SIZE 64 @@ -176,7 +180,16 @@ void limStopTxAndSwitchChannel(tpAniSirGlobal pMac, tANI_U8 sessionId) tSirRetStatus limStartChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry) { limLog(pMac, LOG1, FL(" ENTER")); - + +#ifdef WLAN_FEATURE_LFR_MBB + if (lim_is_mbb_reassoc_in_progress(pMac, psessionEntry)) + { + limLog(pMac, LOGE, + FL("Ignore channel switch as LFR MBB in progress")); + return eSIR_SUCCESS; + } +#endif + /*If channel switch is already running and it is on a different session, just return*/ /*This need to be removed for MCC */ if( limIsChanSwitchRunning (pMac) && @@ -923,7 +936,8 @@ __limProcessQosMapConfigureFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, return; } limSendSmeMgmtFrameInd(pMac, psessionEntry->smeSessionId, - pRxPacketInfo, psessionEntry, 0); + pRxPacketInfo, psessionEntry, + WDA_GET_RX_RSSI_DB(pRxPacketInfo)); } #ifdef ANI_SUPPORT_11H @@ -1225,10 +1239,10 @@ __limValidateDelBAParameterSet( tpAniSirGlobal pMac, tDot11fFfDelBAParameterSet baParameterSet, tpDphHashNode pSta ) { - tSirMacStatusCodes statusCode = eSIR_MAC_STA_BLK_ACK_NOT_SUPPORTED_STATUS; +tSirMacStatusCodes statusCode = eSIR_MAC_STA_BLK_ACK_NOT_SUPPORTED_STATUS; - if (!(baParameterSet.tid < STACFG_MAX_TC)) - return statusCode; + if (!(baParameterSet.tid < STACFG_MAX_TC)) + return statusCode; // Validate if a BA is active for the requested TID if( pSta->tcCfg[baParameterSet.tid].fUseBATx || @@ -1267,7 +1281,7 @@ __limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps tpDphHashNode pSta; tSirMacStatusCodes status = eSIR_MAC_SUCCESS_STATUS; tANI_U16 aid; - tANI_U32 frameLen, nStatus,val; + tANI_U32 frameLen, nStatus,val, val1; tANI_U8 *pBody; tANI_U8 delBAFlag =0; @@ -1275,6 +1289,7 @@ __limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo ); frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo ); val = 0; + val1 = 0; // Unpack the received frame nStatus = dot11fUnpackAddBAReq( pMac, pBody, frameLen, &frmAddBAReq ); @@ -1336,6 +1351,20 @@ __limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps } #endif //WLAN_SOFTAP_VSTA_FEATURE + if (wlan_cfgGetInt(pMac, WNI_CFG_ENABLE_TX_RX_AGGREGATION, &val1) != + eSIR_SUCCESS) + { + limLog(pMac, LOGE, + FL("Unable to get WNI_CFG_ENABLE_TX_RX_AGGREGATION")); + val1 = 1; + } + if (!val1) + { + limLog(pMac, LOGE, + FL("aggregation disabled - ignoring ADDBA")); + goto returnAfterError; + } + if (wlan_cfgGetInt(pMac, WNI_CFG_DEL_ALL_RX_TX_BA_SESSIONS_2_4_G_BTC, &val) != eSIR_SUCCESS) { @@ -2154,7 +2183,8 @@ static void __limProcessSAQueryResponseActionFrame(tpAniSirGlobal pMac, tANI_U8 if (eLIM_STA_ROLE == psessionEntry->limSystemRole) { limSendSmeMgmtFrameInd(pMac, psessionEntry->smeSessionId, - pRxPacketInfo, psessionEntry, 0); + pRxPacketInfo, psessionEntry, + WDA_GET_RX_RSSI_DB(pRxPacketInfo)); return; } @@ -2592,7 +2622,8 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps // type is ACTION limSendSmeMgmtFrameInd(pMac, psessionEntry->smeSessionId, pRxPacketInfo, - psessionEntry, 0); + psessionEntry, + WDA_GET_RX_RSSI_DB(pRxPacketInfo)); } else { @@ -2727,7 +2758,8 @@ limProcessActionFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pBd) { /* Forward to the SME to HDD to wpa_supplicant */ // type is ACTION - limSendSmeMgmtFrameInd(pMac, 0, pBd, NULL, 0); + limSendSmeMgmtFrameInd(pMac, 0, pBd, NULL, + WDA_GET_RX_RSSI_DB(pBd)); } else { diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c index 2e7e5de6838..e1b7978999c 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -260,7 +260,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, limSendAssocRspMgmtFrame( pMac, eSIR_SUCCESS, pStaDs->assocId, pStaDs->staAddr, pStaDs->mlmStaContext.subType, pStaDs, - psessionEntry); + psessionEntry, NULL); limLog(pMac, LOGE, FL("DUT already received an assoc request frame " "and STA is sending another assoc req.So, do not " @@ -300,7 +300,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_UNSPEC_FAILURE_STATUS, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); return ; } @@ -312,7 +312,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_MIC_FAILURE_REASON, 1, pHdr->sa, - subType, 0, psessionEntry); + subType, 0, psessionEntry, NULL); return; } @@ -336,7 +336,8 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, limLog(pMac, LOGW, FL("Parse error AssocRequest, length=%d from "MAC_ADDRESS_STR), framelen, MAC_ADDR_ARRAY(pHdr->sa)); - limSendAssocRspMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_STATUS, 1, pHdr->sa, subType, 0, psessionEntry); + limSendAssocRspMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_STATUS, 1, + pHdr->sa, subType, 0, psessionEntry, NULL); goto error; } @@ -378,7 +379,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry ,NULL); goto error; } @@ -403,7 +404,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_UNSPEC_FAILURE_STATUS, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); goto error; } @@ -442,7 +443,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); goto error; } @@ -455,7 +456,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, limLog(pMac, LOGE, FL("SOFTAP was in 11G only mode, rejecting legacy " "STA : "MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa)); limSendAssocRspMgmtFrame( pMac, eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS, - 1, pHdr->sa, subType, 0, psessionEntry ); + 1, pHdr->sa, subType, 0, psessionEntry, NULL); goto error; }//end if phyMode == 11G_only @@ -467,7 +468,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, limLog(pMac, LOGE, FL("SOFTAP was in 11N only mode, rejecting legacy " "STA : "MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa)); limSendAssocRspMgmtFrame( pMac, eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS, - 1, pHdr->sa, subType, 0, psessionEntry ); + 1, pHdr->sa, subType, 0, psessionEntry, NULL); goto error; }//end if PhyMode == 11N_only @@ -554,7 +555,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_OUTSIDE_SCOPE_OF_SPEC_STATUS, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); goto error; } @@ -584,7 +585,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); #ifdef WLAN_DEBUG @@ -621,7 +622,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_WME_REFUSED_STATUS, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); goto error; } @@ -710,7 +711,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, FL("Invalid RSNIE received")); limSendAssocRspMgmtFrame(pMac, eSIR_MAC_INVALID_RSN_IE_CAPABILITIES_STATUS, - 1, pHdr->sa, subType, 0,psessionEntry); + 1, pHdr->sa, subType, 0,psessionEntry, NULL); goto error; } @@ -732,7 +733,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, status, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); goto error; @@ -751,7 +752,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_UNSUPPORTED_RSN_IE_VERSION_STATUS, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); goto error; } @@ -768,7 +769,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); goto error; @@ -787,7 +788,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, limLog(pMac, LOGE, FL("Invalid WPA IE")); limSendAssocRspMgmtFrame(pMac, eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS, - 1, pHdr->sa, subType, 0,psessionEntry); + 1, pHdr->sa, subType, 0,psessionEntry, NULL); goto error; } /* check the groupwise and pairwise cipher suites */ @@ -803,7 +804,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, status, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); goto error; } @@ -820,7 +821,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); goto error; }/* end - if(pAssocReq->wpa.length) */ @@ -949,7 +950,8 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, */ pStaDs->pmfSaQueryRetryCount = 0; limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1, - pHdr->sa, subType, pStaDs, psessionEntry); + pHdr->sa, subType, pStaDs, + psessionEntry, NULL); limSendSaQueryRequestFrame( pMac, (tANI_U8 *)&(pStaDs->pmfSaQueryCurrentTransId), pHdr->sa, psessionEntry); @@ -970,7 +972,8 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, // Request with try again later case DPH_SA_QUERY_IN_PROGRESS: limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1, - pHdr->sa, subType, 0, psessionEntry); + pHdr->sa, subType, 0, psessionEntry, + NULL); goto error; // SA Query procedure timed out, accept Association Request @@ -1046,7 +1049,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_QAP_NO_BANDWIDTH_REASON, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); #ifdef WLAN_DEBUG pMac->lim.gLimNumAssocReqDropACRejectTS++; #endif @@ -1062,7 +1065,7 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, eSIR_MAC_QAP_NO_BANDWIDTH_REASON, 1, pHdr->sa, - subType, 0,psessionEntry); + subType, 0,psessionEntry, NULL); #ifdef WLAN_DEBUG pMac->lim.gLimNumAssocReqDropACRejectSta++; #endif diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c index d08df5b6355..ccc8ec71041 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -56,6 +56,10 @@ #include "eseApi.h" #endif +#ifdef WLAN_FEATURE_LFR_MBB +#include "lim_mbb.h" +#endif + extern tSirRetStatus schBeaconEdcaProcess(tpAniSirGlobal pMac, tSirMacEdcaParamSetIE *edca, tpPESession psessionEntry); @@ -528,16 +532,18 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub psessionEntry->assocRsp = NULL; } - psessionEntry->assocRsp = vos_mem_malloc(frameLen); - if (NULL == psessionEntry->assocRsp) - { - PELOGE(limLog(pMac, LOGE, FL("Unable to allocate memory to store assoc response, len = %d"), frameLen);) - } - else - { - //Store the Assoc response. This is sent to csr/hdd in join cnf response. - vos_mem_copy(psessionEntry->assocRsp, pBody, frameLen); - psessionEntry->assocRspLen = frameLen; + if (frameLen) { + psessionEntry->assocRsp = vos_mem_malloc(frameLen); + if (NULL == psessionEntry->assocRsp) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to allocate memory to store assoc response, len = %d"), frameLen);) + } + else + { + //Store the Assoc response. This is sent to csr/hdd in join cnf response. + vos_mem_copy(psessionEntry->assocRsp, pBody, frameLen); + psessionEntry->assocRspLen = frameLen; + } } #ifdef WLAN_FEATURE_VOWIFI_11R @@ -549,16 +555,19 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub if(pAssocRsp->ricPresent) { psessionEntry->RICDataLen = pAssocRsp->num_RICData * sizeof(tDot11fIERICDataDesc); - psessionEntry->ricData = vos_mem_malloc(psessionEntry->RICDataLen); - if ( NULL == psessionEntry->ricData ) - { - PELOGE(limLog(pMac, LOGE, FL("Unable to allocate memory to store assoc response"));) - psessionEntry->RICDataLen = 0; - } - else + if (psessionEntry->RICDataLen) { - vos_mem_copy(psessionEntry->ricData, - &pAssocRsp->RICData[0], psessionEntry->RICDataLen); + psessionEntry->ricData = vos_mem_malloc(psessionEntry->RICDataLen); + if ( NULL == psessionEntry->ricData ) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to allocate memory to store assoc response"));) + psessionEntry->RICDataLen = 0; + } + else + { + vos_mem_copy(psessionEntry->ricData, + &pAssocRsp->RICData[0], psessionEntry->RICDataLen); + } } } else @@ -636,6 +645,11 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub limDeactivateAndChangeTimer(pMac, eLIM_ASSOC_FAIL_TIMER); else // Stop Reassociation failure timer { +#ifdef WLAN_FEATURE_LFR_MBB + if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) + limDeactivateAndChangeTimer(pMac, eLIM_REASSOC_MBB_RSP_TIMER); +#endif + #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) pMac->lim.reAssocRetryAttempt = 0; if ((NULL != pMac->lim.pSessionEntry) && (NULL != pMac->lim.pSessionEntry->pLimMlmReassocRetryReq)) @@ -644,7 +658,10 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub pMac->lim.pSessionEntry->pLimMlmReassocRetryReq = NULL; } #endif - limDeactivateAndChangeTimer(pMac, eLIM_REASSOC_FAIL_TIMER); + + /* Dactivate timer when it is not LFR MBB */ + if (!pMac->ft.ftSmeContext.is_preauth_lfr_mbb) + limDeactivateAndChangeTimer(pMac, eLIM_REASSOC_FAIL_TIMER); } if (pAssocRsp->statusCode != eSIR_MAC_SUCCESS_STATUS) @@ -668,6 +685,9 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub }else mlmAssocCnf.resultCode = eSIR_SME_ASSOC_REFUSED; + if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) + goto assocReject; + // Delete Pre-auth context for the associated BSS if (limSearchPreAuthList(pMac, pHdr->sa)) limDeletePreAuthNode(pMac, pHdr->sa); @@ -696,18 +716,22 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub * assoc/reassoc response * NOTE: for BTAMP case, it is being handled in limProcessMlmAssocReq */ - if (!((psessionEntry->bssType == eSIR_BTAMP_STA_MODE) || - ((psessionEntry->bssType == eSIR_BTAMP_AP_MODE) && - (psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE)))) - { - if (limSetLinkState(pMac, eSIR_LINK_POSTASSOC_STATE, psessionEntry->bssId, - psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) + if (!pMac->ft.ftSmeContext.is_preauth_lfr_mbb) { + if (!((psessionEntry->bssType == eSIR_BTAMP_STA_MODE) || + ((psessionEntry->bssType == eSIR_BTAMP_AP_MODE) && + (psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE)))) + { + if (limSetLinkState(pMac, eSIR_LINK_POSTASSOC_STATE, + psessionEntry->bssId, + psessionEntry->selfMacAddr, + NULL, NULL) != eSIR_SUCCESS) { PELOGE(limLog(pMac, LOGE, FL("Set link state to POSTASSOC failed"));) vos_mem_free(pBeaconStruct); vos_mem_free(pAssocRsp); return; } + } } if (subType == LIM_REASSOC) { @@ -776,6 +800,21 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub goto assocReject; } +#ifdef WLAN_FEATURE_LFR_MBB + if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) { + limLog(pMac, LOG1, FL("Reassoc success for LFR MBB in state %d"), + psessionEntry->limMlmState); + if (psessionEntry->limMlmState == + eLIM_MLM_WT_REASSOC_RSP_STATE) { + lim_handle_reassoc_mbb_success(pMac, psessionEntry, + pAssocRsp, pStaDs); + return; + } + goto assocReject; + } +#endif + + #if defined(WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) if (psessionEntry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE) { @@ -882,6 +921,18 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub GET_IE_LEN_IN_BSS(psessionEntry->pLimJoinReq->bssDescription.length), pBeaconStruct); + if (pBeaconStruct->VHTCaps.present) + pStaDs->parsed_ies.vht_caps = pBeaconStruct->VHTCaps; + if (pBeaconStruct->HTCaps.present) + pStaDs->parsed_ies.ht_caps = pBeaconStruct->HTCaps; + if (pBeaconStruct->hs20vendor_ie.present) + pStaDs->parsed_ies.hs20vendor_ie = + pBeaconStruct->hs20vendor_ie; + if (pBeaconStruct->HTInfo.present) + pStaDs->parsed_ies.ht_operation = pBeaconStruct->HTInfo; + if (pBeaconStruct->VHTOperation.present) + pStaDs->parsed_ies.vht_operation = pBeaconStruct->VHTOperation; + if(pMac->lim.gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) limDecideStaProtectionOnAssoc(pMac, pBeaconStruct, psessionEntry); @@ -962,6 +1013,14 @@ assocReject: } #endif /* WLAN_FEATURE_VOWIFI_11R */ } else { +#ifdef WLAN_FEATURE_LFR_MBB + if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) { + lim_handle_reassoc_mbb_fail(pMac, psessionEntry); + vos_mem_free(pBeaconStruct); + vos_mem_free(pAssocRsp); + return; + } +#endif limRestorePreReassocState( pMac, eSIR_SME_REASSOC_REFUSED, mlmAssocCnf.protStatusCode,psessionEntry); } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c index 0f1ee26b701..04d676d8139 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2015, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -51,6 +51,9 @@ #include "limFT.h" #endif #include "vos_utils.h" +#ifdef WLAN_FEATURE_LFR_MBB +#include "lim_mbb.h" +#endif /** @@ -218,19 +221,13 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse goto free; } - encrAuthFrame = vos_mem_malloc(LIM_ENCR_AUTH_BODY_LEN); - if (!encrAuthFrame) { - limLog(pMac, LOGE, FL("failed to allocate memory")); - goto free; - } - plainBody = vos_mem_malloc(LIM_ENCR_AUTH_BODY_LEN); if (!plainBody) { limLog(pMac, LOGE, FL("failed to allocate memory")); goto free; } - challengeTextArray = vos_mem_malloc(SIR_MAC_AUTH_CHALLENGE_LENGTH); + challengeTextArray = vos_mem_malloc(SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH); if(!challengeTextArray) { limLog(pMac, LOGE, FL("failed to allocate memory")); goto free; @@ -238,9 +235,8 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse vos_mem_set(rxAuthFrame, sizeof(tSirMacAuthFrameBody), 0); vos_mem_set(authFrame, sizeof(tSirMacAuthFrameBody), 0); - vos_mem_set(encrAuthFrame, LIM_ENCR_AUTH_BODY_LEN, 0); vos_mem_set(plainBody, LIM_ENCR_AUTH_BODY_LEN, 0); - vos_mem_set(challengeTextArray, SIR_MAC_AUTH_CHALLENGE_LENGTH, 0); + vos_mem_set(challengeTextArray, SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH, 0); /// Determine if WEP bit is set in the FC or received MAC header if (pHdr->fc.wep) @@ -291,7 +287,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse goto free; } - if (frameLen < LIM_ENCR_AUTH_BODY_LEN) + if (frameLen < LIM_ENCR_AUTH_BODY_LEN_SAP) { // Log error limLog(pMac, LOGE, @@ -997,7 +993,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse /* * get random bytes and use as challenge text */ - if( !VOS_IS_STATUS_SUCCESS( vos_rand_get_bytes( 0, (tANI_U8 *)challengeTextArray, SIR_MAC_AUTH_CHALLENGE_LENGTH ) ) ) + if( !VOS_IS_STATUS_SUCCESS( vos_rand_get_bytes( 0, (tANI_U8 *)challengeTextArray, SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH ) ) ) { limLog(pMac, LOGE,FL("Challenge text " "preparation failed in limProcessAuthFrame")); @@ -1021,10 +1017,10 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse authFrame->authStatusCode = eSIR_MAC_SUCCESS_STATUS; authFrame->type = SIR_MAC_CHALLENGE_TEXT_EID; - authFrame->length = SIR_MAC_AUTH_CHALLENGE_LENGTH; + authFrame->length = SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH; vos_mem_copy(authFrame->challengeText, pAuthNode->challengeText, - SIR_MAC_AUTH_CHALLENGE_LENGTH); + SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH); limSendAuthMgmtFrame( pMac, authFrame, @@ -1317,10 +1313,19 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse sirSwapU16ifNeeded((tANI_U16) (pRxAuthFrameBody->authTransactionSeqNumber + 1)); ((tpSirMacAuthFrameBody) plainBody)->authStatusCode = eSIR_MAC_SUCCESS_STATUS; ((tpSirMacAuthFrameBody) plainBody)->type = SIR_MAC_CHALLENGE_TEXT_EID; - ((tpSirMacAuthFrameBody) plainBody)->length = SIR_MAC_AUTH_CHALLENGE_LENGTH; + ((tpSirMacAuthFrameBody) plainBody)->length = pRxAuthFrameBody->length; vos_mem_copy((tANI_U8 *) ((tpSirMacAuthFrameBody) plainBody)->challengeText, pRxAuthFrameBody->challengeText, - SIR_MAC_AUTH_CHALLENGE_LENGTH); + pRxAuthFrameBody->length); + + encrAuthFrame = vos_mem_malloc(pRxAuthFrameBody->length + + LIM_ENCR_AUTH_INFO_LEN); + if (!encrAuthFrame) { + limLog(pMac, LOGE, FL("failed to allocate memory")); + goto free; + } + vos_mem_set(encrAuthFrame, pRxAuthFrameBody->length + + LIM_ENCR_AUTH_INFO_LEN, 0); limEncryptAuthFrame(pMac, 0, pKeyMapEntry->key, @@ -1333,7 +1338,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse limSendAuthMgmtFrame(pMac, (tpSirMacAuthFrameBody) encrAuthFrame, pHdr->sa, - LIM_WEP_IN_FC, + pRxAuthFrameBody->length, psessionEntry, eSIR_FALSE); break; @@ -1397,10 +1402,19 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse sirSwapU16ifNeeded((tANI_U16) (pRxAuthFrameBody->authTransactionSeqNumber + 1)); ((tpSirMacAuthFrameBody) plainBody)->authStatusCode = eSIR_MAC_SUCCESS_STATUS; ((tpSirMacAuthFrameBody) plainBody)->type = SIR_MAC_CHALLENGE_TEXT_EID; - ((tpSirMacAuthFrameBody) plainBody)->length = SIR_MAC_AUTH_CHALLENGE_LENGTH; + ((tpSirMacAuthFrameBody) plainBody)->length = pRxAuthFrameBody->length; vos_mem_copy((tANI_U8 *) ((tpSirMacAuthFrameBody) plainBody)->challengeText, pRxAuthFrameBody->challengeText, - SIR_MAC_AUTH_CHALLENGE_LENGTH); + pRxAuthFrameBody->length); + + encrAuthFrame = vos_mem_malloc(pRxAuthFrameBody->length + + LIM_ENCR_AUTH_INFO_LEN); + if (!encrAuthFrame) { + limLog(pMac, LOGE, FL("failed to allocate memory")); + goto free; + } + vos_mem_set(encrAuthFrame, pRxAuthFrameBody->length + + LIM_ENCR_AUTH_INFO_LEN, 0); limEncryptAuthFrame(pMac, keyId, defaultKey, @@ -1414,7 +1428,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse limSendAuthMgmtFrame(pMac, (tpSirMacAuthFrameBody) encrAuthFrame, pHdr->sa, - LIM_WEP_IN_FC, + pRxAuthFrameBody->length, psessionEntry, eSIR_FALSE); break; @@ -1588,7 +1602,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse if (vos_mem_compare(pRxAuthFrameBody->challengeText, pAuthNode->challengeText, - SIR_MAC_AUTH_CHALLENGE_LENGTH)) + SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH)) { /// Challenge match. STA is autheticated ! @@ -1924,15 +1938,33 @@ tSirRetStatus limProcessAuthFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pBd, vo limLog(pMac, LOG1, FL("Pre-Auth response received from neighbor")); limLog(pMac, LOG1, FL("Pre-Auth done state")); #endif + + limLog(pMac, LOG1, FL("is_preauth_lfr_mbb %d"), + pMac->ft.ftSmeContext.is_preauth_lfr_mbb); + // Stopping timer now, that we have our unicast from the AP // of our choice. - limDeactivateAndChangeTimer(pMac, eLIM_FT_PREAUTH_RSP_TIMER); + if (!pMac->ft.ftSmeContext.is_preauth_lfr_mbb) + limDeactivateAndChangeTimer(pMac, eLIM_FT_PREAUTH_RSP_TIMER); + +#ifdef WLAN_FEATURE_LFR_MBB + if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) + limDeactivateAndChangeTimer(pMac, eLIM_PREAUTH_MBB_RSP_TIMER); +#endif // Save off the auth resp. if ((sirConvertAuthFrame2Struct(pMac, pBody, frameLen, &rxAuthFrame) != eSIR_SUCCESS)) { limLog(pMac, LOGE, FL("failed to convert Auth frame to struct")); + +#ifdef WLAN_FEATURE_LFR_MBB + if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) { + lim_handle_pre_auth_mbb_rsp(pMac, eSIR_FAILURE, psessionEntry); + return eSIR_FAILURE; + } +#endif + limHandleFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry); return eSIR_FAILURE; } @@ -1972,6 +2004,13 @@ tSirRetStatus limProcessAuthFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pBd, vo break; } +#ifdef WLAN_FEATURE_LFR_MBB + if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) { + lim_handle_pre_auth_mbb_rsp(pMac, ret_status, psessionEntry); + return ret_status; + } +#endif + // Send the Auth response to SME limHandleFTPreAuthRsp(pMac, ret_status, pBody, frameLen, psessionEntry); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c index a7d4df8fa24..ef1056e7392 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -36,6 +36,9 @@ #include "limSerDesUtils.h" #include "schApi.h" #include "limSendMessages.h" +#ifdef WLAN_FEATURE_LFR_MBB +#include "lim_mbb.h" +#endif @@ -77,7 +80,6 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); - if ((eLIM_STA_ROLE == psessionEntry->limSystemRole) && (eLIM_SME_WT_DEAUTH_STATE == psessionEntry->limSmeState)) { /*Every 15th deauth frame will be logged in kmsg*/ @@ -229,6 +231,14 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p { pRoamSessionEntry = peFindSessionByBssid(pMac, psessionEntry->limReAssocbssId, &roamSessionId); } + +#ifdef WLAN_FEATURE_LFR_MBB + if (lim_is_mbb_reassoc_in_progress(pMac, psessionEntry)) { + limLog(pMac, LOGE, FL("Ignore Deauth frame as LFR MBB in progress")); + return; + } +#endif + if (limIsReassocInProgress(pMac,psessionEntry) || limIsReassocInProgress(pMac,pRoamSessionEntry)) { if (!IS_REASSOC_BSSID(pMac,pHdr->sa,psessionEntry)) { PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from unknown/different " diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c index 6483854d07c..88585abac91 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -49,6 +49,9 @@ #include "limSerDesUtils.h" #include "limSendMessages.h" #include "schApi.h" +#ifdef WLAN_FEATURE_LFR_MBB +#include "lim_mbb.h" +#endif /** @@ -84,7 +87,6 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); - if (limIsGroupAddr(pHdr->sa)) { // Received Disassoc frame from a BC/MC address @@ -160,6 +162,13 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession return; } +#ifdef WLAN_FEATURE_LFR_MBB + if (lim_is_mbb_reassoc_in_progress(pMac, psessionEntry)) { + limLog(pMac, LOGE, FL("Ignore Disassoc frame as LFR MBB in progress")); + return; + } +#endif + /** If we are in the Wait for ReAssoc Rsp state */ if (limIsReassocInProgress(pMac,psessionEntry)) { /** If we had received the DisAssoc from, diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c index e8b9fced0b3..ddb9f5fa481 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -516,7 +516,7 @@ limCheckMgmtRegisteredFrames(tpAniSirGlobal pMac, tANI_U8 *pBd, /* Indicate this to SME */ limSendSmeMgmtFrameInd( pMac, pLimMgmtRegistration->sessionId, - pBd, psessionEntry, 0); + pBd, psessionEntry, WDA_GET_RX_RSSI_DB(pBd)); if ( (type == SIR_MAC_MGMT_FRAME) && (fc.type == SIR_MAC_MGMT_FRAME) && (subType == SIR_MAC_MGMT_RESERVED15) ) @@ -679,6 +679,71 @@ limProcessEXTScanRealTimeData(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) } /*** end limProcessEXTScanRealTimeData() ***/ #endif /* WLAN_FEATURE_EXTSCAN */ +#ifdef SAP_AUTH_OFFLOAD +/* + * lim_process_sap_offload_indication: function to process add sta/ del sta + * indication for SAP auth offload. + * + * @pMac: mac context + * @pRxPacketInfo: rx buffer + * + * This Function will go through buffer and if + * indication type is ADD_STA_IND, function will extract all data related to + * client and will call limAddSta + * and if indication type is DEL_STA_IND, function will call + * limSendSmeDisassocInd to do cleanup for station. + * + * Return : none + */ +static void lim_process_sap_offload_indication(tpAniSirGlobal pMac, + tANI_U8 *pRxPacketInfo) +{ + int i = 0; + tSapOfldIndications *sap_offload_indication_rx_buf = + (tSapOfldIndications *)WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + tSapOfldInd *sap_offload_ind = + (tSapOfldInd*)sap_offload_indication_rx_buf->indications; + + limLog( pMac, LOG1, + FL("Notify SME with Sap Offload ind and indication type is %d num_indication %d \n"), + sap_offload_ind->indType, + (tANI_U8) sap_offload_indication_rx_buf->num_indications); + + for (i=1; i <= (tANI_U8)(sap_offload_indication_rx_buf->num_indications); + i++) + { + if (sap_offload_ind->indType == SAP_OFFLOAD_ADD_STA_IND) + { + tSapOfldAddStaIndMsg *add_sta; + limLog( pMac, LOG1, + FL("Indication type is SAP_OFFLOAD_ADD_STA_IND")); + add_sta = (tSapOfldAddStaIndMsg *)sap_offload_ind->indication; + lim_sap_offload_add_sta(pMac, add_sta); + if (sap_offload_indication_rx_buf->num_indications > 1) + sap_offload_ind = + (tSapOfldInd *)((tANI_U8 *)sap_offload_ind + + sizeof(tSapOfldAddStaIndMsg) - sizeof(tANI_U8)+ + add_sta->data_len + sizeof(tANI_U32)); + } + else if (sap_offload_ind->indType == SAP_OFFLOAD_DEL_STA_IND) + { + tSapOfldDelStaIndMsg *del_sta; + limLog( pMac, LOG1, + FL("Indication type is SAP_OFFLOAD_DEL_STA_IND")); + del_sta = (tSapOfldDelStaIndMsg *)sap_offload_ind->indication; + lim_sap_offload_del_sta(pMac, del_sta); + sap_offload_ind = (tSapOfldInd *)((tANI_U8 *)sap_offload_ind + + sizeof(tSapOfldDelStaIndMsg) + sizeof(tANI_U32)); + } + else + { + limLog(pMac, LOGE, FL("No Valid indication for connected station")); + } + } + +} +#endif + /** * limHandle80211Frames() * @@ -711,10 +776,20 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) tANI_U8 sessionId; tAniBool isFrmFt = FALSE; tANI_U16 fcOffset = WLANHAL_RX_BD_HEADER_SIZE; + tANI_S8 pe_sessionid = -1; *pDeferMsg= false; limGetBDfromRxPacket(pMac, limMsg->bodyptr, (tANI_U32 **)&pRxPacketInfo); +#ifdef SAP_AUTH_OFFLOAD + if ((WDA_GET_SAP_AUTHOFFLOADIND(pRxPacketInfo) == 1) && + pMac->sap_auth_offload) + { + lim_process_sap_offload_indication(pMac, pRxPacketInfo); + goto end; + } +#endif + #ifdef WLAN_FEATURE_EXTSCAN if ( WDA_GET_EXTSCANFULLSCANRESIND(pRxPacketInfo)) @@ -801,6 +876,24 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) pMac->PERroamCandidatesCnt = 0; } + pe_sessionid = limGetInfraSessionId(pMac); + if (pe_sessionid != -1) { + psessionEntry = peFindSessionBySessionId(pMac, pe_sessionid); + if (psessionEntry != NULL) + { + if ((psessionEntry->limSmeState == eLIM_SME_WT_DEAUTH_STATE) || + (psessionEntry->limSmeState == eLIM_SME_WT_DISASSOC_STATE)) + { + limLog(pMac, LOG1, + FL("Drop candidate ind as deauth/disassoc in progress")); + goto end; + } + } + } + else + limLog(pMac, LOGE, + FL("session id doesn't exist for infra")); + //send a session 0 for now - TBD limSendSmeCandidateFoundInd(pMac, 0); goto end; @@ -1607,6 +1700,9 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) case eWNI_SME_FT_PRE_AUTH_REQ: case eWNI_SME_FT_AGGR_QOS_REQ: #endif +#ifdef WLAN_FEATURE_LFR_MBB + case eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ: +#endif case eWNI_SME_ADD_STA_SELF_REQ: case eWNI_SME_DEL_STA_SELF_REQ: case eWNI_SME_REGISTER_MGMT_FRAME_REQ: @@ -1625,7 +1721,6 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) #endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ case eWNI_SME_MAC_SPOOF_ADDR_IND: case eWNI_SME_REGISTER_MGMT_FRAME_CB: - case eWNI_SME_DEL_TEST_BA: // These messages are from HDD limProcessNormalHddMsg(pMac, limMsg, false); //no need to response to hdd break; @@ -1827,6 +1922,11 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) limHandleBmpsStatusInd(pMac); break; +#ifdef WLAN_FEATURE_APFIND + case WDA_AP_FIND_IND: + limHandleAPFindInd(pMac); + break; +#endif case WDA_MISSED_BEACON_IND: limHandleMissedBeaconInd(pMac, limMsg); vos_mem_free(limMsg->bodyptr); @@ -1908,6 +2008,10 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) case SIR_LIM_DEAUTH_ACK_TIMEOUT: case SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE: case SIR_LIM_AUTH_RETRY_TIMEOUT: +#ifdef WLAN_FEATURE_LFR_MBB + case SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT: + case SIR_LIM_REASSOC_MBB_RSP_TIMEOUT: +#endif // These timeout messages are handled by MLM sub module limProcessMlmReqMessages(pMac, @@ -2419,6 +2523,22 @@ send_chan_switch_resp: limMsg->bodyptr = NULL; break; + case eWNI_SME_CAP_TSF_REQ: + lim_process_sme_cap_tsf_req(pMac, limMsg->bodyptr); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + + case eWNI_SME_GET_TSF_REQ: + lim_process_sme_get_tsf_req(pMac, limMsg->bodyptr); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; + case eWNI_SME_DEL_BA_SES_REQ: + lim_process_sme_del_ba_ses_req(pMac, limMsg->bodyptr); + vos_mem_free((v_VOID_t*)limMsg->bodyptr); + limMsg->bodyptr = NULL; + break; default: vos_mem_free((v_VOID_t*)limMsg->bodyptr); limMsg->bodyptr = NULL; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c index d0eab9bab7b..2e382d9dee9 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -59,6 +59,9 @@ #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM #include "vos_diag_core_log.h" #endif +#ifdef WLAN_FEATURE_LFR_MBB +#include "lim_mbb.h" +#endif // MLM REQ processing function templates @@ -155,6 +158,14 @@ limProcessMlmReqMessages(tpAniSirGlobal pMac, tpSirMsgQ Msg) #ifdef WLAN_FEATURE_VOWIFI_11R case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT:limProcessFTPreauthRspTimeout(pMac); break; #endif +#ifdef WLAN_FEATURE_LFR_MBB + case SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT: + lim_process_preauth_mbb_rsp_timeout(pMac); + break; + case SIR_LIM_REASSOC_MBB_RSP_TIMEOUT: + lim_process_reassoc_mbb_rsp_timeout(pMac); + break; +#endif case SIR_LIM_REMAIN_CHN_TIMEOUT: limProcessRemainOnChnTimeout(pMac); break; case SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT: limProcessInsertSingleShotNOATimeout(pMac); break; @@ -762,8 +773,41 @@ void limSetDFSChannelList(tpAniSirGlobal pMac,tANI_U8 channelNum, tSirDFSChannel return; } +void limDoSendAuthMgmtFrame(tpAniSirGlobal pMac, tpPESession psessionEntry) +{ + tSirMacAuthFrameBody authFrameBody; - + //Prepare & send Authentication frame + authFrameBody.authAlgoNumber = + (tANI_U8) pMac->lim.gpLimMlmAuthReq->authType; + authFrameBody.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1; + authFrameBody.authStatusCode = 0; + pMac->authAckStatus = LIM_AUTH_ACK_NOT_RCD; + limSendAuthMgmtFrame(pMac, + &authFrameBody, + pMac->lim.gpLimMlmAuthReq->peerMacAddr, + LIM_NO_WEP_IN_FC, psessionEntry, eSIR_TRUE); + if (tx_timer_activate(&pMac->lim.limTimers.gLimAuthFailureTimer) + != TX_SUCCESS) { + //Could not start Auth failure timer. + //Log error + limLog(pMac, LOGP, + FL("could not start Auth failure timer")); + //Cleanup as if auth timer expired + limProcessAuthFailureTimeout(pMac); + } else { + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, + psessionEntry->peSessionId, eLIM_AUTH_RETRY_TIMER)); + //Activate Auth Retry timer + if (tx_timer_activate + (&pMac->lim.limTimers.gLimPeriodicAuthRetryTimer) + != TX_SUCCESS) { + limLog(pMac, LOGP, + FL("could not activate Auth Retry timer")); + } + } + return; +} /* * Creates a Raw frame to be sent before every Scan, if required. @@ -2386,7 +2430,6 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { tANI_U32 numPreAuthContexts; tSirMacAddr currentBssId; - tSirMacAuthFrameBody authFrameBody; tLimMlmAuthCnf mlmAuthCnf; struct tLimPreAuthNode *preAuthNode; tpDphHashNode pStaDs; @@ -2513,17 +2556,6 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry->limMlmState = eLIM_MLM_WT_AUTH_FRAME2_STATE; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); - /// Prepare & send Authentication frame - authFrameBody.authAlgoNumber = - (tANI_U8) pMac->lim.gpLimMlmAuthReq->authType; - authFrameBody.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1; - authFrameBody.authStatusCode = 0; - pMac->authAckStatus = LIM_AUTH_ACK_NOT_RCD; - limSendAuthMgmtFrame(pMac, - &authFrameBody, - pMac->lim.gpLimMlmAuthReq->peerMacAddr, - LIM_NO_WEP_IN_FC, psessionEntry, eSIR_TRUE); - //assign appropriate sessionId to the timer object pMac->lim.limTimers.gLimAuthFailureTimer.sessionId = sessionId; /* assign appropriate sessionId to the timer object */ @@ -2531,27 +2563,8 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) limDeactivateAndChangeTimer(pMac, eLIM_AUTH_RETRY_TIMER); // Activate Auth failure timer MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_AUTH_FAIL_TIMER)); - if (tx_timer_activate(&pMac->lim.limTimers.gLimAuthFailureTimer) - != TX_SUCCESS) - { - /// Could not start Auth failure timer. - // Log error - limLog(pMac, LOGP, - FL("could not start Auth failure timer")); - // Cleanup as if auth timer expired - limProcessAuthFailureTimeout(pMac); - } - else - { - MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, - psessionEntry->peSessionId, eLIM_AUTH_RETRY_TIMER)); - // Activate Auth Retry timer - if (tx_timer_activate(&pMac->lim.limTimers.gLimPeriodicAuthRetryTimer) - != TX_SUCCESS) - { - limLog(pMac, LOGP, FL("could not activate Auth Retry timer")); - } - } + + limDoSendAuthMgmtFrame(pMac, psessionEntry); return; } else diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c index 1393690c514..feb52accaf5 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -61,6 +61,10 @@ #include "wlan_qct_wda.h" #include "vos_utils.h" +#ifdef WLAN_FEATURE_LFR_MBB +#include "lim_mbb.h" +#endif + static void limHandleSmeJoinResult(tpAniSirGlobal, tSirResultCodes, tANI_U16,tpPESession); static void limHandleSmeReaasocResult(tpAniSirGlobal, tSirResultCodes, tANI_U16, tpPESession); void limProcessMlmScanCnf(tpAniSirGlobal, tANI_U32 *); @@ -1068,8 +1072,15 @@ limProcessMlmReassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) } sirStoreU16N((tANI_U8 *) &pSirSmeReassocInd->messageType, eWNI_SME_REASSOC_IND); - limReassocIndSerDes(pMac, (tpLimMlmReassocInd) pMsgBuf, - (tANI_U8 *) &(pSirSmeReassocInd->length), psessionEntry); + if (limReassocIndSerDes(pMac, (tpLimMlmReassocInd) pMsgBuf, + (tANI_U8 *) &(pSirSmeReassocInd->length), + psessionEntry, sizeof(tSirSmeReassocInd)) + != eSIR_SUCCESS) + { + limLog(pMac, LOGE,FL(" Received SME message with invalid rem length")); + vos_mem_free(pSirSmeReassocInd); + return; + } // Required for indicating the frames to upper layer pSirSmeReassocInd->assocReqLength = ((tpLimMlmReassocInd) pMsgBuf)->assocReqLength; @@ -1141,8 +1152,14 @@ limProcessMlmAuthInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) return; } limCopyU16((tANI_U8 *) &pSirSmeAuthInd->messageType, eWNI_SME_AUTH_IND); - limAuthIndSerDes(pMac, (tpLimMlmAuthInd) pMsgBuf, - (tANI_U8 *) &(pSirSmeAuthInd->length)); + if (limAuthIndSerDes(pMac, (tpLimMlmAuthInd) pMsgBuf, + (tANI_U8 *) &(pSirSmeAuthInd->length), + sizeof(tSirSmeAuthInd)) != eSIR_SUCCESS) + { + limLog(pMac, LOGE,FL(" Received SME message with invalid rem length")); + vos_mem_free(pSirSmeAuthInd); + return; + } msgQ.type = eWNI_SME_AUTH_IND; msgQ.bodyptr = pSirSmeAuthInd; msgQ.bodyval = 0; @@ -1968,6 +1985,12 @@ void limProcessMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession limProcessBtAmpApMlmAddStaRsp(pMac, limMsgQ,psessionEntry); return; } +#ifdef WLAN_FEATURE_LFR_MBB + if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) { + lim_process_sta_mlm_add_sta_rsp_mbb(pMac, limMsgQ, psessionEntry); + return; + } +#endif limProcessStaMlmAddStaRsp(pMac, limMsgQ,psessionEntry); } void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession psessionEntry) @@ -2145,6 +2168,13 @@ void limProcessStaMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi tpDphHashNode pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); tSirResultCodes statusCode = eSIR_SME_SUCCESS; +#ifdef WLAN_FEATURE_LFR_MBB + if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) { + lim_process_sta_mlm_del_bss_rsp_mbb(pMac, limMsgQ, psessionEntry); + return; + } +#endif + if (NULL == pDelBssParams) { limLog( pMac, LOGE, FL( "Invalid body pointer in message")); @@ -2418,6 +2448,13 @@ void limProcessStaMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi tpDeleteStaParams pDelStaParams = (tpDeleteStaParams) limMsgQ->bodyptr; tpDphHashNode pStaDs = NULL; +#ifdef WLAN_FEATURE_LFR_MBB + if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) { + lim_process_sta_mlm_del_sta_rsp_mbb(pMac, limMsgQ, psessionEntry); + return; + } +#endif + if(NULL == pDelStaParams ) { limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); @@ -3417,9 +3454,16 @@ void limProcessMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) else limProcessApMlmAddBssRsp( pMac,limMsgQ); } - else + else { +#ifdef WLAN_FEATURE_LFR_MBB + if (pMac->ft.ftSmeContext.is_preauth_lfr_mbb) { + lim_process_sta_mlm_add_bss_rsp_mbb(pMac, limMsgQ, psessionEntry); + return; + } +#endif /* Called while processing assoc response */ limProcessStaMlmAddBssRsp( pMac, limMsgQ,psessionEntry); + } } if(limIsInMCC(pMac)) diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c index 81b112e6dd4..a3d8ef423d5 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -669,7 +669,7 @@ limIndicateProbeReqToHDD(tpAniSirGlobal pMac, tANI_U8 *pBd, //send the probe req to SME. limSendSmeMgmtFrameInd( pMac, psessionEntry->smeSessionId, pBd, - psessionEntry, 0); + psessionEntry, WDA_GET_RX_RSSI_DB(pBd)); #ifdef WLAN_FEATURE_P2P_INTERNAL limSendP2PProbeResponse(pMac, pBd, psessionEntry); #endif diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c index cead21d75b1..346585cf75e 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -76,6 +76,10 @@ #include <limFT.h> #endif +#ifdef WLAN_FEATURE_LFR_MBB +#include "lim_mbb.h" +#endif + #define JOIN_FAILURE_TIMEOUT 1000 // in msecs /* This overhead is time for sending NOA start to host in case of GO/sending NULL data & receiving ACK @@ -243,7 +247,7 @@ __limIsSmeAssocCnfValid(tpSirSmeAssocCnf pAssocCnf) * @return Total IE length */ -static tANI_U16 +tANI_U16 __limGetSmeJoinReqSizeForAlloc(tANI_U8 *pBuf) { tANI_U16 len = 0; @@ -1939,6 +1943,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) handleHTCapabilityandHTInfo(pMac, psessionEntry); /* Copy The channel Id to the session Table */ psessionEntry->currentOperChannel = pSmeJoinReq->bssDescription.channelId; + psessionEntry->force_24ghz_in_ht20 = pSmeJoinReq->force_24ghz_in_ht20; psessionEntry->htSupportedChannelWidthSet = (pSmeJoinReq->cbMode)?1:0; // This is already merged value of peer and self - done by csr in csrGetCBModeFromIes psessionEntry->htRecommendedTxWidthSet = psessionEntry->htSupportedChannelWidthSet; psessionEntry->htSecondaryChannelOffset = pSmeJoinReq->cbMode; @@ -1962,8 +1967,10 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /*Store Persona */ psessionEntry->pePersona = pSmeJoinReq->staPersona; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - FL("PE PERSONA=%d cbMode %u"), psessionEntry->pePersona, - pSmeJoinReq->cbMode); + FL("PE PERSONA=%d cbMode %u force_24ghz_in_ht20 %d"), + psessionEntry->pePersona, + pSmeJoinReq->cbMode, + psessionEntry->force_24ghz_in_ht20); /* Copy the SSID from smejoinreq to session entry */ psessionEntry->ssId.length = pSmeJoinReq->ssId.length; @@ -2088,6 +2095,14 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) " max tx = %d", regMax, localPowerConstraint, psessionEntry->maxTxPower ); + if (pSmeJoinReq->powerCap.maxTxPower > psessionEntry->maxTxPower) + { + pSmeJoinReq->powerCap.maxTxPower = psessionEntry->maxTxPower; + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, + "Update MaxTxPower in join Req to %d", + pSmeJoinReq->powerCap.maxTxPower); + } + if (pMac->lim.gLimCurrentBssUapsd) { pMac->lim.gUapsdPerAcBitmask = psessionEntry->pLimJoinReq->uapsdPerAcBitmask; @@ -4018,8 +4033,10 @@ __limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsg */ pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; limLog(pMac, LOG1, FL("sending Assoc Rsp frame to STA (assoc id=%d) "), pStaDs->assocId); - limSendAssocRspMgmtFrame( pMac, eSIR_SUCCESS, pStaDs->assocId, pStaDs->staAddr, - pStaDs->mlmStaContext.subType, pStaDs, psessionEntry); + limSendAssocRspMgmtFrame(pMac, eSIR_SUCCESS, pStaDs->assocId, + pStaDs->staAddr, + pStaDs->mlmStaContext.subType, pStaDs, + psessionEntry, NULL); goto end; } // (assocCnf.statusCode == eSIR_SME_SUCCESS) else @@ -4056,7 +4073,99 @@ end: } /*** end __limProcessSmeAssocCnfNew() ***/ +#ifdef SAP_AUTH_OFFLOAD +/** + * __lim_process_sme_assoc_offload_cnf() station connection confirmation + * message from SME. + * @pMac: SirGlobal handler + * @msgType: message type + * @pMsgBuf: message body + * + * This function handles the station connect confirm of + * Software AP authentication offload feature + * + * Return: None + */ + static void +__lim_process_sme_assoc_offload_cnf(tpAniSirGlobal pmac, + tANI_U32 msg_type, + tANI_U32 *pmsg_buf) +{ + tSirSmeAssocCnf assoc_cnf; + tpDphHashNode sta_ds = NULL; + tpPESession psession_entry= NULL; + tANI_U8 session_id; + tANI_U16 aid=0; + + if (pmsg_buf == NULL) + { + limLog(pmac, LOGE, FL("pmsg_buf is NULL ")); + return; + } + + if ((limAssocCnfSerDes(pmac, &assoc_cnf, (tANI_U8 *) pmsg_buf) == + eSIR_FAILURE) || !__limIsSmeAssocCnfValid(&assoc_cnf)) + { + limLog(pmac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message ")); + return; + } + if((psession_entry = + peFindSessionByBssid(pmac, assoc_cnf.bssId, &session_id))== NULL) + { + limLog(pmac, LOGE, FL("session does not exist for given bssId")); + goto end; + } + + if ((!LIM_IS_AP_ROLE(psession_entry)) || + ((psession_entry->limSmeState != eLIM_SME_NORMAL_STATE) && + (psession_entry->limSmeState != eLIM_SME_NORMAL_CHANNEL_SCAN_STATE))) + { + limLog(pmac, LOGE, + FL("Received unexpected message %X in state %X, in role %X"), + msg_type, psession_entry->limSmeState, + GET_LIM_SYSTEM_ROLE(psession_entry)); + goto end; + } + sta_ds = dphGetHashEntry(pmac, + assoc_cnf.aid, + &psession_entry->dph.dphHashTable); + if (sta_ds != NULL) + { + aid = sta_ds->assocId; + /* Deactivate/delete CNF_WAIT timer since ASSOC_CNF + * has been received */ + limDeactivateAndChangePerStaIdTimer(pmac, + eLIM_CNF_WAIT_TIMER, + aid); + } + if (assoc_cnf.statusCode == eSIR_SME_SUCCESS) + { + sta_ds->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + limLog(pmac, LOG1, FL("Set mlmState to eLIM_MLM_LINK_ESTABLISHED_STATE")); + } + +end: + if((psession_entry != NULL) && (sta_ds != NULL)) + { + if ( psession_entry->parsedAssocReq[aid] != NULL ) + { + if ( ((tpSirAssocReq) + (psession_entry->parsedAssocReq[aid]))->assocReqFrame) + { + vos_mem_free(((tpSirAssocReq) + (psession_entry->parsedAssocReq[aid]))->assocReqFrame); + ((tpSirAssocReq) + (psession_entry->parsedAssocReq[aid]))->assocReqFrame = + NULL; + } + vos_mem_free(psession_entry->parsedAssocReq[aid]); + psession_entry->parsedAssocReq[aid] = NULL; + } + } + +} /*** end __lim_process_sme_assoc_offload_cnf() ***/ +#endif /* SAP_AUTH_OFFLOAD */ static void @@ -5519,57 +5628,6 @@ static void lim_register_mgmt_frame_ind_cb(tpAniSirGlobal pMac, limLog(pMac, LOGE, FL("sme_req->callback is null")); } -static void lim_delba_con_status(tpAniSirGlobal pMac, - void *msg_buf) -{ - tpSmeDelBAPeerInd delba_params; - tpDphHashNode pSta; - tANI_U16 aid; - tLimBAState curBaState; - tpPESession psessionEntry; - tANI_U8 sessionId; - - delba_params = (tpSmeDelBAPeerInd)msg_buf; - - psessionEntry = peFindSessionByBssid(pMac, delba_params->bssId, &sessionId); - if (!psessionEntry) - { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) - return; - } - - pSta = dphLookupHashEntry(pMac, delba_params->bssId, &aid, - &psessionEntry->dph.dphHashTable); - if(!pSta) - { - limLog(pMac, LOGE, - FL("STA context not found - ignoring BA Delete IND from HAL")); - return; - } - - LIM_GET_STA_BA_STATE(pSta, delba_params->baTID, &curBaState); - if( eLIM_BA_STATE_IDLE != curBaState ) - { - limLog(pMac, LOGE, - FL("Received unexpected BA Delete IND when STA BA state is %d"), - curBaState); - return; - } - - if(eSIR_SUCCESS != limPostMlmDelBAReq(pMac, pSta, - delba_params->baDirection, - delba_params->baTID, - eSIR_MAC_PEER_REJECT_MECHANISIM_REASON, - psessionEntry)) { - limLog(pMac, LOGE, FL("Post DEL BA request failed")); - } - else - { - limLog(pMac, LOG1, FL(" Delete BA session StaId %d on tid %d"), - delba_params->staIdx, delba_params->baTID); - } -} - /** * limProcessSmeReqMessages() * @@ -5757,7 +5815,14 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) limLog(pMac, LOG1, FL("Received ASSOC_CNF message")); else limLog(pMac, LOG1, FL("Received REASSOC_CNF message")); +#ifdef SAP_AUTH_OFFLOAD + if (pMac->sap_auth_offload) + __lim_process_sme_assoc_offload_cnf(pMac, pMsg->type, pMsgBuf); + else + __limProcessSmeAssocCnfNew(pMac, pMsg->type, pMsgBuf); +#else __limProcessSmeAssocCnfNew(pMac, pMsg->type, pMsgBuf); +#endif /* SAP_AUTH_OFFLOAD */ break; case eWNI_SME_ADDTS_REQ: @@ -5859,6 +5924,13 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) break; #endif +#ifdef WLAN_FEATURE_LFR_MBB + case eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ: + lim_process_pre_auth_reassoc_req(pMac, pMsg); + bufConsumed = FALSE; + break; +#endif + #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) case eWNI_SME_ESE_ADJACENT_AP_REPORT: limProcessAdjacentAPRepMsg ( pMac, pMsgBuf ); @@ -5916,9 +5988,6 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) case eWNI_SME_REGISTER_MGMT_FRAME_CB: lim_register_mgmt_frame_ind_cb(pMac, pMsgBuf); break; - case eWNI_SME_DEL_TEST_BA: - lim_delba_con_status(pMac, pMsgBuf); - break; default: vos_mem_free((v_VOID_t*)pMsg->bodyptr); pMsg->bodyptr = NULL; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c index f4f668a916a..bd695ed9252 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -203,6 +203,10 @@ limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, } } + + /* Update HS 2.0 Information Element */ + sir_copy_hs20_ie(&psessionEntry->hs20vendor_ie, + &pBeaconStruct->hs20vendor_ie); vos_mem_free(pBeaconStruct); return; } /****** end limExtractApCapability() ******/ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c index ae588284b56..9f88436bf22 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -473,10 +473,6 @@ limDeletePreAuthNode(tpAniSirGlobal pMac, tSirMacAddr macAddr) } /*** end limDeletePreAuthNode() ***/ - - - - /** * limRestoreFromPreAuthState * @@ -515,13 +511,6 @@ limRestoreFromAuthState(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U1 /* Update PE session ID*/ mlmAuthCnf.sessionId = sessionEntry->peSessionId; - - /// Free up buffer allocated - /// for pMac->lim.gLimMlmAuthReq - vos_mem_free(pMac->lim.gpLimMlmAuthReq); - pMac->lim.gpLimMlmAuthReq = NULL; - - sessionEntry->limMlmState = sessionEntry->limPrevMlmState; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, sessionEntry->peSessionId, sessionEntry->limMlmState)); /* Set the authAckStatus status flag as sucess as @@ -548,9 +537,25 @@ limRestoreFromAuthState(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U1 pMac->lim.gLimPreAuthChannelNumber = 0; } - limPostSmeMessage(pMac, + if ((protStatusCode == eSIR_MAC_MAX_ASSOC_STA_REACHED_STATUS) + && (sessionEntry->sta_auth_retries_for_code17 < + pMac->sta_auth_retries_for_code17)) { + limLog(pMac, LOG1, FL("Retry Auth ")); + limDoSendAuthMgmtFrame(pMac, sessionEntry); + sessionEntry->sta_auth_retries_for_code17++; + } else { + /// Free up buffer allocated + /// for pMac->lim.gLimMlmAuthReq + vos_mem_free(pMac->lim.gpLimMlmAuthReq); + pMac->lim.gpLimMlmAuthReq = NULL; + + sessionEntry->limMlmState = sessionEntry->limPrevMlmState; + + limPostSmeMessage(pMac, LIM_MLM_AUTH_CNF, (tANI_U32 *) &mlmAuthCnf); + sessionEntry->sta_auth_retries_for_code17 = 0; + } } /*** end limRestoreFromAuthState() ***/ @@ -614,7 +619,10 @@ limEncryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 keyId, tANI_U8 *pKey, tANI_U8 * tANI_U8 *pEncrBody, tANI_U32 keyLength) { tANI_U8 seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH]; + tANI_U16 frame_len; + frame_len = ((tpSirMacAuthFrameBody)pPlainText)->length + + SIR_MAC_AUTH_FRAME_INFO_LEN + SIR_MAC_CHALLENGE_ID_LEN; keyLength += 3; // Bytes 0-2 of seed is IV @@ -625,15 +633,15 @@ limEncryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 keyId, tANI_U8 *pKey, tANI_U8 * vos_mem_copy((tANI_U8 *) &seed[3], pKey, keyLength - 3); // Compute CRC-32 and place them in last 4 bytes of plain text - limComputeCrc32(icv, pPlainText, sizeof(tSirMacAuthFrameBody)); + limComputeCrc32(icv, pPlainText, frame_len); - vos_mem_copy( pPlainText + sizeof(tSirMacAuthFrameBody), + vos_mem_copy( pPlainText + frame_len, icv, SIR_MAC_WEP_ICV_LENGTH); // Run RC4 on plain text with the seed limRC4(pEncrBody + SIR_MAC_WEP_IV_LENGTH, (tANI_U8 *) pPlainText, seed, keyLength, - LIM_ENCR_AUTH_BODY_LEN - SIR_MAC_WEP_IV_LENGTH); + frame_len + SIR_MAC_WEP_ICV_LENGTH); // Prepare IV pEncrBody[0] = seed[0]; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.h index 1fc227478d7..2526f4e4c12 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.h @@ -42,6 +42,18 @@ #define LIM_ENCR_AUTH_BODY_LEN (sizeof(tSirMacAuthFrameBody) + \ SIR_MAC_WEP_IV_LENGTH + \ SIR_MAC_WEP_ICV_LENGTH) + +#define LIM_ENCR_AUTH_BODY_LEN_SAP (SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH + \ + SIR_MAC_CHALLENGE_ID_LEN + \ + SIR_MAC_AUTH_FRAME_INFO_LEN + \ + SIR_MAC_WEP_IV_LENGTH + \ + SIR_MAC_WEP_ICV_LENGTH) + +#define LIM_ENCR_AUTH_INFO_LEN (SIR_MAC_AUTH_FRAME_INFO_LEN +\ + SIR_MAC_WEP_IV_LENGTH + \ + SIR_MAC_WEP_ICV_LENGTH + \ + SIR_MAC_CHALLENGE_ID_LEN) + struct tLimPreAuthNode; tANI_U8 limIsAuthAlgoSupported(tpAniSirGlobal, tAniAuthType, tpPESession); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c index 1799c447e3b..feb335124a4 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1384,7 +1384,8 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, tANI_U16 aid, tSirMacAddr peerMacAddr, tANI_U8 subType, - tpDphHashNode pSta,tpPESession psessionEntry) + tpDphHashNode pSta,tpPESession psessionEntry, + assoc_rsp_tx_context *tx_complete_context) { static tDot11fAssocResponse frm; tANI_U8 *pFrame, *macAddr; @@ -1763,14 +1764,29 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, if (IS_FEATURE_SUPPORTED_BY_FW(ENHANCED_TXBD_COMPLETION)) { - limLog(pMac, LOG1, FL("Re/AssocRsp - txBdToken %u"), pMac->lim.txBdToken); + limLog(pMac, LOG1, FL("Re/AssocRsp - txBdToken %u"), + pMac->lim.txBdToken); /// Queue Association Response frame in high priority WQ - halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, + if (tx_complete_context) + { + tx_complete_context->txBdToken = pMac->lim.txBdToken; + halstatus = halTxFrameWithTxComplete(pMac, pPacket, + (tANI_U16) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7,//SMAC_SWBD_TX_TID_MGMT_HIGH, + limTxComplete, pFrame, limAssocRspTxCompleteCnf, + txFlag, pMac->lim.txBdToken); + } + else + halstatus = halTxFrameWithTxComplete(pMac, pPacket, + (tANI_U16) nBytes, HAL_TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,//SMAC_SWBD_TX_TID_MGMT_HIGH, limTxComplete, pFrame, limTxBdComplete, - txFlag, pMac->lim.txBdToken ); + txFlag, pMac->lim.txBdToken); + pMac->lim.txBdToken++; } else @@ -3714,7 +3730,7 @@ void limSendAuthMgmtFrame(tpAniSirGlobal pMac, tpSirMacAuthFrameBody pAuthFrameBody, tSirMacAddr peerMacAddr, - tANI_U8 wepBit, + tANI_U8 wep_challenge_len, tpPESession psessionEntry, tAniBool waitForAck ) @@ -3739,7 +3755,7 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, pAuthFrameBody->authStatusCode, (pAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS), MAC_ADDR_ARRAY(peerMacAddr)); - if (wepBit == LIM_WEP_IN_FC) + if (wep_challenge_len) { /// Auth frame3 to be sent with encrypted framebody /** @@ -3749,10 +3765,8 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, * 128 bytes for challenge text and 4 bytes each for * IV & ICV. */ - - frameLen = sizeof(tSirMacMgmtHdr) + LIM_ENCR_AUTH_BODY_LEN; - - bodyLen = LIM_ENCR_AUTH_BODY_LEN; + bodyLen = wep_challenge_len + LIM_ENCR_AUTH_INFO_LEN; + frameLen = sizeof(tSirMacMgmtHdr) + bodyLen; } // if (wepBit == LIM_WEP_IN_FC) else { @@ -3817,9 +3831,11 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, * for challenge text. */ + bodyLen = SIR_MAC_AUTH_FRAME_INFO_LEN + + SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH + + SIR_MAC_CHALLENGE_ID_LEN; frameLen = sizeof(tSirMacMgmtHdr) + - sizeof(tSirMacAuthFrame); - bodyLen = sizeof(tSirMacAuthFrameBody); + bodyLen; } break; @@ -3880,7 +3896,10 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, } pMacHdr = ( tpSirMacMgmtHdr ) pFrame; - pMacHdr->fc.wep = wepBit; + if (wep_challenge_len) + pMacHdr->fc.wep = LIM_WEP_IN_FC; + else + pMacHdr->fc.wep = LIM_NO_WEP_IN_FC; // Prepare BSSId if( (psessionEntry->limSystemRole == eLIM_AP_ROLE)|| (psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE) ) @@ -3893,7 +3912,7 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, /// Prepare Authentication frame body pBody = pFrame + sizeof(tSirMacMgmtHdr); - if (wepBit == LIM_WEP_IN_FC) + if (wep_challenge_len) { vos_mem_copy(pBody, (tANI_U8 *) pAuthFrameBody, bodyLen); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c index 85c577b1dd5..69d186eedd6 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -54,7 +54,7 @@ #include "limSendSmeRspMessages.h" #include "limIbssPeerMgmt.h" #include "limSessionUtils.h" - +#include "lim_mbb.h" /** * limSendSmeRsp() @@ -160,6 +160,29 @@ limSendSmeRsp(tpAniSirGlobal pMac, tANI_U16 msgType, limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); } /*** end limSendSmeRsp() ***/ +/** + * lim_add_bss_info() - copy data from session entry to join rsp + * @session_entry: PE Session Info + * @sme_join_rsp: Join response buffer to be filled up + * + * Return: None + */ +void lim_add_bss_info(tpDphHashNode sta_ds, + tpSirSmeJoinRsp sme_join_rsp) +{ + struct parsed_ies *parsed_ies = &sta_ds->parsed_ies; + + if (parsed_ies->hs20vendor_ie.present) + sme_join_rsp->hs20vendor_ie = parsed_ies->hs20vendor_ie; + if (parsed_ies->vht_caps.present) + sme_join_rsp->vht_caps = parsed_ies->vht_caps; + if (parsed_ies->ht_caps.present) + sme_join_rsp->ht_caps = parsed_ies->ht_caps; + if (parsed_ies->ht_operation.present) + sme_join_rsp->ht_operation = parsed_ies->ht_operation; + if (parsed_ies->vht_operation.present) + sme_join_rsp->vht_operation = parsed_ies->vht_operation; +} /** * limSendSmeJoinReassocRspAfterResume() @@ -382,6 +405,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, pSirSmeJoinRsp->bcastSig = pStaDs->ucBcastSig; pSirSmeJoinRsp->maxRateFlags = limGetMaxRateFlags(pStaDs, psessionEntry); + lim_add_bss_info(pStaDs, pSirSmeJoinRsp); PELOGE(limLog(pMac, LOG1, FL("maxRateFlags: %x"), pSirSmeJoinRsp->maxRateFlags);) } @@ -2815,10 +2839,8 @@ void limHandleDeleteBssRsp(tpAniSirGlobal pMac,tpSirMsgQ MsgQ) { limProcessSmeDelBssRsp(pMac, MsgQ->bodyval,psessionEntry); } - else limProcessMlmDelBssRsp(pMac,MsgQ,psessionEntry); - } #ifdef WLAN_FEATURE_VOWIFI_11R diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c index 3fb524bf1ea..6e14ba5fe00 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1017,6 +1017,14 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) limLog(pMac, LOGE, FL("remaining len %d is too short"), len); return eSIR_FAILURE; } + // Extract cbMode + pJoinReq->force_24ghz_in_ht20 = *pBuf++; + len--; + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + { + limLog(pMac, LOGE, FL("remaining len %d is too short"), len); + return eSIR_FAILURE; + } // Extract uapsdPerAcBitmask pJoinReq->uapsdPerAcBitmask = *pBuf++; @@ -1640,9 +1648,13 @@ limDisassocCnfSerDes(tpAniSirGlobal pMac, tpSirSmeDisassocCnf pDisassocCnf, tANI return eSIR_SUCCESS; } /*** end limDisassocCnfSerDes() ***/ +static inline int CheckRemainingLength(tANI_U16 mLen, tANI_U16 len) +{ + if (mLen > (len - sizeof(tANI_U16))) + return eSIR_FAILURE; - - + return eSIR_SUCCESS; +} /**--------------------------------------------------------------- \fn limReassocIndSerDes @@ -1654,11 +1666,15 @@ limDisassocCnfSerDes(tpAniSirGlobal pMac, tpSirSmeDisassocCnf pDisassocCnf, tANI \param pReassocInd - Pointer to the received tLimMlmReassocInd \param pBuf - Pointer to serialized buffer \param psessionEntry - pointer to PE session entry +\param len - size of tSirSmeReassocInd structure \ -\return None +\return tSirRietStatus Indicates whether message is successfully +\ de-serialized (eSIR_SUCCESS) or +\ not (eSIR_FAILURE) ------------------------------------------------------------------*/ -void -limReassocIndSerDes(tpAniSirGlobal pMac, tpLimMlmReassocInd pReassocInd, tANI_U8 *pBuf, tpPESession psessionEntry) +tSirRetStatus +limReassocIndSerDes(tpAniSirGlobal pMac, tpLimMlmReassocInd pReassocInd, + tANI_U8 *pBuf, tpPESession psessionEntry, tANI_U16 len) { tANI_U8 *pLen = pBuf; tANI_U16 mLen = 0; @@ -1669,68 +1685,97 @@ limReassocIndSerDes(tpAniSirGlobal pMac, tpLimMlmReassocInd pReassocInd, tANI_U8 mLen = sizeof(tANI_U32); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; + pBuf += sizeof(tANI_U16); *pBuf++ = psessionEntry->smeSessionId; mLen += sizeof(tANI_U8); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; // Fill in peerMacAddr vos_mem_copy( pBuf, pReassocInd->peerMacAddr, sizeof(tSirMacAddr)); pBuf += sizeof(tSirMacAddr); mLen += sizeof(tSirMacAddr); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; // Fill in oldMacAddr vos_mem_copy( pBuf, pReassocInd->currentApAddr, sizeof(tSirMacAddr)); pBuf += sizeof(tSirMacAddr); mLen += sizeof(tSirMacAddr); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; // Fill in aid limCopyU16(pBuf, pReassocInd->aid); pBuf += sizeof(tANI_U16); mLen += sizeof(tANI_U16); - + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; + // Fill in bssId vos_mem_copy( pBuf, psessionEntry->bssId, sizeof(tSirMacAddr)); pBuf += sizeof(tSirMacAddr); mLen += sizeof(tSirMacAddr); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; // Fill in staId limCopyU16(pBuf, psessionEntry->staId); pBuf += sizeof(tANI_U16); mLen += sizeof(tANI_U16); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; // Fill in authType limCopyU32(pBuf, pReassocInd->authType); pBuf += sizeof(tAniAuthType); mLen += sizeof(tAniAuthType); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; // Fill in ssId vos_mem_copy( pBuf, (tANI_U8 *) &(pReassocInd->ssId), pReassocInd->ssId.length + 1); pBuf += 1 + pReassocInd->ssId.length; mLen += pReassocInd->ssId.length + 1; + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; // Fill in rsnIE limCopyU16(pBuf, pReassocInd->rsnIE.length); pBuf += sizeof(tANI_U16); mLen += sizeof(tANI_U16); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; + vos_mem_copy( pBuf, (tANI_U8 *) &(pReassocInd->rsnIE.rsnIEdata), pReassocInd->rsnIE.length); pBuf += pReassocInd->rsnIE.length; mLen += pReassocInd->rsnIE.length; + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; // Fill in addIE limCopyU16(pBuf, pReassocInd->addIE.length); pBuf += sizeof(tANI_U16); mLen += sizeof(tANI_U16); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; vos_mem_copy( pBuf, (tANI_U8*) &(pReassocInd->addIE.addIEdata), pReassocInd->addIE.length); pBuf += pReassocInd->addIE.length; mLen += pReassocInd->addIE.length; - + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; limCopyU32(pBuf, pReassocInd->spectrumMgtIndicator); pBuf += sizeof(tAniBool); mLen += sizeof(tAniBool); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; if (pReassocInd->spectrumMgtIndicator == eSIR_TRUE) { @@ -1739,10 +1784,14 @@ limReassocIndSerDes(tpAniSirGlobal pMac, tpLimMlmReassocInd pReassocInd, tANI_U8 *pBuf = pReassocInd->powerCap.maxTxPower; pBuf++; mLen += sizeof(tSirMacPowerCapInfo); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; *pBuf = pReassocInd->supportedChannels.numChnl; pBuf++; mLen++; + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; vos_mem_copy( pBuf, (tANI_U8 *) &(pReassocInd->supportedChannels.channelList), @@ -1750,16 +1799,23 @@ limReassocIndSerDes(tpAniSirGlobal pMac, tpLimMlmReassocInd pReassocInd, tANI_U8 pBuf += pReassocInd->supportedChannels.numChnl; mLen += pReassocInd->supportedChannels.numChnl; + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; + } limCopyU32(pBuf, pReassocInd->WmmStaInfoPresent); pBuf += sizeof(tANI_U32); mLen += sizeof(tANI_U32); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; // Fill in length of SME_REASSOC_IND message limCopyU16(pLen, mLen); PELOG1(limLog(pMac, LOG1, FL("Sending SME_REASSOC_IND length %d bytes:"), mLen);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, mLen);) + + return eSIR_SUCCESS; } /*** end limReassocIndSerDes() ***/ @@ -1782,12 +1838,15 @@ limReassocIndSerDes(tpAniSirGlobal pMac, tpLimMlmReassocInd pReassocInd, tANI_U8 * * @param pAuthInd Pointer to tSirSmeAuthInd being sent * @param pBuf Pointer to serialized buffer + * @param len size of tSirSmeAuthInd structure * - * @return None + * @return tSirRetStatus Indicates whether message is successfully + * de-serialized (eSIR_SUCCESS) or + * not (eSIR_FAILURE) */ -void -limAuthIndSerDes(tpAniSirGlobal pMac, tpLimMlmAuthInd pAuthInd, tANI_U8 *pBuf) +tSirRetStatus +limAuthIndSerDes(tpAniSirGlobal pMac, tpLimMlmAuthInd pAuthInd, tANI_U8 *pBuf, tANI_U16 len) { tANI_U8 *pLen = pBuf; tANI_U16 mLen = 0; @@ -1797,27 +1856,39 @@ limAuthIndSerDes(tpAniSirGlobal pMac, tpLimMlmAuthInd pAuthInd, tANI_U8 *pBuf) #endif mLen = sizeof(tANI_U32); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; pBuf += sizeof(tANI_U16); *pBuf++ = pAuthInd->sessionId; mLen += sizeof(tANI_U8); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; // BTAMP TODO: Fill in bssId vos_mem_set(pBuf, sizeof(tSirMacAddr), 0); pBuf += sizeof(tSirMacAddr); mLen += sizeof(tSirMacAddr); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; vos_mem_copy( pBuf, pAuthInd->peerMacAddr, sizeof(tSirMacAddr)); pBuf += sizeof(tSirMacAddr); mLen += sizeof(tSirMacAddr); + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; limCopyU32(pBuf, pAuthInd->authType); pBuf += sizeof(tAniAuthType); mLen += sizeof(tAniAuthType); - + if (CheckRemainingLength(mLen, len) == eSIR_FAILURE) + return eSIR_FAILURE; + limCopyU16(pLen, mLen); PELOG1(limLog(pMac, LOG1, FL("Sending SME_AUTH_IND length %d bytes:"), mLen);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, mLen);) + + return eSIR_SUCCESS; } /*** end limAuthIndSerDes() ***/ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.h index a43bc131399..29aff5a8519 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -50,13 +50,15 @@ tSirRetStatus limStartBssReqSerDes(tpAniSirGlobal, tpSirSmeStartBssReq, tANI_U tSirRetStatus limStopBssReqSerDes(tpAniSirGlobal, tpSirSmeStopBssReq, tANI_U8 *); tSirRetStatus limJoinReqSerDes(tpAniSirGlobal, tpSirSmeJoinReq, tANI_U8 *); void limAssocIndSerDes(tpAniSirGlobal, tpLimMlmAssocInd, tANI_U8 *, tpPESession); -void limReassocIndSerDes(tpAniSirGlobal, tpLimMlmReassocInd, tANI_U8 *, tpPESession psessionEntry); +tSirRetStatus limReassocIndSerDes(tpAniSirGlobal, tpLimMlmReassocInd, tANI_U8 *, + tpPESession psessionEntry, tANI_U16 len); tSirRetStatus limAssocCnfSerDes(tpAniSirGlobal, tpSirSmeAssocCnf, tANI_U8 *); tSirRetStatus limDisassocCnfSerDes(tpAniSirGlobal, tpSirSmeDisassocCnf, tANI_U8 *); tSirRetStatus limSetContextReqSerDes(tpAniSirGlobal, tpSirSmeSetContextReq, tANI_U8 *); tSirRetStatus limDisassocReqSerDes(tpAniSirGlobal, tSirSmeDisassocReq *, tANI_U8 *); tSirRetStatus limDeauthReqSerDes(tpAniSirGlobal, tSirSmeDeauthReq *, tANI_U8 *); -void limAuthIndSerDes(tpAniSirGlobal, tpLimMlmAuthInd, tANI_U8 *); +tSirRetStatus limAuthIndSerDes(tpAniSirGlobal, tpLimMlmAuthInd, tANI_U8 *, + tANI_U16 len); void limStatSerDes(tpAniSirGlobal, tpAniStaStatStruct, tANI_U8 *); void limGetSessionInfo(tpAniSirGlobal pMac, tANI_U8 *, tANI_U8 *, tANI_U16 *); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c index 58b757186d7..23c53bd616d 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2014, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -236,6 +236,20 @@ tpPESession peFindSessionByBssid(tpAniSirGlobal pMac, tANI_U8* bssid, tANI_ } +tANI_S8 limGetInfraSessionId(tpAniSirGlobal pMac) +{ + tANI_U8 i; + for (i = 0; i < pMac->lim.maxBssId; i++) + { + if ((pMac->lim.gpSession[i].valid) && + (pMac->lim.gpSession[i].limSystemRole == eLIM_STA_ROLE)) + { + return i; + } + } + limLog(pMac, LOG4, FL("Session lookup fails for infra mode")); + return -1; +} /*-------------------------------------------------------------------------- \brief peFindSessionByBssIdx() - looks up the PE session given the bssIdx. diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c index 02372713712..1e474218b12 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -64,6 +64,10 @@ convert ACTIVE DFS channel to DFS channels */ #define ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT 1000 +#ifdef WLAN_FEATURE_LFR_MBB +#define PREAUTH_REASSOC_TIMEOUT 500 +#endif + /** * limCreateTimers() * @@ -624,6 +628,34 @@ limCreateTimers(tpAniSirGlobal pMac) } #endif +#ifdef WLAN_FEATURE_LFR_MBB + cfgValue = PREAUTH_REASSOC_TIMEOUT; + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + if (tx_timer_create(&pMac->lim.limTimers.glim_pre_auth_mbb_rsp_timer, + "PREAUTH MBB RSP TIMEOUT", + limTimerHandler, SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not create PREAUTH_MBB_RSP timer")); + goto err_timer; + } + + cfgValue = PREAUTH_REASSOC_TIMEOUT; + cfgValue = SYS_MS_TO_TICKS(cfgValue); + + if (tx_timer_create(&pMac->lim.limTimers.glim_reassoc_mbb_rsp_timer, + "REASSOC MBB RSP TIMEOUT", + limTimerHandler, SIR_LIM_REASSOC_MBB_RSP_TIMEOUT, + cfgValue, 0, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + limLog(pMac, LOGP, FL("could not create REASSOC_MBB_RSP timer")); + goto err_timer; + } +#endif + #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) cfgValue = 5000; cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -712,6 +744,10 @@ limCreateTimers(tpAniSirGlobal pMac) tx_timer_delete(&pMac->lim.limTimers.gLimEseTsmTimer); #endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD */ tx_timer_delete(&pMac->lim.limTimers.gLimFTPreAuthRspTimer); +#ifdef WLAN_FEATURE_LFR_MBB + tx_timer_delete(&pMac->lim.limTimers.glim_pre_auth_mbb_rsp_timer); + tx_timer_delete(&pMac->lim.limTimers.glim_reassoc_mbb_rsp_timer); +#endif tx_timer_delete(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer); while(((tANI_S32)--i) >= 0) { @@ -1730,6 +1766,30 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) } break; #endif + +#ifdef WLAN_FEATURE_LFR_MBB + case eLIM_PREAUTH_MBB_RSP_TIMER: + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, + NO_SESSION, eLIM_PREAUTH_MBB_RSP_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers. + glim_pre_auth_mbb_rsp_timer) != TX_SUCCESS) { + limLog(pMac, LOGP, + FL("Unable to deactivate preauth response mbb timer")); + return; + } + break; + case eLIM_REASSOC_MBB_RSP_TIMER: + MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, + NO_SESSION, eLIM_REASSOC_MBB_RSP_TIMER)); + if (tx_timer_deactivate(&pMac->lim.limTimers. + glim_reassoc_mbb_rsp_timer) != TX_SUCCESS) { + limLog(pMac, LOGP, + FL("Unable to deactivate reassoc response mbb timer")); + return; + } + break; +#endif + #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) case eLIM_TSM_TIMER: if (tx_timer_deactivate(&pMac->lim.limTimers.gLimEseTsmTimer) diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.h index 19061826dc8..eba64ac72a7 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -77,7 +77,11 @@ enum eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER, eLIM_INSERT_SINGLESHOT_NOA_TIMER, eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE, - eLIM_AUTH_RETRY_TIMER + eLIM_AUTH_RETRY_TIMER, +#ifdef WLAN_FEATURE_LFR_MBB + eLIM_PREAUTH_MBB_RSP_TIMER, + eLIM_REASSOC_MBB_RSP_TIMER +#endif }; #define LIM_DISASSOC_DEAUTH_ACK_TIMEOUT 500 diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c index 662670bac52..d33a33d93c5 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -92,6 +92,10 @@ static tANI_U8* __limTraceGetTimerString( tANI_U16 timerId ) CASE_RETURN_STRING(eLIM_INSERT_SINGLESHOT_NOA_TIMER); CASE_RETURN_STRING(eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE); CASE_RETURN_STRING(eLIM_AUTH_RETRY_TIMER); +#ifdef WLAN_FEATURE_LFR_MBB + CASE_RETURN_STRING(eLIM_PREAUTH_MBB_RSP_TIMER); + CASE_RETURN_STRING(eLIM_REASSOC_MBB_RSP_TIMER); +#endif default: return( "UNKNOWN" ); break; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h index a375494faa0..5fd9ce0702e 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -694,14 +694,16 @@ void limSendAddtsReqActionFrame(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, void limSendAddtsRspActionFrame(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tANI_U16 statusCode, tSirAddtsReqInfo *addts, tSirMacScheduleIE *pSchedule,tpPESession); -void limSendAssocRspMgmtFrame(tpAniSirGlobal, tANI_U16, tANI_U16, tSirMacAddr, tANI_U8, tpDphHashNode pSta,tpPESession); +void limSendAssocRspMgmtFrame(tpAniSirGlobal, tANI_U16, tANI_U16, tSirMacAddr, + tANI_U8, tpDphHashNode pSta,tpPESession, + assoc_rsp_tx_context *tx_complete_context); void limSendNullDataFrame(tpAniSirGlobal, tpDphHashNode); void limSendDisassocMgmtFrame(tpAniSirGlobal, tANI_U16, tSirMacAddr, tpPESession, tANI_BOOLEAN waitForAck); void limSendDeauthMgmtFrame(tpAniSirGlobal, tANI_U16, tSirMacAddr, tpPESession, tANI_BOOLEAN waitForAck); void limSendSmeDisassocDeauthNtf( tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *pCtx ); - +void limDoSendAuthMgmtFrame(tpAniSirGlobal, tpPESession); void limContinueChannelScan(tpAniSirGlobal); tSirResultCodes limMlmAddBss(tpAniSirGlobal, tLimMlmStartReq *,tpPESession psessionEntry); @@ -1072,5 +1074,15 @@ tSirRetStatus limProcessSmeSetTdls2040BSSCoexReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf); tSirRetStatus limProcessSmeDelAllTdlsPeers(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf); + +tSirRetStatus lim_process_sme_cap_tsf_req(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf); + +tSirRetStatus lim_process_sme_get_tsf_req(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf); + +tSirRetStatus lim_process_sme_del_ba_ses_req(tpAniSirGlobal pMac, + tANI_U32 *pMsgBuf); + #endif /* __LIM_TYPES_H */ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c index f8c315a8cf0..ec59de06dd2 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -59,6 +59,9 @@ #ifdef WLAN_FEATURE_11W #include "wniCfg.h" #endif +#ifdef SAP_AUTH_OFFLOAD +#include "limAssocUtils.h" +#endif /* Static global used to mark situations where pMac->lim.gLimTriggerBackgroundScanDuringQuietBss is SET * and limTriggerBackgroundScanDuringQuietBss() returned failure. In this case, we will stop data @@ -645,6 +648,13 @@ char *limMsgStr(tANI_U32 msgType) return "SIR_LIM_FT_PREAUTH_RSP_TIMEOUT"; #endif +#ifdef WLAN_FEATURE_LFR_MBB + case SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT: + return "SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT"; + case SIR_LIM_REASSOC_MBB_RSP_TIMEOUT: + return "SIR_LIM_REASSOC_MBB_RSP_TIMEOUT"; +#endif + case SIR_HAL_APP_SETUP_NTF: return "SIR_HAL_APP_SETUP_NTF"; case SIR_HAL_INITIAL_CAL_FAILED_NTF: @@ -5241,6 +5251,13 @@ void limUpdateStaRunTimeHTSwitchChnlParams( tpAniSirGlobal pMac, if( !limGetHTCapability( pMac, eHT_SUPPORTED_CHANNEL_WIDTH_SET, psessionEntry )) return; + if ((RF_CHAN_14 >= psessionEntry->currentOperChannel) && + psessionEntry->force_24ghz_in_ht20) { + limLog(pMac, LOG1, + FL("force_24_gh_in_ht20 is set and channel is 2.4 Ghz")); + return; + } + #if !defined WLAN_FEATURE_VOWIFI if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) { limLog( pMac, LOGP, FL( "Unable to get Local Power Constraint from cfg" )); @@ -8524,6 +8541,84 @@ eHalStatus limTxBdComplete(tpAniSirGlobal pMac, void *pData) return eHAL_STATUS_SUCCESS; } +eHalStatus limAssocRspTxCompleteCnf(tpAniSirGlobal pMac, void *pData) +{ + tpSirTxBdStatus pTxBdStatus; + tpDphHashNode pStaDs; + tpPESession psessionEntry; + VOS_STATUS vosStatus; + vos_list_node_t *pNode= NULL, *pNext = NULL; + assoc_rsp_tx_context *tmp_tx_context = NULL; + + if (!pData) + { + limLog(pMac, LOGE, FL("pData is NULL")); + return eHAL_STATUS_FAILURE; + } + + pTxBdStatus = (tpSirTxBdStatus) pData; + + limLog(pMac, LOG1, FL("txBdToken %u, txBdStatus %u"), + pTxBdStatus->txBdToken, pTxBdStatus->txCompleteStatus); + + vos_list_peek_front(&pMac->assoc_rsp_completion_list, + &pNode); + + while(pNode) + { + tmp_tx_context = container_of(pNode, assoc_rsp_tx_context, node); + if (tmp_tx_context->txBdToken != pTxBdStatus->txBdToken) + { + limLog(pMac, LOG1, FL("expecting txBdToken %u, got txBdToken %u"), + tmp_tx_context->txBdToken, pTxBdStatus->txBdToken); + + vosStatus = vos_list_peek_next ( + &pMac->assoc_rsp_completion_list, + pNode, &pNext ); + pNode = pNext; + pNext = NULL; + } + else + { + limLog(pMac, LOG1, FL("expecting txBdToken %u, got txBdToken %u"), + tmp_tx_context->txBdToken, pTxBdStatus->txBdToken); + break; + } + } + + if (!tmp_tx_context) { + limLog(pMac, LOGE, FL("context is NULL")); + return eHAL_STATUS_SUCCESS; + } + psessionEntry = peFindSessionBySessionId(pMac, tmp_tx_context->psessionID); + if (!psessionEntry) { + limLog(pMac, LOGE, FL("failed to get psession pointer")); + vos_list_remove_node(&pMac->assoc_rsp_completion_list, + pNode); + vos_mem_free(tmp_tx_context); + return eHAL_STATUS_SUCCESS; + } + pStaDs = dphGetHashEntry(pMac, tmp_tx_context->staId, + &psessionEntry->dph.dphHashTable); + if (pStaDs == NULL) + { + limLog(pMac, LOGW, + FL("STA context not found")); + vos_list_remove_node(&pMac->assoc_rsp_completion_list, + pNode); + vos_mem_free(tmp_tx_context); + + return eHAL_STATUS_SUCCESS; + } + + /* Receive path cleanup */ + limCleanupRxPath(pMac, pStaDs, psessionEntry); + vos_list_remove_node(&pMac->assoc_rsp_completion_list, + pNode); + vos_mem_free(tmp_tx_context); + + return eHAL_STATUS_SUCCESS; +} /** * lim_is_robust_mgmt_action_frame() - Check if action catagory is * robust action frame @@ -8617,3 +8712,542 @@ void lim_update_caps_info_for_bss(tpAniSirGlobal mac_ctx, limLog(mac_ctx, LOG1, FL("Clearing Immed Blk Ack:no AP support")); } } +#ifdef SAP_AUTH_OFFLOAD +/** + * _sap_offload_parse_assoc_req - Parse assoc request and store it. + * + * @pmac: mac context + * @assoc_req: Assoc request + * @add_sta_req: Add Sta request + * + * This function process recieved add sta message and store it as + * sta ds entry. This function will add this sta entry to DPH as well. + * + * Return: DPH hash node + */ +static tpDphHashNode +_sap_offload_parse_assoc_req(tpAniSirGlobal pmac, + tpSirAssocReq assoc_req, + tSapOfldAddStaIndMsg *add_sta_req) +{ + tpSirMacAssocReqFrame mac_assoc_req = NULL; + tpSirAssocReq temp_assoc_req; + tSirRetStatus status; + tpDphHashNode sta_ds = NULL; + uint8_t *frame_body = NULL; + + tpPESession session_entry = limIsApSessionActive(pmac); + + if (session_entry == NULL) + { + PELOGE(limLog(pmac, LOGE, FL(" Session not found"));) + return NULL; + } + + /* Update Attribute and Remove IE for + * Software AP Authentication Offload + */ + frame_body = (tANI_U8 *)add_sta_req->bufp; + mac_assoc_req = (tpSirMacAssocReqFrame)frame_body; + mac_assoc_req->capabilityInfo.privacy = 0; + + status = sirConvertAssocReqFrame2Struct(pmac, + frame_body, + add_sta_req->data_len, + assoc_req); + if (status != eSIR_SUCCESS) + { + limLog(pmac, LOGW, FL("sap_offload_add_sta_req parse error")); + goto error; + } + /* For software AP Auth Offload feature + * Host will take it as none security station + * Force change to none security + */ + assoc_req->rsnPresent = 0; + assoc_req->wpaPresent = 0; + + sta_ds = dphAddHashEntry(pmac, + add_sta_req->peer_macaddr, + add_sta_req->assoc_id, + &session_entry->dph.dphHashTable); + if (sta_ds == NULL) + { + /* Could not add hash table entry at DPH */ + limLog(pmac, LOGE, + FL("could not add hash entry at DPH for aid=%d, MacAddr:" + MAC_ADDRESS_STR), + add_sta_req->assoc_id,MAC_ADDR_ARRAY(add_sta_req->peer_macaddr)); + goto error; + } + + if (session_entry->parsedAssocReq != NULL) + { + temp_assoc_req = session_entry->parsedAssocReq[sta_ds->assocId]; + if (temp_assoc_req != NULL) + { + if (temp_assoc_req->assocReqFrame) + { + vos_mem_free(temp_assoc_req->assocReqFrame); + temp_assoc_req->assocReqFrame = NULL; + temp_assoc_req->assocReqFrameLength = 0; + } + vos_mem_free(temp_assoc_req); + temp_assoc_req = NULL; + } + session_entry->parsedAssocReq[sta_ds->assocId] = assoc_req; + } +error: + return sta_ds; +} + +/** + * _sap_offload_parse_sta_capability - Parse sta caps from assoc request + * + * @sta_ds: STA state node + * @assoc_req: Assoc request + * @add_sta_req: Add Sta request + * + * This function process recieved add sta message and store station's caps + * in station ds entry. + * + * Return: none + */ +static void +_sap_offload_parse_sta_capability(tpDphHashNode sta_ds, + tpSirAssocReq assoc_req, + tSapOfldAddStaIndMsg *add_sta_req) + +{ + + sta_ds->mlmStaContext.htCapability = assoc_req->HTCaps.present; +#ifdef WLAN_FEATURE_11AC + sta_ds->mlmStaContext.vhtCapability = assoc_req->VHTCaps.present; +#endif + sta_ds->qos.addtsPresent = (assoc_req->addtsPresent==0) ? false : true; + sta_ds->qos.addts = assoc_req->addtsReq; + sta_ds->qos.capability = assoc_req->qosCapability; + sta_ds->versionPresent = 0; + /* short slot and short preamble should be + * updated before doing limaddsta + */ + sta_ds->shortPreambleEnabled = + (tANI_U8)assoc_req->capabilityInfo.shortPreamble; + sta_ds->shortSlotTimeEnabled = + (tANI_U8)assoc_req->capabilityInfo.shortSlotTime; + + sta_ds->valid = 0; + /* The Auth Type of Software AP Authentication Offload + * is always Open System is host side + */ + sta_ds->mlmStaContext.authType = eSIR_OPEN_SYSTEM; + sta_ds->staType = STA_ENTRY_PEER; + + /* Assoc Response frame to requesting STA */ + sta_ds->mlmStaContext.subType = 0; + + sta_ds->mlmStaContext.listenInterval = assoc_req->listenInterval; + sta_ds->mlmStaContext.capabilityInfo = assoc_req->capabilityInfo; + + /* The following count will be used to knock-off the station + * if it doesn't come back to receive the buffered data. + * The AP will wait for numTimSent number of beacons after + * sending TIM information for the station, before assuming that + * the station is no more associated and disassociates it + */ + + /* timWaitCount is used by PMM for monitoring the STA's in PS for LINK*/ + sta_ds->timWaitCount = + (tANI_U8)GET_TIM_WAIT_COUNT(assoc_req->listenInterval); + + /* Initialise the Current successful + * MPDU's tranfered to this STA count as 0 + */ + sta_ds->curTxMpduCnt = 0; +} + +/** + * _sap_offload_parse_sta_vht - Parse sta's HT/VHT caps from assoc request + * + * @pmac: mac context + * @sta_ds: STA state node + * @assoc_req: Assoc request + * + * This function process recieved add sta message and store station's HT and + * and VHT caps and store them in station ds entry. + * + * Return: tSirRetStatus + */ +static tSirRetStatus +_sap_offload_parse_sta_vht(tpAniSirGlobal pmac, + tpDphHashNode sta_ds, + tpSirAssocReq assoc_req) +{ + tpPESession session_entry = limIsApSessionActive(pmac); + + if (IS_DOT11_MODE_HT(session_entry->dot11mode) && + assoc_req->HTCaps.present && assoc_req->wmeInfoPresent) + { + sta_ds->htGreenfield = (tANI_U8)assoc_req->HTCaps.greenField; + sta_ds->htAMpduDensity = assoc_req->HTCaps.mpduDensity; + sta_ds->htDsssCckRate40MHzSupport = + (tANI_U8)assoc_req->HTCaps.dsssCckMode40MHz; + sta_ds->htLsigTXOPProtection = + (tANI_U8)assoc_req->HTCaps.lsigTXOPProtection; + sta_ds->htMaxAmsduLength = + (tANI_U8)assoc_req->HTCaps.maximalAMSDUsize; + sta_ds->htMaxRxAMpduFactor = assoc_req->HTCaps.maxRxAMPDUFactor; + sta_ds->htMIMOPSState = assoc_req->HTCaps.mimoPowerSave; + sta_ds->htShortGI20Mhz = (tANI_U8)assoc_req->HTCaps.shortGI20MHz; + sta_ds->htShortGI40Mhz = (tANI_U8)assoc_req->HTCaps.shortGI40MHz; + sta_ds->htSupportedChannelWidthSet = + (tANI_U8)assoc_req->HTCaps.supportedChannelWidthSet; + /* peer just follows AP; so when we are softAP/GO, + * we just store our session entry's secondary channel offset here + * in peer INFRA STA. However, if peer's 40MHz channel width support + * is disabled then secondary channel will be zero + */ + sta_ds->htSecondaryChannelOffset = + (sta_ds->htSupportedChannelWidthSet) ? + session_entry->htSecondaryChannelOffset : 0; +#ifdef WLAN_FEATURE_11AC + if (assoc_req->operMode.present) + { + sta_ds->vhtSupportedChannelWidthSet = + (tANI_U8)((assoc_req->operMode.chanWidth == + eHT_CHANNEL_WIDTH_80MHZ) ? + WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ : + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ); + sta_ds->htSupportedChannelWidthSet = + (tANI_U8)(assoc_req->operMode.chanWidth ? + eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ); + } + else if (assoc_req->VHTCaps.present) + { + /* Check if STA has enabled it's channel bonding mode. + * If channel bonding mode is enabled, we decide based on + * SAP's current configuration else, we set it to VHT20. + */ + sta_ds->vhtSupportedChannelWidthSet = + (tANI_U8)((sta_ds->htSupportedChannelWidthSet == + eHT_CHANNEL_WIDTH_20MHZ) ? + WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ : + session_entry->vhtTxChannelWidthSet ); + sta_ds->htMaxRxAMpduFactor = assoc_req->VHTCaps.maxAMPDULenExp; + } + + /* Lesser among the AP and STA bandwidth of operation. */ + sta_ds->htSupportedChannelWidthSet = + (sta_ds->htSupportedChannelWidthSet < + session_entry->htSupportedChannelWidthSet) ? + sta_ds->htSupportedChannelWidthSet : + session_entry->htSupportedChannelWidthSet ; +#endif + sta_ds->baPolicyFlag = 0xFF; + sta_ds->htLdpcCapable = (tANI_U8)assoc_req->HTCaps.advCodingCap; + } + + if (assoc_req->VHTCaps.present && assoc_req->wmeInfoPresent) + sta_ds->vhtLdpcCapable = (tANI_U8)assoc_req->VHTCaps.ldpcCodingCap; + + if (!assoc_req->wmeInfoPresent) + { + sta_ds->mlmStaContext.htCapability = 0; +#ifdef WLAN_FEATURE_11AC + sta_ds->mlmStaContext.vhtCapability = 0; +#endif + } +#ifdef WLAN_FEATURE_11AC + if (limPopulateMatchingRateSet(pmac, + sta_ds, + &(assoc_req->supportedRates), + &(assoc_req->extendedRates), + assoc_req->HTCaps.supportedMCSSet, + &(assoc_req->propIEinfo.propRates), + session_entry , &assoc_req->VHTCaps) + != eSIR_SUCCESS) + { +#else + if (limPopulateMatchingRateSet(pmac, + sta_ds, + &(assoc_req->supportedRates), + &(assoc_req->extendedRates), + assoc_req->HTCaps.supportedMCSSet, + &(assoc_req->propIEinfo.propRates), + session_entry) != eSIR_SUCCESS) + { +#endif + limLog(pmac, LOGE, + FL("Rate set mismatched for aid=%d, MacAddr: " + MAC_ADDRESS_STR), + sta_ds->assocId, MAC_ADDR_ARRAY(sta_ds->staAddr)); + goto error; + } + return eSIR_SUCCESS; +error: + return eSIR_FAILURE; +} + +/** + * _sap_offload_parse_sta_qos - Parse sta's QOS caps from assoc request + * + * @pmac: mac context + * @sta_ds: STA state node + * @assoc_req: Assoc request + * + * This function process recieved add sta message and store station's QOS + * store them in station ds entry. + * + * Return: none + */ +static void + _sap_offload_parse_sta_qos(tpAniSirGlobal pmac, + tpDphHashNode sta_ds, + tpSirAssocReq assoc_req) +{ + tHalBitVal qos_mode; + tHalBitVal wsm_mode, wme_mode; + tpPESession session_entry = limIsApSessionActive(pmac); + + limGetQosMode(session_entry, &qos_mode); + sta_ds->qosMode = eANI_BOOLEAN_FALSE; + sta_ds->lleEnabled = eANI_BOOLEAN_FALSE; + + if (assoc_req->capabilityInfo.qos && (qos_mode == eHAL_SET)) + { + sta_ds->lleEnabled = eANI_BOOLEAN_TRUE; + sta_ds->qosMode = eANI_BOOLEAN_TRUE; + } + + sta_ds->wmeEnabled = eANI_BOOLEAN_FALSE; + sta_ds->wsmEnabled = eANI_BOOLEAN_FALSE; + limGetWmeMode(session_entry, &wme_mode); + if ((!sta_ds->lleEnabled) && assoc_req->wmeInfoPresent && + (wme_mode == eHAL_SET)) + { + sta_ds->wmeEnabled = eANI_BOOLEAN_TRUE; + sta_ds->qosMode = eANI_BOOLEAN_TRUE; + limGetWsmMode(session_entry, &wsm_mode); + /* WMM_APSD - WMM_SA related processing should be + * separate; WMM_SA and WMM_APSD can coexist + */ + if (assoc_req->WMMInfoStation.present) + { + /* check whether AP supports or not */ + if ((session_entry->limSystemRole == eLIM_AP_ROLE) + && (session_entry->apUapsdEnable == 0) && + (assoc_req->WMMInfoStation.acbe_uapsd + || assoc_req->WMMInfoStation.acbk_uapsd + || assoc_req->WMMInfoStation.acvo_uapsd + || assoc_req->WMMInfoStation.acvi_uapsd)) + { + /* + * Received Re/Association Request from + * STA when UPASD is not supported + */ + limLog( pmac, LOGE, FL( "AP do not support UAPSD so reply " + "to STA accordingly" )); + /* update UAPSD and send it to LIM to add STA */ + sta_ds->qos.capability.qosInfo.acbe_uapsd = 0; + sta_ds->qos.capability.qosInfo.acbk_uapsd = 0; + sta_ds->qos.capability.qosInfo.acvo_uapsd = 0; + sta_ds->qos.capability.qosInfo.acvi_uapsd = 0; + sta_ds->qos.capability.qosInfo.maxSpLen = 0; + } + else + { + /* update UAPSD and send it to LIM to add STA */ + sta_ds->qos.capability.qosInfo.acbe_uapsd = + assoc_req->WMMInfoStation.acbe_uapsd; + sta_ds->qos.capability.qosInfo.acbk_uapsd = + assoc_req->WMMInfoStation.acbk_uapsd; + sta_ds->qos.capability.qosInfo.acvo_uapsd = + assoc_req->WMMInfoStation.acvo_uapsd; + sta_ds->qos.capability.qosInfo.acvi_uapsd = + assoc_req->WMMInfoStation.acvi_uapsd; + sta_ds->qos.capability.qosInfo.maxSpLen = + assoc_req->WMMInfoStation.max_sp_length; + } + } + if (assoc_req->wsmCapablePresent && (wsm_mode == eHAL_SET)) + sta_ds->wsmEnabled = eANI_BOOLEAN_TRUE; + } +} + +/** + * lim_sap_offload_add_sta - Parse Add sta request from firmware + * + * @pmac: mac context + * @lim_msgq: Add Sta indication buffer + * + * This function will recieve buffer from firmware. This buffer will store + * information about connected client. driver will process this buffer and + * will register this client with driver. Driver will call limAddSta + * + * Return: none + */ +void lim_sap_offload_add_sta(tpAniSirGlobal pmac, + tSapOfldAddStaIndMsg *lim_msgq) +{ + tpSirAssocReq assoc_req = NULL; + tpDphHashNode sta_ds = NULL; + + tSapOfldAddStaIndMsg *add_sta_req = NULL; + tpPESession session_entry = limIsApSessionActive(pmac); + + if (session_entry == NULL) + { + PELOGE(limLog(pmac, LOGE, FL(" Session not found"));) + return; + } + add_sta_req = lim_msgq; + assoc_req = vos_mem_malloc(sizeof(*assoc_req)); + if (NULL == assoc_req) { + limLog(pmac, LOGP, FL("Allocate Memory failed in AssocReq")); + return; + } + vos_mem_set(assoc_req , sizeof(*assoc_req), 0); + + /* parse Assoc req frame for station information */ + sta_ds = _sap_offload_parse_assoc_req(pmac, assoc_req, add_sta_req); + if (sta_ds == NULL) + { + PELOGE(limLog(pmac, LOGE, FL("could not add hash entry for"));) + limPrintMacAddr(pmac, add_sta_req->peer_macaddr, LOGE); + vos_mem_free(assoc_req); + goto error; + } + + /* Parse Station Capability */ + _sap_offload_parse_sta_capability(sta_ds, assoc_req, add_sta_req); + + /* Parse Station HT/VHT information */ + if (_sap_offload_parse_sta_vht(pmac, sta_ds, assoc_req) + == eSIR_FAILURE) + { + PELOGE(limLog(pmac, LOGE, FL("mismatch ht/vht information for "));) + limPrintMacAddr(pmac, add_sta_req->peer_macaddr, LOGE); + vos_mem_free(assoc_req); + goto error; + + } + + /* Parse Station QOS information */ + _sap_offload_parse_sta_qos(pmac, sta_ds, assoc_req); + + session_entry->parsedAssocReq[sta_ds->assocId] = assoc_req; + sta_ds->staIndex = add_sta_req->staIdx; + sta_ds->dpuIndex = add_sta_req->dpuIndex; + sta_ds->bcastDpuIndex = add_sta_req->bcastDpuIndex; + sta_ds->bcastMgmtDpuIdx = add_sta_req->bcastMgmtDpuIdx; + sta_ds->ucUcastSig = add_sta_req->ucUcastSig; + sta_ds->ucBcastSig = add_sta_req->ucBcastSig; + sta_ds->ucMgmtSig = add_sta_req->ucMgmtSig; + sta_ds->bssId = add_sta_req->bssIdx; + + limLog(pmac, LOG1, FL("StaIndex %d BssIDx %d dpuIndex %d bcastDpuIndex %d bcastMgmtDpuIdx %d ucUcastSig %d ucBcastSig %d ucMgmtSig %d AssocId %d"), + sta_ds->staIndex, + sta_ds->bssId, + sta_ds->dpuIndex, + sta_ds->bcastDpuIndex, + sta_ds->bcastMgmtDpuIdx, + sta_ds->ucUcastSig, + sta_ds->ucBcastSig, + sta_ds->ucMgmtSig, + sta_ds->assocId); + + if (limAddSta(pmac, sta_ds, false, session_entry) != eSIR_SUCCESS) { + limLog(pmac, LOGE, FL("could not Add STA with assocId=%d"), + sta_ds->assocId); + } + +error: + return; +} + +/** + * lim_sap_offload_del_sta - Parse Del sta request from firmware + * + * @pmac: mac context + * @lim_msgq: Del Sta indication buffer + * + * This function will recieve buffer from firmware. This buffer will + * have information about clinet to remove with reason code. + * This function will call limSendSmeDisassocInd to do cleanup + * for station entry + * + * Return: none + */ +void +lim_sap_offload_del_sta(tpAniSirGlobal pmac, tSapOfldDelStaIndMsg *lim_msgq) +{ + tSapOfldDelStaIndMsg *del_sta_req = NULL; + tpDphHashNode sta_ds = NULL; + tANI_U16 assoc_id = 0; + tpPESession psession_entry = limIsApSessionActive(pmac); + + if (psession_entry == NULL) + { + PELOGE(limLog(pmac, LOGE, FL(" Session not found"));) + goto error; + } + + del_sta_req = lim_msgq; + sta_ds = dphLookupHashEntry(pmac, + del_sta_req->peer_macaddr, + &assoc_id, + &psession_entry->dph.dphHashTable); + if (sta_ds == NULL) + { + /* + * Disassociating STA is not associated. + * Log error + */ + PELOGE(limLog(pmac, LOGE, + FL("received del sta event that sta not exist in table " + "reasonCode=%d, addr "MAC_ADDRESS_STR), + del_sta_req->reason, + MAC_ADDR_ARRAY(del_sta_req->peer_macaddr));) + goto error; + } + + if (assoc_id != (tANI_U16)del_sta_req->assoc_id) + { + /* + * Associate Id mismatch + * Log error + */ + PELOGE(limLog(pmac, LOGE, + FL("received del sta event that sta assoc Id mismatch"));) + goto error; + } + + sta_ds->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DISASSOC; + sta_ds->mlmStaContext.disassocReason = + (tSirMacReasonCodes) del_sta_req->reason; + + limSendSmeDisassocInd(pmac, sta_ds, psession_entry); + +error: + return; +} +#endif /* SAP_AUTH_OFFLOAD */ + +int peFindBssIdxFromSmeSessionId(tpAniSirGlobal pMac, tANI_U8 sme_sessionId) +{ + tANI_U8 i; + tpPESession psessionEntry = NULL; + + for(i =0; i < pMac->lim.maxBssId; i++) + { + /* If BSSID matches return corresponding tables address*/ + if( (pMac->lim.gpSession[i].valid) && (pMac->lim.gpSession[i].smeSessionId == sme_sessionId)) + { + psessionEntry = (&pMac->lim.gpSession[i]); + return psessionEntry->bssIdx; + } + } + + limLog(pMac, LOG4, FL("Session lookup fails for sme_sessionId: ")); + return(0xFF); +} diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h index 622774aceb5..8083629c600 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -573,9 +573,15 @@ extern tANI_U32 limGetMaxRateFlags(tpDphHashNode pStaDs, void limDecrementPendingMgmtCount (tpAniSirGlobal pMac); eHalStatus limTxBdComplete(tpAniSirGlobal pMac, void *pData); +eHalStatus limAssocRspTxCompleteCnf(tpAniSirGlobal pMac, void *pData); bool lim_is_robust_mgmt_action_frame(uint8 action_catagory); tANI_U8 lim_compute_ext_cap_ie_length (tDot11fIEExtCap *ext_cap); void lim_update_caps_info_for_bss(tpAniSirGlobal mac_ctx, uint16_t *caps, uint16_t bss_caps); - +#ifdef SAP_AUTH_OFFLOAD +void lim_sap_offload_add_sta(tpAniSirGlobal pmac, + tSapOfldAddStaIndMsg *lim_msgq); +void lim_sap_offload_del_sta(tpAniSirGlobal pmac, + tSapOfldDelStaIndMsg *lim_msgq); +#endif #endif /* __LIM_UTILS_H */ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/lim_mbb.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/lim_mbb.c new file mode 100644 index 00000000000..e9977b54c84 --- /dev/null +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/lim_mbb.c @@ -0,0 +1,1754 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "aniGlobal.h" +#include "limTypes.h" +#include "limUtils.h" +#include "limFT.h" +#include "limSendMessages.h" +#include "limAssocUtils.h" +#include "limSerDesUtils.h" +#include "limSmeReqUtils.h" +#include "limAdmitControl.h" +#include "sirApi.h" +#include "rrmApi.h" +#include "wlan_qct_tl.h" + +#define PREAUTH_REASSOC_TIMEOUT 500 + +void lim_cleanup_connected_ap(tpAniSirGlobal mac, tpDphHashNode sta_ds, + tpPESession session_entry); + +/** + * lim_post_pre_auth_reassoc_rsp() -Posts preauth_reassoc response to SME + * @mac: MAC context + * @status: status + * @session_entry: session entry + * @reason: indicates which type of clean up needs to be performed + * + * This function process preauth_reassoc response to SME + */ +void lim_post_pre_auth_reassoc_rsp(tpAniSirGlobal mac, + tSirRetStatus status, tpPESession session_entry, + enum sir_roam_cleanup_type reason) +{ + tpSirFTPreAuthRsp pre_auth_rsp; + tSirMsgQ mmh_msg; + tANI_U16 rsp_len = sizeof(tSirFTPreAuthRsp); + tpPESession session_entry_con_ap; + tpDphHashNode sta_ds = NULL; + + pre_auth_rsp = (tpSirFTPreAuthRsp)vos_mem_malloc(rsp_len); + if (NULL == pre_auth_rsp) { + limLog(mac, LOGE, FL("Failed to allocate memory")); + return; + } + + limLog(mac, LOG1, FL("reason %d"), reason); + + vos_mem_zero(pre_auth_rsp, rsp_len); + pre_auth_rsp->messageType = eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP; + pre_auth_rsp->length = (tANI_U16)rsp_len; + pre_auth_rsp->status = status; + pre_auth_rsp->reason = reason; + + if (session_entry) + pre_auth_rsp->smeSessionId = session_entry->smeSessionId; + + /* The bssid of the AP we are sending Auth1 to. */ + if (mac->ft.ftPEContext.pFTPreAuthReq) + sirCopyMacAddr(pre_auth_rsp->preAuthbssId, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId); + + if (status != eSIR_SUCCESS) { + limLog(mac, LOG1, FL("Pre-Auth Failed, Cleanup!")); + limLog(mac, LOG1, FL("flushing cached packets")); + WLANTL_PreAssocForward(false); + + /* + * If reason is full clean up, add sme session id that + * will be useful in CSR during cleanup. + */ + if (reason == SIR_MBB_DISCONNECTED) { + session_entry_con_ap = + (tpPESession)mac->ft.ftPEContext.psavedsessionEntry; + pre_auth_rsp->smeSessionId = + session_entry_con_ap->smeSessionId; + } + limFTCleanup(mac); + } + + if (status == eSIR_SUCCESS) { + limLog(mac, LOG1, FL("Success")); + + rsp_len = session_entry->assocReqLen + session_entry->assocRspLen + + session_entry->bcnLen; + + pre_auth_rsp->roam_info = vos_mem_malloc(sizeof(tCsrRoamInfo)); + if (pre_auth_rsp->roam_info == NULL) { + limLog(mac, LOGE, + FL("Failed to allocate memory for roam info")); + return; + } + vos_mem_set(pre_auth_rsp->roam_info, sizeof(tCsrRoamInfo), 0); + + pre_auth_rsp->roam_info->pbFrames = vos_mem_malloc(rsp_len); + if (pre_auth_rsp->roam_info->pbFrames == NULL) { + limLog(mac, LOGE, + FL("Failed to allocate memory for roam info frames")); + return; + } + vos_mem_set(pre_auth_rsp->roam_info->pbFrames, rsp_len, 0); + + + pre_auth_rsp->length += rsp_len + sizeof(tCsrRoamInfo); + + session_entry_con_ap = + (tpPESession)mac->ft.ftPEContext.psavedsessionEntry; + pre_auth_rsp->smeSessionId = session_entry_con_ap->smeSessionId; + + if(session_entry->beacon != NULL) { + pre_auth_rsp->roam_info->nBeaconLength = session_entry->bcnLen; + vos_mem_copy(pre_auth_rsp->roam_info->pbFrames, + session_entry->beacon, + session_entry->bcnLen); + limLog(mac, LOG1, FL("Beacon len %d"), session_entry->bcnLen); + + vos_mem_free(session_entry->beacon); + session_entry->beacon = NULL; + } + + if(session_entry->assocReq != NULL) { + pre_auth_rsp->roam_info->nAssocReqLength = + session_entry->assocReqLen; + vos_mem_copy(pre_auth_rsp->roam_info->pbFrames + + session_entry->bcnLen, + session_entry->assocReq, + session_entry->assocReqLen); + + vos_mem_free(session_entry->assocReq); + session_entry->assocReq = NULL; + + limLog(mac, LOG1, FL("AssocReq len %d"), session_entry->assocReqLen); + } + + if(session_entry->assocRsp != NULL) { + pre_auth_rsp->roam_info->nAssocRspLength = + session_entry->assocRspLen; + vos_mem_copy(pre_auth_rsp->roam_info->pbFrames + + session_entry->bcnLen + session_entry->assocReqLen, + session_entry->assocRsp, + session_entry->assocRspLen); + + vos_mem_free(session_entry->assocRsp); + session_entry->assocRsp = NULL; + + limLog(mac, LOG1, FL("AssocRsp len %d"), session_entry->assocRspLen); + } + + sta_ds = dphGetHashEntry(mac, DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + if(NULL == sta_ds) { + limLog(mac, LOGE, + FL("Unable to get the DPH Hash Entry for AID - %d"), + DPH_STA_HASH_INDEX_PEER); + return; + } + + pre_auth_rsp->roam_info->staId = sta_ds->staIndex; + pre_auth_rsp->roam_info->ucastSig = sta_ds->ucUcastSig; + pre_auth_rsp->roam_info->bcastSig = sta_ds->ucBcastSig; + pre_auth_rsp->roam_info->maxRateFlags = + limGetMaxRateFlags(sta_ds, session_entry); + } + + mmh_msg.type = pre_auth_rsp->messageType; + mmh_msg.bodyptr = pre_auth_rsp; + mmh_msg.bodyval = 0; + + limLog(mac, LOG1, + FL("Posted Auth Rsp to SME with status of 0x%x"), status); + + limSysProcessMmhMsgApi(mac, &mmh_msg, ePROT); +} + +/* + * lim_reassoc_fail_cleanup() -handles cleanup during reassoc failure + * @mac: MAC context + * @status: status + * @data: pointer to data + * + * This function handles cleanup during reassoc failure + */ +void lim_reassoc_fail_cleanup(tpAniSirGlobal mac, + eHalStatus status, tANI_U32 *data) +{ + tpPESession session_entry; + + session_entry = (tpPESession)data; + + if (!mac->ft.ftPEContext.pFTPreAuthReq) { + limLog(mac, LOGE, FL("pFTPreAuthReq is NULL")); + return; + } + + if (dphDeleteHashEntry(mac, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId, + DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable) != eSIR_SUCCESS) { + limLog(mac, LOGE, FL("error deleting hash entry")); + } + + /* Delete session as session was created during preauth success */ + peDeleteSession(mac, session_entry); + + /* Add bss parameter cleanup happens as part of this processing*/ + if ((status == eHAL_STATUS_MBB_DEL_BSS_FAIL) || + (status == eHAL_STATUS_INVALID_PARAMETER) || + (status == eHAL_STATUS_MBB_ADD_BSS_FAIL)) + lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL, + SIR_MBB_DISCONNECTED); + else + lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL, + SIR_MBB_CONNECTED); +} + +/* + * lim_perform_post_reassoc_mbb_channel_change() -invokes resume callback + * @mac: MAC context + * @status: status + * @data: pointer to data + * @session_entry: session entry + * + * This function invokes resume callback + */ +void lim_perform_post_reassoc_mbb_channel_change(tpAniSirGlobal mac, + eHalStatus status, tANI_U32 *data, tpPESession session_entry) +{ + tpPESession session_entry_con_ap; + tANI_U8 session_id; + + session_entry_con_ap = peFindSessionByBssid(mac, + mac->ft.ftPEContext.pFTPreAuthReq->currbssId, + &session_id); + if (session_entry_con_ap == NULL) { + limLog(mac, LOGE, + FL("session does not exist for given BSSID" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac->ft.ftPEContext.pFTPreAuthReq->currbssId)); + + lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL, + SIR_MBB_CONNECTED); + return; + } + + peSetResumeChannel(mac, session_entry_con_ap->currentOperChannel, 0); + limResumeLink(mac, lim_reassoc_fail_cleanup, + (tANI_U32 *)session_entry); +} + +/* + * lim_handle_reassoc_mbb_fail() -handles reassoc failure + * @mac: MAC context + * @session_entry: session entry + * + * This function handles reassoc failure + */ +void lim_handle_reassoc_mbb_fail(tpAniSirGlobal mac, + tpPESession session_entry) +{ + tpPESession session_entry_con_ap; + tANI_U8 session_id; + + session_entry_con_ap = peFindSessionByBssid(mac, + mac->ft.ftPEContext.pFTPreAuthReq->currbssId, + &session_id); + if (session_entry_con_ap == NULL) { + limLog(mac, LOGE, + FL("session does not exist for given BSSID" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac->ft.ftPEContext.pFTPreAuthReq->currbssId)); + + lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL, + SIR_MBB_CONNECTED); + return; + } + + limLog(mac, LOG1, FL("currentOperChannel %d preAuthchannelNum %d"), + session_entry_con_ap->currentOperChannel, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum); + + /* Restore set link to post assoc for currently connected AP */ + if (limSetLinkState(mac, eSIR_LINK_POSTASSOC_STATE, + session_entry_con_ap->bssId, + session_entry_con_ap->selfMacAddr, + NULL, NULL) != eSIR_SUCCESS) { + limLog(mac, LOGE, FL("Set link state to POSTASSOC failed")); + + lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL, + SIR_MBB_CONNECTED); + return; + } + + /* Change channel if required as channel might be changed during preauth */ + if (session_entry_con_ap->currentOperChannel != + mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum) { + limChangeChannelWithCallback(mac, + session_entry_con_ap->currentOperChannel, + lim_perform_post_reassoc_mbb_channel_change, NULL, session_entry); + } else { + /* + * Link needs to be resumed as link was suspended + * for same channel during preauth. + */ + peSetResumeChannel(mac, session_entry_con_ap->currentOperChannel, 0); + limResumeLink(mac, lim_reassoc_fail_cleanup, + (tANI_U32 *)session_entry); + } +} + +/* + * lim_preauth_fail_cleanup() -handles cleanup during preauth failure + * @mac: MAC context + * @status: status + * @data: pointer to data + * + * This function handles cleanup during reassoc failure + */ +void lim_preauth_fail_cleanup(tpAniSirGlobal mac, + eHalStatus status, tANI_U32 *data) +{ + tpPESession session_entry; + + session_entry = (tpPESession)data; + + lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL, + SIR_MBB_CONNECTED); +} + +/* + * lim_perform_preauth_mbb_fail_channel_change() -invokes resume callback + * @mac: MAC context + * @status: status + * @data: pointer to data + * @session_entry: session entry + * + * This function invokes resume callback + */ +void lim_perform_preauth_mbb_fail_channel_change(tpAniSirGlobal mac, + eHalStatus status, tANI_U32 *data, tpPESession session_entry) +{ + peSetResumeChannel(mac, session_entry->currentOperChannel, 0); + limResumeLink(mac, lim_preauth_fail_cleanup, + (tANI_U32 *)session_entry); +} + +/* + * lim_handle_preauth_mbb_fail() -handles preauth failure + * @mac: MAC context + * @session_entry: session entry + * + * This function handles reassoc failure + */ +void lim_handle_preauth_mbb_fail(tpAniSirGlobal mac, + tpPESession session_entry) +{ + limLog(mac, LOG1, FL("currentOperChannel %d preAuthchannelNum %d"), + session_entry->currentOperChannel, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum); + + /* Restore set link to post assoc for currently connected AP */ + if (limSetLinkState(mac, eSIR_LINK_POSTASSOC_STATE, + session_entry->bssId, + session_entry->selfMacAddr, + NULL, NULL) != eSIR_SUCCESS) { + limLog(mac, LOGE, FL("Set link state to POSTASSOC failed")); + + lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL, + SIR_MBB_CONNECTED); + return; + } + + /* Change channel if required as channel might be changed during preauth */ + if (session_entry->currentOperChannel != + mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum) { + limChangeChannelWithCallback(mac, + session_entry->currentOperChannel, + lim_perform_preauth_mbb_fail_channel_change, NULL, session_entry); + } else { + /* + * Link needs to be resumed as link was suspended + * for same channel during preauth. + */ + peSetResumeChannel(mac, session_entry->currentOperChannel, 0); + limResumeLink(mac, lim_preauth_fail_cleanup, + (tANI_U32 *)session_entry); + } +} + + +/* + * lim_del_sta_mbb() -performs del sta + * @mac: MAC context + * @sta_ds_connected_ap: station entry of connected AP + * @resp_reqd: indicates whether response is required or not + * @session_entry_connected_ap: session entry of connected AP + * + * This function performs del sta + */ +tSirRetStatus lim_del_sta_mbb(tpAniSirGlobal mac, + tpDphHashNode sta_ds_connected_ap, + tANI_BOOLEAN resp_reqd, + tpPESession session_entry_connected_ap) +{ + tpDeleteStaParams del_sta_params; + tSirMsgQ msg; + tSirRetStatus ret_code; + + del_sta_params = vos_mem_malloc(sizeof(*del_sta_params)); + if (NULL == del_sta_params) { + limLog(mac, LOGE, FL("Unable to allocate memory during DEL_STA" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_zero(del_sta_params, sizeof(*del_sta_params)); + + del_sta_params->sessionId = session_entry_connected_ap->peSessionId; + del_sta_params->status = eHAL_STATUS_SUCCESS; + +#ifdef FEATURE_WLAN_TDLS + if(((eLIM_STA_ROLE == GET_LIM_SYSTEM_ROLE(session_entry_connected_ap)) && + (sta_ds_connected_ap->staType != STA_ENTRY_TDLS_PEER)) || + (eLIM_BT_AMP_STA_ROLE == + GET_LIM_SYSTEM_ROLE(session_entry_connected_ap))) +#else + if((eLIM_STA_ROLE == GET_LIM_SYSTEM_ROLE(session_entry_connected_ap)) || + (eLIM_BT_AMP_STA_ROLE == + GET_LIM_SYSTEM_ROLE(session_entry_connected_ap))) +#endif + del_sta_params->staIdx = session_entry_connected_ap->staId; + else + del_sta_params->staIdx = sta_ds_connected_ap->staIndex; + + del_sta_params->assocId = sta_ds_connected_ap->assocId; + del_sta_params->respReqd = resp_reqd; + + /* Change Mlm state of connected AP to Del sta rsp state */ + session_entry_connected_ap->limMlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + MTRACE(macTrace(mac, TRACE_CODE_MLM_STATE, + session_entry_connected_ap->peSessionId, eLIM_MLM_WT_DEL_STA_RSP_STATE)); + + msg.type = WDA_DELETE_STA_REQ; + msg.reserved = 0; + msg.bodyptr = del_sta_params; + msg.bodyval = 0; + + limLog(mac, LOG1, + FL("sessionId %d staIdx: %d assocId: %d for "MAC_ADDRESS_STR), + del_sta_params->sessionId, del_sta_params->staIdx, + del_sta_params->assocId, + MAC_ADDR_ARRAY(sta_ds_connected_ap->staAddr)); + + MTRACE(macTraceMsgTx(mac, session_entry_connected_ap->peSessionId, + msg.type)); + + ret_code = wdaPostCtrlMsg(mac, &msg); + if( eSIR_SUCCESS != ret_code) { + if(resp_reqd) + SET_LIM_PROCESS_DEFD_MESGS(mac, true); + limLog(mac, LOGE, + FL("Posting DELETE_STA_REQ failed, reason=%X"), ret_code); + vos_mem_free(del_sta_params); + } + + return ret_code; +} + +/* + * lim_del_bss_mbb() -performs del bss of connected AP + * @mac: MAC context + * @sta_ds: station entry + * @bss_idx:BSS index + * @session_entry: session entry + * + * This function performs del bss of connected AP + */ +tSirRetStatus lim_del_bss_mbb(tpAniSirGlobal mac, tpDphHashNode sta_ds, + tANI_U16 bss_idx,tpPESession session_entry) +{ + tpDeleteBssParams delbss_params = NULL; + tSirMsgQ msg; + tSirRetStatus ret_code = eSIR_SUCCESS; + + delbss_params = vos_mem_malloc(sizeof(tDeleteBssParams)); + if (NULL == delbss_params) { + limLog(mac, LOGE, + FL("Unable to allocate memory during del bss" )); + return eSIR_MEM_ALLOC_FAILED; + } + vos_mem_set((tANI_U8 *) delbss_params, sizeof(tDeleteBssParams), 0); + + delbss_params->sessionId = session_entry->peSessionId; + + if (sta_ds != NULL) { + delbss_params->bssIdx = sta_ds->bssId; + sta_ds->valid = 0; + sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_BSS_RSP_STATE; + } + else + delbss_params->bssIdx = bss_idx; + + session_entry->limMlmState = eLIM_MLM_WT_DEL_BSS_RSP_STATE; + MTRACE(macTrace(mac, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, eLIM_MLM_WT_DEL_BSS_RSP_STATE)); + + delbss_params->status= eHAL_STATUS_SUCCESS; + delbss_params->respReqd = 1; + + limLog(mac, LOG1, FL("Sessionid %d bss idx: %x BSSID:" MAC_ADDRESS_STR), + delbss_params->sessionId, delbss_params->bssIdx, + MAC_ADDR_ARRAY(session_entry->bssId)); + + /* we need to defer the message until we get the response back from HAL. */ + SET_LIM_PROCESS_DEFD_MESGS(mac, false); + + msg.type = WDA_DELETE_BSS_REQ; + msg.reserved = 0; + msg.bodyptr = delbss_params; + msg.bodyval = 0; + + MTRACE(macTraceMsgTx(mac, session_entry->peSessionId, msg.type)); + + if(eSIR_SUCCESS != (ret_code = wdaPostCtrlMsg(mac, &msg))) + { + SET_LIM_PROCESS_DEFD_MESGS(mac, true); + limLog(mac, LOGE, + FL("Posting DELETE_BSS_REQ to HAL failed, reason=%X"), ret_code); + vos_mem_free(delbss_params); + } + + return ret_code; +} + +/* + * lim_add_bss_mbb() -performs add bss of new roamable AP + * @mac: MAC context + * @sta_ds: station entry + * @bss_idx:BSS index + * @session_entry: session entry + * + * This function performs add bss of new roamable AP + */ +void lim_add_bss_mbb(tpAniSirGlobal mac, tpDphHashNode sta_ds, + tpPESession session_entry) +{ + tSirMsgQ msg; + tSirRetStatus ret_code; + + /* we need to defer the message until we get the response back from HAL. */ + SET_LIM_PROCESS_DEFD_MESGS(mac, false); + + msg.type = SIR_HAL_ADD_BSS_REQ; + msg.reserved = 0; + msg.bodyptr = mac->ft.ftPEContext.pAddBssReq; + msg.bodyval = 0; + + limLog(mac, LOG1, FL("Sending SIR_HAL_ADD_BSS_REQ")); + + session_entry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE; + + MTRACE(macTrace(mac, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE)); + + MTRACE(macTraceMsgTx(mac, session_entry->peSessionId, msg.type)); + + ret_code = wdaPostCtrlMsg(mac, &msg); + if( eSIR_SUCCESS != ret_code) { + vos_mem_free(mac->ft.ftPEContext.pAddBssReq); + limLog(mac, LOGE, + FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), ret_code); + } + /* Dont need this anymore */ + mac->ft.ftPEContext.pAddBssReq = NULL; +} + +tSirRetStatus lim_add_sta_mbb(tpAniSirGlobal mac, tANI_U16 assoc_id, + tpPESession session_entry) +{ + tpAddStaParams add_sta_params = NULL; + tSirMsgQ msg; + tSirRetStatus retCode = eSIR_SUCCESS; + + add_sta_params = mac->ft.ftPEContext.pAddStaReq; + add_sta_params->assocId = assoc_id; + + msg.type = SIR_HAL_ADD_STA_REQ; + msg.reserved = 0; + msg.bodyptr = add_sta_params; + msg.bodyval = 0; + + limLog(mac, LOG1, + FL("Sending SIR_HAL_ADD_STA_REQ. aid %d)"), + add_sta_params->assocId); + + session_entry->limPrevMlmState = session_entry->limMlmState; + session_entry->limMlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE; + + MTRACE(macTrace(mac, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, eLIM_MLM_WT_ADD_STA_RSP_STATE)); + + MTRACE(macTraceMsgTx(mac, session_entry->peSessionId, msg.type)); + + if(eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( mac, &msg))) { + limLog(mac, LOGE, + FL("Posting ADD_STA_REQ to HAL failed, reason=%X"), retCode); + vos_mem_free(add_sta_params); + } + + mac->ft.ftPEContext.pAddStaReq = NULL; + return retCode; +} + +/* + * lim_handle_reassoc_mbb_success() -handles reassoc success + * @mac: MAC context + * @session_entry: session entry + * @assoc_rsp: pointer to assoc response + * @sta_ds : station entry + * + * This function handles reassoc success + */ +void lim_handle_reassoc_mbb_success(tpAniSirGlobal mac, + tpPESession session_entry, tpSirAssocRsp assoc_rsp, tpDphHashNode sta_ds) +{ + tpPESession session_entry_con_ap; + tANI_U8 session_id_connected_ap; + tpDphHashNode sta_ds_connected_ap; + tANI_U16 aid; + tSirRetStatus ret_code; + + limUpdateAssocStaDatas(mac, sta_ds, assoc_rsp, session_entry); + + /* Store assigned AID for TIM processing */ + session_entry->limAID = assoc_rsp->aid & 0x3FFF; + + /* De register STA for currently connected AP */ + mac->sme.roaming_mbb_callback(mac, mac->ft.ftSmeContext.smeSessionId, + NULL, NULL, SIR_ROAMING_DEREGISTER_STA); + + mac->sme.roaming_mbb_callback(mac, mac->ft.ftSmeContext.smeSessionId, + NULL, NULL, SIR_STOP_ROAM_OFFLOAD_SCAN); + + if((session_entry_con_ap = peFindSessionByBssid(mac, + mac->ft.ftPEContext.pFTPreAuthReq->currbssId, + &session_id_connected_ap))== NULL) { + limLog(mac, LOGE, + FL("session does not exist for given BSSID" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac->ft.ftPEContext.pFTPreAuthReq->currbssId)); + goto end; + } + + session_entry->smeSessionId = session_entry_con_ap->smeSessionId; + + sta_ds_connected_ap = dphLookupHashEntry(mac, + mac->ft.ftPEContext.pFTPreAuthReq->currbssId, + &aid, + &session_entry_con_ap->dph.dphHashTable); + if (sta_ds_connected_ap == NULL) { + limLog(mac, LOGE, + FL("sta_ds NULL for given BSSID" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac->ft.ftPEContext.pFTPreAuthReq->currbssId)); + goto end; + } + + /* + * Change Mlm state of new AP to Del sta rsp state so that + * duplicate reassoc response will be dropped. + */ + session_entry->limMlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; + MTRACE(macTrace(mac, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, eLIM_MLM_WT_DEL_STA_RSP_STATE)); + + /* Delete sta for currently connected AP */ + ret_code = lim_del_sta_mbb(mac, sta_ds_connected_ap, + false, session_entry_con_ap); + if (ret_code == eSIR_SUCCESS) + return; + +end: + /* Connected AP lim cleanup.*/ + lim_cleanup_connected_ap(mac, sta_ds_connected_ap, session_entry_con_ap); + /* + * eHAL_STATUS_INVALID_PARAMETER is used + * so that full cleanup is triggered. + */ + lim_reassoc_fail_cleanup(mac, eHAL_STATUS_INVALID_PARAMETER, + (tANI_U32 *)session_entry); +} + + +/* + * lim_process_preauth_mbb_result() -process pre auth result + * @mac: MAC context + * @status: status + * @data: pointer to data + * + * This function invokes resume callback + */ +static inline void lim_process_preauth_mbb_result(tpAniSirGlobal mac, + eHalStatus status, tANI_U32 *data) +{ + tpPESession session_entry, ft_session_entry; + tpDphHashNode sta_ds; + tAddBssParams *add_bss_params; + tSirSmeJoinReq *reassoc_req; + tLimMlmReassocReq *mlm_reassoc_req; + tANI_U16 caps; + tANI_U16 nSize; + tpSirSmeJoinReq pReassocReq = NULL; + + if (!mac->ft.ftPEContext.pFTPreAuthReq) { + limLog(mac, LOG1, "Pre-Auth request is NULL!"); + goto end; + } + + session_entry = (tpPESession)data; + + /* Post the FT Pre Auth Response to SME in case of failure*/ + if (mac->ft.ftPEContext.ftPreAuthStatus == eSIR_FAILURE) + goto end; + + /* Flow for preauth success */ + limFTSetupAuthSession(mac, session_entry); + + /* + * Prepare reassoc request. Memory allocated for tSirSmeJoinReq + *reassoc_req in csr_fill_reassoc_req. Free that memory here. + */ + mac->sme.roaming_mbb_callback(mac, mac->ft.ftSmeContext.smeSessionId, + mac->ft.ftPEContext.pFTPreAuthReq->pbssDescription, + &reassoc_req, SIR_PREPARE_REASSOC_REQ); + if (reassoc_req == NULL) { + limLog(mac, LOGE, + FL("reassoc req is NULL")); + goto end; + } + + nSize = __limGetSmeJoinReqSizeForAlloc((tANI_U8 *) reassoc_req); + pReassocReq = vos_mem_malloc(nSize); + if ( NULL == pReassocReq ) + { + limLog(mac, LOGE, + FL("call to AllocateMemory failed for pReassocReq")); + goto end; + } + vos_mem_set((void *) pReassocReq, nSize, 0); + if ((limJoinReqSerDes(mac, (tpSirSmeJoinReq) pReassocReq, + (tANI_U8 *) reassoc_req) == eSIR_FAILURE) || + (!limIsSmeJoinReqValid(mac, + (tpSirSmeJoinReq) pReassocReq))) + { + limLog(mac, LOGE, + FL("received SME_REASSOC_REQ with invalid data")); + goto end; + } + + ft_session_entry = mac->ft.ftPEContext.pftSessionEntry; + + ft_session_entry->pLimReAssocReq = pReassocReq; + vos_mem_free(reassoc_req); + + add_bss_params = mac->ft.ftPEContext.pAddBssReq; + + mlm_reassoc_req = vos_mem_malloc(sizeof(tLimMlmReassocReq)); + if (NULL == mlm_reassoc_req) { + limLog(mac, LOGE, + FL("call to AllocateMemory failed for mlmReassocReq")); + goto end; + } + + vos_mem_copy(mlm_reassoc_req->peerMacAddr, + ft_session_entry->limReAssocbssId, + sizeof(tSirMacAddr)); + mlm_reassoc_req->reassocFailureTimeout = PREAUTH_REASSOC_TIMEOUT; + + if (cfgGetCapabilityInfo(mac, &caps, ft_session_entry) != eSIR_SUCCESS) { + limLog(mac, LOGE, FL("could not retrieve Capabilities value")); + vos_mem_free(mlm_reassoc_req); + goto end; + } + + lim_update_caps_info_for_bss(mac, &caps, + reassoc_req->bssDescription.capabilityInfo); + + limLog(mac, LOG1, FL("Capabilities info Reassoc: 0x%X"), caps); + + mlm_reassoc_req->capabilityInfo = caps; + mlm_reassoc_req->sessionId = ft_session_entry->peSessionId; + mlm_reassoc_req->listenInterval = WNI_CFG_LISTEN_INTERVAL_STADEF; + + if ((sta_ds = dphAddHashEntry(mac, add_bss_params->bssId, + DPH_STA_HASH_INDEX_PEER, + &ft_session_entry->dph.dphHashTable)) == NULL) { + limLog(mac, LOGE, FL("could not add hash entry at DPH")); + limPrintMacAddr(mac, add_bss_params->bssId, LOGE); + vos_mem_free(mlm_reassoc_req); + goto end; + } + + /* Start timer here to handle reassoc timeout */ + mac->lim.limTimers.glim_reassoc_mbb_rsp_timer.sessionId = + ft_session_entry->peSessionId; + + MTRACE(macTrace(mac, TRACE_CODE_TIMER_ACTIVATE, + session_entry->peSessionId, eLIM_REASSOC_MBB_RSP_TIMER)); + + if(TX_SUCCESS != + tx_timer_activate(&mac->lim.limTimers.glim_reassoc_mbb_rsp_timer)) { + limLog(mac, LOGE, FL("Reassoc MBB Rsp Timer Start Failed")); + + if (ft_session_entry->pLimReAssocReq) { + vos_mem_free(ft_session_entry->pLimReAssocReq); + ft_session_entry->pLimReAssocReq = NULL; + } + + vos_mem_free(mlm_reassoc_req); + goto end; + } + + limLog(mac, LOG1, FL("enabling caching")); + WLANTL_EnablePreAssocCaching(); + + /* To do: Add changes for reassoc fail timer */ + limSendReassocReqWithFTIEsMgmtFrame(mac, + mlm_reassoc_req, ft_session_entry); + + ft_session_entry->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE; + + limLog(mac, LOG1, FL("Set the mlm state to %d session=%d"), + ft_session_entry->limMlmState, ft_session_entry->peSessionId); + return; + +end: + lim_handle_reassoc_mbb_fail(mac, ft_session_entry); +} + +/* + * lim_perform_post_preauth_mbb_channel_change() -invokes resume callback + * @mac: MAC context + * @status: status + * @data: pointer to data + * @session_entry: session entry + * + * This function invokes resume callback after successful reception of + * pre auth + */ +static inline +void lim_perform_post_preauth_mbb_channel_change(tpAniSirGlobal mac, + eHalStatus status, tANI_U32 *data, tpPESession session_entry) +{ + peSetResumeChannel(mac, 0, 0); + limResumeLink(mac, lim_process_preauth_mbb_result, + (tANI_U32 *)session_entry); +} + +/* + * lim_handle_pre_auth_mbb_rsp() -handles preauth response + * @mac: MAC context + * @status: status of message + * @session_entry: session entry + * + * This function process preauth response + */ +void lim_handle_pre_auth_mbb_rsp(tpAniSirGlobal mac, + tSirRetStatus status, tpPESession session_entry) +{ + tpPESession ft_session_entry; + tANI_U8 session_id; + tpSirBssDescription bss_description; + + mac->ft.ftPEContext.ftPreAuthStatus = status; + + mac->ft.ftPEContext.saved_auth_rsp_length = 0; + + limLog(mac, LOG1, FL("preauth status %d"), + mac->ft.ftPEContext.ftPreAuthStatus); + + /* Create FT session for the re-association at this point */ + if (mac->ft.ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) { + bss_description = mac->ft.ftPEContext.pFTPreAuthReq->pbssDescription; + if((ft_session_entry = peCreateSession(mac, bss_description->bssId, + &session_id, mac->lim.maxStation)) == NULL) { + limLog(mac, LOGE, + FL("session can not be created for pre-auth AP")); + mac->ft.ftPEContext.ftPreAuthStatus = eSIR_FAILURE; + goto out; + } + ft_session_entry->peSessionId = session_id; + sirCopyMacAddr(ft_session_entry->selfMacAddr, + session_entry->selfMacAddr); + sirCopyMacAddr(ft_session_entry->limReAssocbssId, + bss_description->bssId); + ft_session_entry->bssType = session_entry->bssType; + + if (ft_session_entry->bssType == eSIR_INFRASTRUCTURE_MODE) + ft_session_entry->limSystemRole = eLIM_STA_ROLE; + + ft_session_entry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + mac->ft.ftPEContext.pftSessionEntry = ft_session_entry; + limLog(mac, LOG1,"%s:created session (%p) with id = %d", + __func__, ft_session_entry, ft_session_entry->peSessionId); + + /* Update the ReAssoc BSSID of the current session */ + sirCopyMacAddr(session_entry->limReAssocbssId, bss_description->bssId); + limPrintMacAddr(mac, session_entry->limReAssocbssId, LOG1); + + /* Prepare session for roamable AP */ + lim_process_preauth_mbb_result(mac, + mac->ft.ftPEContext.ftPreAuthStatus, (tANI_U32 *)session_entry); + return; + }else { + lim_handle_preauth_mbb_fail(mac, session_entry); + return; + } + +out: + /* This sequence needs to be executed in case of failure*/ + if (session_entry->currentOperChannel != + mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum) { + limChangeChannelWithCallback(mac, session_entry->currentOperChannel, + lim_perform_post_preauth_mbb_channel_change, NULL, session_entry); + } else { + /* Link needs to be resumed as link was suspended for same channel */ + peSetResumeChannel(mac, 0, 0); + limResumeLink(mac, lim_process_preauth_mbb_result, + (tANI_U32 *)session_entry); + } +} + +/** + * lim_process_preauth_mbb_rsp_timeout() -Process preauth response timeout + * @mac: MAC context + * + * This function is called if preauth response is not received from the AP + * within timeout + */ +void lim_process_preauth_mbb_rsp_timeout(tpAniSirGlobal mac) +{ + tpPESession session_entry; + + /* + * Pre auth is failed. Need to resume link and get back on + * to home channel. + */ + limLog(mac, LOG1, FL("Pre-Auth MBB Time Out!!!!")); + + if((session_entry = peFindSessionBySessionId(mac, + mac->lim.limTimers.glim_pre_auth_mbb_rsp_timer.sessionId))== NULL) { + limLog(mac, LOGE, FL("session does not exist for given session id")); + return; + } + + /* + * To handle the race condition where we recieve preauth rsp after + * timer has expired. + */ + if (mac->ft.ftPEContext.pFTPreAuthReq == NULL) { + limLog(mac, LOGE, FL("Auth Rsp might already be posted to SME" + "and cleanup done! sessionId:%d"), + mac->lim.limTimers.glim_pre_auth_mbb_rsp_timer.sessionId); + return; + } + + if (eANI_BOOLEAN_TRUE == + mac->ft.ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) { + limLog(mac, LOGE, + FL("Auth rsp already posted to SME session %p"), session_entry); + return; + } else { + /* + * Here we are sending preauth rsp with failure state + * and which is forwarded to SME. Now, if we receive an preauth + * resp from AP with success it would create a FT pesession, but + * will be dropped in SME leaving behind the pesession. + * Mark Preauth rsp processed so that any rsp from AP is dropped in + * limProcessAuthFrameNoSession. + */ + limLog(mac,LOG1, + FL("Auth rsp not yet posted to SME session %p)"), session_entry); + mac->ft.ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed = + eANI_BOOLEAN_TRUE; + } + /* + * Ok, so attempted a Pre-Auth and failed. If we are off channel. We need + * to get back. + */ + lim_handle_pre_auth_mbb_rsp(mac, eSIR_FAILURE, session_entry); + } + +/** + * lim_process_reassoc_mbb_rsp_timeout() -Process reassoc response timeout + * @mac: MAC context + * + * This function is called if preauth response is not received from the + * AP within timeout + */ +void lim_process_reassoc_mbb_rsp_timeout(tpAniSirGlobal mac) +{ + tpPESession session_entry, ft_session_entry; + tANI_U8 session_id; + + if((ft_session_entry = peFindSessionBySessionId(mac, + mac->lim.limTimers.glim_reassoc_mbb_rsp_timer.sessionId))== NULL) { + limLog(mac, LOGE, + FL("ft session does not exist for given session id %d"), + mac->lim.limTimers.glim_reassoc_mbb_rsp_timer.sessionId); + return; + } + + limLog(mac, LOG1, FL("Reassoc timeout happened in state %d"), + ft_session_entry->limMlmState); + + if((session_entry = peFindSessionByBssid(mac, + mac->ft.ftPEContext.pFTPreAuthReq->currbssId, &session_id))== NULL) { + limLog(mac, LOGE, + FL("session does not exist for given BSSID" MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(mac->ft.ftPEContext.pFTPreAuthReq->currbssId)); + return; + } + + lim_handle_reassoc_mbb_fail(mac, ft_session_entry); + +} + + +/** + * lim_perform_pre_auth_reassoc() -Sends preauth request + * @mac: MAC context + * @status: status of message + * @data: gives information of session + * @session_entry: session entry + * + * This function process preauth request received from CSR + */ +static inline +void lim_perform_pre_auth_reassoc(tpAniSirGlobal mac, eHalStatus status, + tANI_U32 *data, tpPESession session_entry) +{ + tSirMacAuthFrameBody authFrame; + + if (status != eHAL_STATUS_SUCCESS) { + limLog(mac, LOGE, + FL("Change channel not successful for pre-auth")); + goto preauth_fail; + } + + limLog(mac, LOGE, + FL("session id %d"), session_entry->peSessionId); + + mac->ft.ftPEContext.psavedsessionEntry = session_entry; + + authFrame.authAlgoNumber = eSIR_OPEN_SYSTEM; + authFrame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1; + authFrame.authStatusCode = 0; + + /* Start timer here to come back to operating channel. */ + mac->lim.limTimers.glim_pre_auth_mbb_rsp_timer.sessionId = + session_entry->peSessionId; + + limSendAuthMgmtFrame(mac, &authFrame, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId, + LIM_NO_WEP_IN_FC, session_entry, eSIR_FALSE); + + MTRACE(macTrace(mac, TRACE_CODE_TIMER_ACTIVATE, + session_entry->peSessionId, eLIM_PREAUTH_MBB_RSP_TIMER)); + + if(TX_SUCCESS != + tx_timer_activate(&mac->lim.limTimers.glim_pre_auth_mbb_rsp_timer)) { + limLog(mac, LOGE, FL("Pre Auth MBB Rsp Timer Start Failed")); + + mac->ft.ftPEContext.psavedsessionEntry = NULL; + goto preauth_fail; + } + + return; + +preauth_fail: + lim_handle_pre_auth_mbb_rsp(mac, eSIR_FAILURE, session_entry); + return; +} + +/** + * pre_auth_mbb_suspend_link_handler() -Handler for suspend link + * @mac: MAC context + * @status: status of message + * @data: gives information of session + * + * This function process preauth request received from CSR + */ +static inline +void pre_auth_mbb_suspend_link_handler(tpAniSirGlobal mac, + eHalStatus status, tANI_U32 *data) +{ + tpPESession session_entry; + + if (status != eHAL_STATUS_SUCCESS) { + limLog(mac, LOGE, FL("Link suspend failed")); + lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, + (tpPESession)data, SIR_MBB_CONNECTED); + return; + } + + session_entry = (tpPESession)data; + + if (session_entry->currentOperChannel != + mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum) { + limChangeChannelWithCallback(mac, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum, + lim_perform_pre_auth_reassoc, NULL, session_entry); + return; + } else { + lim_perform_pre_auth_reassoc(mac, eHAL_STATUS_SUCCESS, + NULL, session_entry); + return; + } +} + +/** + * lim_process_pre_auth_reassoc_req() -Process preauth request + * @hal: HAL context + * @msg: message + * + * This function process preauth request received from CSR + */ +void lim_process_pre_auth_reassoc_req(tpAniSirGlobal mac, tpSirMsgQ msg) +{ + tpPESession session_entry; + tANI_U8 session_id; + + limFTInit(mac); + + /* Can set it only after sending auth */ + mac->ft.ftPEContext.ftPreAuthStatus = eSIR_FAILURE; + + /* We need information from the Pre-Auth Req. Lets save that */ + mac->ft.ftPEContext.pFTPreAuthReq = (tpSirFTPreAuthReq)msg->bodyptr; + if (!mac->ft.ftPEContext.pFTPreAuthReq) { + limLog(mac, LOGE, + FL("pFTPreAuthReq is NULL")); + lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL, + SIR_MBB_CONNECTED); + return; + } + + /* Get the current session entry */ + session_entry = peFindSessionByBssid(mac, + mac->ft.ftPEContext.pFTPreAuthReq->currbssId, &session_id); + if (session_entry == NULL) { + limLog(mac, LOGE, + FL("Unable to find session for the following bssid")); + limPrintMacAddr(mac, + mac->ft.ftPEContext.pFTPreAuthReq->currbssId, LOGE); + + /* Post the pre auth response to SME */ + lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL, + SIR_MBB_CONNECTED); + return; + } + + limLog(mac, LOG1, + FL("set link with eSIR_LINK_PRE_AUTH_REASSOC_STATE")); + + if (limSetLinkState(mac, eSIR_LINK_PRE_AUTH_REASSOC_STATE, + session_entry->bssId, session_entry->selfMacAddr, + NULL, NULL) != eSIR_SUCCESS) { + limLog(mac, LOGE, + FL("set link failed for eSIR_LINK_PRE_AUTH_REASSOC_STATE")); + lim_post_pre_auth_reassoc_rsp(mac, eSIR_FAILURE, NULL, + SIR_MBB_CONNECTED); + return; + } + + /* + * Suspend link for same channel or different channel so that STA + * can be in power save for connected AP. + */ + limLog(mac, LOG1, + FL("pre-auth on channel %d (session %p) currentOperChannel %d"), + mac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum, + session_entry, session_entry->currentOperChannel); + limSuspendLink(mac, eSIR_CHECK_ROAMING_SCAN, + pre_auth_mbb_suspend_link_handler, + (tANI_U32 *)session_entry); +} + + +/** + * lim_process_sta_mlm_del_sta_rsp_mbb() -Process del sta response + * @mac: MAC context + * @lim_msg: lim message + * @session_entry: session entry + * + * This function process del sta response + */ +void lim_process_sta_mlm_del_sta_rsp_mbb(tpAniSirGlobal mac, + tpSirMsgQ lim_msg, tpPESession session_entry) +{ + tpDeleteStaParams del_sta_params = (tpDeleteStaParams)lim_msg->bodyptr; + tpDphHashNode sta_ds = NULL; + tANI_U8 session_id; + tpPESession ft_session_entry; + + if(NULL == del_sta_params) { + limLog(mac, LOGE, FL("Encountered NULL Pointer")); + goto end; + } + + limLog(mac, LOG1, FL("Del STA RSP received. Status:%d AssocID:%d"), + del_sta_params->status, del_sta_params->assocId); + + if (eHAL_STATUS_SUCCESS != del_sta_params->status) { + limLog(mac, LOGE, FL("Del STA failed! Status:%d, still proceeding" + "with Del BSS"), del_sta_params->status); + } + + sta_ds = dphGetHashEntry(mac, DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + + if (sta_ds == NULL) { + limLog( mac, LOGE, FL("DPH Entry for STA %X missing"), + del_sta_params->assocId); + goto end; + } + + if (eLIM_MLM_WT_DEL_STA_RSP_STATE != session_entry->limMlmState) { + limLog(mac, LOGE, + FL( "Received unexpected WDA_DELETE_STA_RSP in state %s" ), + limMlmStateStr(session_entry->limMlmState)); + goto end; + } + + limLog( mac, LOG1, FL("STA AssocID %d MAC "), sta_ds->assocId); + limPrintMacAddr(mac, sta_ds->staAddr, LOG1); + + /* + * we must complete all cleanup related to del sta + * before calling del bss. + */ + if (NULL != lim_msg->bodyptr) { + vos_mem_free(del_sta_params); + lim_msg->bodyptr = NULL; + } + + /* Proceed to do del bss even if del sta resulted in failure */ + lim_del_bss_mbb(mac, sta_ds, 0, session_entry); + return; + +end: + if(NULL != lim_msg->bodyptr) { + vos_mem_free(del_sta_params); + lim_msg->bodyptr = NULL; + } + + /* Connected AP lim cleanup.*/ + lim_cleanup_connected_ap(mac, sta_ds, session_entry); + + ft_session_entry = peFindSessionByBssid(mac, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId, + &session_id); + if (ft_session_entry == NULL) { + limLog(mac, LOGE, + FL("Unable to find session for the following bssid")); + limPrintMacAddr(mac, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId, LOGE); + return; + } + + /* + * eHAL_STATUS_INVALID_PARAMETER is used + * so that full cleanup is triggered. + */ + lim_reassoc_fail_cleanup(mac, eHAL_STATUS_INVALID_PARAMETER, + (tANI_U32 *)ft_session_entry); +} + +/** + * lim_cleanup_rx_path_mbb() -cleans up tspec related info + * @mac: MAC context + * @sta_ds: station entry + * @session_entry: session entry of connected AP + * + * This function cleans up tspec related info + */ +void lim_cleanup_rx_path_mbb(tpAniSirGlobal mac, + tpDphHashNode sta_ds,tpPESession session_entry) +{ + limLog(mac, LOG1, FL("AID %d limSmeState %d, mlmState %d"), + sta_ds->assocId, session_entry->limSmeState, + sta_ds->mlmStaContext.mlmState); + + session_entry->isCiscoVendorAP = FALSE; + + if (mac->lim.gLimAddtsSent) + tx_timer_deactivate(&mac->lim.limTimers.gLimAddtsRspTimer); + + /* delete all tspecs associated with this sta. */ + limAdmitControlDeleteSta(mac, sta_ds->assocId); +} + + +/** + * lim_cleanup_connected_ap() -cleans up connected AP lim info + * @mac: MAC context + * @sta_ds: station entry + * @session_entry: session entry of connected AP + * + * This function cleans up connected AP lim info + */ +void lim_cleanup_connected_ap(tpAniSirGlobal mac, tpDphHashNode sta_ds, + tpPESession session_entry) +{ + lim_cleanup_rx_path_mbb(mac, sta_ds, session_entry); + limDeleteDphHashEntry(mac, sta_ds->staAddr, + sta_ds->assocId, session_entry); + + /** + * Make STA hash entry invalid at eCPU so that DPH + * does not process any more data packets and + * releases those BDs + */ + sta_ds->valid = 0; + + peDeleteSession(mac, session_entry); +} + +/** + * lim_process_sta_mlm_del_bss_rsp_mbb() -Process del bss response of + * connected AP + * @mac: MAC context + * @lim_msg: lim message + * @session_entry: session entry of connected AP + * + * This function process del sta response + */ +void lim_process_sta_mlm_del_bss_rsp_mbb(tpAniSirGlobal mac, + tpSirMsgQ lim_msg, tpPESession session_entry) +{ + tpDeleteBssParams delbss_params = (tpDeleteBssParams)lim_msg->bodyptr; + tpDphHashNode sta_ds = dphGetHashEntry(mac, DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + tpPESession ft_session_entry; + tANI_U8 session_id; + + if (NULL == delbss_params) { + limLog(mac, LOGE, FL( "Invalid body pointer in message")); + goto end; + } + + ft_session_entry = peFindSessionByBssid(mac, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId, + &session_id); + if (ft_session_entry == NULL) { + limLog(mac, LOGE, + FL("Unable to find session for the following bssid")); + limPrintMacAddr(mac, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId, LOGE); + goto end; + } + + if(eHAL_STATUS_SUCCESS == delbss_params->status) { + limLog(mac, LOG1, + FL( "STA received the DEL_BSS_RSP for BSSID: %X."), + delbss_params->bssIdx); + + if(sta_ds == NULL) { + limLog(mac, LOGE, FL("DPH Entry for STA missing")); + goto end; + } + if(eLIM_MLM_WT_DEL_BSS_RSP_STATE != session_entry->limMlmState) { + limLog(mac, LOGE, + FL("Received unexpected WDA_DEL_BSS_RSP in state %d"), + session_entry->limMlmState); + goto end; + } + limLog(mac, LOG1, FL("STA AssocID %d MAC "), sta_ds->assocId ); + limPrintMacAddr(mac, sta_ds->staAddr, LOG1); + + lim_cleanup_connected_ap(mac, sta_ds, session_entry); + + lim_add_bss_mbb(mac, sta_ds, ft_session_entry); + + if(NULL != lim_msg->bodyptr) { + vos_mem_free(delbss_params); + lim_msg->bodyptr = NULL; + } + return; + } else { + /* + * If del bss response is failure, cleanup sessions of both currently + * connected AP and roamable AP as add bss can not be send + * without successful delbss. + */ + limLog(mac, LOGE, + FL("DEL BSS failed! Status:%d"), delbss_params->status); + + if(NULL != lim_msg->bodyptr) { + vos_mem_free(delbss_params); + lim_msg->bodyptr = NULL; + } + + /* Connected AP lim cleanup.*/ + lim_cleanup_connected_ap(mac, sta_ds, session_entry); + + /* Newly created session cleanup */ + lim_reassoc_fail_cleanup(mac, eHAL_STATUS_MBB_DEL_BSS_FAIL, + (tANI_U32 *)ft_session_entry); + return; + } + +end: + if(NULL != lim_msg->bodyptr) { + vos_mem_free(delbss_params); + lim_msg->bodyptr = NULL; + } + + lim_cleanup_connected_ap(mac, sta_ds, session_entry); + + ft_session_entry = peFindSessionByBssid(mac, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId, + &session_id); + if (ft_session_entry == NULL) { + limLog(mac, LOGE, + FL("Unable to find session for the following bssid")); + limPrintMacAddr(mac, + mac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId, LOGE); + return; + } + + /* + * eHAL_STATUS_INVALID_PARAMETER is used + * so that full cleanup is triggered. + */ + lim_reassoc_fail_cleanup(mac, eHAL_STATUS_INVALID_PARAMETER, + (tANI_U32 *)ft_session_entry); +} + + +void lim_fill_add_sta_params_mbb(tpAniSirGlobal mac, + tpPESession session_entry, tpAddStaParams add_sta_params) +{ + tANI_U32 listen_interval = WNI_CFG_LISTEN_INTERVAL_STADEF; + tANI_U32 self_sta_dot11_mode = 0; + + vos_mem_copy(add_sta_params->staMac, session_entry->selfMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy(add_sta_params->bssId, session_entry->bssId, + sizeof(tSirMacAddr)); + + add_sta_params->staType = STA_ENTRY_SELF; + add_sta_params->status = eHAL_STATUS_SUCCESS; + add_sta_params->respReqd = 1; + + add_sta_params->sessionId = session_entry->peSessionId; + add_sta_params->staIdx = HAL_STA_INVALID_IDX; + add_sta_params->updateSta = FALSE; + + add_sta_params->shortPreambleSupported = + session_entry->beaconParams.fShortPreamble; + +#ifdef WLAN_FEATURE_11AC + limPopulatePeerRateSet(mac, &add_sta_params->supportedRates, NULL, + false,session_entry, NULL); +#else + limPopulatePeerRateSet(mac, &add_sta_params->supportedRates, NULL, + false,session_entry); +#endif + + if(session_entry->htCapability) { + add_sta_params->htCapable = session_entry->htCapability; +#ifdef WLAN_FEATURE_11AC + add_sta_params->vhtCapable = session_entry->vhtCapability; + add_sta_params->vhtTxChannelWidthSet = session_entry->vhtTxChannelWidthSet; +#endif + +#ifdef DISABLE_GF_FOR_INTEROP + if((session_entry->pLimJoinReq != NULL) && + (!session_entry->pLimJoinReq->bssDescription.aniIndicator)) { + limLog(mac, LOGE, + FL("Turning off Greenfield, when adding self entry")); + add_sta_params->greenFieldCapable = + WNI_CFG_GREENFIELD_CAPABILITY_DISABLE; + } + else +#endif + add_sta_params->greenFieldCapable = + limGetHTCapability( mac, eHT_GREENFIELD, session_entry); + + if (session_entry->limRFBand == SIR_BAND_2_4_GHZ) + add_sta_params->txChannelWidthSet = + mac->roam.configParam.channelBondingMode24GHz; + else + add_sta_params->txChannelWidthSet = + mac->roam.configParam.channelBondingMode5GHz; + + add_sta_params->mimoPS = + limGetHTCapability(mac, eHT_MIMO_POWER_SAVE, session_entry); + add_sta_params->rifsMode = + limGetHTCapability(mac, eHT_RIFS_MODE, session_entry); + add_sta_params->lsigTxopProtection = + limGetHTCapability(mac, eHT_LSIG_TXOP_PROTECTION, session_entry); + add_sta_params->delBASupport = + limGetHTCapability(mac, eHT_DELAYED_BA, session_entry); + add_sta_params->maxAmpduDensity = + limGetHTCapability(mac, eHT_MPDU_DENSITY, session_entry); + add_sta_params->maxAmpduSize = + limGetHTCapability(mac, eHT_MAX_RX_AMPDU_FACTOR, session_entry); + add_sta_params->maxAmsduSize = + limGetHTCapability(mac, eHT_MAX_AMSDU_LENGTH, session_entry); + add_sta_params->fDsssCckMode40Mhz = + limGetHTCapability(mac, eHT_DSSS_CCK_MODE_40MHZ, session_entry); + add_sta_params->fShortGI20Mhz = + limGetHTCapability(mac, eHT_SHORT_GI_20MHZ, session_entry); + add_sta_params->fShortGI40Mhz = + limGetHTCapability(mac, eHT_SHORT_GI_40MHZ, session_entry); + } + + if (wlan_cfgGetInt(mac, WNI_CFG_LISTEN_INTERVAL, + &listen_interval) != eSIR_SUCCESS) + limLog(mac, LOGE, FL("Couldn't get LISTEN_INTERVAL")); + + add_sta_params->listenInterval = (tANI_U16)listen_interval; + + wlan_cfgGetInt(mac, WNI_CFG_DOT11_MODE, &self_sta_dot11_mode); + add_sta_params->supportedRates.opRateMode = + limGetStaRateMode((tANI_U8)self_sta_dot11_mode); + + mac->ft.ftPEContext.pAddStaReq = add_sta_params; + + +} + +void lim_process_sta_mlm_add_bss_rsp_mbb(tpAniSirGlobal mac, + tpSirMsgQ limMsgQ,tpPESession session_entry) +{ + tpAddBssParams add_bss_params = (tpAddBssParams)limMsgQ->bodyptr; + tpAddStaParams add_sta_params = NULL; + tpDphHashNode sta_ds = dphGetHashEntry(mac, DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + + if(add_bss_params == 0) + goto end; + + limLog(mac, LOG1, FL("Add BSS RSP received. Status:%d"), + add_bss_params->status); + + if(eHAL_STATUS_SUCCESS == add_bss_params->status) { + + if(eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE != session_entry->limMlmState) { + limLog(mac, LOGE, + FL("Received unexpected ADD BSS in state %d"), + session_entry->limMlmState); + goto end; + } + + session_entry->bssIdx = add_bss_params->bssIdx; + + sta_ds->bssId = add_bss_params->bssIdx; + sta_ds->staIndex = add_bss_params->staContext.staIdx; + sta_ds->ucUcastSig = add_bss_params->staContext.ucUcastSig; + sta_ds->ucBcastSig = add_bss_params->staContext.ucBcastSig; + + rrmCacheMgmtTxPower(mac, add_bss_params->txMgmtPower, session_entry); + + /* Allocate memory for add sta params */ + add_sta_params = vos_mem_malloc(sizeof( tAddStaParams )); + if (NULL == add_sta_params) { + limLog(mac, LOGE, + FL("Unable to allocate memory during ADD_STA")); + goto end; + } + vos_mem_set(add_sta_params, sizeof(tAddStaParams), 0); + + /* Prepare add sta params */ + lim_fill_add_sta_params_mbb(mac, session_entry, add_sta_params); + + if(0 != limMsgQ->bodyptr) { + vos_mem_free(add_bss_params); + add_bss_params = NULL; + limMsgQ->bodyptr = NULL; + } + + lim_add_sta_mbb(mac, session_entry->limAID, session_entry); + + } else { + /* + * If add bss response is failure, cleanup session of roamable AP + * as cleanup of connected bss happened during del bss + */ + limLog(mac, LOGE, + FL("ADD BSS failed! Status:%d"), add_bss_params->status); + + /* Newly created session cleanup */ + lim_reassoc_fail_cleanup(mac, eHAL_STATUS_MBB_ADD_BSS_FAIL, + (tANI_U32 *)session_entry); + } + +end: + if(0 != limMsgQ->bodyptr) { + vos_mem_free(add_bss_params); + add_bss_params = NULL; + limMsgQ->bodyptr = NULL; + } +} + +/* + * lim_perform_post_add_sta_rsp() -invokes resume callback to handle add sta response + * @mac: MAC context + * @status: status + * @data: pointer to data + * + * This function invokes resume callback + */ +void lim_perform_post_add_sta_rsp(tpAniSirGlobal mac, + eHalStatus status, tANI_U32 *data) +{ + tpDphHashNode sta_ds; + /* session entry for newly roamed ap */ + tpPESession session_entry; + + session_entry = (tpPESession)data; + + limLog(mac, LOG1, FL("forwarding cached packets")); + WLANTL_PreAssocForward(true); + + sta_ds = dphGetHashEntry(mac, DPH_STA_HASH_INDEX_PEER, + &session_entry->dph.dphHashTable); + if(NULL != sta_ds) + sta_ds->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + else { + limLog(mac, LOGE, + FL("Unable to get the DPH Hash Entry for AID - %d"), + DPH_STA_HASH_INDEX_PEER); + return; + } + + session_entry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; + MTRACE(macTrace(mac, TRACE_CODE_MLM_STATE, + session_entry->peSessionId, eLIM_MLM_LINK_ESTABLISHED_STATE)); + +#ifdef FEATURE_WLAN_TDLS + /* initialize TDLS peer related data */ + limInitTdlsData(mac, session_entry); +#endif + + if (limSetLinkState(mac, eSIR_LINK_POSTASSOC_STATE, session_entry->bssId, + session_entry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) { + limLog(mac, LOGE, FL("Set link state to POSTASSOC failed")); + return; + } + + session_entry->limSmeState = eLIM_SME_LINK_EST_STATE; + + lim_post_pre_auth_reassoc_rsp(mac, eSIR_SUCCESS, session_entry, + SIR_MBB_CONNECTED); + + /* Freeup the cached preauth request */ + if (mac->ft.ftPEContext.pFTPreAuthReq) { + limLog(mac, LOG1, FL("Freeing pFTPreAuthReq= %p"), + mac->ft.ftPEContext.pFTPreAuthReq); + if (mac->ft.ftPEContext.pFTPreAuthReq->pbssDescription) { + vos_mem_free(mac->ft.ftPEContext.pFTPreAuthReq->pbssDescription); + mac->ft.ftPEContext.pFTPreAuthReq->pbssDescription = NULL; + } + vos_mem_free(mac->ft.ftPEContext.pFTPreAuthReq); + mac->ft.ftPEContext.pFTPreAuthReq = NULL; + } +} + +void lim_process_sta_mlm_add_sta_rsp_mbb(tpAniSirGlobal mac, + tpSirMsgQ limMsgQ,tpPESession session_entry) +{ + tpAddStaParams add_sta_params = (tpAddStaParams)limMsgQ->bodyptr; + + if(NULL == add_sta_params) { + limLog(mac, LOGE, FL("Encountered NULL Pointer")); + return; + } + + limLog(mac, LOG1, FL("Add STA RSP received. Status:%d"), + add_sta_params->status); + + if (eHAL_STATUS_SUCCESS == add_sta_params->status) { + if ( eLIM_MLM_WT_ADD_STA_RSP_STATE != session_entry->limMlmState) { + limLog(mac, LOGE, + FL("Received unexpected ADD_STA_RSP in state %d"), + session_entry->limMlmState); + goto end; + } + + /* + * Storing the self StaIndex(Generated by HAL) in session context, + * instead of storing it in DPH Hash entry for Self STA. + * DPH entry for the self STA stores the sta index for the BSS entry + * to which the STA is associated. + */ + session_entry->staId = add_sta_params->staIdx; + + limLog(mac, LOG1, FL("resuming to oper ch %d"), + session_entry->currentOperChannel); + + peSetResumeChannel(mac, session_entry->currentOperChannel, 0); + limResumeLink(mac, lim_perform_post_add_sta_rsp, (tANI_U32 *)session_entry); + } else { + limLog(mac, LOGE, FL( "ADD_STA failed!")); + + /* Newly created session cleanup */ + lim_reassoc_fail_cleanup(mac, eHAL_STATUS_MBB_ADD_BSS_FAIL, + (tANI_U32 *)session_entry); + + } +end: + if( 0 != limMsgQ->bodyptr ) + { + vos_mem_free(add_sta_params); + limMsgQ->bodyptr = NULL; + } +} + +eAniBoolean lim_is_mbb_reassoc_in_progress(tpAniSirGlobal mac, + tpPESession session_entry) +{ + if (session_entry == NULL) + return eANI_BOOLEAN_FALSE; + + if ((eLIM_STA_ROLE == session_entry->limSystemRole) && + mac->ft.ftSmeContext.is_preauth_lfr_mbb) { + limLog(mac, LOG1, FL("MBB Reassoc in progress")); + return eANI_BOOLEAN_TRUE; + } + + return eANI_BOOLEAN_FALSE; +} diff --git a/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c b/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c index 21ac26cb2d7..1c31dc8ec3c 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -2176,14 +2176,22 @@ void pmmEnterWowlRequestHandler(tpAniSirGlobal pMac, tpSirMsgQ pMsg) goto end; } #endif - - - if ((pMac->pmm.gPmmState != ePMM_STATE_BMPS_SLEEP) && (pMac->pmm.gPmmState != ePMM_STATE_WOWLAN)) + /** + * In SAP mode BMPS is not supported skip bmps validation and + * send command directly. + */ + if (pSessionEntry->operMode != BSS_OPERATIONAL_MODE_AP) { - pmmLog(pMac, LOGE, FL("Rcvd PMC_ENTER_WOWL_REQ in invalid Power Save state ")); - limSendSmeRsp(pMac, eWNI_PMC_ENTER_WOWL_RSP, eSIR_SME_INVALID_PMM_STATE, 0, 0); - goto end; - } + if ((pMac->pmm.gPmmState != ePMM_STATE_BMPS_SLEEP) && + (pMac->pmm.gPmmState != ePMM_STATE_WOWLAN)) + { + pmmLog(pMac, LOGE, FL("Rcvd PMC_ENTER_WOWL_REQ in invalid Power Save state ")); + limSendSmeRsp(pMac, eWNI_PMC_ENTER_WOWL_RSP, + eSIR_SME_INVALID_PMM_STATE, 0, 0); + goto end; + } + } else + pmmLog(pMac,LOG1, FL("SAP dosn't support BMPS mode directly post wowl request")); pHalWowlParams = vos_mem_malloc(sizeof(*pHalWowlParams)); if ( NULL == pHalWowlParams ) @@ -2363,6 +2371,7 @@ void pmmExitWowlanRequestHandler(tpAniSirGlobal pMac) tpPESession pSessionEntry; tpSirHalWowlExitParams pHalWowlMsg = NULL; tANI_U8 PowersavesessionId = 0; + tANI_U8 smeSessionId = 0; PowersavesessionId = pMac->pmm.sessionId; @@ -2373,6 +2382,8 @@ void pmmExitWowlanRequestHandler(tpAniSirGlobal pMac) goto failure; } + smeSessionId = pSessionEntry->smeSessionId; + pHalWowlMsg = vos_mem_malloc(sizeof(*pHalWowlMsg)); if ( NULL == pHalWowlMsg ) { @@ -2410,7 +2421,7 @@ void pmmExitWowlanRequestHandler(tpAniSirGlobal pMac) failure: if (pHalWowlMsg != NULL) vos_mem_free(pHalWowlMsg); - limSendSmeRsp(pMac, eWNI_PMC_EXIT_WOWL_RSP, smeRspCode, 0, 0); + limSendSmeRsp(pMac, eWNI_PMC_EXIT_WOWL_RSP, smeRspCode, smeSessionId, 0); return; } @@ -2461,6 +2472,8 @@ void pmmExitWowlanResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) tpSirHalWowlExitParams pHalWowlRspMsg; eHalStatus rspStatus = eHAL_STATUS_FAILURE; + tpPESession psessionEntry = NULL; + tANI_U8 smeSessionId = 0; /* we need to process all the deferred messages enqueued * since the initiating the WDA_WOWL_EXIT_REQ. @@ -2477,17 +2490,23 @@ void pmmExitWowlanResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) // restore PMM state to BMPS mode pMac->pmm.gPmmState = ePMM_STATE_BMPS_SLEEP; rspStatus = pHalWowlRspMsg->status; + psessionEntry = peFindSessionByBssIdx(pMac, pHalWowlRspMsg->bssIdx); + if (psessionEntry) { + smeSessionId = psessionEntry->smeSessionId; + if (LIM_IS_AP_ROLE(psessionEntry)) + pMac->pmm.gPmmState = ePMM_STATE_READY; + } } if( rspStatus == eHAL_STATUS_SUCCESS) { pmmLog(pMac, LOGW, FL("Rcvd successful rsp from HAL to exit WOWLAN ")); - limSendSmeRsp(pMac, eWNI_PMC_EXIT_WOWL_RSP, eSIR_SME_SUCCESS, 0, 0); + limSendSmeRsp(pMac, eWNI_PMC_EXIT_WOWL_RSP, eSIR_SME_SUCCESS, smeSessionId, 0); } else { pmmLog(pMac, LOGE, FL("Rcvd failure rsp from HAL to exit WOWLAN ")); - limSendSmeRsp(pMac, eWNI_PMC_EXIT_WOWL_RSP, eSIR_SME_WOWL_EXIT_REQ_FAILED, 0, 0); + limSendSmeRsp(pMac, eWNI_PMC_EXIT_WOWL_RSP, eSIR_SME_WOWL_EXIT_REQ_FAILED, smeSessionId, 0); } return; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconGen.c b/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconGen.c index 0fc798995ae..15438a7796c 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconGen.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconGen.c @@ -386,6 +386,13 @@ tSirRetStatus schSetFixedBeaconFields(tpAniSirGlobal pMac,tpPESession psessionEn &pBcn2->WPA ); PopulateDot11fRSNOpaque( pMac, &psessionEntry->pLimStartBssReq->rsnIE, &pBcn2->RSNOpaque ); +#ifdef SAP_AUTH_OFFLOAD + /* Software AP Authentication Offload feature + * only support WPA2-PSK AES and we + * need to update RSNIE for beacon + */ + sap_auth_offload_update_rsn_ie(pMac, &pBcn2->RSNOpaque); +#endif } if(psessionEntry->limWmeEnabled) diff --git a/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c b/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c index 79f1ae8b0e6..7152d3be962 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c @@ -380,9 +380,14 @@ static void __schBeaconProcessForSession( tpAniSirGlobal pMac, goto fail; } - if( RF_CHAN_14 >= psessionEntry->currentOperChannel ) + if(RF_CHAN_14 >= psessionEntry->currentOperChannel) { - channelBondingMode = pMac->roam.configParam.channelBondingMode24GHz; + if (psessionEntry->force_24ghz_in_ht20) + channelBondingMode = + WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; + else + channelBondingMode = + pMac->roam.configParam.channelBondingMode24GHz; } else { diff --git a/drivers/staging/prima/CORE/SAP/inc/sapApi.h b/drivers/staging/prima/CORE/SAP/inc/sapApi.h index dcb24828958..390e10b5d39 100644 --- a/drivers/staging/prima/CORE/SAP/inc/sapApi.h +++ b/drivers/staging/prima/CORE/SAP/inc/sapApi.h @@ -884,6 +884,30 @@ typedef VOS_STATUS (*tpWLAN_SAPEventCB)( tpSap_Event pSapEvent, v_PVOID_t pUsrC v_U8_t WLANSAP_getState ( v_PVOID_t pvosGCtx); /*========================================================================== + FUNCTION WLANSAP_get_sessionId + + DESCRIPTION + This api returns the current SAP sessionId to the caller. + + DEPENDENCIES + + PARAMETERS + + IN + pContext : Pointer to Sap Context structure + v_U8_t : Pointer to sessionID + + RETURN VALUE + VOS_STATUS_SUCCESS on success. + + VOS_STATUS_E_INVAL: Pointer to SAP cb is NULL ; access would cause a page + fault +============================================================================*/ +VOS_STATUS WLANSAP_get_sessionId +( + v_PVOID_t pvosGCtx, v_U8_t *sessionId +); +/*========================================================================== FUNCTION WLANSAP_StartBss DESCRIPTION diff --git a/drivers/staging/prima/CORE/SAP/src/sapModule.c b/drivers/staging/prima/CORE/SAP/src/sapModule.c index 5376ce60789..e8171b1782c 100644 --- a/drivers/staging/prima/CORE/SAP/src/sapModule.c +++ b/drivers/staging/prima/CORE/SAP/src/sapModule.c @@ -532,7 +532,52 @@ v_U8_t WLANSAP_getState } return pSapCtx->sapsMachine; } +/*========================================================================== + FUNCTION WLANSAP_get_sessionId + + DESCRIPTION + This api returns the current SAP sessionId to the caller. + + DEPENDENCIES + + PARAMETERS + + IN + pContext : Pointer to Sap Context structure + v_U8_t : Pointer to sessionID + + RETURN VALUE + VOS_STATUS_SUCCESS on success. + VOS_STATUS_E_INVAL: Pointer to SAP cb is NULL ; access would cause a page + fault +============================================================================*/ +VOS_STATUS WLANSAP_get_sessionId +( + v_PVOID_t pvosGCtx, v_U8_t *sessionId +) +{ + ptSapContext pSapCtx = NULL; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + pSapCtx = VOS_GET_SAP_CB(pvosGCtx); + + if ( NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + status = VOS_STATUS_E_INVAL; + } + + if (pSapCtx->sapsMachine == eSAP_STARTED) { + *sessionId = pSapCtx->sessionId; + status = VOS_STATUS_SUCCESS; + } + else + status = VOS_STATUS_E_FAILURE; + + return status; +} /*========================================================================== FUNCTION WLANSAP_StartBss diff --git a/drivers/staging/prima/CORE/SME/inc/csrApi.h b/drivers/staging/prima/CORE/SME/inc/csrApi.h index 3d6f28e80a5..715c7e6a24d 100644 --- a/drivers/staging/prima/CORE/SME/inc/csrApi.h +++ b/drivers/staging/prima/CORE/SME/inc/csrApi.h @@ -666,8 +666,6 @@ typedef enum eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED, // Participating in a Infra network and connected to a peer eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED, - /* Disconnecting with AP or stop connecting process */ - eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING, }eCsrConnectState; @@ -959,6 +957,7 @@ typedef struct tagCsrRoamProfile tCsrMobilityDomainInfo MDID; #endif tVOS_CON_MODE csrPersona; + bool force_24ghz_in_ht20; tCsrBssid bssid_hint; }tCsrRoamProfile; @@ -1033,6 +1032,7 @@ typedef struct tagCsrNeighborRoamConfigParams tANI_U16 nNeighborResultsRefreshPeriod; tANI_U16 nEmptyScanRefreshPeriod; tANI_U8 nNeighborInitialForcedRoamTo5GhEnable; + tANI_U8 nWeakZoneRssiThresholdForRoam; }tCsrNeighborRoamConfigParams; #endif @@ -1199,6 +1199,11 @@ typedef struct tagCsrConfigParam v_U32_t PERtimerThreshold; v_U32_t PERroamTriggerPercent; #endif + +#ifdef WLAN_FEATURE_LFR_MBB + tANI_BOOLEAN enable_lfr_mbb; +#endif + #endif tANI_BOOLEAN ignorePeerErpInfo; @@ -1239,6 +1244,7 @@ typedef struct tagCsrConfigParam uint32_t edca_bk_aifs; uint32_t edca_be_aifs; tANI_BOOLEAN disable_scan_during_sco; + uint32_t sta_auth_retries_for_code17; }tCsrConfigParam; //Tush @@ -1330,6 +1336,12 @@ typedef struct tagCsrRoamInfo #ifdef WLAN_FEATURE_AP_HT40_24G tpSirHT2040CoexInfoInd pSmeHT2040CoexInfoInd; #endif + tDot11fIEHTCaps ht_caps; + tDot11fIEVHTCaps vht_caps; + tDot11fIEhs20vendor_ie hs20vendor_ie; + tDot11fIEVHTOperation vht_operation; + tDot11fIEHTInfo ht_operation; + bool reassoc; }tCsrRoamInfo; typedef struct tagCsrFreqScanInfo @@ -1554,6 +1566,18 @@ struct tagCsrDelStaParams u8 subtype; }; + +/** + * struct csr_set_tx_max_pwr_per_band - Req params to + * set max tx power per band + * @band: band for which power to be set + * @power: power to set in dB + */ +struct csr_set_tx_max_pwr_per_band { + eCsrBand band; + tPowerdBm power; +}; + ////////////////////////////////////////////Common SCAN starts //void *p2 -- the second context pass in for the caller @@ -1754,6 +1778,5 @@ eHalStatus csrSetBand(tHalHandle hHal, eCsrBand eBand); ---------------------------------------------------------------------------*/ eCsrBand csrGetCurrentBand (tHalHandle hHal); - #endif diff --git a/drivers/staging/prima/CORE/SME/inc/csrInternal.h b/drivers/staging/prima/CORE/SME/inc/csrInternal.h index 2693992afa4..3d1fff6ac83 100644 --- a/drivers/staging/prima/CORE/SME/inc/csrInternal.h +++ b/drivers/staging/prima/CORE/SME/inc/csrInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -206,7 +206,7 @@ typedef enum eCsrLostLink1Abort, eCsrLostLink2Abort, eCsrLostLink3Abort, - + ecsr_mbb_perform_preauth_reassoc, }eCsrRoamReason; typedef enum @@ -520,6 +520,7 @@ typedef struct tagCsrNeighborRoamConfig tANI_U16 nNeighborResultsRefreshPeriod; tANI_U16 nEmptyScanRefreshPeriod; tANI_U8 nNeighborInitialForcedRoamTo5GhEnable; + tANI_U8 nWeakZoneRssiThresholdForRoam; }tCsrNeighborRoamConfig; #endif @@ -636,6 +637,10 @@ typedef struct tagCsrConfig #endif #endif +#ifdef WLAN_FEATURE_LFR_MBB + tANI_BOOLEAN enable_lfr_mbb; +#endif + #ifdef FEATURE_WLAN_ESE tANI_U8 isEseIniFeatureEnabled; #endif @@ -1495,3 +1500,18 @@ void csrDisableDfsChannel(tpAniSirGlobal pMac); eHalStatus csrEnableRMC(tpAniSirGlobal pMac, tANI_U32 sessionId); eHalStatus csrDisableRMC(tpAniSirGlobal pMac, tANI_U32 sessionId); #endif /* WLAN_FEATURE_RMC */ + +eHalStatus csrRoamStopNetwork(tpAniSirGlobal pMac, tANI_U32 sessionId, + tCsrRoamProfile *pProfile, tSirBssDescription *pBssDesc, + tDot11fBeaconIEs *pIes); + +eHalStatus csrRoamSaveSecurityRspIE(tpAniSirGlobal pMac, + tANI_U32 sessionId, eCsrAuthType authType, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes); + +void csrRoamSubstateChange(tpAniSirGlobal pMac, + eCsrRoamSubState NewSubstate, tANI_U32 sessionId); + +eHalStatus csrRoamFreeConnectedInfo(tpAniSirGlobal pMac, + tCsrRoamConnectedInfo *pConnectedInfo); diff --git a/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h b/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h index 5df4eee3d3d..93bfc0769ce 100644 --- a/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h +++ b/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2014, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -41,6 +41,12 @@ #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING #include "sme_Api.h" +/* 15 seconds, for WPA, WPA2, CCKM */ +#define CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD (15 * PAL_TIMER_TO_SEC_UNIT) +/* 120 seconds, for WPS */ +#define CSR_WAIT_FOR_WPS_KEY_TIMEOUT_PERIOD (120 * PAL_TIMER_TO_SEC_UNIT) + + /* Enumeration of various states in neighbor roam algorithm */ typedef enum { @@ -55,6 +61,10 @@ typedef enum eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING, eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE, #endif /* WLAN_FEATURE_VOWIFI_11R */ +#ifdef WLAN_FEATURE_LFR_MBB + eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC, +#endif + eNEIGHBOR_STATE_MAX } eCsrNeighborRoamState; @@ -71,6 +81,7 @@ typedef struct sCsrNeighborRoamCfgParams tANI_U16 neighborResultsRefreshPeriod; tANI_U16 emptyScanRefreshPeriod; tANI_U8 neighborInitialForcedRoamTo5GhEnable; + tANI_U8 WeakZoneRssiThresholdForRoam; } tCsrNeighborRoamCfgParams, *tpCsrNeighborRoamCfgParams; #define CSR_NEIGHBOR_ROAM_INVALID_CHANNEL_INDEX 255 @@ -206,6 +217,11 @@ typedef struct sCsrNeighborRoamControlInfo vos_timer_t forcedInitialRoamTo5GHTimer; tANI_U8 isForcedInitialRoamTo5GH; tANI_U8 lastSentCmd; + +#ifdef WLAN_FEATURE_LFR_MBB + bool is_pre_auth_reassoc_mbb_timer_started; +#endif + } tCsrNeighborRoamControlInfo, *tpCsrNeighborRoamControlInfo; @@ -251,6 +267,15 @@ VOS_STATUS csrNeighborRoamMergeChannelLists(tpAniSirGlobal pMac, tANI_U8 *pOutputChannelList, tANI_U8 outputNumOfChannels, tANI_U8 *pMergedOutputNumOfChannels); +tANI_BOOLEAN +csrNeighborRoamRemoveRoamableAPListEntry(tpAniSirGlobal pMac, + tDblLinkList *pList, tpCsrNeighborRoamBSSInfo pNeighborEntry); +eHalStatus +csrNeighborRoamAddBssIdToPreauthFailList(tpAniSirGlobal pMac, + tSirMacAddr bssId); +void csrNeighborRoamFreeNeighborRoamBSSNode(tpAniSirGlobal pMac, + tpCsrNeighborRoamBSSInfo neighborRoamBSSNode); + #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD #define ROAM_SCAN_OFFLOAD_START 1 @@ -282,6 +307,10 @@ eHalStatus csrNeighborRoamHandoffReqHdlr(tpAniSirGlobal pMac, void* pMsg); eHalStatus csrNeighborRoamProceedWithHandoffReq(tpAniSirGlobal pMac); eHalStatus csrNeighborRoamSssidScanDone(tpAniSirGlobal pMac, eHalStatus status); eHalStatus csrNeighborRoamStartLfrScan(tpAniSirGlobal pMac, tANI_U8 OffloadCmdStopReason); +eHalStatus csrRoamStartWaitForKeyTimer(tpAniSirGlobal pMac, + tANI_U32 interval); +void csrRoamLinkUp(tpAniSirGlobal pMac, tCsrBssid bssid); + #endif #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) diff --git a/drivers/staging/prima/CORE/SME/inc/csr_roam_mbb.h b/drivers/staging/prima/CORE/SME/inc/csr_roam_mbb.h new file mode 100644 index 00000000000..aa0bcbcaa97 --- /dev/null +++ b/drivers/staging/prima/CORE/SME/inc/csr_roam_mbb.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +eHalStatus csr_neighbor_roam_issue_preauth_reassoc(tpAniSirGlobal mac); + +eHalStatus csr_roam_issue_preauth_reassoc_req(tHalHandle hal, + tANI_U32 session_id, tpSirBssDescription bss_description); + +void csr_roam_preauth_rsp_mbb_processor(tHalHandle hal, + tpSirFTPreAuthRsp pre_auth_rsp); + +void csr_preauth_reassoc_mbb_timer_callback(void *context); + +void csr_stop_preauth_reassoc_mbb_timer(tpAniSirGlobal mac); + diff --git a/drivers/staging/prima/CORE/SME/inc/pmc.h b/drivers/staging/prima/CORE/SME/inc/pmc.h index e6ffe81d06a..cc15dc0b2ae 100644 --- a/drivers/staging/prima/CORE/SME/inc/pmc.h +++ b/drivers/staging/prima/CORE/SME/inc/pmc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -174,6 +174,7 @@ typedef struct sPmcInfo tANI_BOOLEAN wowlEnabled; /* TRUE if WoWL is enabled */ tANI_BOOLEAN wowlModeRequired; /* TRUE if device should go to WOWL on entering BMPS */ tWowlExitSource wowlExitSrc; /*WoWl exiting because of wakeup pkt or user explicitly disabling WoWL*/ + tANI_BOOLEAN isAPWOWExit; /* TRUE if last WOW exit is from soft ap */ void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status); /* routine to call for wowl request */ void *enterWowlCallbackContext;/* value to be passed as parameter to routine specified above */ tSirSmeWowlEnterParams wowlEnterParams; /* WOWL mode configuration */ diff --git a/drivers/staging/prima/CORE/SME/inc/smeInside.h b/drivers/staging/prima/CORE/SME/inc/smeInside.h index bb947dc3ea2..902e0a0c6a3 100644 --- a/drivers/staging/prima/CORE/SME/inc/smeInside.h +++ b/drivers/staging/prima/CORE/SME/inc/smeInside.h @@ -207,6 +207,8 @@ typedef struct tagSmeCmd tAniGetFrameLogReq getFramelogCmd; struct s_ani_set_tx_max_pwr set_tx_max_pwr; tpNanRequest pNanReq; + struct csr_set_tx_max_pwr_per_band set_tx_max_pwr_per_band; + tpSirUpdateChanList chan_list; }u; }tSmeCmd; diff --git a/drivers/staging/prima/CORE/SME/inc/smeInternal.h b/drivers/staging/prima/CORE/SME/inc/smeInternal.h index 3280a92dc2a..79f27af6ec2 100644 --- a/drivers/staging/prima/CORE/SME/inc/smeInternal.h +++ b/drivers/staging/prima/CORE/SME/inc/smeInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -76,6 +76,8 @@ typedef enum eSmeCommandType eSmeCommandMacSpoofRequest, eSmeCommandGetFrameLogRequest, eSmeCommandSetMaxTxPower, + eSmeCommandSetMaxTxPowerPerBand, + eSmeCommandUpdateChannelList, #ifdef FEATURE_WLAN_TDLS //eSmeTdlsCommandMask = 0x80000, //To identify TDLS commands <TODO> //These can be considered as csr commands. @@ -187,7 +189,10 @@ typedef struct tagSmeStruct void (*pOemDataIndCb) (void *, const tANI_U16, void *, tANI_U32); void *pOemDataCallbackContext; #endif /* FEATURE_OEM_DATA_SUPPORT */ - +#ifdef WLAN_FEATURE_LFR_MBB + void (*roaming_mbb_callback)(void* mac, tANI_U32 session_id, + void* bss_description, void *reassoc_req, tANI_U32 csr_roam_op_code); +#endif } tSmeStruct, *tpSmeStruct; diff --git a/drivers/staging/prima/CORE/SME/inc/sme_Api.h b/drivers/staging/prima/CORE/SME/inc/sme_Api.h index 7039efc8666..5d4a8070b24 100644 --- a/drivers/staging/prima/CORE/SME/inc/sme_Api.h +++ b/drivers/staging/prima/CORE/SME/inc/sme_Api.h @@ -337,6 +337,15 @@ typedef enum eSME_ROAM_TRIGGER_MAX } tSmeFastRoamTrigger; +#ifdef WLAN_FEATURE_APFIND +struct sme_ap_find_request_req +{ + u_int16_t request_data_len; + const u_int8_t* request_data; +}; +#endif /* WLAN_FEATURE_APFIND */ + + /*------------------------------------------------------------------------- Function declarations and documentation. ------------------------------------------------------------------------*/ @@ -2722,15 +2731,19 @@ eHalStatus sme_p2pGetResultFilter(tHalHandle hHal, tANI_U8 HDDSessionId, eHalStatus sme_SetMaxTxPower(tHalHandle hHal, tSirMacAddr pBssid, tSirMacAddr pSelfMacAddress, v_S7_t dB); -/* --------------------------------------------------------------------------- - \fn sme_SetMaxTxPowerPerBand - \brief Used to set the Maximum Transmit Power for - specific band dynamically. Note: this setting will not persist over reboots - \param band - \param power to set in dB - \- return eHalStatus - -------------------------------------------------------------------------*/ -eHalStatus sme_SetMaxTxPowerPerBand(eCsrBand band, v_S7_t db); +/** + * sme_SetMaxTxPowerPerBand() - Set the Maximum Transmit Power + * specific to band dynamically + * @band: Band for which power needs to be applied + * @dB: power to set in dB + * @hal: HAL handle + * + * Set the maximum transmit power dynamically per band + * + * Return: eHalStatus + */ +eHalStatus sme_SetMaxTxPowerPerBand(eCsrBand band, v_S7_t dB, + tHalHandle hal); /* --------------------------------------------------------------------------- @@ -3941,14 +3954,59 @@ void sme_set_mgmt_frm_via_wq5(tHalHandle hHal, tANI_BOOLEAN sendMgmtPktViaWQ5); eHalStatus sme_update_cfg_int_param(tHalHandle hHal, tANI_U32 cfg_id); +#ifdef WLAN_FEATURE_APFIND +VOS_STATUS sme_apfind_set_cmd(struct sme_ap_find_request_req *input); +#endif /* WLAN_FEATURE_APFIND */ + +#ifdef SAP_AUTH_OFFLOAD +/** + * sme_set_sap_auth_offload() enable/disable SAP Auth Offload + * @hHal: hal layer handler + * @sap_auth_offload_info: the information of SAP Auth Offload + * + * This function provide enable/disable SAP authenticaiton offload + * feature on target firmware + * + * Return: eHalStatus. + */ +eHalStatus sme_set_sap_auth_offload(tHalHandle hHal, + struct tSirSapOffloadInfo *sap_auth_offload_info); + +#endif /* SAP_AUTH_OFFLOAD */ +#ifdef DHCP_SERVER_OFFLOAD +eHalStatus sme_set_dhcp_srv_offload(tHalHandle hal, + sir_dhcp_srv_offload_info_t *dhcp_srv_info); +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +eHalStatus sme_set_mdns_offload(tHalHandle hal, + sir_mdns_offload_info_t *mdns_info); + +eHalStatus sme_set_mdns_fqdn(tHalHandle hal, + sir_mdns_fqdn_info_t *mdns_fqdn); + +eHalStatus sme_set_mdns_resp(tHalHandle hal, + sir_mdns_resp_info_t *mdns_resp); +#endif /* MDNS_OFFLOAD */ + +eHalStatus sme_update_hb_threshold(tHalHandle hHal, tANI_U32 cfgId, + tANI_U8 hbThresh, eCsrBand eBand); + +eHalStatus sme_capture_tsf_req(tHalHandle hHal, + tSirCapTsfParams capTsfParams); + +eHalStatus sme_get_tsf_req(tHalHandle hHal, + tSirCapTsfParams capTsfParams); + +eHalStatus sme_set_tsfcb(tHalHandle hHal, + tsf_rsp_cb rsp_cb, struct stsf *pTsf, + void *pcallbackcontext); + /* ARP DEBUG STATS */ eHalStatus sme_set_nud_debug_stats(tHalHandle hHal, psetArpStatsParams pSetStatsParam); eHalStatus sme_get_nud_debug_stats(tHalHandle hHal, pgetArpStatsParams pGetStatsParam); -eHalStatus sme_test_con_alive(tHalHandle hHal); -eHalStatus sme_get_con_alive(tHalHandle hHal, - pgetConStatusParams conStatusParams); -eHalStatus sme_test_con_delba(tHalHandle hHal, uint8_t sta_id, - uint8_t session_id); +eHalStatus sme_del_sta_ba_session_req(tHalHandle hHal, + tDelBaParams sta_del_params); #endif //#if !defined( __SME_API_H ) diff --git a/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h b/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h index 4eed9f51ce8..0a57aa5e8e0 100644 --- a/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h +++ b/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -72,6 +72,12 @@ typedef struct sFTSMEContext tCsrRoamSetKey *pCsrFTKeyInfo; v_BOOL_t addMDIE; + + tANI_BOOLEAN is_preauth_lfr_mbb; + +#ifdef WLAN_FEATURE_LFR_MBB + vos_timer_t pre_auth_reassoc_mbb_timer; +#endif } tftSMEContext, *tpftSMEContext; /*-------------------------------------------------------------------------- diff --git a/drivers/staging/prima/CORE/SME/inc/sme_Trace.h b/drivers/staging/prima/CORE/SME/inc/sme_Trace.h index 9967cacb260..77ff1d68903 100644 --- a/drivers/staging/prima/CORE/SME/inc/sme_Trace.h +++ b/drivers/staging/prima/CORE/SME/inc/sme_Trace.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -146,6 +146,9 @@ enum { TRACE_CODE_SME_RX_HDD_LPHB_CONFIG_REQ, #endif /* FEATURE_WLAN_LPHB */ TRACE_CODE_SME_RX_HDD_ROAM_DEL_PMKIDCACHE, + TRACE_CODE_SME_TX_HDD_CAP_TSF_REQ, + TRACE_CODE_SME_TX_HDD_GET_TSF_REQ, + TRACE_CODE_SME_DEL_STA_BA_SESSION_REQ, /* New trace commands to be added before this comment not at the end */ /* Trace codes for SME commands */ TRACE_CODE_SME_COMMAND = 250, diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c b/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c index 47ccdef61f9..074fc3da612 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c @@ -76,14 +76,16 @@ #include "csrEse.h" #endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD */ #include "vos_utils.h" +#ifdef WLAN_FEATURE_LFR_MBB +#include "csr_roam_mbb.h" +#endif + + #define CSR_NUM_IBSS_START_CHANNELS_50 4 #define CSR_NUM_IBSS_START_CHANNELS_24 3 #define CSR_DEF_IBSS_START_CHANNEL_50 36 #define CSR_DEF_IBSS_START_CHANNEL_24 1 -/* 15 seconds, for WPA, WPA2, CCKM */ -#define CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD (15 * PAL_TIMER_TO_SEC_UNIT) -/* 120 seconds, for WPS */ -#define CSR_WAIT_FOR_WPS_KEY_TIMEOUT_PERIOD (120 * PAL_TIMER_TO_SEC_UNIT) + /*--------------------------------------------------------------------------- OBIWAN recommends [8 10]% : pick 9% ---------------------------------------------------------------------------*/ @@ -214,12 +216,10 @@ tANI_BOOLEAN csrRoamIsSameProfileKeys(tpAniSirGlobal pMac, tCsrRoamConnectedProf static eHalStatus csrRoamStartRoamingTimer(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 interval); static eHalStatus csrRoamStopRoamingTimer(tpAniSirGlobal pMac, tANI_U32 sessionId); static void csrRoamRoamingTimerHandler(void *pv); -eHalStatus csrRoamStartWaitForKeyTimer(tpAniSirGlobal pMac, tANI_U32 interval); eHalStatus csrRoamStopWaitForKeyTimer(tpAniSirGlobal pMac); static void csrRoamWaitForKeyTimeOutHandler(void *pv); static eHalStatus CsrInit11dInfo(tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo); static eHalStatus csrInitChannelPowerList( tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo); -static eHalStatus csrRoamFreeConnectedInfo( tpAniSirGlobal pMac, tCsrRoamConnectedInfo *pConnectedInfo ); eHalStatus csrSendMBSetContextReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr peerMacAddr, tANI_U8 numKeys, tAniEdType edType, tANI_BOOLEAN fUnicast, tAniKeyDirection aniKeyDirection, @@ -230,7 +230,6 @@ static eHalStatus csrRoamIssueReassociate( tpAniSirGlobal pMac, tANI_U32 session tCsrRoamProfile *pProfile ); void csrRoamStatisticsTimerHandler(void *pv); void csrRoamStatsGlobalClassDTimerHandler(void *pv); -static void csrRoamLinkUp(tpAniSirGlobal pMac, tCsrBssid bssid); VOS_STATUS csrRoamVccTriggerRssiIndCallback(tHalHandle hHal, v_U8_t rssiNotification, void * context); @@ -557,12 +556,13 @@ eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac) tCsrScanStruct *pScan = &pMac->scan; tANI_U32 numChan = 0; tANI_U32 bufLen ; - vos_msg_t msg; tANI_U8 i, j; tANI_U8 num_channel = 0; tANI_U8 channel_state; tANI_U8 cfgnumChannels = 0; tANI_U8 *cfgChannelList = NULL; + eHalStatus status; + tSmeCmd *command; limInitOperatingClasses((tHalHandle)pMac); numChan = sizeof(pMac->roam.validChannelList); @@ -673,21 +673,28 @@ eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac) "%s : regID : %d \n", __func__, pChanList->regId); - msg.type = WDA_UPDATE_CHAN_LIST_REQ; - msg.reserved = 0; - msg.bodyptr = pChanList; pChanList->numChan = num_channel; - MTRACE(vos_trace(VOS_MODULE_ID_SME, - TRACE_CODE_SME_TX_WDA_MSG, NO_SESSION, msg.type)); - if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) - { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, - "%s: Failed to post msg to WDA", __func__); - vos_mem_free(pChanList); - return eHAL_STATUS_FAILURE; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) { + command = csrGetCommandBuffer(pMac); + if (command) { + command->command = eSmeCommandUpdateChannelList; + command->u.chan_list = pChanList; + + status = csrQueueSmeCommand(pMac, command, eANI_BOOLEAN_TRUE); + if (!HAL_STATUS_SUCCESS(status)) { + smsLog(pMac, LOGE, FL("fail to send msg status = %d"), status); + csrReleaseCommand(pMac, command); + } + } else { + smsLog(pMac, LOGE, FL("can not obtain a common buffer")); + status = eHAL_STATUS_RESOURCES; + } + sme_ReleaseGlobalLock(&pMac->sme); } - return eHAL_STATUS_SUCCESS; + return status; } eHalStatus csrStart(tpAniSirGlobal pMac) @@ -753,7 +760,6 @@ eHalStatus csrStop(tpAniSirGlobal pMac, tHalStopType stopType) (void) pmcDeregisterPowerSaveCheck(pMac, csrCheckPSReady); //Reset the domain back to the deault pMac->scan.domainIdCurrent = pMac->scan.domainIdDefault; - csrResetCountryInformation(pMac, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_FALSE ); for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ ) { @@ -1000,7 +1006,7 @@ eHalStatus csrRoamFreeConnectProfile(tpAniSirGlobal pMac, tCsrRoamConnectedProfi return (status); } -static eHalStatus csrRoamFreeConnectedInfo( tpAniSirGlobal pMac, tCsrRoamConnectedInfo *pConnectedInfo ) +eHalStatus csrRoamFreeConnectedInfo( tpAniSirGlobal pMac, tCsrRoamConnectedInfo *pConnectedInfo ) { eHalStatus status = eHAL_STATUS_SUCCESS; if( pConnectedInfo->pbFrames ) @@ -1269,6 +1275,7 @@ static void initConfigParam(tpAniSirGlobal pMac) pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod = 20000; //20 seconds pMac->roam.configParam.neighborRoamConfig.nEmptyScanRefreshPeriod = 0; pMac->roam.configParam.neighborRoamConfig.nNeighborInitialForcedRoamTo5GhEnable = 0; + pMac->roam.configParam.neighborRoamConfig.nWeakZoneRssiThresholdForRoam = 0; #endif #ifdef WLAN_FEATURE_11AC pMac->roam.configParam.nVhtChannelWidth = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ + 1; @@ -1969,6 +1976,11 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa pParam->PERMinRssiThresholdForRoam; pMac->PERroamTimeout = pParam->waitPeriodForNextPERScan; #endif + +#ifdef WLAN_FEATURE_LFR_MBB + pMac->roam.configParam.enable_lfr_mbb = pParam->enable_lfr_mbb; +#endif + #ifdef FEATURE_WLAN_LFR pMac->roam.configParam.isFastRoamIniFeatureEnabled = pParam->isFastRoamIniFeatureEnabled; pMac->roam.configParam.MAWCEnabled = pParam->MAWCEnabled; @@ -1989,6 +2001,7 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa smsLog( pMac, LOG1, "nNeighborResultsRefreshPeriod = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod); smsLog( pMac, LOG1, "nEmptyScanRefreshPeriod = %d", pMac->roam.configParam.neighborRoamConfig.nEmptyScanRefreshPeriod); smsLog( pMac, LOG1, "nNeighborInitialForcedRoamTo5GhEnable = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborInitialForcedRoamTo5GhEnable); + smsLog( pMac, LOG1, "nWeakZoneRssiThresholdForRoam = %d", pMac->roam.configParam.neighborRoamConfig.nWeakZoneRssiThresholdForRoam); { int i; smsLog( pMac, LOG1, FL("Num of Channels in CFG Channel List: %d"), pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels); @@ -2199,6 +2212,11 @@ eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->PERMinRssiThresholdForRoam = pMac->roam.configParam.PERMinRssiThresholdForRoam; #endif + +#ifdef WLAN_FEATURE_LFR_MBB + pParam->enable_lfr_mbb = pMac->roam.configParam.enable_lfr_mbb; +#endif + #ifdef FEATURE_WLAN_LFR pParam->isFastRoamIniFeatureEnabled = pMac->roam.configParam.isFastRoamIniFeatureEnabled; #endif @@ -3284,6 +3302,8 @@ eHalStatus csrRoamPrepareBssConfig(tpAniSirGlobal pMac, tCsrRoamProfile *pProfil pBssConfig->uCfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; } } + smsLog(pMac, LOG1, FL("phyMode %d uCfgDot11Mode %d"), + pProfile->phyMode, pBssConfig->uCfgDot11Mode); //Qos if ((pBssConfig->uCfgDot11Mode != eCSR_CFG_DOT11_MODE_11N) && (pMac->roam.configParam.WMMSupportMode == eCsrRoamWmmNoQos)) @@ -3364,6 +3384,12 @@ eHalStatus csrRoamPrepareBssConfig(tpAniSirGlobal pMac, tCsrRoamProfile *pProfil } //validate CB pBssConfig->cbMode = csrGetCBModeFromIes(pMac, pBssDesc->channelId, pIes); + if (CSR_IS_CHANNEL_24GHZ(pBssDesc->channelId) && + pProfile->force_24ghz_in_ht20) { + pBssConfig->cbMode = PHY_SINGLE_CHANNEL_CENTERED; + smsLog(pMac, LOG1, + FL("force_24ghz_in_ht20 is set so set cbmode to 0")); + } smsLog(pMac, LOG1, FL("Bss Cb is %d, join timeout is %d, HB thresh is %d,"), pBssConfig->cbMode, pBssConfig->uJoinTimeOut, pBssConfig->uHeartBeatThresh); }while(0); @@ -5057,6 +5083,20 @@ eHalStatus csrRoamProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) pCommand->u.roamCmd.pLastRoamBss); break; +#ifdef WLAN_FEATURE_LFR_MBB + case ecsr_mbb_perform_preauth_reassoc: + smsLog(pMac, LOG1, FL("Attempting MBB PreAuth/Reassoc Req")); + status = csr_roam_issue_preauth_reassoc_req(pMac, sessionId, + pCommand->u.roamCmd.pLastRoamBss); + if (eHAL_STATUS_SUCCESS != status) + { + pMac->ft.ftSmeContext.is_preauth_lfr_mbb = false; + smsLog(pMac, LOG1, FL("is_preauth_lfr_mbb %d"), + pMac->ft.ftSmeContext.is_preauth_lfr_mbb); + } + break; +#endif + default: csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId ); @@ -5194,9 +5234,10 @@ void csrResetBKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId ) #endif /* FEATURE_WLAN_WAPI */ extern tANI_U8 csrWpaOui[][ CSR_WPA_OUI_SIZE ]; -static eHalStatus csrRoamSaveSecurityRspIE(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrAuthType authType, - tSirBssDescription *pSirBssDesc, - tDot11fBeaconIEs *pIes) +eHalStatus csrRoamSaveSecurityRspIE(tpAniSirGlobal pMac, + tANI_U32 sessionId, eCsrAuthType authType, + tSirBssDescription *pSirBssDesc, + tDot11fBeaconIEs *pIes) { eHalStatus status = eHAL_STATUS_SUCCESS; tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); @@ -5610,10 +5651,12 @@ static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pComman case eCsrReassocSuccess: if(eCsrReassocSuccess == Result) { + roamInfo.reassoc = true; ind_qos = SME_QOS_CSR_REASSOC_COMPLETE; } else { + roamInfo.reassoc = false; ind_qos = SME_QOS_CSR_ASSOC_COMPLETE; } // Success Join Response from LIM. Tell NDIS we are connected and save the @@ -5819,6 +5862,12 @@ static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pComman roamInfo.ucastSig = ( tANI_U8 )pJoinRsp->ucastSig; roamInfo.bcastSig = ( tANI_U8 )pJoinRsp->bcastSig; roamInfo.maxRateFlags = pJoinRsp->maxRateFlags; + roamInfo.vht_caps = pJoinRsp->vht_caps; + roamInfo.ht_caps = pJoinRsp->ht_caps; + roamInfo.hs20vendor_ie = pJoinRsp->hs20vendor_ie; + roamInfo.ht_operation = pJoinRsp->ht_operation; + roamInfo.vht_operation = pJoinRsp->vht_operation; + } else { @@ -6354,7 +6403,8 @@ static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pComman { if ( CSR_IS_INFRA_AP(&pSession->connectedProfile) ) { - roamInfo.u.pConnectedProfile = &pSession->connectedProfile; + roamInfo.u.pConnectedProfile = + &pSession->connectedProfile; vos_mem_copy(roamInfo.peerMac, pCommand->u.roamCmd.peerMac, sizeof(tSirMacAddr)); @@ -6362,7 +6412,8 @@ static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pComman roamInfo.statusCode = eSIR_SME_SUCCESS; status = csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, - eCSR_ROAM_LOSTLINK, eCSR_ROAM_RESULT_FORCED); + eCSR_ROAM_LOSTLINK, + eCSR_ROAM_RESULT_FORCED); } } else @@ -6585,6 +6636,8 @@ eHalStatus csrRoamCopyProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pDstProfile, pDstProfile->cfg_protection = pSrcProfile->cfg_protection; pDstProfile->wps_state = pSrcProfile->wps_state; pDstProfile->ieee80211d = pSrcProfile->ieee80211d; + pDstProfile->force_24ghz_in_ht20 = + pSrcProfile->force_24ghz_in_ht20; vos_mem_copy(&pDstProfile->Keys, &pSrcProfile->Keys, sizeof(pDstProfile->Keys)); #ifdef WLAN_FEATURE_VOWIFI_11R @@ -6989,19 +7042,7 @@ eHalStatus csrRoamConnect(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfi #ifdef FEATURE_WLAN_BTAMP_UT_RF pSession->maxRetryCount = CSR_JOIN_MAX_RETRY_COUNT; #endif - /* - * If roamSession.connectState is disconnecting that mean - * disconnect/stop adapter was received with scan for ssid - * in progress and dropped. This state will ensure that - * connect will not be issued from scan for ssid completion. - * Thus if this fresh connect also issue scan for ssid the connect - * command will be dropped assuming disconnect is in progress. - * Thus reset connectState here - */ - if (eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING == - pMac->roam.roamSession[sessionId].connectState) - pMac->roam.roamSession[sessionId].connectState = - eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + if(CSR_INVALID_SCANRESULT_HANDLE != hBssListIn) { smsLog(pMac, LOG1, FL("is called with BSSList")); @@ -7393,6 +7434,9 @@ eHalStatus csrRoamProcessDisassocDeauth( tpAniSirGlobal pMac, tSmeCmd *pCommand, csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac); } #endif +#ifdef WLAN_FEATURE_LFR_MBB + csr_stop_preauth_reassoc_mbb_timer(pMac); +#endif } if( fDisassoc ) @@ -7593,9 +7637,8 @@ eHalStatus csrRoamDisconnectInternal(tpAniSirGlobal pMac, tANI_U32 sessionId, eC } else { - pMac->roam.roamSession[sessionId].connectState = - eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING; csrScanAbortScanForSSID(pMac, sessionId); + csrScanStartIdleScan(pMac); status = eHAL_STATUS_CMD_NOT_QUEUED; smsLog(pMac, LOGE, FL("Disconnect not queued, Abort Scan for SSID")); @@ -8181,6 +8224,12 @@ static void csrRoamingStateConfigCnfProcessor( tpAniSirGlobal pMac, tANI_U32 res if(pCommand->u.roamCmd.pRoamBssEntry) { pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link); + if (!pScanResult) + { + smsLog(pMac, LOGE, + FL("Failed to get base address for pScanResult")); + return; + } pBssDesc = &pScanResult->Result.BssDescriptor; } if ( csrIsBssTypeIBSS( pCommand->u.roamCmd.roamProfile.BSSType ) || @@ -8208,6 +8257,12 @@ static void csrRoamingStateConfigCnfProcessor( tpAniSirGlobal pMac, tANI_U32 res } // If we are roaming TO an Infrastructure BSS... VOS_ASSERT(pScanResult != NULL); + if( !pScanResult->Result.pvIes ) + { + smsLog(pMac, LOGE, FL(" pvIes is NULL")); + return; + } + if ( csrIsInfraBssDesc( pBssDesc ) ) { tDot11fBeaconIEs *pIesLocal = (tDot11fBeaconIEs *)pScanResult->Result.pvIes; @@ -9952,6 +10007,15 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_WDS_IND, eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND);//Sta if(CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile)) { +#ifdef SAP_AUTH_OFFLOAD + if (pMac->sap_auth_offload) + { + smsLog(pMac, LOGW, FL(" Auth is not required to set in Auth offload case \n")); + pRoamInfo->fAuthRequired = FALSE; + } + else + { +#endif if( CSR_IS_ENC_TYPE_STATIC( pSession->pCurRoamProfile->negotiatedUCEncryptionType )) { csrRoamIssueSetContextReq( pMac, sessionId, pSession->pCurRoamProfile->negotiatedUCEncryptionType, @@ -9964,6 +10028,9 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) { pRoamInfo->fAuthRequired = TRUE; } +#ifdef SAP_AUTH_OFFLOAD + } +#endif status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND); if (!HAL_STATUS_SUCCESS(status)) pRoamInfo->statusCode = eSIR_SME_ASSOC_REFUSED;// Refused due to Mac filtering @@ -10028,6 +10095,10 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac); } #endif +#ifdef WLAN_FEATURE_LFR_MBB + csr_stop_preauth_reassoc_mbb_timer(pMac); +#endif + pSession = CSR_GET_SESSION( pMac, sessionId ); if (!pSession) @@ -10104,6 +10175,9 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac); } #endif +#ifdef WLAN_FEATURE_LFR_MBB + csr_stop_preauth_reassoc_mbb_timer(pMac); +#endif pSession = CSR_GET_SESSION( pMac, sessionId ); if(!pSession) @@ -10683,6 +10757,12 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) { tpSirSetActiveModeSetBncFilterReq pMsg; pMsg = vos_mem_malloc(sizeof(tSirSetActiveModeSetBncFilterReq)); + if (NULL == pMsg) + { + smsLog(pMac, LOGE, FL("vos_mem_malloc failed")); + return; + } + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SET_BCN_FILTER_REQ); pMsg->length = pal_cpu_to_be16(sizeof( tSirSetActiveModeSetBncFilterReq)); @@ -10706,6 +10786,12 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) { tpSirSmeHT40OBSSScanInd pMsg; pMsg = vos_mem_malloc(sizeof(tSirSmeHT40OBSSScanInd)); + if (NULL == pMsg) + { + smsLog(pMac, LOGE, FL("vos_mem_malloc failed")); + return; + } + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_HT40_OBSS_SCAN_IND); pMsg->length = @@ -10884,6 +10970,13 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) csrRoamFTPreAuthRspProcessor( pMac, (tpSirFTPreAuthRsp)pSirMsg ); break; #endif +#ifdef WLAN_FEATURE_LFR_MBB + case eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP: + csr_roam_preauth_rsp_mbb_processor(pMac, + (tpSirFTPreAuthRsp)pSirMsg); + break; +#endif + case eWNI_SME_MAX_ASSOC_EXCEEDED: pSmeMaxAssocInd = (tSmeMaxAssocInd*)pSirMsg; smsLog( pMac, LOG1, FL("send indication that max assoc have been reached and the new peer cannot be accepted")); @@ -11105,35 +11198,35 @@ void csrRoamWaitForKeyTimeOutHandler(void *pv) macTraceGetcsrRoamSubState( pMac->roam.curSubState[pInfo->sessionId])); - if( CSR_IS_WAIT_FOR_KEY( pMac, pInfo->sessionId ) ) + if (pSession) { -#ifdef FEATURE_WLAN_LFR - if (csrNeighborRoamIsHandoffInProgress(pMac)) + if( CSR_IS_WAIT_FOR_KEY( pMac, pInfo->sessionId ) ) { - /* - * Enable heartbeat timer when hand-off is in progress - * and Key Wait timer expired. - */ - smsLog(pMac, LOG2, "Enabling HB timer after WaitKey expiry" - " (nHBCount=%d)", - pMac->roam.configParam.HeartbeatThresh24); - ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, - pMac->roam.configParam.HeartbeatThresh24, - NULL, eANI_BOOLEAN_FALSE); - } +#ifdef FEATURE_WLAN_LFR + if (csrNeighborRoamIsHandoffInProgress(pMac)) + { + /* + * Enable heartbeat timer when hand-off is in progress + * and Key Wait timer expired. + */ + smsLog(pMac, LOG2, "Enabling HB timer after WaitKey expiry" + " (nHBCount=%d)", + pMac->roam.configParam.HeartbeatThresh24); + ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, + pMac->roam.configParam.HeartbeatThresh24, + NULL, eANI_BOOLEAN_FALSE); + } #endif - smsLog(pMac, LOGE, " SME pre-auth state timeout. "); + smsLog(pMac, LOGE, " SME pre-auth state timeout. "); - //Change the substate so command queue is unblocked. - if (CSR_ROAM_SESSION_MAX > pInfo->sessionId) - { - csrRoamSubstateChange(pMac, eCSR_ROAM_SUBSTATE_NONE, - pInfo->sessionId); - } + //Change the substate so command queue is unblocked. + if (CSR_ROAM_SESSION_MAX > pInfo->sessionId) + { + csrRoamSubstateChange(pMac, eCSR_ROAM_SUBSTATE_NONE, + pInfo->sessionId); + } - if (pSession) - { - if( csrIsConnStateConnectedInfra(pMac, pInfo->sessionId) ) + if( csrIsConnStateConnectedInfra(pMac, pInfo->sessionId) ) { csrRoamLinkUp(pMac, pSession->connectedProfile.bssid); smeProcessPendingQueue(pMac); @@ -11691,7 +11784,13 @@ static eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, tCsrRo } /* Incase of WEP Security encryption type is coming as part of add key. So while STart BSS dont have information */ - if( (!CSR_IS_11n_ALLOWED(pProfile->EncryptionType.encryptionType[0] ) || ((pProfile->privacy == 1) && (pProfile->EncryptionType.encryptionType[0] == eCSR_ENCRYPT_TYPE_NONE)) ) && + if ( +#ifdef SAP_AUTH_OFFLOAD + (!pMac->sap_auth_offload && !pMac->sap_auth_offload_sec_type) && +#endif + ((!CSR_IS_11n_ALLOWED(pProfile->EncryptionType.encryptionType[0] ) || + ((pProfile->privacy == 1) && + (pProfile->EncryptionType.encryptionType[0] == eCSR_ENCRYPT_TYPE_NONE)))) && ((eCSR_CFG_DOT11_MODE_11N == cfgDot11Mode) || #ifdef WLAN_FEATURE_11AC (eCSR_CFG_DOT11_MODE_11AC == cfgDot11Mode) || @@ -13397,6 +13496,9 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe //Need to disable VHT operation in 2.4 GHz band ucDot11Mode = WNI_CFG_DOT11_MODE_11N; } + smsLog(pMac, LOG1, FL("dot11mode %d uCfgDot11Mode %d"), + ucDot11Mode, pSession->bssParams.uCfgDot11Mode); + *pBuf = (tANI_U8)ucDot11Mode; pBuf++; //Persona @@ -13409,9 +13511,13 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe //CBMode *pBuf = (tANI_U8)pSession->bssParams.cbMode; pBuf++; + *pBuf = (tANI_U8)pProfile->force_24ghz_in_ht20; + pBuf++; VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, - FL("CSR PERSONA=%d CSR CbMode %d"), pProfile->csrPersona, pSession->bssParams.cbMode); + FL("CSR PERSONA=%d CSR CbMode %d force_24ghz_in_ht20 %d"), + pProfile->csrPersona, pSession->bssParams.cbMode, + pProfile->force_24ghz_in_ht20); // uapsdPerAcBitmask *pBuf = pProfile->uapsd_mask; @@ -13968,6 +14074,719 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe return( status ); } +#ifdef WLAN_FEATURE_LFR_MBB +/** + * csr_prepare_reassoc_req () - Prepares reassoc request + * @mac: MAC context + * @session_id: session id + * @pbss_description: bss description + * @ies: pointer to beacon IE's + * @reassoc_req: pointer to reassociation request + * + *Return: None + */ +eHalStatus csr_fill_reassoc_req(tpAniSirGlobal mac, tANI_U32 session_id, + tSirBssDescription *bss_description, tDot11fBeaconIEs *ies, + tSirSmeJoinReq **reassoc_req) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirSmeJoinReq *csr_join_req; + tANI_U8 *buf; + v_U8_t acm_mask = 0, uapsd_mask; + tANI_U16 msg_len, w_tmp, ie_len; + tSirMacRateSet op_rate_set; + tSirMacRateSet ex_rate_set; + tCsrRoamSession *session = CSR_GET_SESSION(mac, session_id); + tANI_U32 dw_tmp; + tANI_U8 wpa_rsn_ie[DOT11F_IE_RSN_MAX_LEN]; + tANI_U32 uc_dot11_mode = 0; + tANI_U8 tx_bf_csn_value = 0; + tANI_U16 rate_bitmap = 0; + tANI_U16 message_type = eWNI_SME_REASSOC_REQ; + tCsrRoamProfile *profile; + + if(!session) { + smsLog(mac, LOGE, FL(" session %d not found "), session_id); + return eHAL_STATUS_FAILURE; + } + + if (NULL == bss_description) { + smsLog(mac, LOGE, FL(" pBssDescription is NULL")); + return eHAL_STATUS_FAILURE; + } + + smsLog(mac, LOG1, + FL("session_id %d"), session_id); + + profile = vos_mem_malloc(sizeof(*profile)); + if (NULL == profile) { + smsLog(mac, LOGE, FL("Memory allocation failure for profile")); + return eHAL_STATUS_RESOURCES; + } + + status = csrRoamCopyProfile(mac, profile, session->pCurRoamProfile); + if(!HAL_STATUS_SUCCESS(status)) { + smsLog(mac, LOGE, FL("Profile copy failed")); + return eHAL_STATUS_FAILURE; + } + + do { + /* + * There are a number of variable length fields to consider. + * First, the tSirSmeJoinReq includes a single bssDescription. + * bssDescription includes a single tANI_U32 for the IE fields, + * but the length field in the bssDescription needs to be + * interpreted to determine length of the IE fields. + * So, take the size of the JoinReq, subtract the size of the + * bssDescription and add in the length from the bssDescription + * (then add the size of the 'length' field itself because that is + * NOT included in the length field). msgLen = + * sizeof( tSirSmeJoinReq ) - sizeof( *pBssDescription ) + + * pBssDescription->length + sizeof( pBssDescription->length ) + + * sizeof( tCsrWpaIe ) + sizeof( tCsrWpaAuthIe ) + sizeof( tANI_U16 ); + * add in the size of the WPA IE that we may build. + */ + + msg_len = sizeof(tSirSmeJoinReq) - sizeof(*bss_description) + + bss_description->length + sizeof(bss_description->length) + + sizeof(tCsrWpaIe) + sizeof(tCsrWpaAuthIe) + sizeof(tANI_U16); + + csr_join_req = vos_mem_malloc(msg_len); + if (NULL == csr_join_req) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if (!HAL_STATUS_SUCCESS(status)) break; + + vos_mem_set(csr_join_req, msg_len, 0); + *reassoc_req = csr_join_req; + + csr_join_req->messageType = pal_cpu_to_be16(eWNI_SME_REASSOC_REQ); + csr_join_req->length = pal_cpu_to_be16(msg_len); + buf = &csr_join_req->sessionId; + + /* session_id */ + *buf = (tANI_U8)session_id; + buf++; + + /* transactionId */ + *buf = 0; + *(buf + 1) = 0; + buf += sizeof(tANI_U16); + + /* ssId */ + if(ies->SSID.present && ies->SSID.num_ssid) + { + /* ssId len */ + *buf = ies->SSID.num_ssid; + buf++; + vos_mem_copy(buf, ies->SSID.ssid, ies->SSID.num_ssid); + buf += ies->SSID.num_ssid; + } + else + { + *buf = 0; + buf++; + } + + /* selfMacAddr */ + vos_mem_copy((tSirMacAddr *)buf, &session->selfMacAddr, + sizeof(tSirMacAddr)); + buf += sizeof(tSirMacAddr); + + /* bsstype */ + dw_tmp = + pal_cpu_to_be32(csrTranslateBsstypeToMacType(profile->BSSType)); + /* Override BssType for BTAMP */ + if (dw_tmp == eSIR_BTAMP_STA_MODE) dw_tmp = eSIR_BTAMP_AP_MODE; + vos_mem_copy(buf, &dw_tmp, sizeof(tSirBssType)); + buf += sizeof(tSirBssType); + + /* dot11mode */ + uc_dot11_mode = + csrTranslateToWNICfgDot11Mode(mac, session->bssParams.uCfgDot11Mode); + if (bss_description->channelId <= 14 && + FALSE == mac->roam.configParam.enableVhtFor24GHz && + WNI_CFG_DOT11_MODE_11AC == uc_dot11_mode) + { + /* Need to disable VHT operation in 2.4 GHz band */ + uc_dot11_mode = WNI_CFG_DOT11_MODE_11N; + } + *buf = (tANI_U8)uc_dot11_mode; + buf++; + + /* Persona */ + *buf = (tANI_U8)profile->csrPersona; + buf++; + *buf = (tANI_U8)profile->bOSENAssociation; + buf++; + *buf = (tANI_U8)profile->bWPSAssociation; + buf++; + + /* CBMode */ + *buf = (tANI_U8)session->bssParams.cbMode; + buf++; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("CSR PERSONA=%d CSR CbMode %d"), profile->csrPersona, + session->bssParams.cbMode); + + /* uapsdPerAcBitmask */ + *buf = profile->uapsd_mask; + buf++; + + + status = csrGetRateSet(mac, profile, (eCsrPhyMode)profile->phyMode, + bss_description, ies, &op_rate_set, &ex_rate_set,&rate_bitmap); + if (HAL_STATUS_SUCCESS(status)) + { + /* OperationalRateSet */ + if (op_rate_set.numRates) { + *buf++ = op_rate_set.numRates; + vos_mem_copy(buf, op_rate_set.rate, op_rate_set.numRates); + buf += op_rate_set.numRates; + } else *buf++ = 0; + + /* ExtendedRateSet */ + if (ex_rate_set.numRates) { + *buf++ = ex_rate_set.numRates; + vos_mem_copy(buf, ex_rate_set.rate, ex_rate_set.numRates); + buf += ex_rate_set.numRates; + } else *buf++ = 0; + } + else + { + *buf++ = 0; + *buf++ = 0; + } + + /* rateBitmap */ + vos_mem_copy(buf, &rate_bitmap, sizeof(tANI_U16)); + buf += sizeof(tANI_U16); + + profile->negotiatedAuthType = + mac->roam.roamSession[session_id].connectedProfile.AuthType; + profile->negotiatedUCEncryptionType = + mac->roam.roamSession[session_id].connectedProfile.EncryptionType; + + /* rsnIE */ + if ( csrIsProfileWpa(profile)) + { + /* Insert the Wpa IE into the join request */ + ie_len = csrRetrieveWpaIe(mac, profile, bss_description, ies, + (tCsrWpaIe *)(wpa_rsn_ie)); + } + else if( csrIsProfileRSN(profile)) + { + /* Insert the RSN IE into the join request */ + ie_len = csrRetrieveRsnIe(mac, session_id, profile, bss_description, + ies, (tCsrRSNIe *)(wpa_rsn_ie)); + } +#ifdef FEATURE_WLAN_WAPI + else if( csrIsProfileWapi(profile)) + { + /* Insert the WAPI IE into the join request */ + ie_len = csrRetrieveWapiIe(mac, session_id, profile, + bss_description, ies, (tCsrWapiIe *)(wpa_rsn_ie)); + } +#endif + else + { + ie_len = 0; + } + /* remember the IE for future use */ + if(ie_len) + { + if(ie_len > DOT11F_IE_RSN_MAX_LEN) + { + smsLog(mac, LOGE, + FL("WPA RSN IE length :%d is more than RSN_MAX_LEN %d"), + ie_len, DOT11F_IE_RSN_MAX_LEN); + ie_len = DOT11F_IE_RSN_MAX_LEN; + } +#ifdef FEATURE_WLAN_WAPI + if( csrIsProfileWapi(profile)) + { + /* Check whether we need to allocate more memory */ + if(ie_len > session->nWapiReqIeLength) + { + if(session->pWapiReqIE && session->nWapiReqIeLength) + { + vos_mem_free(session->pWapiReqIE); + } + session->pWapiReqIE = vos_mem_malloc(ie_len); + if (NULL == session->pWapiReqIE) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) break; + } + session->nWapiReqIeLength = ie_len; + vos_mem_copy(session->pWapiReqIE, wpa_rsn_ie, ie_len); + w_tmp = pal_cpu_to_be16(ie_len); + vos_mem_copy(buf, &w_tmp, sizeof(tANI_U16)); + buf += sizeof(tANI_U16); + vos_mem_copy(buf, wpa_rsn_ie, ie_len); + buf += ie_len; + } + else /* should be WPA/WPA2 otherwise */ +#endif + { + /* Check whether we need to allocate more memory */ + if(ie_len > session->nWpaRsnReqIeLength) + { + if(session->pWpaRsnReqIE && session->nWpaRsnReqIeLength) + { + vos_mem_free(session->pWpaRsnReqIE); + } + session->pWpaRsnReqIE = vos_mem_malloc(ie_len); + if (NULL == session->pWpaRsnReqIE) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) break; + } + session->nWpaRsnReqIeLength = ie_len; + vos_mem_copy(session->pWpaRsnReqIE, wpa_rsn_ie, ie_len); + w_tmp = pal_cpu_to_be16(ie_len); + vos_mem_copy(buf, &w_tmp, sizeof(tANI_U16)); + buf += sizeof(tANI_U16); + vos_mem_copy(buf, wpa_rsn_ie, ie_len); + buf += ie_len; + } + } + else + { + /* free whatever old info */ + session->nWpaRsnReqIeLength = 0; + if(session->pWpaRsnReqIE) + { + vos_mem_free(session->pWpaRsnReqIE); + session->pWpaRsnReqIE = NULL; + } +#ifdef FEATURE_WLAN_WAPI + session->nWapiReqIeLength = 0; + if(session->pWapiReqIE) + { + vos_mem_free(session->pWapiReqIE); + session->pWapiReqIE = NULL; + } +#endif + /* length is two bytes */ + *buf = 0; + *(buf + 1) = 0; + buf += 2; + } +#ifdef FEATURE_WLAN_ESE + if(eWNI_SME_JOIN_REQ == message_type) + { + /* + * Never include the cckmIE in an Join Request + * length is two bytes + */ + *buf = 0; + *(buf + 1) = 0; + buf += 2; + } + else if(eWNI_SME_REASSOC_REQ == message_type) + { + /* cckmIE */ + if( csrIsProfileESE(profile)) + { + /* Insert the CCKM IE into the join request */ +#ifdef FEATURE_WLAN_ESE_UPLOAD + ie_len = session->suppCckmIeInfo.cckmIeLen; + vos_mem_copy((void *) (wpa_rsn_ie), + session->suppCckmIeInfo.cckmIe, ie_len); +#else + ie_len = csrConstructEseCckmIe(mac, + session, + profile, + bss_description, + session->pWpaRsnReqIE, + session->nWpaRsnReqIeLength, + (void *)(wpa_rsn_ie)); +#endif + } + else + { + ie_len = 0; + } + /* + * If present, copy the IE into the eWNI_SME_REASSOC_REQ + * message buffer + */ + if(ie_len) + { + /* Copy the CCKM IE over from the temp buffer (wpaRsnIE) */ + w_tmp = pal_cpu_to_be16(ie_len); + vos_mem_copy(buf, &w_tmp, sizeof(tANI_U16)); + buf += sizeof(tANI_U16); + vos_mem_copy(buf, wpa_rsn_ie, ie_len); + buf += ie_len; + } + else + { + /* Indicate you have no CCKM IE length is two bytes */ + *buf = 0; + *(buf + 1) = 0; + buf += 2; + } + } +#endif + /* addIEScan */ + if (profile->nAddIEScanLength) + { + ie_len = profile->nAddIEScanLength; + memset(session->addIEScan, 0 , session->nAddIEScanLength); + session->nAddIEScanLength = ie_len; + vos_mem_copy(session->addIEScan, profile->addIEScan, ie_len); + w_tmp = pal_cpu_to_be16(ie_len); + vos_mem_copy(buf, &w_tmp, sizeof(tANI_U16)); + buf += sizeof(tANI_U16); + vos_mem_copy(buf, profile->addIEScan, ie_len); + buf += ie_len; + } + else + { + memset(session->addIEScan, 0, session->nAddIEScanLength); + session->nAddIEScanLength = 0; + *buf = 0; + *(buf + 1) = 0; + buf += 2; + } + /* addIEAssoc */ + if(profile->nAddIEAssocLength && profile->pAddIEAssoc) + { + ie_len = profile->nAddIEAssocLength; + if(ie_len > session->nAddIEAssocLength) + { + if(session->pAddIEAssoc && session->nAddIEAssocLength) + { + vos_mem_free(session->pAddIEAssoc); + } + session->pAddIEAssoc = vos_mem_malloc(ie_len); + if (NULL == session->pAddIEAssoc) + status = eHAL_STATUS_FAILURE; + else + status = eHAL_STATUS_SUCCESS; + if(!HAL_STATUS_SUCCESS(status)) break; + } + session->nAddIEAssocLength = ie_len; + vos_mem_copy(session->pAddIEAssoc, profile->pAddIEAssoc, ie_len); + w_tmp = pal_cpu_to_be16(ie_len); + vos_mem_copy(buf, &w_tmp, sizeof(tANI_U16)); + buf += sizeof(tANI_U16); + vos_mem_copy(buf, profile->pAddIEAssoc, ie_len); + buf += ie_len; + } + else + { + session->nAddIEAssocLength = 0; + if(session->pAddIEAssoc) + { + vos_mem_free(session->pAddIEAssoc); + session->pAddIEAssoc = NULL; + } + *buf = 0; + *(buf + 1) = 0; + buf += 2; + } + + if(eWNI_SME_REASSOC_REQ == message_type ) + { + /*Unmask any AC in reassoc that is ACM-set */ + uapsd_mask = (v_U8_t)profile->uapsd_mask; + if( uapsd_mask && (NULL != bss_description)) + { + if( CSR_IS_QOS_BSS(ies) && CSR_IS_UAPSD_BSS(ies) ) + { +#ifndef WLAN_MDM_CODE_REDUCTION_OPT + acm_mask = sme_QosGetACMMask(mac, bss_description, ies); +#endif + } + else + { + uapsd_mask = 0; + } + } + } + + dw_tmp = pal_cpu_to_be32(csrTranslateEncryptTypeToEdType( + profile->negotiatedUCEncryptionType)); + vos_mem_copy(buf, &dw_tmp, sizeof(tANI_U32)); + buf += sizeof(tANI_U32); + + dw_tmp = pal_cpu_to_be32(csrTranslateEncryptTypeToEdType( + profile->negotiatedMCEncryptionType)); + vos_mem_copy(buf, &dw_tmp, sizeof(tANI_U32)); + buf += sizeof(tANI_U32); +#ifdef WLAN_FEATURE_11W + /* MgmtEncryption */ + if (profile->MFPEnabled) + { + dw_tmp = pal_cpu_to_be32(eSIR_ED_AES_128_CMAC); + } + else + { + dw_tmp = pal_cpu_to_be32(eSIR_ED_NONE); + } + vos_mem_copy(buf, &dw_tmp, sizeof(tANI_U32)); + buf += sizeof(tANI_U32); +#endif +#ifdef WLAN_FEATURE_VOWIFI_11R + profile->MDID.mdiePresent = bss_description->mdiePresent; + if (csrIsProfile11r(profile) +#ifdef FEATURE_WLAN_ESE + && !((profile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM) && + (ies->ESEVersion.present) && + (mac->roam.configParam.isEseIniFeatureEnabled)) +#endif + ) + { + /* is11Rconnection */ + dw_tmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)) ; + buf += sizeof(tAniBool); + } + else + { + /* is11Rconnection */ + dw_tmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } +#endif +#ifdef FEATURE_WLAN_ESE + + /* isESEFeatureIniEnabled */ + if (TRUE == mac->roam.configParam.isEseIniFeatureEnabled) + { + dw_tmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } + else + { + dw_tmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } + + /* A profile can not be both ESE and 11R. But an 802.11R AP + * may be advertising support for ESE as well. So if we are + * associating Open or explicitly ESE then we will get ESE. + * If we are associating explictly 11R only then we will get + * 11R. + */ + if ((csrIsProfileESE(profile) || + ((ies->ESEVersion.present) + && ((profile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM) + || (profile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA) + || (profile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK) + || (profile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN) +#ifdef WLAN_FEATURE_11W + || (profile->negotiatedAuthType == + eCSR_AUTH_TYPE_RSN_PSK_SHA256) + || (profile->negotiatedAuthType == + eCSR_AUTH_TYPE_RSN_8021X_SHA256) +#endif + || (profile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK)))) + && (mac->roam.configParam.isEseIniFeatureEnabled)) + { + /* isESEconnection */ + dw_tmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } + else + { + /* isESEconnection */ + dw_tmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } + + if (eWNI_SME_JOIN_REQ == message_type) + { + tESETspecInfo eseTspec; + /* + * ESE-Tspec IEs in the ASSOC request is presently not supported + * so nullify the TSPEC parameters + */ + vos_mem_set(&eseTspec, sizeof(tESETspecInfo), 0); + vos_mem_copy(buf, &eseTspec, sizeof(tESETspecInfo)); + buf += sizeof(tESETspecInfo); + } + else if (eWNI_SME_REASSOC_REQ == message_type) + { + if ((csrIsProfileESE(profile) || + ((ies->ESEVersion.present) + && ((profile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM) + || (profile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA) + || (profile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK) + || (profile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN) +#ifdef WLAN_FEATURE_11W + || (profile->negotiatedAuthType == + eCSR_AUTH_TYPE_RSN_PSK_SHA256) + || (profile->negotiatedAuthType == + eCSR_AUTH_TYPE_RSN_8021X_SHA256) +#endif + || (profile->negotiatedAuthType == + eCSR_AUTH_TYPE_RSN_PSK)))) + && (mac->roam.configParam.isEseIniFeatureEnabled)) + { + tESETspecInfo eseTspec; + /* ESE Tspec information */ + vos_mem_set(&eseTspec, sizeof(tESETspecInfo), 0); + eseTspec.numTspecs = sme_QosESERetrieveTspecInfo(mac, session_id, + (tTspecInfo *) &eseTspec.tspec[0]); + *buf = eseTspec.numTspecs; + buf += sizeof(tANI_U8); + // Copy the TSPEC information only if present + if (eseTspec.numTspecs) { + vos_mem_copy(buf, (void*)&eseTspec.tspec[0], + (eseTspec.numTspecs*sizeof(tTspecInfo))); + } + buf += sizeof(eseTspec.tspec); + } + else + { + tESETspecInfo eseTspec; + /* + * ESE-Tspec IEs in the ASSOC request is presently + * not supported so nullify the TSPEC parameters + */ + vos_mem_set(&eseTspec, sizeof(tESETspecInfo), 0); + vos_mem_copy(buf, &eseTspec, sizeof(tESETspecInfo)); + buf += sizeof(tESETspecInfo); + } + } +#endif +#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) + /* Fill in isFastTransitionEnabled */ + if (mac->roam.configParam.isFastTransitionEnabled +#ifdef FEATURE_WLAN_LFR + || csrRoamIsFastRoamEnabled(mac, session_id) +#endif + ) + { + dw_tmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } + else + { + dw_tmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } +#endif +#ifdef FEATURE_WLAN_LFR + if(csrRoamIsFastRoamEnabled(mac, session_id)) + { + /* legacy fast roaming enabled */ + dw_tmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } + else + { + dw_tmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } +#endif + + /* txLdpcIniFeatureEnabled */ + *buf = (tANI_U8)mac->roam.configParam.txLdpcEnable; + buf++; + + if ((csrIs11hSupported(mac)) && + (CSR_IS_CHANNEL_5GHZ(bss_description->channelId)) && + (ies->Country.present) &&\ + (!mac->roam.configParam.fSupplicantCountryCodeHasPriority)) + { + csrSaveToChannelPower2G_5G(mac, + ies->Country.num_triplets * sizeof(tSirMacChanInfo), + (tSirMacChanInfo *)(&ies->Country.triplets[0])); + csrApplyPower2Current(mac); + } + +#ifdef WLAN_FEATURE_11AC + /* txBFIniFeatureEnabled */ + *buf = (tANI_U8)mac->roam.configParam.txBFEnable; + buf++; + + /* txBFCsnValue */ + if (IS_BSS_VHT_CAPABLE(ies->VHTCaps)) + { + tx_bf_csn_value = (tANI_U8)mac->roam.configParam.txBFCsnValue; + if (ies->VHTCaps.numSoundingDim) + tx_bf_csn_value = CSR_ROAM_MIN + (tx_bf_csn_value, ies->VHTCaps.numSoundingDim); + } + *buf = tx_bf_csn_value; + buf++; + + /* Only enable MuBf if no other MuBF session exist + * and FW and HOST is MuBF capable. + */ + if (IS_MUMIMO_BFORMEE_CAPABLE && (FALSE == mac->isMuBfsessionexist)) + { + *buf = (tANI_U8)mac->roam.configParam.txMuBformee; + buf++; + } + else + { + *buf = 0; + buf++; + } +#endif + *buf = (tANI_U8)mac->roam.configParam.isAmsduSupportInAMPDU; + buf++; + + /* WME */ + if(mac->roam.roamSession[session_id].fWMMConnection) + { + /* WME enabled */ + dw_tmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } + else + { + dw_tmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } + + /* QOS */ + if(mac->roam.roamSession[session_id].fQOSConnection) + { + /* QOS enabled */ + dw_tmp = pal_cpu_to_be32(TRUE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } + else + { + dw_tmp = pal_cpu_to_be32(FALSE); + vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)); + buf += sizeof(tAniBool); + } + /* BssDesc */ + csrPrepareJoinReassocReqBuffer(mac, bss_description, buf, + (tANI_U8)profile->uapsd_mask); + } while( 0 ); + + smsLog(mac, LOG1, FL("status %d"), status); + + vos_mem_free(profile); + return status; +} +#endif + // eHalStatus csrSendMBDisassocReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr bssId, tANI_U16 reasonCode ) { @@ -15410,7 +16229,7 @@ static tANI_U32 csrFindIbssSession( tpAniSirGlobal pMac ) } return (nRet); } -static void csrRoamLinkUp(tpAniSirGlobal pMac, tCsrBssid bssid) +void csrRoamLinkUp(tpAniSirGlobal pMac, tCsrBssid bssid) { VOS_STATUS status = VOS_STATUS_SUCCESS; @@ -17268,6 +18087,8 @@ eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reas } VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG,"HomeAwayTime:%d",pRequestBuf->HomeAwayTime); + pRequestBuf->WeakZoneRssiThresholdForRoam = + pMac->roam.configParam.neighborRoamConfig.nWeakZoneRssiThresholdForRoam; /*Prepare a probe request for 2.4GHz band and one for 5GHz band*/ ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode )); @@ -17818,6 +18639,10 @@ eHalStatus csrIsFullPowerNeeded( tpAniSirGlobal pMac, tSmeCmd *pCommand, case eCsrCapsChange: fNeedFullPower = eANI_BOOLEAN_TRUE; break; + case eCsrForcedDisassocSta: + case eCsrForcedDeauthSta: + fNeedFullPower = eANI_BOOLEAN_FALSE; + break; default: //Check whether the profile is already connected. If so, no need for full power //Note: IBSS is ignored for now because we don't support powersave in IBSS @@ -18120,6 +18945,59 @@ eHalStatus csrRoamUpdateWPARSNIEs( tpAniSirGlobal pMac, tANI_U32 sessionId, tSir return ( status ); } +tANI_U32 csrGetdot11Mode(tHalHandle hHal, tANI_U32 sessionId, + tpSirBssDescription pBssDescription) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId); + eCsrCfgDot11Mode uCfgDot11Mode, cfgDot11Mode; + eHalStatus status; + tDot11fBeaconIEs *ies_local = NULL; + tANI_U32 dot11mode = 0; + + smsLog(pMac, LOG1, FL("phyMode %d"), pSession->pCurRoamProfile->phyMode); + + /* Get IE's */ + status = csrGetParsedBssDescriptionIEs(pMac, pBssDescription, &ies_local); + if (!HAL_STATUS_SUCCESS(status)) { + smsLog(pMac, LOGE, + FL("csrGetParsedBssDescriptionIEs failed")); + return 0; + } + if(ies_local == NULL) { + smsLog(pMac, LOGE, + FL("ies_local is NULL")); + return 0; + } + + if(csrIsPhyModeMatch(pMac, pSession->pCurRoamProfile->phyMode, + pBssDescription, pSession->pCurRoamProfile, &cfgDot11Mode, ies_local)) + uCfgDot11Mode = cfgDot11Mode; + else + { + smsLog(pMac, LOGE, "Can not find match phy mode"); + if(CSR_IS_CHANNEL_5GHZ(pBssDescription->channelId)) + uCfgDot11Mode = eCSR_CFG_DOT11_MODE_11A; + else + uCfgDot11Mode = eCSR_CFG_DOT11_MODE_11G; + } + + /* dot11mode */ + dot11mode = csrTranslateToWNICfgDot11Mode(pMac, uCfgDot11Mode); + smsLog(pMac, LOG1, + FL("dot11mode %d uCfgDot11Mode %d"), dot11mode, uCfgDot11Mode); + + if (pBssDescription->channelId <= 14 && + FALSE == pMac->roam.configParam.enableVhtFor24GHz && + WNI_CFG_DOT11_MODE_11AC == dot11mode) + { + /* Need to disable VHT operation in 2.4 GHz band */ + dot11mode = WNI_CFG_DOT11_MODE_11N; + } + vos_mem_free(ies_local); + return dot11mode; +} + #ifdef WLAN_FEATURE_VOWIFI_11R //eHalStatus csrRoamIssueFTPreauthReq(tHalHandle hHal, tANI_U32 sessionId, tCsrBssid preAuthBssid, tANI_U8 channelId) eHalStatus csrRoamIssueFTPreauthReq(tHalHandle hHal, tANI_U32 sessionId, tpSirBssDescription pBssDescription) @@ -18145,6 +19023,14 @@ eHalStatus csrRoamIssueFTPreauthReq(tHalHandle hHal, tANI_U32 sessionId, tpSirBs pftPreAuthReq->messageType = pal_cpu_to_be16(eWNI_SME_FT_PRE_AUTH_REQ); pftPreAuthReq->preAuthchannelNum = pBssDescription->channelId; + pftPreAuthReq->dot11mode = + csrGetdot11Mode(hHal, sessionId, pBssDescription); + if (!pftPreAuthReq->dot11mode) + { + smsLog(pMac, LOGE, FL("pftPreAuthReq->dot11mode is zero")); + vos_mem_free(pftPreAuthReq); + return eHAL_STATUS_FAILURE; + } vos_mem_copy((void *)&pftPreAuthReq->currbssId, (void *)pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); @@ -18270,6 +19156,10 @@ void csrRoamFTPreAuthRspProcessor( tHalHandle hHal, tpSirFTPreAuthRsp pFTPreAuth tANI_U16 ft_ies_length; ft_ies_length = pFTPreAuthRsp->ric_ies_length; + if (pMac->roam.roamSession[pMac->ft.ftSmeContext.smeSessionId]. + connectedProfile.MDID.mdiePresent) + pMac->ft.ftSmeContext.addMDIE = TRUE; + if ( (pMac->ft.ftSmeContext.reassoc_ft_ies) && (pMac->ft.ftSmeContext.reassoc_ft_ies_length)) { @@ -18277,6 +19167,12 @@ void csrRoamFTPreAuthRspProcessor( tHalHandle hHal, tpSirFTPreAuthRsp pFTPreAuth pMac->ft.ftSmeContext.reassoc_ft_ies_length = 0; } + if (!ft_ies_length) + { + pMac->ft.ftSmeContext.psavedFTPreAuthRsp = NULL; + return; + } + pMac->ft.ftSmeContext.reassoc_ft_ies = vos_mem_malloc(ft_ies_length); if ( NULL == pMac->ft.ftSmeContext.reassoc_ft_ies ) { diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c b/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c index 0cf87c38ba0..4a737a10f9c 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c @@ -1728,13 +1728,8 @@ eHalStatus csrScanHandleSearchForSSID(tpAniSirGlobal pMac, tSmeCmd *pCommand) smsLog(pMac, LOGE, FL("session %d not found"), sessionId); break; } - /* If Disconnect is already issued from HDD no need to issue connect - * pSession->abortConnection will not be set in case of try - * disconnect or hdd stop adaptor use connectState for these cases. - */ - if (pSession->abortConnection || - (pMac->roam.roamSession[sessionId].connectState == - eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING)) + /* If Disconnect is already issued from HDD no need to issue connect */ + if (pSession->abortConnection) { smsLog(pMac, LOGE, FL("Disconnect in progress, no need to issue connect")); @@ -9217,6 +9212,25 @@ eHalStatus csrScanSavePreferredNetworkFound(tpAniSirGlobal pMac, vos_mem_copy((tANI_U8 *) &pBssDescr->bssId, (tANI_U8 *) macHeader->bssId, sizeof(tSirMacAddr)); pBssDescr->nReceivedTime = vos_timer_get_system_time(); +#ifdef WLAN_FEATURE_VOWIFI_11R + // MobilityDomain + pBssDescr->mdie[0] = 0; + pBssDescr->mdie[1] = 0; + pBssDescr->mdie[2] = 0; + pBssDescr->mdiePresent = FALSE; + // If mdie is present in the probe resp we fill it in the bss description + if(pParsedFrame->mdiePresent) + { + pBssDescr->mdiePresent = TRUE; + pBssDescr->mdie[0] = pParsedFrame->mdie[0]; + pBssDescr->mdie[1] = pParsedFrame->mdie[1]; + pBssDescr->mdie[2] = pParsedFrame->mdie[2]; + } + smsLog(pMac, LOG1, FL("mdie=%02x%02x%02x"), + (unsigned int)pBssDescr->mdie[0], (unsigned int)pBssDescr->mdie[1], + (unsigned int)pBssDescr->mdie[2]); +#endif + smsLog( pMac, LOG1, FL("Bssid= "MAC_ADDRESS_STR " chan= %d, rssi = %d "), MAC_ADDR_ARRAY(pBssDescr->bssId), diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrCmdProcess.c b/drivers/staging/prima/CORE/SME/src/csr/csrCmdProcess.c index e9c47c04be4..c773cc9a128 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrCmdProcess.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrCmdProcess.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -96,7 +96,9 @@ eHalStatus csrMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ) * workable due to failure or finding the condition meets both SAP and infra/IBSS requirement. */ if( (eWNI_SME_SETCONTEXT_RSP == pSmeRsp->messageType) || - (eWNI_SME_REMOVEKEY_RSP == pSmeRsp->messageType) ) + (eWNI_SME_REMOVEKEY_RSP == pSmeRsp->messageType) || + (pSmeRsp->messageType == eWNI_SME_FT_PRE_AUTH_RSP) || + (eWNI_SME_GET_STATISTICS_RSP == pSmeRsp->messageType)) { smsLog(pMac, LOGW, FL(" handling msg 0x%X CSR state is %d"), pSmeRsp->messageType, pMac->roam.curState[pSmeRsp->sessionId]); csrRoamCheckForLinkStatusChange(pMac, pSmeRsp); diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h b/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h index 302b385c68d..2f57205e423 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h +++ b/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h @@ -257,13 +257,15 @@ struct csr_scan_for_ssid_context ( eCSR_ENCRYPT_TYPE_WEP40 != (encType) ) && \ ( eCSR_ENCRYPT_TYPE_WEP104 != (encType) ) ) -#define CSR_IS_DISCONNECT_COMMAND(pCommand) ( ( eSmeCommandRoam == (pCommand)->command ) &&\ - ( ( eCsrForcedDisassoc == (pCommand)->u.roamCmd.roamReason ) ||\ - ( eCsrForcedDeauth == (pCommand)->u.roamCmd.roamReason ) ||\ - ( eCsrSmeIssuedDisassocForHandoff ==\ - (pCommand)->u.roamCmd.roamReason ) ||\ - ( eCsrForcedDisassocMICFailure ==\ - (pCommand)->u.roamCmd.roamReason ) ) ) +#define CSR_IS_DISCONNECT_COMMAND(pCommand) ((eSmeCommandRoam == \ + (pCommand)->command) &&\ + ((eCsrForcedDisassoc == (pCommand)->u.roamCmd.roamReason) ||\ + (eCsrForcedIbssLeave == (pCommand)->u.roamCmd.roamReason) ||\ + (eCsrForcedDeauth == (pCommand)->u.roamCmd.roamReason) ||\ + (eCsrSmeIssuedDisassocForHandoff ==\ + (pCommand)->u.roamCmd.roamReason) ||\ + (eCsrForcedDisassocMICFailure ==\ + (pCommand)->u.roamCmd.roamReason))) eCsrRoamState csrRoamStateChange( tpAniSirGlobal pMac, eCsrRoamState NewRoamState, tANI_U8 sessionId); eHalStatus csrScanningStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ); @@ -271,6 +273,10 @@ void csrRoamingStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ); void csrRoamJoinedStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ); tANI_BOOLEAN csrScanComplete( tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp ); void csrReleaseCommandRoam(tpAniSirGlobal pMac, tSmeCmd *pCommand); +tpCsrNeighborRoamBSSInfo csrNeighborRoamGetRoamableAPListNextEntry(tpAniSirGlobal pMac, + tDblLinkList *pList, tpCsrNeighborRoamBSSInfo pNeighborEntry); +v_U8_t *csrNeighborRoamStateToString(v_U8_t state); +void csrReleaseCommandPreauth(tpAniSirGlobal pMac, tSmeCmd *pCommand); void csrReleaseCommandScan(tpAniSirGlobal pMac, tSmeCmd *pCommand); void csrReleaseCommandWmStatusChange(tpAniSirGlobal pMac, tSmeCmd *pCommand); //pIes2 can be NULL @@ -400,6 +406,10 @@ void csrRoamRemoveDuplicateCommand(tpAniSirGlobal pMac, tANI_U32 sessionId, tSme eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pBssDescription, tCsrRoamProfile *pProfile, tDot11fBeaconIEs *pIes, tANI_U16 messageType ); eHalStatus csrSendMBDisassocReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr bssId, tANI_U16 reasonCode ); +#ifdef WLAN_FEATURE_LFR_MBB +eHalStatus csr_fill_reassoc_req(tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pBssDescription, + tDot11fBeaconIEs *pIes, tSirSmeJoinReq **reassoc_req); +#endif eHalStatus csrSendMBDeauthReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr bssId, tANI_U16 reasonCode ); eHalStatus csrSendMBDisassocCnfMsg( tpAniSirGlobal pMac, tpSirSmeDisassocInd pDisassocInd ); eHalStatus csrSendMBDeauthCnfMsg( tpAniSirGlobal pMac, tpSirSmeDeauthInd pDeauthInd ); diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c b/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c index bce1abd66a3..1467f5919a6 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -72,6 +72,9 @@ #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) #include "csrEse.h" #endif +#ifdef WLAN_FEATURE_LFR_MBB +#include "csr_roam_mbb.h" +#endif #define WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG 1 #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG @@ -112,6 +115,9 @@ v_U8_t *csrNeighborRoamStateToString(v_U8_t state) CASE_RETURN_STRING( eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN ); CASE_RETURN_STRING( eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING ); CASE_RETURN_STRING( eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE ); +#ifdef WLAN_FEATURE_LFR_MBB + CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC); +#endif default: return "eCSR_NEIGHBOR_ROAM_STATE_UNKNOWN"; } @@ -253,6 +259,36 @@ static eHalStatus csrNeighborRoamTriggerHandoff(tpAniSirGlobal pMac, tpCsrNeighborRoamControlInfo pNeighborRoamInfo) { eHalStatus status = eHAL_STATUS_SUCCESS; + +#ifdef WLAN_FEATURE_LFR_MBB + smsLog(pMac, LOG1, FL("enable_lfr_mbb %d is mbb supported %d"), + pMac->roam.configParam.enable_lfr_mbb, + sme_IsFeatureSupportedByFW(MAKE_BEFORE_BREAK)); + + if (pMac->roam.configParam.enable_lfr_mbb + && sme_IsFeatureSupportedByFW(MAKE_BEFORE_BREAK) +#ifdef WLAN_FEATURE_VOWIFI_11R + && (!pNeighborRoamInfo->is11rAssoc) +#endif +#ifdef FEATURE_WLAN_ESE + && (!pNeighborRoamInfo->isESEAssoc) +#endif + ) { + smsLog(pMac, LOG1, + FL("Issuing preauth reassoc")); + status = csr_neighbor_roam_issue_preauth_reassoc(pMac); + if (eHAL_STATUS_SUCCESS != status) + { + pMac->ft.ftSmeContext.is_preauth_lfr_mbb = false; + smsLog(pMac, LOG1, FL("is_preauth_lfr_mbb %d"), + pMac->ft.ftSmeContext.is_preauth_lfr_mbb); + } + return status; + } + + +#endif + #ifdef WLAN_FEATURE_VOWIFI_11R if ((pNeighborRoamInfo->is11rAssoc) #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD @@ -1156,14 +1192,20 @@ eHalStatus csrNeighborRoamPreauthRspHandler(tpAniSirGlobal pMac, tSirRetStatus l { tpCsrNeighborRoamBSSInfo pNeighborBssNode = NULL; tListElem *pEntry; + uint32_t retries; + + retries = pMac->sta_auth_retries_for_code17 > + CSR_NEIGHBOR_ROAM_MAX_NUM_PREAUTH_RETRIES ? + pMac->sta_auth_retries_for_code17 : + CSR_NEIGHBOR_ROAM_MAX_NUM_PREAUTH_RETRIES; smsLog(pMac, LOGE, FL("Preauth failed retry number %d, status = 0x%x"), pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries, limStatus); /* Preauth failed. Add the bssId to the preAuth failed list MAC Address. Also remove the AP from roamable AP list */ - if ((pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries >= - CSR_NEIGHBOR_ROAM_MAX_NUM_PREAUTH_RETRIES) || - (eSIR_LIM_MAX_STA_REACHED_ERROR == limStatus)) + if ((pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries >= retries) || + ((eSIR_LIM_MAX_STA_REACHED_ERROR == limStatus) && + (pMac->sta_auth_retries_for_code17 == 0))) { /* We are going to remove the node as it fails for more than MAX tries. Reset this count to 0 */ pNeighborRoamInfo->FTRoamInfo.numPreAuthRetries = 0; @@ -4426,6 +4468,10 @@ eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessio */ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT); pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pNeighborRoamInfo->uOsRequestedHandoff = 0; +#endif + } break; @@ -4453,6 +4499,10 @@ eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessio #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD } #endif + +#ifdef WLAN_FEATURE_LFR_MBB + csr_stop_preauth_reassoc_mbb_timer(pMac); +#endif break; case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN: @@ -4460,6 +4510,7 @@ eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessio pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; csrNeighborRoamResetCfgListChanScanControlInfo(pMac); #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pNeighborRoamInfo->uOsRequestedHandoff = 0; if (!csrRoamIsRoamOffloadScanEnabled(pMac)) { #endif @@ -4496,6 +4547,9 @@ eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessio NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Transitioning to INIT state")); CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT) pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pNeighborRoamInfo->uOsRequestedHandoff = 0; +#endif break; } #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD @@ -4571,12 +4625,18 @@ eHalStatus csrNeighborRoamIndicateConnect(tpAniSirGlobal pMac, tANI_U8 sessionId switch (pNeighborRoamInfo->neighborRoamState) { +#ifdef WLAN_FEATURE_LFR_MBB + case eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC: +#endif case eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING: if (VOS_STATUS_SUCCESS != vosStatus) { /* Just transition the state to INIT state. Rest of the clean up happens when we get next connect indication */ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT) pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pNeighborRoamInfo->uOsRequestedHandoff = 0; +#endif break; } /* Fall through if the status is SUCCESS */ @@ -4816,6 +4876,8 @@ eHalStatus csrNeighborRoamInit(tpAniSirGlobal pMac) pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod = pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod; pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod = pMac->roam.configParam.neighborRoamConfig.nEmptyScanRefreshPeriod; pNeighborRoamInfo->cfgParams.neighborInitialForcedRoamTo5GhEnable = pMac->roam.configParam.neighborRoamConfig.nNeighborInitialForcedRoamTo5GhEnable; + pNeighborRoamInfo->cfgParams.WeakZoneRssiThresholdForRoam = + pMac->roam.configParam.neighborRoamConfig.nWeakZoneRssiThresholdForRoam; pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels; @@ -4943,6 +5005,9 @@ eHalStatus csrNeighborRoamInit(tpAniSirGlobal pMac) CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT) pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pNeighborRoamInfo->uOsRequestedHandoff = 0; +#endif //Set the Last Sent Cmd as RSO_STOP pNeighborRoamInfo->lastSentCmd = ROAM_SCAN_OFFLOAD_STOP; @@ -5268,6 +5333,9 @@ void csrNeighborRoamTranistionPreauthDoneToDisconnected(tpAniSirGlobal pMac) // Transition to init state CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT) pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_FALSE; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pNeighborRoamInfo->uOsRequestedHandoff = 0; +#endif } /* --------------------------------------------------------------------------- @@ -5300,7 +5368,14 @@ tANI_BOOLEAN csrNeighborMiddleOfRoaming (tHalHandle hHal) (eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING == pMac->roam.neighborRoamInfo.neighborRoamState) || (eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE == pMac->roam.neighborRoamInfo.neighborRoamState) || (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pMac->roam.neighborRoamInfo.neighborRoamState) || - (eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN == pMac->roam.neighborRoamInfo.neighborRoamState); + (eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN == pMac->roam.neighborRoamInfo.neighborRoamState) + +#ifdef WLAN_FEATURE_LFR_MBB + || (eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC == + pMac->roam.neighborRoamInfo.neighborRoamState); +#else + ; +#endif return (val); } #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD diff --git a/drivers/staging/prima/CORE/SME/src/csr/csr_roam_mbb.c b/drivers/staging/prima/CORE/SME/src/csr/csr_roam_mbb.c new file mode 100644 index 00000000000..f70172217ae --- /dev/null +++ b/drivers/staging/prima/CORE/SME/src/csr/csr_roam_mbb.c @@ -0,0 +1,890 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "aniGlobal.h" +#include "smeInside.h" +#include "csrInsideApi.h" +#include "smsDebug.h" +#include "macTrace.h" +#include "csrNeighborRoam.h" +#include "csr_roam_mbb.h" +#include "csrInternal.h" +#include "wlan_qct_wda.h" + +eHalStatus csr_register_roaming_mbb_callback(tpAniSirGlobal mac); + +#define PREAUTH_REASSOC_MBB_TIMER_VALUE 60 + +#define CSR_NEIGHBOR_ROAM_STATE_TRANSITION(newState)\ +{\ + mac->roam.neighborRoamInfo.prevNeighborRoamState = mac->roam.neighborRoamInfo.neighborRoamState;\ + mac->roam.neighborRoamInfo.neighborRoamState = newState;\ + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, \ + FL("Neighbor Roam Transition from state %s ==> %s"), \ + csrNeighborRoamStateToString (mac->roam.neighborRoamInfo.prevNeighborRoamState), \ + csrNeighborRoamStateToString (newState));\ +} + +/** + * csr_roam_issue_preauth_reassoc_req() -Prepares preauth request + * @hal: HAL context + * @session_id: session id + * @bss_description: BSS description + * + * This function prepares preauth request and sends request to PE + * + * Return: eHAL_STATUS_SUCCESS on success, + * : eHAL_STATUS_RESOURCES when resource allocation is failure + * : eHAL_STATUS_FAILURE otherwise + */ +eHalStatus csr_roam_issue_preauth_reassoc_req(tHalHandle hal, + tANI_U32 session_id, tpSirBssDescription bss_description) +{ + tpAniSirGlobal mac = PMAC_STRUCT(hal); + tpSirFTPreAuthReq pre_auth_req; + tANI_U16 auth_req_len = 0; + tCsrRoamSession *session = CSR_GET_SESSION(mac, session_id); + tpCsrNeighborRoamControlInfo neighbor_roam_info = + &mac->roam.neighborRoamInfo; + eHalStatus status; + + auth_req_len = sizeof(tSirFTPreAuthReq); + pre_auth_req = (tpSirFTPreAuthReq)vos_mem_malloc(auth_req_len); + if (NULL == pre_auth_req) { + smsLog(mac, LOGE, + FL("Memory allocation for Preauth request failed")); + return eHAL_STATUS_RESOURCES; + } + + /* + * If neighborRoamState is eCSR_NEIGHBOR_ROAM_STATE_INIT + * by the time this API is invoked, disconnect would have happened. + * So, need to proceed further. + */ + if (mac->roam.neighborRoamInfo.neighborRoamState == + eCSR_NEIGHBOR_ROAM_STATE_INIT) { + smsLog(mac, LOGE, FL("neighborRoamState %d"), + mac->roam.neighborRoamInfo.neighborRoamState); + return eHAL_STATUS_FAILURE; + } + + /* + * Save the SME Session ID here. We need it while processing + * the preauth response. + */ + mac->ft.ftSmeContext.smeSessionId = session_id; + vos_mem_zero(pre_auth_req, auth_req_len); + + pre_auth_req->pbssDescription = (tpSirBssDescription)vos_mem_malloc( + sizeof(bss_description->length) + bss_description->length); + if (NULL == pre_auth_req->pbssDescription) { + smsLog(mac, LOGE, + FL("Unable to allocate memory for preauth bss description")); + return eHAL_STATUS_RESOURCES; + } + + pre_auth_req->messageType = + pal_cpu_to_be16(eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ); + + pre_auth_req->preAuthchannelNum = bss_description->channelId; + + vos_mem_copy((void *)&pre_auth_req->currbssId, + (void *)session->connectedProfile.bssid, sizeof(tSirMacAddr)); + vos_mem_copy((void *)&pre_auth_req->preAuthbssId, + (void *)bss_description->bssId, sizeof(tSirMacAddr)); + + vos_mem_copy(pre_auth_req->pbssDescription, bss_description, + sizeof(bss_description->length) + bss_description->length); + pre_auth_req->length = pal_cpu_to_be16(auth_req_len); + + /* Register mbb callback */ + smsLog(mac, LOG1, FL("Registering mbb callback")); + csr_register_roaming_mbb_callback(mac); + + csrReleaseProfile(mac, &neighbor_roam_info->csrNeighborRoamProfile); + + /* Copy current profile to be used in csr_update_roamed_info_mbb */ + status = csrRoamCopyProfile(mac, + &neighbor_roam_info->csrNeighborRoamProfile, + session->pCurRoamProfile); + if(!HAL_STATUS_SUCCESS(status)) { + smsLog(mac, LOGE, FL("Profile copy failed")); + return status; + } + + return palSendMBMessage(mac->hHdd, pre_auth_req); +} + +/** + * csr_neighbor_roam_issue_preauth_reassoc() -issues preauth_reassoc request + * @mac: MAC context + * + * This function issues preauth_reassoc request to PE with the 1st AP + * entry in the roamable AP list + * + * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE otherwise + */ +eHalStatus csr_neighbor_roam_issue_preauth_reassoc(tpAniSirGlobal mac) +{ + tpCsrNeighborRoamControlInfo neighbor_roam_info = + &mac->roam.neighborRoamInfo; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamBSSInfo neighbor_bss_node; + tCsrRoamInfo roam_info; + + VOS_ASSERT(neighbor_roam_info->FTRoamInfo.preauthRspPending == + eANI_BOOLEAN_FALSE); + + neighbor_bss_node = csrNeighborRoamGetRoamableAPListNextEntry(mac, + &neighbor_roam_info->roamableAPList, NULL); + + if (neighbor_bss_node == NULL) + { + smsLog(mac, LOGE, FL("Roamable AP list is empty")); + csrRoamOffloadScan(mac, ROAM_SCAN_OFFLOAD_RESTART, + REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW); + return eHAL_STATUS_FAILURE; + } + else + { + /* + * Set is_preauth_lfr_mbb which will be checked in + * different API's. + */ + mac->ft.ftSmeContext.is_preauth_lfr_mbb = true; + smsLog(mac, LOG1, FL("is_preauth_lfr_mbb %d"), + mac->ft.ftSmeContext.is_preauth_lfr_mbb); + + status = csrRoamEnqueuePreauth(mac, + neighbor_roam_info->csrSessionId, + neighbor_bss_node->pBssDescription, + ecsr_mbb_perform_preauth_reassoc, + eANI_BOOLEAN_TRUE); + + smsLog(mac, LOG1, FL("Before Pre-Auth: BSSID "MAC_ADDRESS_STR", Ch:%d"), + MAC_ADDR_ARRAY(neighbor_bss_node->pBssDescription->bssId), + neighbor_bss_node->pBssDescription->channelId); + + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(mac, LOGE, + FL("Send Preauth request to PE failed with status %d"), + status); + return status; + } + } + + neighbor_roam_info->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_TRUE; + + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC) + + if (csrRoamIsFastRoamEnabled(mac, CSR_SESSION_ID_INVALID)) + { + smsLog(mac, LOG1, FL("Invoking eCSR_ROAM_PMK_NOTIFY")); + vos_mem_copy((void *)&roam_info.bssid, + (void *)neighbor_bss_node->pBssDescription->bssId, + sizeof(tCsrBssid)); + csrRoamCallCallback(mac, neighbor_roam_info->csrSessionId, &roam_info, + 0, eCSR_ROAM_PMK_NOTIFY, 0); + } + return status; +} + +/** + * csr_stop_preauth_reassoc_mbb_timer() -stops preauth_reassoc timer + * @mac: MAC context + * + * This function stops preauth_reassoc timer + * + */ +void csr_stop_preauth_reassoc_mbb_timer(tpAniSirGlobal mac) +{ + VOS_STATUS vos_status = VOS_STATUS_SUCCESS; + + if (mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started) { + vos_status = + vos_timer_stop(&mac->ft.ftSmeContext.pre_auth_reassoc_mbb_timer); + mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started = + false; + } +} + + +/** + * csr_preauth_reassoc_mbb_timer_callback() -preauth_reassoc timer callback + * @mac: MAC context + * + * This function issues preauth_reassoc with another roamable entry + * + */ +void csr_preauth_reassoc_mbb_timer_callback(void *context) +{ + tpAniSirGlobal mac = (tpAniSirGlobal)context; + + mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started = 0; + + smsLog(mac, LOG1, FL("is_pre_auth_reassoc_mbb_timer_started %d"), + mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started); + + csr_neighbor_roam_issue_preauth_reassoc(mac); +} + + +/** + * csr_roam_dequeue_preauth_reassoc() -Dequeues + * ecsr_mbb_perform_preauth_reassoc + * @mac: MAC context + * + * This function dequeues ecsr_mbb_perform_preauth_reassoc + * + */ +eHalStatus csr_roam_dequeue_preauth_reassoc(tpAniSirGlobal mac) +{ + tListElem *entry; + tSmeCmd *command; + entry = csrLLPeekHead(&mac->sme.smeCmdActiveList, LL_ACCESS_LOCK); + if (entry) { + command = GET_BASE_ADDR(entry, tSmeCmd, Link); + if ((eSmeCommandRoam == command->command) && + (ecsr_mbb_perform_preauth_reassoc == + command->u.roamCmd.roamReason)) { + smsLog(mac, LOG1, FL("DQ-Command = %d, Reason = %d"), + command->command, command->u.roamCmd.roamReason); + if (csrLLRemoveEntry( &mac->sme.smeCmdActiveList, + entry, LL_ACCESS_LOCK)) { + csrReleaseCommandPreauth( mac, command ); + } + } else { + smsLog(mac, LOGE, FL("Command = %d, Reason = %d "), + command->command, command->u.roamCmd.roamReason); + } + } + else { + smsLog(mac, LOGE, + FL("pEntry NULL for eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP")); + } + smeProcessPendingQueue( mac ); + return eHAL_STATUS_SUCCESS; +} + +/** + * csr_neighbor_roam_preauth_reassoc_rsp_handler() -handles preauth + * reassoc response + * @mac: MAC context + * @lim_status: status of preauth reassoc response from lim + * @bss_description: bss description pointer + * + * This function handles preauth_reassoc response from PE. When + * preauth_reassoc response failure is received, preauth reassoc + * with new candidate will be attempted. In success case, candidate will be + * removed from roamable entry. + * + */ +eHalStatus +csr_neighbor_roam_preauth_reassoc_rsp_handler(tpAniSirGlobal mac, + tSirRetStatus lim_status, tSirBssDescription **bss_description) +{ + tpCsrNeighborRoamControlInfo neighbor_roam_info = + &mac->roam.neighborRoamInfo; + eHalStatus status = eHAL_STATUS_SUCCESS; + eHalStatus preauth_processed = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamBSSInfo preauth_rsp_node = NULL; + + if (eANI_BOOLEAN_FALSE == + neighbor_roam_info->FTRoamInfo.preauthRspPending) { + /* + * This can happen when we disconnect immediately after sending + * a pre-auth request. During processing of the disconnect command, + * we would have reset preauthRspPending and transitioned to INIT state. + */ + smsLog(mac, LOGE, + FL("Unexpected pre-auth response in state %d"), + neighbor_roam_info->neighborRoamState); + preauth_processed = eHAL_STATUS_FAILURE; + goto DEQ_PREAUTH; + } + + if ((neighbor_roam_info->neighborRoamState != + eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC)) { + smsLog(mac, LOGE, + FL("Preauth response received in state %s"), + macTraceGetNeighbourRoamState( + neighbor_roam_info->neighborRoamState)); + preauth_processed = eHAL_STATUS_FAILURE; + goto DEQ_PREAUTH; + } + + neighbor_roam_info->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_FALSE; + + if (eSIR_SUCCESS == lim_status) + preauth_rsp_node = csrNeighborRoamGetRoamableAPListNextEntry(mac, + &neighbor_roam_info->roamableAPList, NULL); + + if ((eSIR_SUCCESS == lim_status) && (NULL != preauth_rsp_node)) { + smsLog(mac, LOG1, FL("MBB Reassoc completed successfully")); + + smsLog(mac, LOG1, FL("After MBB reassoc BSSID "MAC_ADDRESS_STR" Ch %d"), + MAC_ADDR_ARRAY(preauth_rsp_node->pBssDescription->bssId), + preauth_rsp_node->pBssDescription->channelId); + + /* Memory will be freed in caller of this */ + *bss_description = (tpSirBssDescription)vos_mem_malloc( + sizeof(preauth_rsp_node->pBssDescription->length) + + preauth_rsp_node->pBssDescription->length); + if (NULL == *bss_description) { + smsLog(mac, LOGE, + FL("Unable to allocate memory for preauth bss description")); + preauth_processed = eHAL_STATUS_RESOURCES; + goto DEQ_PREAUTH; + } + + vos_mem_copy(*bss_description, preauth_rsp_node->pBssDescription, + sizeof(preauth_rsp_node->pBssDescription->length) + + preauth_rsp_node->pBssDescription->length); + + /* + * MBB Reassoc competer successfully. Insert the preauthenticated + * node to tail of preAuthDoneList + */ + csrNeighborRoamRemoveRoamableAPListEntry(mac, + &neighbor_roam_info->roamableAPList, preauth_rsp_node); + csrLLInsertTail(&neighbor_roam_info->FTRoamInfo.preAuthDoneList, + &preauth_rsp_node->List, LL_ACCESS_LOCK); + return eHAL_STATUS_SUCCESS; + } else { + tpCsrNeighborRoamBSSInfo neighbor_bss_node = NULL; + tListElem *entry; + + /* + * Pre-auth failed. Add the bssId to the preAuth failed list MAC Address. + * Also remove the AP from roamable AP list. The one in the head of the + * list should be one with which we issued pre-auth and failed. + */ + entry = csrLLRemoveHead(&neighbor_roam_info->roamableAPList, + LL_ACCESS_LOCK); + if(entry) { + neighbor_bss_node = GET_BASE_ADDR(entry, + tCsrNeighborRoamBSSInfo, List); + /* + * Add the BSSID to pre-auth fail list if it is + * not requested by HDD + */ + status = csrNeighborRoamAddBssIdToPreauthFailList(mac, + neighbor_bss_node->pBssDescription->bssId); + + smsLog(mac, LOG1, + FL("MBB reassoc failed BSSID "MAC_ADDRESS_STR" Ch:%d status %d"), + MAC_ADDR_ARRAY(neighbor_bss_node->pBssDescription->bssId), + neighbor_bss_node->pBssDescription->channelId, lim_status); + + /* Now we can free this node */ + csrNeighborRoamFreeNeighborRoamBSSNode(mac, neighbor_bss_node); + } + + /* + * Move state to Connected. Connected state here signifies connection + * with current AP as preauth failed with roamable AP. Still driver has + * connection with current AP. + */ + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED) + + /* Start a timer to issue preauth_reassoc request for the next entry*/ + status = vos_timer_start(&mac->ft.ftSmeContext. + pre_auth_reassoc_mbb_timer, PREAUTH_REASSOC_MBB_TIMER_VALUE); + if (eHAL_STATUS_SUCCESS != status) { + smsLog(mac, LOGE, + FL("pre_auth_reassoc_mbb_timer start failed status %d"), + status); + preauth_processed = eHAL_STATUS_FAILURE; + goto DEQ_PREAUTH; + } + mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started = true; + smsLog(mac, LOG1, FL("is_pre_auth_reassoc_mbb_timer_started %d"), + mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started); + preauth_processed = eHAL_STATUS_SUCCESS; + } + +DEQ_PREAUTH: + csr_roam_dequeue_preauth_reassoc(mac); + return preauth_processed; +} + +eHalStatus csr_update_roamed_info_mbb(tHalHandle hal, + tpSirBssDescription bss_description, tpSirFTPreAuthRsp pre_auth_rsp) +{ + eHalStatus status; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + tDot11fBeaconIEs *ies_local = NULL; + tCsrRoamSession *session = NULL; + tCsrRoamProfile *profile; + tSirMacAddr broadcast_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + tANI_U32 key_timeout_interval; + tCsrRoamInfo roam_info; + sme_QosAssocInfo assoc_info; + tANI_U32 len; + tANI_U8 sme_session_id = pre_auth_rsp->smeSessionId; + tANI_U8 acm_mask = 0; + + /* Get profile */ + session = CSR_GET_SESSION(mac, sme_session_id); + + profile = vos_mem_malloc(sizeof(*profile)); + if (NULL == profile) { + smsLog(mac, LOGE, FL("Memory allocation failure for profile")); + return eHAL_STATUS_FAILURE; + } + + /* + * session->pCurRoamProfile is copied into csrNeighborRoamProfile + * in csr_roam_issue_preauth_reassoc_req as there is a chance of + * session->pCurRoamProfile getting freed when disconnect is issued + * from upper layer. + */ + status = csrRoamCopyProfile(mac, profile, + &mac->roam.neighborRoamInfo.csrNeighborRoamProfile); + if(!HAL_STATUS_SUCCESS(status)) { + smsLog(mac, LOGE, FL("Profile copy failed")); + vos_mem_free(profile); + return status; + } + + profile->negotiatedAuthType = + mac->roam.roamSession[sme_session_id].connectedProfile.AuthType; + profile->negotiatedUCEncryptionType = + mac->roam.roamSession[sme_session_id].connectedProfile.EncryptionType; + profile->mcEncryptionType = + mac->roam.roamSession[sme_session_id].connectedProfile.mcEncryptionInfo; + profile->negotiatedMCEncryptionType = + mac->roam.roamSession[sme_session_id].connectedProfile.mcEncryptionType; + + smsLog(mac, LOG1, + FL("AuthType %d UCEType %d Entries %d encryptionType %d MCEType %d"), + profile->negotiatedAuthType, + profile->negotiatedUCEncryptionType, + profile->mcEncryptionType.numEntries, + profile->mcEncryptionType.encryptionType[0], + profile->negotiatedMCEncryptionType); + + /* Get IE's */ + status = csrGetParsedBssDescriptionIEs(mac, bss_description, &ies_local); + if (!HAL_STATUS_SUCCESS(status)) { + smsLog(mac, LOGE, + FL("csrGetParsedBssDescriptionIEs failed")); + vos_mem_free(profile); + return status; + } + if(ies_local == NULL) { + smsLog(mac, LOGE, + FL("ies_local is NULL ")); + vos_mem_free(profile); + return eHAL_STATUS_FAILURE; + } + + vos_mem_set(&roam_info, sizeof(roam_info), 0); + + csrRoamStopNetwork(mac, sme_session_id, profile, + bss_description, ies_local); + + session->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED; + + csrRoamSaveConnectedInfomation(mac, sme_session_id, profile, + bss_description, ies_local); + csrRoamSaveSecurityRspIE(mac, sme_session_id, + profile->negotiatedAuthType, bss_description, + ies_local); + + csrRoamStateChange(mac, eCSR_ROAMING_STATE_JOINED, sme_session_id); + + /* + * If abortConnection is set, it implies that disconnect in progress + * from upper layer. So there is no point in proceeding further. + * By this point, pConnectBssDesc is updated in + * csrRoamSaveConnectedInfomation. This pConnectBssDesc is used + * during processing of disconnect in CSR and this has new BSSID info. + * By this time, original AP related info was cleaned up in LIM. So, + * disconnect queued while roaming in progress will take care of + * cleaning up roamed AP related info in LIM. + */ + if (session->abortConnection) { + smsLog(mac, LOGE, FL("Disconnect in progress")); + + smsLog(mac, LOGE, FL("MBB reassoc BSSID "MAC_ADDRESS_STR" Ch %d"), + MAC_ADDR_ARRAY(bss_description->bssId), + bss_description->channelId); + + vos_mem_free(profile); + return eHAL_STATUS_FAILURE; + } + + if(CSR_IS_ENC_TYPE_STATIC(profile->negotiatedUCEncryptionType) && + !profile->bWPSAssociation) { + /* + * Issue the set Context request to LIM to establish the + * Unicast STA context + */ + if(!HAL_STATUS_SUCCESS(csrRoamIssueSetContextReq(mac, + sme_session_id, + profile->negotiatedUCEncryptionType, + bss_description, &(bss_description->bssId), FALSE, TRUE, + eSIR_TX_RX, 0, 0, NULL, 0))) { + smsLog(mac, LOGE, FL("Set context for unicast fail")); + csrRoamSubstateChange(mac, eCSR_ROAM_SUBSTATE_NONE, + sme_session_id); + } + /* + * Issue the set Context request to LIM to establish the + * Broadcast STA context + */ + csrRoamIssueSetContextReq(mac, sme_session_id, + profile->negotiatedMCEncryptionType, + bss_description, &broadcast_mac, + FALSE, FALSE, eSIR_TX_RX, 0, 0, NULL, 0); + } else if (!session->abortConnection) { + /* Need to wait for supplicant authtication */ + roam_info.fAuthRequired = eANI_BOOLEAN_TRUE; + /* Set the subestate to WaitForKey in case authentiation is needed */ + csrRoamSubstateChange(mac, eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY, + sme_session_id); + + if(profile->bWPSAssociation) + key_timeout_interval = CSR_WAIT_FOR_WPS_KEY_TIMEOUT_PERIOD; + else + key_timeout_interval = CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD; + + /* Save sessionId in case of timeout */ + mac->roam.WaitForKeyTimerInfo.sessionId = sme_session_id; + /* + * This time should be long enough for the rest of the + * process plus setting key + */ + if(!HAL_STATUS_SUCCESS(csrRoamStartWaitForKeyTimer(mac, + key_timeout_interval))) { + /* Reset our state so nothting is blocked */ + smsLog(mac, LOGE, FL("Failed to start pre-auth timer")); + csrRoamSubstateChange(mac, eCSR_ROAM_SUBSTATE_NONE, + sme_session_id); + } + } + + csrRoamFreeConnectedInfo(mac, &session->connectedInfo); + + assoc_info.pBssDesc = bss_description; + assoc_info.pProfile = profile; + + len = pre_auth_rsp->roam_info->nBeaconLength + + pre_auth_rsp->roam_info->nAssocReqLength + + pre_auth_rsp->roam_info->nAssocRspLength; + + if(len) { + session->connectedInfo.pbFrames = vos_mem_malloc(len); + if (session->connectedInfo.pbFrames != NULL ) { + vos_mem_copy(session->connectedInfo.pbFrames, + pre_auth_rsp->roam_info->pbFrames, len); + session->connectedInfo.nAssocReqLength = + pre_auth_rsp->roam_info->nAssocReqLength; + session->connectedInfo.nAssocRspLength = + pre_auth_rsp->roam_info->nAssocRspLength; + session->connectedInfo.nBeaconLength = + pre_auth_rsp->roam_info->nBeaconLength; + + roam_info.nAssocReqLength = pre_auth_rsp->roam_info->nAssocReqLength; + roam_info.nAssocRspLength = pre_auth_rsp->roam_info->nAssocRspLength; + roam_info.nBeaconLength = pre_auth_rsp->roam_info->nBeaconLength; + roam_info.pbFrames = session->connectedInfo.pbFrames; + } + session->connectedInfo.staId = pre_auth_rsp->roam_info->staId; + roam_info.staId = pre_auth_rsp->roam_info->staId; + roam_info.ucastSig = pre_auth_rsp->roam_info->ucastSig; + roam_info.bcastSig = pre_auth_rsp->roam_info->bcastSig; + roam_info.maxRateFlags = pre_auth_rsp->roam_info->maxRateFlags; + } + + roam_info.statusCode = eSIR_SME_SUCCESS; + roam_info.reasonCode = eSIR_SME_SUCCESS; + roam_info.pBssDesc = bss_description; + + vos_mem_copy(&roam_info.bssid, &bss_description->bssId, + sizeof(tCsrBssid)); + + mac->roam.roamSession[sme_session_id].connectState = + eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + + sme_QosCsrEventInd(mac, sme_session_id, + SME_QOS_CSR_HANDOFF_ASSOC_REQ, NULL); + sme_QosCsrEventInd(mac, sme_session_id, SME_QOS_CSR_REASSOC_REQ, NULL); + sme_QosCsrEventInd(mac, sme_session_id, SME_QOS_CSR_HANDOFF_COMPLETE, NULL); + + mac->roam.roamSession[sme_session_id].connectState = + eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED; + sme_QosCsrEventInd(mac, sme_session_id, + SME_QOS_CSR_REASSOC_COMPLETE, &assoc_info); + + + acm_mask = sme_QosGetACMMask(mac, bss_description, NULL); + + session->connectedProfile.acm_mask = acm_mask; + if(session->connectedProfile.modifyProfileFields.uapsd_mask) { + smsLog(mac, LOGE, "uapsd_mask (0x%X) set, request UAPSD now", + session->connectedProfile.modifyProfileFields.uapsd_mask); + pmcStartUapsd(mac, NULL, NULL); + } + session->connectedProfile.dot11Mode = session->bssParams.uCfgDot11Mode; + roam_info.u.pConnectedProfile = &session->connectedProfile; + + if(!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) && + (csrIsConcurrentSessionRunning(mac))) + mac->roam.configParam.doBMPSWorkaround = 1; + + csr_roam_dequeue_preauth_reassoc(mac); + + csrRoamCallCallback(mac, sme_session_id, &roam_info, 0, + eCSR_ROAM_ASSOCIATION_COMPLETION, eCSR_ROAM_RESULT_ASSOCIATED); + + csrResetPMKIDCandidateList(mac, sme_session_id); +#ifdef FEATURE_WLAN_WAPI + csrResetBKIDCandidateList(mac, sme_session_id); +#endif + + if(!CSR_IS_WAIT_FOR_KEY(mac, sme_session_id)) { + smsLog(mac, LOG1, "NO CSR_IS_WAIT_FOR_KEY -> csr_roam_link_up"); + csrRoamLinkUp(mac, session->connectedProfile.bssid); + } + + if (pmcShouldBmpsTimerRun(mac)) { + if(eANI_BOOLEAN_TRUE == roam_info.fAuthRequired) { + mac->pmc.full_power_till_set_key = true; + smsLog(mac, LOG1, + FL("full_power_till_set_key is made true")); + } + + if (pmcStartTrafficTimer(mac, BMPS_TRAFFIC_TIMER_ALLOW_SECURITY_DHCP) + != eHAL_STATUS_SUCCESS) + smsLog(mac, LOGE, FL("Cannot start BMPS Retry timer")); + + smsLog(mac, LOG1, FL("BMPS Retry Timer already running or started")); + } + + vos_mem_free(pre_auth_rsp->roam_info->pbFrames); + vos_mem_free(pre_auth_rsp->roam_info); + vos_mem_free(profile); + vos_mem_free(ies_local); + + return eHAL_STATUS_SUCCESS; +} + + +/** + * csr_roam_preauth_rsp_mbb_processor() -handles + * eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP + * @hal: HAL context + * + * This function invokes preauth reassoc response handler and + * updates CSR with new connection information. + * + */ +void csr_roam_preauth_rsp_mbb_processor(tHalHandle hal, + tpSirFTPreAuthRsp pre_auth_rsp) +{ + tpAniSirGlobal mac = PMAC_STRUCT(hal); + eHalStatus status; + tCsrRoamInfo roam_info; + tpSirBssDescription bss_description = NULL; + tCsrRoamSession *session = NULL; + + mac->ft.ftSmeContext.is_preauth_lfr_mbb = false; + smsLog(mac, LOG1, FL("is_preauth_lfr_mbb %d"), + mac->ft.ftSmeContext.is_preauth_lfr_mbb); + + /* + * When reason is SIR_MBB_DISCONNECTED, cleanup CSR info + * of connected AP. + */ + if (pre_auth_rsp->reason == SIR_MBB_DISCONNECTED) { + /* Dequeue ecsr_perform_preauth_reassoc */ + csr_roam_dequeue_preauth_reassoc(mac); + + vos_mem_zero(&roam_info, sizeof(tCsrRoamInfo)); + csrRoamCallCallback(mac, pre_auth_rsp->smeSessionId, &roam_info, 0, + eCSR_ROAM_FT_REASSOC_FAILED, eSIR_SME_SUCCESS); + + csrRoamComplete(mac, eCsrJoinFailure, NULL); + } + + status = csr_neighbor_roam_preauth_reassoc_rsp_handler(mac, + pre_auth_rsp->status, &bss_description); + if (status != eHAL_STATUS_SUCCESS) { + smsLog(mac, LOGE,FL("Preauth was not processed: %d SessionID: %d"), + status, pre_auth_rsp->smeSessionId); + /* + * Preauth_reassoc is dequeued already in + * csr_neighbor_roam_preauth_reassoc_rsp_handler for error cases. + */ + return; + } + + session = CSR_GET_SESSION(mac, pre_auth_rsp->smeSessionId); + if (session->abortConnection) { + smsLog(mac, LOGE, + FL("Disconnect in progress, stop preauth/reassoc timer")); + vos_timer_stop(&mac->ft.ftSmeContext.pre_auth_reassoc_mbb_timer); + } + + /* + * The below function calls/timers should be invoked only + * if the pre-auth is successful. Also, Preauth_reassoc is dequeued + * already in csr_neighbor_roam_preauth_reassoc_rsp_handler. + */ + if (VOS_STATUS_SUCCESS != (VOS_STATUS)pre_auth_rsp->status) + return; + + mac->ft.ftSmeContext.FTState = eFT_AUTH_COMPLETE; + + /* Save the received response */ + vos_mem_copy((void *)&mac->ft.ftSmeContext.preAuthbssId, + (void *)pre_auth_rsp->preAuthbssId, sizeof(tCsrBssid)); + + + /* + * bss_description is updated in + * csr_neighbor_roam_preauth_reassoc_rsp_handler + */ + if (NULL == bss_description) { + smsLog(mac, LOGE, + FL("bss description is NULL")); + goto DEQ_PREAUTH; + } + + /* Update CSR for new connection */ + status = csr_update_roamed_info_mbb(hal, bss_description, pre_auth_rsp); + /* In success case preauth reassoc is dequeued in + * csr_update_roamed_info_mbb before updating HDD. + */ + if(HAL_STATUS_SUCCESS(status)) + return; + +DEQ_PREAUTH: + csr_roam_dequeue_preauth_reassoc(mac); +} + +/** + * csr_prepare_reassoc_req () - Prepares reassoc request + * @pmac: MAC context + * @session_id: session id + * @pbss_description: bss description + * @preassoc_req: pointer to reassociation request + * + *Return: None + */ +static void csr_prepare_reassoc_req(void* pmac, tANI_U32 session_id, + void* pbss_description, void *preassoc_req) +{ + tDot11fBeaconIEs *ies_local = NULL; + eHalStatus status; + tpAniSirGlobal mac = (tpAniSirGlobal)pmac; + tpSirBssDescription bss_description = (tpSirBssDescription)pbss_description; + tSirSmeJoinReq **reassoc_req = (tSirSmeJoinReq **)preassoc_req; + + /* Get IE's */ + status = csrGetParsedBssDescriptionIEs(mac, bss_description, &ies_local); + if (!HAL_STATUS_SUCCESS(status)) { + smsLog(mac, LOGE, + FL("csrGetParsedBssDescriptionIEs failed")); + return; + } + if(ies_local == NULL) { + smsLog(mac, LOGE, + FL("ies_local is NULL")); + return; + } + + smsLog(mac, LOG1, FL("session_id %d"), session_id); + + status = csr_fill_reassoc_req(mac, session_id, bss_description, + ies_local, reassoc_req); + if (!HAL_STATUS_SUCCESS(status)) { + smsLog(mac, LOGE, + FL("Reassociation request filling failed")); + return; + } + vos_mem_free(ies_local); + smsLog(mac, LOG1, FL("status %d"), status); +} + +/** + * csr_roaming_mbb_callback () - handles mbb callback + * @pmac: MAC context + * @session_id: session id + * @pbss_description: bss description + * @preassoc_req: pointer to reassociation request + * @csr_roam_op_code: callback opcode + * + *Return: None + */ +static void csr_roaming_mbb_callback(void* pmac, tANI_U32 session_id, + void* pbss_description, void *preassoc_req, tANI_U32 csr_roam_op_code) +{ + tpAniSirGlobal mac = (tpAniSirGlobal)pmac; + + smsLog(mac, LOG1, + FL("csr_roam_op_code %d"), csr_roam_op_code); + + switch(csr_roam_op_code) { + case SIR_ROAMING_DEREGISTER_STA: + csrRoamCallCallback(mac, session_id, NULL, 0, + eCSR_ROAM_FT_START, eSIR_SME_SUCCESS); + break; + case SIR_STOP_ROAM_OFFLOAD_SCAN: + csrRoamOffloadScan(mac, ROAM_SCAN_OFFLOAD_STOP, REASON_DISCONNECTED); + break; + case SIR_PREPARE_REASSOC_REQ: + csr_prepare_reassoc_req(pmac, session_id, pbss_description, + preassoc_req); + break; + } +} + +/** + * csr_register_roaming_mbb_callback () - registers roaming callback + * @mac: MAC context + * + *Return: eHAL_STATUS_SUCCESS on success, otherwise failure + */ +eHalStatus csr_register_roaming_mbb_callback(tpAniSirGlobal mac) +{ + eHalStatus status; + + status = sme_AcquireGlobalLock(&mac->sme); + if (eHAL_STATUS_SUCCESS == status) { + mac->sme.roaming_mbb_callback = csr_roaming_mbb_callback; + sme_ReleaseGlobalLock(&mac->sme); + } else + smsLog(mac, LOGE, + FL("sme_AcquireGlobalLock error")); + return status; +} diff --git a/drivers/staging/prima/CORE/SME/src/pmc/pmc.c b/drivers/staging/prima/CORE/SME/src/pmc/pmc.c index f87339e92b2..f5539ff6692 100644 --- a/drivers/staging/prima/CORE/SME/src/pmc/pmc.c +++ b/drivers/staging/prima/CORE/SME/src/pmc/pmc.c @@ -1584,7 +1584,38 @@ void pmcDoDeviceStateUpdateCallbacks (tHalHandle hHal, tPmcState state) eHalStatus pmcRequestEnterWowlState(tHalHandle hHal, tpSirSmeWowlEnterParams wowlEnterParams) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); - pmcLog(pMac, LOG1, FL("Enter. PMC State is %d"),pMac->pmc.pmcState); + tpPESession pSessionEntry; + tANI_U8 peSessionId = 0; + + pSessionEntry = peFindSessionByBssid(pMac, wowlEnterParams->bssId, + &peSessionId); + if (NULL == pSessionEntry) + { + pmcLog(pMac, LOGE, + FL("session does not exist for given BSSId")); + + if (wowlEnterParams != NULL) + vos_mem_free(wowlEnterParams); + + return eHAL_STATUS_FAILURE; + } + + pmcLog(pMac, LOG1, FL("Enter. PMC State is %d"),pMac->pmc.pmcState); + + /* Incase of SAP send command directly */ + if ((pSessionEntry->operMode == BSS_OPERATIONAL_MODE_AP)) + { + if (pmcIssueCommand(hHal, eSmeCommandEnterWowl, wowlEnterParams, + sizeof(tSirSmeWowlEnterParams), FALSE) != eHAL_STATUS_SUCCESS) + { + pmcLog(pMac, LOGE, + FL("PMC: failure to send message eWNI_PMC_ENTER_WOWL_REQ")); + if (wowlEnterParams != NULL) + vos_mem_free(wowlEnterParams); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; + } switch (pMac->pmc.pmcState) { @@ -2069,6 +2100,9 @@ eHalStatus pmcIssueCommand( tpAniSirGlobal pMac, eSmeCommandType cmdType, void * tANI_BOOLEAN pmcProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) { eHalStatus status = eHAL_STATUS_SUCCESS; + tpPESession pSessionEntry; + tANI_U8 peSessionId = 0; + tANI_BOOLEAN fRemoveCmd = eANI_BOOLEAN_TRUE; pmcLog(pMac, LOG1, FL("PMC command is 0x%x"), pCommand->command); do @@ -2255,7 +2289,13 @@ tANI_BOOLEAN pmcProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) case eSmeCommandEnterWowl: { tPmcState origState = pMac->pmc.pmcState; - if( ( BMPS == pMac->pmc.pmcState ) || ( WOWL == pMac->pmc.pmcState ) ) + pSessionEntry = peFindSessionByBssid(pMac, + pCommand->u.pmcCmd.u.enterWowlInfo.bssId, + &peSessionId); + if (( BMPS == pMac->pmc.pmcState ) || + ( WOWL == pMac->pmc.pmcState ) || + ((pSessionEntry != NULL) && + (pSessionEntry->operMode == BSS_OPERATIONAL_MODE_AP))) { pMac->pmc.pmcState = REQUEST_ENTER_WOWL; status = pmcSendMessage(pMac, eWNI_PMC_ENTER_WOWL_REQ, diff --git a/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c b/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c index 406317df43f..e46cd350514 100644 --- a/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c +++ b/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -203,6 +203,7 @@ eHalStatus pmcStart (tHalHandle hHal) pMac->pmc.uapsdSessionRequired = FALSE; pMac->pmc.wowlModeRequired = FALSE; pMac->pmc.wowlExitSrc = eWOWL_EXIT_USER; + pMac->pmc.isAPWOWExit = FALSE; pMac->pmc.bmpsRequestedByHdd = FALSE; pMac->pmc.remainInPowerActiveTillDHCP = FALSE; pMac->pmc.full_power_till_set_key = false; @@ -1239,6 +1240,7 @@ static void pmcProcessResponse( tpAniSirGlobal pMac, tSirSmeRsp *pMsg ) tListElem *pEntry = NULL; tSmeCmd *pCommand = NULL; tANI_BOOLEAN fRemoveCommand = eANI_BOOLEAN_TRUE; + tCsrRoamSession *pSession = NULL; pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK); if(pEntry) @@ -1563,11 +1565,25 @@ static void pmcProcessResponse( tpAniSirGlobal pMac, tSirSmeRsp *pMsg ) break; } - /* Enter BMPS State */ - if (pMsg->statusCode != eSIR_SME_SUCCESS) { - pmcLog(pMac, LOGP, "PMC: response message to request to exit " - "WOWL indicates failure, status %d", pMsg->statusCode); - } + /* Enter BMPS State */ + if (pMsg->statusCode != eSIR_SME_SUCCESS) { + pmcLog(pMac, LOGP, "PMC: response message to request to exit " + "WOWL indicates failure, status %d", pMsg->statusCode); + } + + pSession = CSR_GET_SESSION(pMac, pMsg->sessionId); + if (pSession && pSession->pCurRoamProfile && + CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) + { + pMac->pmc.pmcState = FULL_POWER; + pMac->pmc.isAPWOWExit = TRUE; + break; + } + else + { + pMac->pmc.isAPWOWExit = FALSE; + } + pmcEnterBmpsState(pMac); break; @@ -1779,7 +1795,9 @@ eHalStatus pmcRequestBmps ( /* If DUT exits from WoWL because of wake-up indication then it enters * into WoWL again. Disable WoWL only when user explicitly disables. */ - if(pMac->pmc.wowlModeRequired == FALSE && pMac->pmc.wowlExitSrc == eWOWL_EXIT_WAKEIND) + if(pMac->pmc.wowlModeRequired == FALSE && + pMac->pmc.wowlExitSrc == eWOWL_EXIT_WAKEIND && + !pMac->pmc.isAPWOWExit) { pMac->pmc.wowlModeRequired = TRUE; } @@ -2258,11 +2276,14 @@ eHalStatus pmcWowlAddBcastPattern ( return eHAL_STATUS_FAILURE; } - if( !csrIsConnStateConnected(pMac, sessionId) ) + if (!(CSR_IS_INFRA_AP(pSession->pCurRoamProfile))) { - pmcLog(pMac, LOGE, FL("Cannot add WoWL Pattern session in %d state"), - pSession->connectState); - return eHAL_STATUS_FAILURE; + if( !csrIsConnStateConnected(pMac, sessionId) ) + { + pmcLog(pMac, LOGE, FL("Cannot add WoWL Pattern session in %d state"), + pSession->connectState); + return eHAL_STATUS_FAILURE; + } } vos_mem_copy(pattern->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); @@ -2448,11 +2469,22 @@ eHalStatus pmcEnterWowl ( return eHAL_STATUS_FAILURE; } - /* Check if BMPS is enabled. */ - if (!pMac->pmc.bmpsEnabled) + if ((!(CSR_IS_INFRA_AP(pSession->pCurRoamProfile))) + && !(vos_get_concurrency_mode()& VOS_STA_SAP)) { - pmcLog(pMac, LOGE, "PMC: Cannot enter WoWL. BMPS is disabled"); - return eHAL_STATUS_PMC_DISABLED; + /* Check if BMPS is enabled. */ + if (!pMac->pmc.bmpsEnabled) + { + pmcLog(pMac, LOGE, "PMC: Cannot enter WoWL. BMPS is disabled"); + return eHAL_STATUS_PMC_DISABLED; + } + /* Check that we are associated with single Session. */ + if (!pmcValidateConnectState( pMac )) + { + pmcLog(pMac, LOGE, "PMC: Cannot enable WOWL. STA not associated " + "with an Access Point in Infra Mode with single active session"); + return eHAL_STATUS_FAILURE; + } } /* Check if WoWL is enabled. */ @@ -2462,14 +2494,6 @@ eHalStatus pmcEnterWowl ( return eHAL_STATUS_PMC_DISABLED; } - /* Check that we are associated with single Session. */ - if (!pmcValidateConnectState( pMac )) - { - pmcLog(pMac, LOGE, "PMC: Cannot enable WOWL. STA not associated " - "with an Access Point in Infra Mode with single active session"); - return eHAL_STATUS_FAILURE; - } - /* Is there a pending UAPSD request? HDD should have triggered QoS module to do the necessary cleanup before triggring WOWL*/ if(pMac->pmc.uapsdSessionRequired) diff --git a/drivers/staging/prima/CORE/SME/src/pmc/pmcLogDump.c b/drivers/staging/prima/CORE/SME/src/pmc/pmcLogDump.c index c8c222fc717..ed9e32b8533 100644 --- a/drivers/staging/prima/CORE/SME/src/pmc/pmcLogDump.c +++ b/drivers/staging/prima/CORE/SME/src/pmc/pmcLogDump.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -85,6 +85,7 @@ dump_pmc_state( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3 p += log_sprintf( pMac,p, " PMC: RequestFullPowerPending = %d\n", pMac->pmc.requestFullPowerPending); p += log_sprintf( pMac,p, " PMC: UapsdSessionRequired = %d\n", pMac->pmc.uapsdSessionRequired); p += log_sprintf( pMac,p, " PMC: wowlModeRequired = %d\n\n", pMac->pmc.wowlModeRequired); + p += log_sprintf( pMac,p, " PMC: isAPWOWExit = %d\n\n", pMac->pmc.isAPWOWExit); pmcLog(pMac, LOGW, "\n%s", ptr); diff --git a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c index 05d20d2eae3..5ca51dc7cea 100644 --- a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c +++ b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c @@ -73,6 +73,7 @@ #include "sapApi.h" #include "macTrace.h" #include "vos_utils.h" +#include "limSession.h" extern tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); @@ -803,6 +804,79 @@ eHalStatus sme_process_set_max_tx_power(tpAniSirGlobal pMac, return eHAL_STATUS_SUCCESS; } +/** + * sme_process_set_max_tx_power_per_band() - Set the Maximum Transmit Power + * specific to band dynamically + * @mac_ctx: mac context + * @command: cmd param containing band, and power in db + * + * Set the maximum transmit power dynamically per band + * + * Return: eHalStatus + */ +eHalStatus sme_process_set_max_tx_power_per_band(tpAniSirGlobal mac_ctx, + tSmeCmd *command) +{ + vos_msg_t msg; + tMaxTxPowerPerBandParams *max_tx_params_per_band; + + max_tx_params_per_band = + vos_mem_malloc(sizeof(*max_tx_params_per_band)); + if (max_tx_params_per_band == NULL) { + smsLog(mac_ctx, LOGE, + FL("fail to allocate memory")); + return eHAL_STATUS_FAILURE; + } + + max_tx_params_per_band->bandInfo = + command->u.set_tx_max_pwr_per_band.band; + max_tx_params_per_band->power = + command->u.set_tx_max_pwr_per_band.power; + + msg.type = WDA_SET_MAX_TX_POWER_PER_BAND_REQ; + msg.reserved = 0; + msg.bodyptr = max_tx_params_per_band; + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) { + smsLog(mac_ctx, LOGE, + FL("Unable to post message to WDA")); + vos_mem_free(max_tx_params_per_band); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; +} + + +/** + * sme_process_update_channel_list() - Update channel list + * @mac_ctx: mac context + * @command: cmd param containing band, and power in db + * + * Return: eHalStatus + */ +eHalStatus sme_process_update_channel_list(tpAniSirGlobal mac_ctx, + tSmeCmd *command) +{ + vos_msg_t msg; + + msg.type = WDA_UPDATE_CHAN_LIST_REQ; + msg.reserved = 0; + msg.bodyptr = command->u.chan_list; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_TX_WDA_MSG, NO_SESSION, msg.type)); + + if (VOS_STATUS_SUCCESS != + vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) { + smsLog(mac_ctx, LOGE, + FL("Unable to post message to WDA")); + vos_mem_free(command->u.chan_list); + return eHAL_STATUS_FAILURE; + } + return eHAL_STATUS_SUCCESS; +} + static void smeProcessNanReq(tpAniSirGlobal pMac, tSmeCmd *pCommand ) { tSirMsgQ msgQ; @@ -1087,6 +1161,32 @@ sme_process_cmd: } pMac->max_power_cmd_pending = false; break; + case eSmeCommandSetMaxTxPowerPerBand: + csrLLUnlock(&pMac->sme.smeCmdActiveList); + sme_process_set_max_tx_power_per_band(pMac, + pCommand); + /* We need to re-run the command */ + fContinue = eANI_BOOLEAN_TRUE; + /* No Rsp expected, free cmd from active list */ + if (csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK)) { + csrReleaseCommand(pMac, pCommand); + } + pMac->max_power_cmd_pending = false; + break; + + case eSmeCommandUpdateChannelList: + csrLLUnlock(&pMac->sme.smeCmdActiveList); + sme_process_update_channel_list(pMac, pCommand); + if (csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, + &pCommand->Link, LL_ACCESS_LOCK)) { + csrReleaseCommand(pMac, pCommand); + } + smsLog(pMac, LOG1, + FL("eSmeCommandUpdateChannelList processed")); + fContinue = eANI_BOOLEAN_TRUE; + break; + #ifdef FEATURE_OEM_DATA_SUPPORT case eSmeCommandOemDataReq: csrLLUnlock(&pMac->sme.smeCmdActiveList); @@ -1437,6 +1537,7 @@ eHalStatus sme_Open(tHalHandle hHal) #if defined WLAN_FEATURE_VOWIFI_11R sme_FTOpen(pMac); #endif + sme_p2pOpen(pMac); smeTraceInit(pMac); sme_register_debug_callback(); @@ -1671,6 +1772,9 @@ eHalStatus sme_UpdateConfig(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams) pMac->fDeferIMPSTime = pSmeConfigParams->fDeferIMPSTime; pMac->fBtcEnableIndTimerVal = pSmeConfigParams->fBtcEnableIndTimerVal; + pMac->sta_auth_retries_for_code17 = + pSmeConfigParams->csrConfig.sta_auth_retries_for_code17; + return status; } @@ -2481,12 +2585,16 @@ eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg) smsLog( pMac, LOG1, FL("SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4")); sme_RequestFullPower(hHal, NULL, NULL, eSME_REASON_OTHER); pMac->isCoexScoIndSet = 1; + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_FALSE; + pMac->scan.fCancelIdleScan = eANI_BOOLEAN_TRUE; } else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4) { smsLog( pMac, LOG1, FL("SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4")); pMac->isCoexScoIndSet = 0; sme_RequestBmps(hHal, NULL, NULL); + pMac->scan.fRestartIdleScan = eANI_BOOLEAN_TRUE; + pMac->scan.fCancelIdleScan = eANI_BOOLEAN_FALSE; } status = btcHandleCoexInd((void *)pMac, pMsg->bodyptr); @@ -3720,7 +3828,13 @@ eHalStatus sme_RoamDisconnect(tHalHandle hHal, tANI_U8 sessionId, eCsrRoamDiscon { if( CSR_IS_SESSION_VALID( pMac, sessionId ) ) { - status = csrRoamDisconnect( pMac, sessionId, reason ); + /* + * Indicate csr of disconnect so that + * in progress connection, scan for ssid and preauth + * can be aborted + */ + csr_abortConnection(pMac, sessionId); + status = csrRoamDisconnect(pMac, sessionId, reason); } else { @@ -5212,7 +5326,6 @@ eHalStatus sme_RoamSetKey(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamSetKey *pS smsLog(pMac, LOGE, FL("Invalid key length %d"), pSetKey->keyLength); return eHAL_STATUS_FAILURE; } - status = sme_AcquireGlobalLock( &pMac->sme ); if ( HAL_STATUS_SUCCESS( status ) ) { @@ -5240,6 +5353,15 @@ eHalStatus sme_RoamSetKey(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamSetKey *pS if(CSR_IS_INFRA_AP(&pSession->connectedProfile)) { +#ifdef SAP_AUTH_OFFLOAD + if (pMac->sap_auth_offload_sec_type) + { + smsLog(pMac, LOGE, + FL("No set key is required in sap auth offload enable")); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_SUCCESS; + } +#endif if(pSetKey->keyDirection == eSIR_TX_DEFAULT) { if ( ( eCSR_ENCRYPT_TYPE_WEP40 == pSetKey->encType ) || @@ -9168,7 +9290,7 @@ eHalStatus sme_8023MulticastList (tHalHandle hHal, tANI_U8 sessionId, tpSirRcvFl if(pSession == NULL ) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Unable to find " + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, "%s: Unable to find " "the right session", __func__); return eHAL_STATUS_FAILURE; } @@ -9625,51 +9747,61 @@ eHalStatus sme_SetMaxTxPower(tHalHandle hHal, tSirMacAddr bssid, return (status); } -/* --------------------------------------------------------------------------- - - \fn sme_SetMaxTxPowerPerBand - - \brief Set the Maximum Transmit Power specific to band dynamically. - Note: this setting will not persist over reboots. - - \param band - \param power to set in dB - \- return eHalStatus - - ----------------------------------------------------------------------------*/ -eHalStatus sme_SetMaxTxPowerPerBand(eCsrBand band, v_S7_t dB) +/** + * sme_SetMaxTxPowerPerBand() - Set the Maximum Transmit Power + * specific to band dynamically + * @band: Band for which power needs to be applied + * @dB: power to set in dB + * @hal: HAL handle + * + * Set the maximum transmit power dynamically per band + * + * Return: eHalStatus + */ +eHalStatus sme_SetMaxTxPowerPerBand(eCsrBand band, v_S7_t dB, + tHalHandle hal) { vos_msg_t msg; - tpMaxTxPowerPerBandParams pMaxTxPowerPerBandParams = NULL; + eHalStatus status; + tSmeCmd *set_max_tx_pwr_per_band; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); - pMaxTxPowerPerBandParams = vos_mem_malloc(sizeof(tMaxTxPowerPerBandParams)); - if (NULL == pMaxTxPowerPerBandParams) - { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, - "%s:Not able to allocate memory for pMaxTxPowerPerBandParams", - __func__); - return eHAL_STATUS_FAILURE; - } + if (mac_ctx->max_power_cmd_pending) + { + smsLog(mac_ctx, LOG1, + FL("set max tx power already in progress")); + return eHAL_STATUS_RESOURCES; + } - pMaxTxPowerPerBandParams->power = dB; - pMaxTxPowerPerBandParams->bandInfo = band; + smsLog(mac_ctx, LOG1, + FL("band : %d power %d dB"), + band, dB); - msg.type = WDA_SET_MAX_TX_POWER_PER_BAND_REQ; - msg.reserved = 0; - msg.bodyptr = pMaxTxPowerPerBandParams; + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_TX_WDA_MSG, NO_SESSION, msg.type)); - MTRACE(vos_trace(VOS_MODULE_ID_SME, - TRACE_CODE_SME_TX_WDA_MSG, NO_SESSION, msg.type)); - if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) - { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, - "%s:Not able to post WDA_SET_MAX_TX_POWER_PER_BAND_REQ", - __func__); - vos_mem_free(pMaxTxPowerPerBandParams); - return eHAL_STATUS_FAILURE; + status = sme_AcquireGlobalLock(&mac_ctx->sme); + if (HAL_STATUS_SUCCESS(status)) { + set_max_tx_pwr_per_band = csrGetCommandBuffer(mac_ctx); + if (set_max_tx_pwr_per_band) { + set_max_tx_pwr_per_band->command = eSmeCommandSetMaxTxPowerPerBand; + set_max_tx_pwr_per_band->u.set_tx_max_pwr_per_band.band = band; + set_max_tx_pwr_per_band->u.set_tx_max_pwr_per_band.power = dB; + mac_ctx->max_power_cmd_pending = true; + status = csrQueueSmeCommand(mac_ctx, set_max_tx_pwr_per_band, + eANI_BOOLEAN_TRUE); + if (!HAL_STATUS_SUCCESS(status)) { + smsLog(mac_ctx, LOGE, FL("fail to send msg status = %d"), status); + csrReleaseCommand(mac_ctx, set_max_tx_pwr_per_band); + mac_ctx->max_power_cmd_pending = false; + } + } else { + smsLog(mac_ctx, LOGE, FL("can not obtain a common buffer")); + status = eHAL_STATUS_RESOURCES; + } + sme_ReleaseGlobalLock(&mac_ctx->sme); } - - return eHAL_STATUS_SUCCESS; + return status; } /* --------------------------------------------------------------------------- @@ -14416,96 +14548,545 @@ eHalStatus sme_get_nud_debug_stats(tHalHandle hHal, return VOS_STATUS_SUCCESS; } -eHalStatus sme_test_con_alive(tHalHandle hHal) + +#ifdef SAP_AUTH_OFFLOAD +/** + * sme_set_sap_auth_offload() enable/disable Software AP Auth Offload + * @hHal: hal layer handler + * @sap_auth_offload_info: the information of Software AP Auth offload + * + * This function provide enable/disable Software AP authenticaiton offload + * feature on target firmware + * + * Return: Return eHalStatus. + */ +eHalStatus sme_set_sap_auth_offload(tHalHandle hHal, + struct tSirSapOffloadInfo *sap_auth_offload_info) { - vos_msg_t wdaMsg = {0}; + vos_msg_t vosMessage; + struct tSirSapOffloadInfo *sme_sap_auth_offload_info; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); - wdaMsg.type = WDA_TRIGGER_ADD_BA_REQ; - wdaMsg.bodyptr = NULL; - wdaMsg.reserved = 0; + pMac->sap_auth_offload_sec_type = + sap_auth_offload_info->sap_auth_offload_sec_type; + pMac->sap_auth_offload = sap_auth_offload_info->sap_auth_offload_enable; - if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_WDA, &wdaMsg)) - return VOS_STATUS_E_FAILURE; + sme_sap_auth_offload_info = + vos_mem_malloc(sizeof(*sme_sap_auth_offload_info)); - return VOS_STATUS_SUCCESS; + if (!sme_sap_auth_offload_info) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WDA_SET_SAP_AUTH_OFL", + __func__); + return eHAL_STATUS_E_MALLOC_FAILED; + } + vos_mem_copy(sme_sap_auth_offload_info, sap_auth_offload_info, + sizeof(*sap_auth_offload_info)); + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) + { + /* serialize the req through MC thread */ + vosMessage.type = WDA_SET_SAP_AUTH_OFL; + vosMessage.bodyptr = sme_sap_auth_offload_info; + + if (!VOS_IS_STATUS_SUCCESS( + vos_mq_post_message(VOS_MODULE_ID_WDA, &vosMessage))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to post WDA_SET_SAP_AUTH_OFL to WDA!", + __func__); + vos_mem_free(sme_sap_auth_offload_info); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + else + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: sme_AcquireGlobalLock error!", + __func__); + vos_mem_free(sme_sap_auth_offload_info); + status = eHAL_STATUS_FAILURE; + } + + return (status); } +#endif +#ifdef DHCP_SERVER_OFFLOAD +/** + * sme_set_dhcp_srv_offload() - sme api to set dhcp server offload info + * @hal: handle to hal + * @dhcp_srv_info: pointer to dhcp server info + * + * Return: eHalStatus + * eHAL_STATUS_SUCCESS - success or else failure code + */ +eHalStatus sme_set_dhcp_srv_offload(tHalHandle hal, + sir_dhcp_srv_offload_info_t *dhcp_srv_info) +{ + vos_msg_t vos_msg; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + sir_dhcp_srv_offload_info_t *dhcp_serv_info = NULL; + + dhcp_serv_info = + vos_mem_malloc(sizeof(*dhcp_serv_info)); + if (NULL == dhcp_serv_info) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to alloc memory"); + return VOS_STATUS_E_NOMEM; + } + + vos_mem_copy(dhcp_serv_info, dhcp_srv_info, + sizeof(*dhcp_serv_info)); + + dhcp_serv_info->bssidx = peFindBssIdxFromSmeSessionId(mac, dhcp_srv_info->bssidx); + status = sme_AcquireGlobalLock(&mac->sme); + if (eHAL_STATUS_SUCCESS == status) { + /* serialize the req through MC thread */ + vos_msg.type = WDA_SET_DHCP_SERVER_OFFLOAD_REQ; + vos_msg.bodyptr = dhcp_serv_info; + + if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message + (VOS_MODULE_ID_WDA, &vos_msg))) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to post WDA_SET_DHCP_SERVER_OFFLOAD_REQ to WDA!", + __func__); + vos_mem_free(dhcp_serv_info); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + } else { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: sme_AcquireGlobalLock error!", + __func__); + vos_mem_free(dhcp_serv_info); + } + + return status; +} +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +/** + * sme_set_mdns_offload() - sme API to set mdns offload enable/disable + * @hal: handle to hal pointer + * @mdns_info: pointer to mdns offload info + * + * Return - eHalStatus + */ +eHalStatus sme_set_mdns_offload(tHalHandle hal, + sir_mdns_offload_info_t *mdns_info) +{ + vos_msg_t vos_msg; + sir_mdns_offload_info_t *mdns_offload; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + + mdns_offload = vos_mem_malloc(sizeof(*mdns_offload)); + + if (!mdns_offload) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WDA_SET_MDNS_OFFLOAD_CMD", + __func__); + return eHAL_STATUS_E_MALLOC_FAILED; + } -eHalStatus sme_get_con_alive(tHalHandle hHal, - pgetConStatusParams conStatusParams) + vos_mem_copy(mdns_offload, mdns_info, sizeof(*mdns_offload)); + mdns_offload->bss_idx = + peFindBssIdxFromSmeSessionId(mac, mdns_info->bss_idx); + status = sme_AcquireGlobalLock(&mac->sme); + if (eHAL_STATUS_SUCCESS == status) { + /* serialize the req through MC thread */ + vos_msg.type = WDA_SET_MDNS_OFFLOAD_CMD; + vos_msg.bodyptr = mdns_offload; + + if (!VOS_IS_STATUS_SUCCESS( + vos_mq_post_message(VOS_MODULE_ID_WDA, + &vos_msg))) { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to post WDA_SET_MDNS_OFFLOAD_CMD to WDA!", + __func__); + vos_mem_free(mdns_offload); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + } else { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: sme_AcquireGlobalLock error!", + __func__); + vos_mem_free(mdns_offload); + } + + return (status); +} + +/** + * sme_set_mdns_fqdn() - SME API to set mDNS Fqdn info + * @hal: hal handle + * @mdns_fqdn: mDNS Fqdn info struct + * + * Return - return eHalStatus + */ +eHalStatus sme_set_mdns_fqdn(tHalHandle hal, + sir_mdns_fqdn_info_t *mdns_fqdn) { - vos_msg_t wdaMsg = {0}; - pgetConStatusParams statusParams; - VOS_STATUS vosStatus; + vos_msg_t vos_msg; + sir_mdns_fqdn_info_t *fqdn_info; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); - statusParams = vos_mem_malloc(sizeof(getConStatusParams)); - if (NULL == statusParams) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, - FL("Memory allocation failure")); - return VOS_STATUS_E_NOMEM; - } + fqdn_info = vos_mem_malloc(sizeof(*fqdn_info)); - vos_mem_copy(statusParams, conStatusParams, sizeof(getConStatusParams)); - wdaMsg.type = WDA_GET_CON_STATUS; - wdaMsg.bodyptr = statusParams; - wdaMsg.reserved = 0; + if (!fqdn_info) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WDA_SET_MDNS_FQDN_CMD", + __func__); + return eHAL_STATUS_E_MALLOC_FAILED; + } - vosStatus = vos_mq_post_message(VOS_MQ_ID_WDA, &wdaMsg); - if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, - FL(" Not able to post message")); - vos_mem_free(statusParams); - return VOS_STATUS_E_FAILURE; - } + vos_mem_copy(fqdn_info, mdns_fqdn, sizeof(*fqdn_info)); + fqdn_info->bss_idx = peFindBssIdxFromSmeSessionId(mac, mdns_fqdn->bss_idx); + status = sme_AcquireGlobalLock(&mac->sme); + if (eHAL_STATUS_SUCCESS == status) { + /* serialize the req through MC thread */ + vos_msg.type = WDA_SET_MDNS_FQDN_CMD; + vos_msg.bodyptr = fqdn_info; + + if (!VOS_IS_STATUS_SUCCESS( + vos_mq_post_message(VOS_MODULE_ID_WDA, + &vos_msg))) { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to post WDA_SET_MDNS_FQDN_CMD to WDA!", + __func__); + vos_mem_free(fqdn_info); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + } else { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: sme_AcquireGlobalLock error!", + __func__); + vos_mem_free(fqdn_info); + } - return VOS_STATUS_SUCCESS; + return (status); } -eHalStatus sme_test_con_delba(tHalHandle hHal, uint8_t sta_id, - uint8_t session_id) +/** + * sme_set_mdns_resp() - SME API to set mDNS response info + * @hal: hal handle + * @mdns_resp : mDNS response info struct + * + * Return - eHalStatus + */ +eHalStatus sme_set_mdns_resp(tHalHandle hal, + sir_mdns_resp_info_t *mdns_resp) { - tpSmeDelBAPeerInd msg; - tpAniSirGlobal pMac = PMAC_STRUCT(hHal); - tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, session_id); - eHalStatus status = eHAL_STATUS_FAILURE; + vos_msg_t vos_msg; + sir_mdns_resp_info_t *resp_info; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); - if (!CSR_IS_SESSION_VALID(pMac, session_id)) - { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, - FL("Session is invalid")); - return status; - } + resp_info = vos_mem_malloc(sizeof(*resp_info)); - if (!pMac->lim.test_status_bainfo.tx_aggr) - { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, - FL("BA session not established")); - return status; - } + if (!resp_info) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for WDA_SET_MDNS_RESPONSE_CMD", + __func__); + return eHAL_STATUS_E_MALLOC_FAILED; + } - if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&pMac->sme)) - { - msg = vos_mem_malloc(sizeof(tSmeDelBAPeerInd)); - if (NULL == msg) - { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + vos_mem_copy(resp_info, mdns_resp, sizeof(*resp_info)); + resp_info->bss_idx = peFindBssIdxFromSmeSessionId(mac, mdns_resp->bss_idx); + status = sme_AcquireGlobalLock(&mac->sme); + if (eHAL_STATUS_SUCCESS == status) { + /* serialize the req through MC thread */ + vos_msg.type = WDA_SET_MDNS_RESPONSE_CMD; + vos_msg.bodyptr = resp_info; + + if (!VOS_IS_STATUS_SUCCESS( + vos_mq_post_message(VOS_MODULE_ID_WDA, + &vos_msg))) { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to post WDA_SET_MDNS_RESPONSE_CMD to WDA!", + __func__); + vos_mem_free(resp_info); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&mac->sme); + } else { + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: sme_AcquireGlobalLock error!", + __func__); + vos_mem_free(resp_info); + } + + return (status); +} +#endif /* MDNS_OFFLOAD */ + +/** + * sme_update_hb_threshold() - Set heartbeat Threshold value. + * @hal: HAL pointer + * @cfgId: cfg param id + * @hbThresh: heartbeat threshold value. + * + * Return: Success/Failure + */ +eHalStatus sme_update_hb_threshold(tHalHandle hHal, tANI_U32 cfgId, + tANI_U8 hbThresh, eCsrBand eBand) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + + if ((hbThresh < WNI_CFG_HEART_BEAT_THRESHOLD_STAMIN) || + (hbThresh > WNI_CFG_HEART_BEAT_THRESHOLD_STAMAX)) { + smsLog(pMac, LOGE, FL("invalid heartbeat threshold %hhu"), hbThresh); + return eHAL_STATUS_FAILURE; + } + + if(eBand == eCSR_BAND_24) + pMac->roam.configParam.HeartbeatThresh24 = hbThresh; + + if(eBand == eCSR_BAND_5G) + pMac->roam.configParam.HeartbeatThresh50 = hbThresh; + + status = sme_update_cfg_int_param(hHal, WNI_CFG_HEART_BEAT_THRESHOLD); + if (eHAL_STATUS_SUCCESS != status) { + smsLog(pMac, LOGE, FL("WLAN set heartbeat threshold FAILED")); + status = eHAL_STATUS_FAILURE; + } + return status; +} + +#ifdef WLAN_FEATURE_APFIND +/** + * sme_apfind_set_cmd() - set apfind configuration to firmware + * @input: pointer to apfind request data. + * + * SME API to set APFIND configuations to firmware. + * + * Return: VOS_STATUS. + */ +VOS_STATUS sme_apfind_set_cmd(struct sme_ap_find_request_req *input) +{ + vos_msg_t msg; + struct hal_apfind_request *data; + size_t data_len; + + data_len = sizeof(struct hal_apfind_request) + input->request_data_len; + data = vos_mem_malloc(data_len); + + if (data == NULL) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("Memory allocation failure")); - return VOS_STATUS_E_NOMEM; - } + return VOS_STATUS_E_NOMEM; + } - msg->staIdx = sta_id; - msg->baTID = pMac->lim.test_status_bainfo.tid; - vos_mem_copy(msg->bssId, pSession->connectedProfile.bssid, - sizeof(tSirMacAddr)); - msg->baDirection = eBA_INITIATOR; + vos_mem_zero(data, data_len); + data->request_data_len = input->request_data_len; + if (input->request_data_len) { + vos_mem_copy(data->request_data, + input->request_data, input->request_data_len); + } - msg->mesgType = eWNI_SME_DEL_TEST_BA; - msg->mesgLen = sizeof(tSmeDelBAPeerInd); + msg.type = WDA_APFIND_SET_CMD; + msg.reserved = 0; + msg.bodyptr = data; - status = palSendMBMessage(pMac->hHdd, msg); + if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + FL("Not able to post WDA_APFIND_SET_CMD message to WDA")); + vos_mem_free(data); + return VOS_STATUS_E_FAILURE; + } - sme_ReleaseGlobalLock(&pMac->sme); - } + return VOS_STATUS_SUCCESS; +} - return status; +#endif /* WLAN_FEATURE_APFIND */ + +/** + * sme_capture_tsf_req() - send tsf capture request to firmware + * @hHal: hal handle. + * @cap_tsf_params: capture tsf request params. + * + * Return: hal status. + */ +eHalStatus sme_capture_tsf_req(tHalHandle hHal, tSirCapTsfParams cap_tsf_params) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + tpSirCapTsfParams tsf_params = NULL; + VOS_STATUS vos_status; + tCsrRoamSession *pSession; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_TX_HDD_CAP_TSF_REQ, NO_SESSION, 0)); + if (eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock(&pMac->sme))) + { + pSession = CSR_GET_SESSION(pMac, cap_tsf_params.session_id); + if (!pSession) + { + smsLog(pMac, LOGE, FL("session %d not found"), + cap_tsf_params.bss_idx); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + tsf_params = (tpSirCapTsfParams) + vos_mem_malloc(sizeof(*tsf_params)); + + if (NULL == tsf_params) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for sme_capture_tsf_req", + __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy(&tsf_params->bssid, &pSession->connectedProfile.bssid, + sizeof(tsf_params->bssid)); + + tsf_params->tsf_rsp_cb_func = cap_tsf_params.tsf_rsp_cb_func; + tsf_params->tsf_rsp_cb_ctx = cap_tsf_params.tsf_rsp_cb_ctx; + + /* serialize the req through MC thread */ + /* TODO: check if callback is required */ + vosMessage.bodyptr = tsf_params; + vosMessage.type = eWNI_SME_CAP_TSF_REQ; + + vos_status = vos_mq_post_message(VOS_MQ_ID_PE, &vosMessage); + + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post Set TM Level MSG fail", __func__); + vos_mem_free(tsf_params); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return(status); +} + +eHalStatus sme_del_sta_ba_session_req(tHalHandle hHal, + tDelBaParams sta_del_params) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + ptDelBaParams del_params = NULL; + VOS_STATUS vos_status; + tCsrRoamSession *pSession; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_DEL_STA_BA_SESSION_REQ, NO_SESSION, 0)); + if (eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock(&pMac->sme))) + { + pSession = CSR_GET_SESSION(pMac, sta_del_params.session_id); + if (!pSession) + { + smsLog(pMac, LOGE, FL("session not found")); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + + del_params = (ptDelBaParams) vos_mem_malloc(sizeof(*del_params)); + + if (NULL == del_params) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for sme_del_sta_ba_session_req", __func__); + sme_ReleaseGlobalLock( &pMac->sme ); + return eHAL_STATUS_FAILURE; + } + vos_mem_copy(&del_params->session_id, &pSession->sessionId, + sizeof(del_params->session_id)); + + vosMessage.bodyptr = del_params; + vosMessage.type = eWNI_SME_DEL_BA_SES_REQ; + + vos_status = vos_mq_post_message(VOS_MQ_ID_PE, &vosMessage); + + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post Set TM Level MSG fail", __func__); + vos_mem_free(del_params); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return(status); +} + +/** + * sme_get_tsf_req() - send tsf get request to firmware + * @hHal: hal handle. + * @cap_tsf_params: capture tsf request params. + * + * Return: hal status. + */ +eHalStatus sme_get_tsf_req(tHalHandle hHal, tSirCapTsfParams cap_tsf_params) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + vos_msg_t vosMessage; + tpSirCapTsfParams tsf_params = NULL; + VOS_STATUS vosStatus; + tCsrRoamSession *pSession; + + MTRACE(vos_trace(VOS_MODULE_ID_SME, + TRACE_CODE_SME_TX_HDD_GET_TSF_REQ, NO_SESSION, 0)); + + if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme))) + { + pSession = CSR_GET_SESSION(pMac, cap_tsf_params.session_id); + + if (!pSession) + { + smsLog(pMac, LOGE, FL("session %d not found"), + cap_tsf_params.bss_idx); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + + tsf_params = (tpSirCapTsfParams) + vos_mem_malloc(sizeof(*tsf_params)); + if (NULL == tsf_params) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for sme_capture_tsf_req", + __func__); + sme_ReleaseGlobalLock(&pMac->sme); + return eHAL_STATUS_FAILURE; + } + + vos_mem_copy(&tsf_params->bssid, &pSession->connectedProfile.bssid, + sizeof(tsf_params->bssid)); + tsf_params->tsf_rsp_cb_func = cap_tsf_params.tsf_rsp_cb_func; + tsf_params->tsf_rsp_cb_ctx = cap_tsf_params.tsf_rsp_cb_ctx; + + /* serialize the req through MC thread */ + /* TODO: check if callback is required */ + vosMessage.bodyptr = tsf_params; + vosMessage.type = eWNI_SME_GET_TSF_REQ; + + vosStatus = vos_mq_post_message(VOS_MQ_ID_PE, &vosMessage); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Post Set TM Level MSG fail", __func__); + vos_mem_free(tsf_params); + status = eHAL_STATUS_FAILURE; + } + sme_ReleaseGlobalLock(&pMac->sme); + } + return(status); } diff --git a/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c b/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c index 4d988afb85f..fef98d3dd8c 100644 --- a/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c +++ b/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -41,6 +41,11 @@ #include <csrNeighborRoam.h> #include "vos_utils.h" +#ifdef WLAN_FEATURE_LFR_MBB +#include "csr_roam_mbb.h" +#endif + + /*-------------------------------------------------------------------------- Initialize the FT context. ------------------------------------------------------------------------*/ @@ -60,6 +65,18 @@ void sme_FTOpen(tHalHandle hHal) return; } vos_reset_roam_timer_log(); + +#ifdef WLAN_FEATURE_LFR_MBB + status = vos_timer_init(&pMac->ft.ftSmeContext.pre_auth_reassoc_mbb_timer, + VOS_TIMER_TYPE_SW, + csr_preauth_reassoc_mbb_timer_callback, + (void *)pMac); + + if (eHAL_STATUS_SUCCESS != status) { + smsLog(pMac, LOGE, FL("pre_auth_reassoc_mbb_timer allocation failed")); + return; + } +#endif } /*-------------------------------------------------------------------------- @@ -71,6 +88,10 @@ void sme_FTClose(tHalHandle hHal) //Clear the FT Context. sme_FTReset(hHal); vos_timer_destroy(&pMac->ft.ftSmeContext.preAuthReassocIntvlTimer); + +#ifdef WLAN_FEATURE_LFR_MBB + vos_timer_destroy(&pMac->ft.ftSmeContext.pre_auth_reassoc_mbb_timer); +#endif } void sme_SetFTPreAuthState(tHalHandle hHal, v_BOOL_t state) @@ -116,6 +137,9 @@ void sme_SetFTIEs( tHalHandle hHal, tANI_U8 sessionId, const tANI_U8 *ft_ies, { case eFT_START_READY: case eFT_AUTH_REQ_READY: +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG + smsLog( pMac, LOG1, FL("ft_ies_length: %d"), ft_ies_length); +#endif if ((pMac->ft.ftSmeContext.auth_ft_ies) && (pMac->ft.ftSmeContext.auth_ft_ies_length)) { @@ -123,7 +147,7 @@ void sme_SetFTIEs( tHalHandle hHal, tANI_U8 sessionId, const tANI_U8 *ft_ies, vos_mem_free(pMac->ft.ftSmeContext.auth_ft_ies); pMac->ft.ftSmeContext.auth_ft_ies_length = 0; } - + ft_ies_length = VOS_MIN(ft_ies_length, MAX_FTIE_SIZE); // Save the FT IEs pMac->ft.ftSmeContext.auth_ft_ies = vos_mem_malloc(ft_ies_length); if ( NULL == pMac->ft.ftSmeContext.auth_ft_ies ) @@ -138,9 +162,6 @@ void sme_SetFTIEs( tHalHandle hHal, tANI_U8 sessionId, const tANI_U8 *ft_ies, ft_ies,ft_ies_length); pMac->ft.ftSmeContext.FTState = eFT_AUTH_REQ_READY; -#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG - smsLog( pMac, LOG1, "ft_ies_length=%d", ft_ies_length); -#endif break; case eFT_AUTH_COMPLETE: diff --git a/drivers/staging/prima/CORE/SVC/inc/wlan_btc_svc.h b/drivers/staging/prima/CORE/SVC/inc/wlan_btc_svc.h index 104de94301c..a1f27be514a 100644 --- a/drivers/staging/prima/CORE/SVC/inc/wlan_btc_svc.h +++ b/drivers/staging/prima/CORE/SVC/inc/wlan_btc_svc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -35,5 +35,6 @@ void send_btc_nlink_msg (int type, int dest_pid); int btc_activate_service(void *pAdapter); +void btc_deactivate_service(void); #endif diff --git a/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c b/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c index bc38829c660..f64605d81f2 100644 --- a/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c +++ b/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -213,6 +213,21 @@ int btc_activate_service(void *pAdapter) nl_srv_register(WLAN_NL_MSG_BTC, btc_msg_callback); return 0; } + +/**--------------------------------------------------------------------------- + + \brief btc_deactivate_service() - Deactivate btc message handler + + This function unregisters a handler to receive netlink messages + addressed to WLAN_NL_MSG_BTC from user space. + + \return - none + --------------------------------------------------------------------------*/ +void btc_deactivate_service() +{ + //unregister the msg handler for msgs addressed to ANI_NL_MSG_BTC + nl_srv_unregister(WLAN_NL_MSG_BTC, btc_msg_callback); +} /* * Callback function invoked by Netlink service for all netlink * messages (from user space) addressed to WLAN_NL_MSG_BTC diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c index ebdb096da29..a27f48aa954 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c +++ b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c @@ -28,7 +28,7 @@ * * * This file was automatically generated by 'framesc' - * Tue Jul 4 11:19:48 2017 from the following file(s): + * Wed Jul 12 16:02:49 2017 from the following file(s): * * dot11f.frms * @@ -469,7 +469,7 @@ static tANI_U32 GetContainerIesLen(tpAniSirGlobal pCtx, { const tIEDefn *pIe, *pIeFirst; tANI_U8 *pBufRemaining = pBuf; - tANI_U8 len = 0; + tANI_U32 len = 0; (void)pCtx; @@ -5640,6 +5640,47 @@ tANI_U32 dot11fUnpackIeWscReassocRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 #define SigIeWscReassocRes ( 0x008f ) +tANI_U32 dot11fUnpackIehs20vendor_ie(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEhs20vendor_ie *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + tANI_U8 tmp78__; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + tmp78__ = *pBuf; + pBuf += 1; + ielen -= 1; + pDst->dgaf_dis = tmp78__ >> 0 & 0x1; + pDst->hs_id_present = tmp78__ >> 1 & 0x3; + pDst->reserved = tmp78__ >> 3 & 0x1; + pDst->release_num = tmp78__ >> 4 & 0xf; + if ( ! ielen ) + { + return 0U; + } + else + { + switch (pDst->hs_id_present) + { + case 1: + framesntohs(pCtx, &pDst->hs_id.pps_mo.pps_mo_id, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + break; + case 2: + framesntohs(pCtx, &pDst->hs_id.anqp_domain.anqp_domain_id, pBuf, 0); + pBuf += 2; + ielen -= (tANI_U8)2; + break; + } + } + (void)pCtx; + return status; +} /* End dot11fUnpackIehs20vendor_ie. */ + +#define SigIehs20vendor_ie ( 0x0090 ) + + static const tFFDefn FFS_AddBAReq[] = { { "Category", offsetof(tDot11fAddBAReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, { "Action", offsetof(tDot11fAddBAReq, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, @@ -6297,6 +6338,7 @@ tANI_U32 dot11fUnpackAddTSResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 {offsetof(tDot11fAssocRequest, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 3, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, {offsetof(tDot11fAssocRequest, OperatingMode), offsetof(tDot11fIEOperatingMode, present), 0, "OperatingMode" , 0, 3, 3, SigIeOperatingMode, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OPERATINGMODE, 0, }, {offsetof(tDot11fAssocRequest, QosMapSet), offsetof(tDot11fIEQosMapSet, present), 0, "QosMapSet" , 0, 2, 62, SigIeQosMapSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSMAPSET, 0, }, + {offsetof(tDot11fAssocRequest, hs20vendor_ie), offsetof(tDot11fIEhs20vendor_ie, present), 0, "hs20vendor_ie" , 0, 7, 9, SigIehs20vendor_ie, {80, 111, 154, 16, 0}, 4, DOT11F_EID_HS20VENDOR_IE, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; tANI_U32 dot11fUnpackAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fAssocRequest *pFrm) @@ -6889,6 +6931,27 @@ tANI_U32 dot11fUnpackAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("num_dscp_exceptions: %d.\n"), pFrm->QosMapSet.num_dscp_exceptions); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->QosMapSet.dscp_exceptions, pFrm->QosMapSet.num_dscp_exceptions); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } } # endif // DOT11F_DUMP_FRAMES return status; @@ -8501,6 +8564,7 @@ tANI_U32 dot11fUnpackAuthentication(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 {offsetof(tDot11fBeacon, OperatingMode), offsetof(tDot11fIEOperatingMode, present), 0, "OperatingMode" , 0, 3, 3, SigIeOperatingMode, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OPERATINGMODE, 0, }, {offsetof(tDot11fBeacon, WiderBWChanSwitchAnn), offsetof(tDot11fIEWiderBWChanSwitchAnn, present), 0, "WiderBWChanSwitchAnn" , 0, 5, 5, SigIeWiderBWChanSwitchAnn, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WIDERBWCHANSWITCHANN, 0, }, {offsetof(tDot11fBeacon, OBSSScanParameters), offsetof(tDot11fIEOBSSScanParameters, present), 0, "OBSSScanParameters" , 0, 16, 16, SigIeOBSSScanParameters, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OBSSSCANPARAMETERS, 0, }, + {offsetof(tDot11fBeacon, hs20vendor_ie), offsetof(tDot11fIEhs20vendor_ie, present), 0, "hs20vendor_ie" , 0, 7, 9, SigIehs20vendor_ie, {80, 111, 154, 16, 0}, 4, DOT11F_EID_HS20VENDOR_IE, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; tANI_U32 dot11fUnpackBeacon(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fBeacon *pFrm) @@ -9551,6 +9615,27 @@ tANI_U32 dot11fUnpackBeacon(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, t FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } } # endif // DOT11F_DUMP_FRAMES return status; @@ -9687,6 +9772,7 @@ tANI_U32 dot11fUnpackBeacon1(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, {offsetof(tDot11fBeacon2, OperatingMode), offsetof(tDot11fIEOperatingMode, present), 0, "OperatingMode" , 0, 3, 3, SigIeOperatingMode, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OPERATINGMODE, 0, }, {offsetof(tDot11fBeacon2, WiderBWChanSwitchAnn), offsetof(tDot11fIEWiderBWChanSwitchAnn, present), 0, "WiderBWChanSwitchAnn" , 0, 5, 5, SigIeWiderBWChanSwitchAnn, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WIDERBWCHANSWITCHANN, 0, }, {offsetof(tDot11fBeacon2, OBSSScanParameters), offsetof(tDot11fIEOBSSScanParameters, present), 0, "OBSSScanParameters" , 0, 16, 16, SigIeOBSSScanParameters, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OBSSSCANPARAMETERS, 0, }, + {offsetof(tDot11fBeacon2, hs20vendor_ie), offsetof(tDot11fIEhs20vendor_ie, present), 0, "hs20vendor_ie" , 0, 7, 9, SigIehs20vendor_ie, {80, 111, 154, 16, 0}, 4, DOT11F_EID_HS20VENDOR_IE, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; tANI_U32 dot11fUnpackBeacon2(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fBeacon2 *pFrm) @@ -10585,6 +10671,27 @@ tANI_U32 dot11fUnpackBeacon2(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } } # endif // DOT11F_DUMP_FRAMES return status; @@ -10641,6 +10748,7 @@ tANI_U32 dot11fUnpackBeacon2(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, {offsetof(tDot11fBeaconIEs, OperatingMode), offsetof(tDot11fIEOperatingMode, present), 0, "OperatingMode" , 0, 3, 3, SigIeOperatingMode, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OPERATINGMODE, 0, }, {offsetof(tDot11fBeaconIEs, WiderBWChanSwitchAnn), offsetof(tDot11fIEWiderBWChanSwitchAnn, present), 0, "WiderBWChanSwitchAnn" , 0, 5, 5, SigIeWiderBWChanSwitchAnn, {0, 0, 0, 0, 0}, 0, DOT11F_EID_WIDERBWCHANSWITCHANN, 0, }, {offsetof(tDot11fBeaconIEs, OBSSScanParameters), offsetof(tDot11fIEOBSSScanParameters, present), 0, "OBSSScanParameters" , 0, 16, 16, SigIeOBSSScanParameters, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OBSSSCANPARAMETERS, 0, }, + {offsetof(tDot11fBeaconIEs, hs20vendor_ie), offsetof(tDot11fIEhs20vendor_ie, present), 0, "hs20vendor_ie" , 0, 7, 9, SigIehs20vendor_ie, {80, 111, 154, 16, 0}, 4, DOT11F_EID_HS20VENDOR_IE, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; tANI_U32 dot11fUnpackBeaconIEs(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fBeaconIEs *pFrm) @@ -11799,6 +11907,27 @@ tANI_U32 dot11fUnpackBeaconIEs(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } } # endif // DOT11F_DUMP_FRAMES return status; @@ -14132,6 +14261,7 @@ tANI_U32 dot11fUnpackProbeRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n {offsetof(tDot11fProbeResponse, VHTExtBssLoad), offsetof(tDot11fIEVHTExtBssLoad, present), 0, "VHTExtBssLoad" , 0, 7, 7, SigIeVHTExtBssLoad, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTEXTBSSLOAD, 0, }, {offsetof(tDot11fProbeResponse, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 3, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, {offsetof(tDot11fProbeResponse, OBSSScanParameters), offsetof(tDot11fIEOBSSScanParameters, present), 0, "OBSSScanParameters" , 0, 16, 16, SigIeOBSSScanParameters, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OBSSSCANPARAMETERS, 0, }, + {offsetof(tDot11fProbeResponse, hs20vendor_ie), offsetof(tDot11fIEhs20vendor_ie, present), 0, "hs20vendor_ie" , 0, 7, 9, SigIehs20vendor_ie, {80, 111, 154, 16, 0}, 4, DOT11F_EID_HS20VENDOR_IE, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; tANI_U32 dot11fUnpackProbeResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fProbeResponse *pFrm) @@ -15236,6 +15366,27 @@ tANI_U32 dot11fUnpackProbeResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } } # endif // DOT11F_DUMP_FRAMES return status; @@ -15703,6 +15854,7 @@ tANI_U32 dot11fUnpackRadioMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, {offsetof(tDot11fReAssocRequest, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 3, 11, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, {offsetof(tDot11fReAssocRequest, OperatingMode), offsetof(tDot11fIEOperatingMode, present), 0, "OperatingMode" , 0, 3, 3, SigIeOperatingMode, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OPERATINGMODE, 0, }, {offsetof(tDot11fReAssocRequest, QosMapSet), offsetof(tDot11fIEQosMapSet, present), 0, "QosMapSet" , 0, 2, 62, SigIeQosMapSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSMAPSET, 0, }, + {offsetof(tDot11fReAssocRequest, hs20vendor_ie), offsetof(tDot11fIEhs20vendor_ie, present), 0, "hs20vendor_ie" , 0, 7, 9, SigIehs20vendor_ie, {80, 111, 154, 16, 0}, 4, DOT11F_EID_HS20VENDOR_IE, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; tANI_U32 dot11fUnpackReAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fReAssocRequest *pFrm) @@ -16682,6 +16834,27 @@ tANI_U32 dot11fUnpackReAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_dscp_exceptions: %d.\n"), pFrm->QosMapSet.num_dscp_exceptions); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->QosMapSet.dscp_exceptions, pFrm->QosMapSet.num_dscp_exceptions); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } } # endif // DOT11F_DUMP_FRAMES return status; @@ -20714,6 +20887,9 @@ static tANI_U32 UnpackCore(tpAniSirGlobal pCtx, case SigIeWscReassocRes: status |= dot11fUnpackIeWscReassocRes(pCtx, pBufRemaining, len, ( tDot11fIEWscReassocRes* )(pFrm + pIe->offset + sizeof(tDot11fIEWscReassocRes)*countOffset) ); break; + case SigIehs20vendor_ie: + status |= dot11fUnpackIehs20vendor_ie(pCtx, pBufRemaining, len, ( tDot11fIEhs20vendor_ie* )(pFrm + pIe->offset + sizeof(tDot11fIEhs20vendor_ie)*countOffset) ); + break; default: FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR" ": I don't know about the IE signature %d" @@ -21840,6 +22016,31 @@ tANI_U32 dot11fGetPackedIEWscReassocRes(tpAniSirGlobal pCtx, tDot11fIEWscReassoc return status; } /* End dot11fGetPackedIEWscReassocRes. */ +tANI_U32 dot11fGetPackedIEhs20vendor_ie(tpAniSirGlobal pCtx, tDot11fIEhs20vendor_ie *pIe, tANI_U32 *pnNeeded) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void)pCtx; + while ( pIe->present ) + { + *pnNeeded += 1; + if ( pIe->hs_id_present ) + { + switch (pIe->hs_id_present) + { + case 1: + *pnNeeded += 2; + break; + case 2: + *pnNeeded += 2; + break; + } + } + else break; + break; + } + return status; +} /* End dot11fGetPackedIEhs20vendor_ie. */ + tANI_U32 dot11fGetPackedAddBAReqSize(tpAniSirGlobal pCtx, tDot11fAddBAReq *pFrm, tANI_U32 *pnNeeded) { tANI_U32 status = 0; @@ -23044,6 +23245,10 @@ static tANI_U32 GetPackedSizeCore(tpAniSirGlobal pCtx, offset = sizeof(tDot11fIEWscReassocRes); status |= dot11fGetPackedIEWscReassocRes(pCtx, ( tDot11fIEWscReassocRes* )(pFrm + pIe->offset + offset * i ), pnNeeded); break; + case SigIehs20vendor_ie: + offset = sizeof(tDot11fIEhs20vendor_ie); + status |= dot11fGetPackedIEhs20vendor_ie(pCtx, ( tDot11fIEhs20vendor_ie* )(pFrm + pIe->offset + offset * i ), pnNeeded); + break; default: FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR-- I don" "'t know about the IE signature %d; this is most l" @@ -23296,13 +23501,13 @@ void dot11fPackFfAddBAParameterSet(tpAniSirGlobal pCtx, tDot11fFfAddBAParameterSet *pSrc, tANI_U8 *pBuf) { - tANI_U16 tmp78__; - tmp78__ = 0U; - tmp78__ |= ( pSrc->amsduSupported << 0 ); - tmp78__ |= ( pSrc->policy << 1 ); - tmp78__ |= ( pSrc->tid << 2 ); - tmp78__ |= ( pSrc->bufferSize << 6 ); - frameshtons(pCtx, pBuf, tmp78__, 0); + tANI_U16 tmp79__; + tmp79__ = 0U; + tmp79__ |= ( pSrc->amsduSupported << 0 ); + tmp79__ |= ( pSrc->policy << 1 ); + tmp79__ |= ( pSrc->tid << 2 ); + tmp79__ |= ( pSrc->bufferSize << 6 ); + frameshtons(pCtx, pBuf, tmp79__, 0); (void)pCtx; } /* End dot11fPackFfAddBAParameterSet. */ @@ -23326,11 +23531,11 @@ void dot11fPackFfBAStartingSequenceControl(tpAniSirGlobal pCtx, tDot11fFfBAStartingSequenceControl *pSrc, tANI_U8 *pBuf) { - tANI_U16 tmp79__; - tmp79__ = 0U; - tmp79__ |= ( pSrc->fragNumber << 0 ); - tmp79__ |= ( pSrc->ssn << 4 ); - frameshtons(pCtx, pBuf, tmp79__, 0); + tANI_U16 tmp80__; + tmp80__ = 0U; + tmp80__ |= ( pSrc->fragNumber << 0 ); + tmp80__ |= ( pSrc->ssn << 4 ); + frameshtons(pCtx, pBuf, tmp80__, 0); (void)pCtx; } /* End dot11fPackFfBAStartingSequenceControl. */ @@ -23354,25 +23559,25 @@ void dot11fPackFfCapabilities(tpAniSirGlobal pCtx, tDot11fFfCapabilities *pSrc, tANI_U8 *pBuf) { - tANI_U16 tmp80__; - tmp80__ = 0U; - tmp80__ |= ( pSrc->ess << 0 ); - tmp80__ |= ( pSrc->ibss << 1 ); - tmp80__ |= ( pSrc->cfPollable << 2 ); - tmp80__ |= ( pSrc->cfPollReq << 3 ); - tmp80__ |= ( pSrc->privacy << 4 ); - tmp80__ |= ( pSrc->shortPreamble << 5 ); - tmp80__ |= ( pSrc->pbcc << 6 ); - tmp80__ |= ( pSrc->channelAgility << 7 ); - tmp80__ |= ( pSrc->spectrumMgt << 8 ); - tmp80__ |= ( pSrc->qos << 9 ); - tmp80__ |= ( pSrc->shortSlotTime << 10 ); - tmp80__ |= ( pSrc->apsd << 11 ); - tmp80__ |= ( pSrc->rrm << 12 ); - tmp80__ |= ( pSrc->dsssOfdm << 13 ); - tmp80__ |= ( pSrc->delayedBA << 14 ); - tmp80__ |= ( pSrc->immediateBA << 15 ); - frameshtons(pCtx, pBuf, tmp80__, 0); + tANI_U16 tmp81__; + tmp81__ = 0U; + tmp81__ |= ( pSrc->ess << 0 ); + tmp81__ |= ( pSrc->ibss << 1 ); + tmp81__ |= ( pSrc->cfPollable << 2 ); + tmp81__ |= ( pSrc->cfPollReq << 3 ); + tmp81__ |= ( pSrc->privacy << 4 ); + tmp81__ |= ( pSrc->shortPreamble << 5 ); + tmp81__ |= ( pSrc->pbcc << 6 ); + tmp81__ |= ( pSrc->channelAgility << 7 ); + tmp81__ |= ( pSrc->spectrumMgt << 8 ); + tmp81__ |= ( pSrc->qos << 9 ); + tmp81__ |= ( pSrc->shortSlotTime << 10 ); + tmp81__ |= ( pSrc->apsd << 11 ); + tmp81__ |= ( pSrc->rrm << 12 ); + tmp81__ |= ( pSrc->dsssOfdm << 13 ); + tmp81__ |= ( pSrc->delayedBA << 14 ); + tmp81__ |= ( pSrc->immediateBA << 15 ); + frameshtons(pCtx, pBuf, tmp81__, 0); (void)pCtx; } /* End dot11fPackFfCapabilities. */ @@ -23396,12 +23601,12 @@ void dot11fPackFfDelBAParameterSet(tpAniSirGlobal pCtx, tDot11fFfDelBAParameterSet *pSrc, tANI_U8 *pBuf) { - tANI_U16 tmp81__; - tmp81__ = 0U; - tmp81__ |= ( pSrc->reserved << 0 ); - tmp81__ |= ( pSrc->initiator << 11 ); - tmp81__ |= ( pSrc->tid << 12 ); - frameshtons(pCtx, pBuf, tmp81__, 0); + tANI_U16 tmp82__; + tmp82__ = 0U; + tmp82__ |= ( pSrc->reserved << 0 ); + tmp82__ |= ( pSrc->initiator << 11 ); + tmp82__ |= ( pSrc->tid << 12 ); + frameshtons(pCtx, pBuf, tmp82__, 0); (void)pCtx; } /* End dot11fPackFfDelBAParameterSet. */ @@ -23457,13 +23662,13 @@ void dot11fPackFfOperatingMode(tpAniSirGlobal pCtx, tDot11fFfOperatingMode *pSrc, tANI_U8 *pBuf) { - tANI_U8 tmp82__; - tmp82__ = 0U; - tmp82__ |= ( pSrc->chanWidth << 0 ); - tmp82__ |= ( pSrc->reserved << 2 ); - tmp82__ |= ( pSrc->rxNSS << 4 ); - tmp82__ |= ( pSrc->rxNSSType << 7 ); - *pBuf = tmp82__; + tANI_U8 tmp83__; + tmp83__ = 0U; + tmp83__ |= ( pSrc->chanWidth << 0 ); + tmp83__ |= ( pSrc->reserved << 2 ); + tmp83__ |= ( pSrc->rxNSS << 4 ); + tmp83__ |= ( pSrc->rxNSSType << 7 ); + *pBuf = tmp83__; (void)pCtx; } /* End dot11fPackFfOperatingMode. */ @@ -23551,12 +23756,12 @@ void dot11fPackFfSMPowerModeSet(tpAniSirGlobal pCtx, tDot11fFfSMPowerModeSet *pSrc, tANI_U8 *pBuf) { - tANI_U8 tmp83__; - tmp83__ = 0U; - tmp83__ |= ( pSrc->PowerSave_En << 0 ); - tmp83__ |= ( pSrc->Mode << 1 ); - tmp83__ |= ( pSrc->reserved << 2 ); - *pBuf = tmp83__; + tANI_U8 tmp84__; + tmp84__ = 0U; + tmp84__ |= ( pSrc->PowerSave_En << 0 ); + tmp84__ |= ( pSrc->Mode << 1 ); + tmp84__ |= ( pSrc->reserved << 2 ); + *pBuf = tmp84__; (void)pCtx; } /* End dot11fPackFfSMPowerModeSet. */ @@ -23596,19 +23801,19 @@ void dot11fPackFfTSInfo(tpAniSirGlobal pCtx, tDot11fFfTSInfo *pSrc, tANI_U8 *pBuf) { - tANI_U32 tmp84__; - tmp84__ = 0U; - tmp84__ |= ( pSrc->traffic_type << 0 ); - tmp84__ |= ( pSrc->tsid << 1 ); - tmp84__ |= ( pSrc->direction << 5 ); - tmp84__ |= ( pSrc->access_policy << 7 ); - tmp84__ |= ( pSrc->aggregation << 9 ); - tmp84__ |= ( pSrc->psb << 10 ); - tmp84__ |= ( pSrc->user_priority << 11 ); - tmp84__ |= ( pSrc->tsinfo_ack_pol << 14 ); - tmp84__ |= ( pSrc->schedule << 16 ); - tmp84__ |= ( pSrc->unused << 17 ); - frameshtonl(pCtx, pBuf, tmp84__, 0); + tANI_U32 tmp85__; + tmp85__ = 0U; + tmp85__ |= ( pSrc->traffic_type << 0 ); + tmp85__ |= ( pSrc->tsid << 1 ); + tmp85__ |= ( pSrc->direction << 5 ); + tmp85__ |= ( pSrc->access_policy << 7 ); + tmp85__ |= ( pSrc->aggregation << 9 ); + tmp85__ |= ( pSrc->psb << 10 ); + tmp85__ |= ( pSrc->user_priority << 11 ); + tmp85__ |= ( pSrc->tsinfo_ack_pol << 14 ); + tmp85__ |= ( pSrc->schedule << 16 ); + tmp85__ |= ( pSrc->unused << 17 ); + frameshtonl(pCtx, pBuf, tmp85__, 0); (void)pCtx; } /* End dot11fPackFfTSInfo. */ @@ -23729,7 +23934,7 @@ tANI_U32 dot11fPackTlvVersion2(tpAniSirGlobal pCtx, tANI_U8* pTlvLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp85__; + tANI_U8 tmp86__; nNeeded += 3; if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; while ( pSrc->present ) @@ -23738,10 +23943,10 @@ tANI_U32 dot11fPackTlvVersion2(tpAniSirGlobal pCtx, pBuf += 1; *pnConsumed += 1; pTlvLen = pBuf; pBuf += 1; *pnConsumed += 1; - tmp85__ = 0U; - tmp85__ |= ( pSrc->minor << 0 ); - tmp85__ |= ( pSrc->major << 4 ); - *pBuf = tmp85__; + tmp86__ = 0U; + tmp86__ |= ( pSrc->minor << 0 ); + tmp86__ |= ( pSrc->major << 4 ); + *pBuf = tmp86__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -24950,7 +25155,7 @@ tANI_U32 dot11fPackTlvVersion(tpAniSirGlobal pCtx, tANI_U8* pTlvLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp86__; + tANI_U8 tmp87__; nNeeded += 5; if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; while ( pSrc->present ) @@ -24959,10 +25164,10 @@ tANI_U32 dot11fPackTlvVersion(tpAniSirGlobal pCtx, pBuf += 2; *pnConsumed += 2; pTlvLen = pBuf; pBuf += 2; *pnConsumed += 2; - tmp86__ = 0U; - tmp86__ |= ( pSrc->minor << 0 ); - tmp86__ |= ( pSrc->major << 4 ); - *pBuf = tmp86__; + tmp87__ = 0U; + tmp87__ |= ( pSrc->minor << 0 ); + tmp87__ |= ( pSrc->major << 4 ); + *pBuf = tmp87__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -25168,7 +25373,7 @@ tANI_U32 dot11fPackIeGTK(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U16 tmp87__; + tANI_U16 tmp88__; nNeeded += (pSrc->num_key + 11); while ( pSrc->present ) { @@ -25177,10 +25382,10 @@ tANI_U32 dot11fPackIeGTK(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp87__ = 0U; - tmp87__ |= ( pSrc->keyId << 0 ); - tmp87__ |= ( pSrc->reserved << 2 ); - frameshtons(pCtx, pBuf, tmp87__, 0); + tmp88__ = 0U; + tmp88__ |= ( pSrc->keyId << 0 ); + tmp88__ |= ( pSrc->reserved << 2 ); + frameshtons(pCtx, pBuf, tmp88__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -25476,7 +25681,6 @@ tANI_U32 dot11fPackIePropEDCAParams(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp88__; tANI_U8 tmp89__; tANI_U8 tmp90__; tANI_U8 tmp91__; @@ -25484,6 +25688,7 @@ tANI_U32 dot11fPackIePropEDCAParams(tpAniSirGlobal pCtx, tANI_U8 tmp93__; tANI_U8 tmp94__; tANI_U8 tmp95__; + tANI_U8 tmp96__; nNeeded += 18; while ( pSrc->present ) { @@ -25498,79 +25703,79 @@ tANI_U32 dot11fPackIePropEDCAParams(tpAniSirGlobal pCtx, *pBuf = pSrc->reserved; *pnConsumed += 1; pBuf += 1; - tmp88__ = 0U; - tmp88__ |= ( pSrc->acbe_aifsn << 0 ); - tmp88__ |= ( pSrc->acbe_acm << 4 ); - tmp88__ |= ( pSrc->acbe_aci << 5 ); - tmp88__ |= ( pSrc->unused1 << 7 ); - *pBuf = tmp88__; - *pnConsumed += 1; - pBuf += 1; - nBuf -= 1 ; tmp89__ = 0U; - tmp89__ |= ( pSrc->acbe_min << 0 ); - tmp89__ |= ( pSrc->acbe_max << 4 ); + tmp89__ |= ( pSrc->acbe_aifsn << 0 ); + tmp89__ |= ( pSrc->acbe_acm << 4 ); + tmp89__ |= ( pSrc->acbe_aci << 5 ); + tmp89__ |= ( pSrc->unused1 << 7 ); *pBuf = tmp89__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); - *pnConsumed += 2; - pBuf += 2; tmp90__ = 0U; - tmp90__ |= ( pSrc->acbk_aifsn << 0 ); - tmp90__ |= ( pSrc->acbk_acm << 4 ); - tmp90__ |= ( pSrc->acbk_aci << 5 ); - tmp90__ |= ( pSrc->unused2 << 7 ); + tmp90__ |= ( pSrc->acbe_min << 0 ); + tmp90__ |= ( pSrc->acbe_max << 4 ); *pBuf = tmp90__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; tmp91__ = 0U; - tmp91__ |= ( pSrc->acbk_min << 0 ); - tmp91__ |= ( pSrc->acbk_max << 4 ); + tmp91__ |= ( pSrc->acbk_aifsn << 0 ); + tmp91__ |= ( pSrc->acbk_acm << 4 ); + tmp91__ |= ( pSrc->acbk_aci << 5 ); + tmp91__ |= ( pSrc->unused2 << 7 ); *pBuf = tmp91__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); - *pnConsumed += 2; - pBuf += 2; tmp92__ = 0U; - tmp92__ |= ( pSrc->acvi_aifsn << 0 ); - tmp92__ |= ( pSrc->acvi_acm << 4 ); - tmp92__ |= ( pSrc->acvi_aci << 5 ); - tmp92__ |= ( pSrc->unused3 << 7 ); + tmp92__ |= ( pSrc->acbk_min << 0 ); + tmp92__ |= ( pSrc->acbk_max << 4 ); *pBuf = tmp92__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; tmp93__ = 0U; - tmp93__ |= ( pSrc->acvi_min << 0 ); - tmp93__ |= ( pSrc->acvi_max << 4 ); + tmp93__ |= ( pSrc->acvi_aifsn << 0 ); + tmp93__ |= ( pSrc->acvi_acm << 4 ); + tmp93__ |= ( pSrc->acvi_aci << 5 ); + tmp93__ |= ( pSrc->unused3 << 7 ); *pBuf = tmp93__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); - *pnConsumed += 2; - pBuf += 2; tmp94__ = 0U; - tmp94__ |= ( pSrc->acvo_aifsn << 0 ); - tmp94__ |= ( pSrc->acvo_acm << 4 ); - tmp94__ |= ( pSrc->acvo_aci << 5 ); - tmp94__ |= ( pSrc->unused4 << 7 ); + tmp94__ |= ( pSrc->acvi_min << 0 ); + tmp94__ |= ( pSrc->acvi_max << 4 ); *pBuf = tmp94__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; tmp95__ = 0U; - tmp95__ |= ( pSrc->acvo_min << 0 ); - tmp95__ |= ( pSrc->acvo_max << 4 ); + tmp95__ |= ( pSrc->acvo_aifsn << 0 ); + tmp95__ |= ( pSrc->acvo_acm << 4 ); + tmp95__ |= ( pSrc->acvo_aci << 5 ); + tmp95__ |= ( pSrc->unused4 << 7 ); *pBuf = tmp95__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + tmp96__ = 0U; + tmp96__ |= ( pSrc->acvo_min << 0 ); + tmp96__ |= ( pSrc->acvo_max << 4 ); + *pBuf = tmp96__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; frameshtons(pCtx, pBuf, pSrc->acvo_txoplimit, 0); *pnConsumed += 2; // fieldsEndFlag = 1 @@ -25755,7 +25960,7 @@ tANI_U32 dot11fPackIeTaurus(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U16 tmp96__; + tANI_U16 tmp97__; nNeeded += 6; while ( pSrc->present ) { @@ -25770,10 +25975,10 @@ tANI_U32 dot11fPackIeTaurus(tpAniSirGlobal pCtx, frameshtons(pCtx, pBuf, pSrc->baPolicy, 0); *pnConsumed += 2; pBuf += 2; - tmp96__ = 0U; - tmp96__ |= ( pSrc->baBufferSize << 0 ); - tmp96__ |= ( pSrc->rsvd << 12 ); - frameshtons(pCtx, pBuf, tmp96__, 0); + tmp97__ = 0U; + tmp97__ |= ( pSrc->baBufferSize << 0 ); + tmp97__ |= ( pSrc->rsvd << 12 ); + frameshtons(pCtx, pBuf, tmp97__, 0); *pnConsumed += 2; // fieldsEndFlag = 1 nBuf -= 2 ; @@ -26192,11 +26397,11 @@ tANI_U32 dot11fPackIeRRMEnabledCap(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp97__; tANI_U8 tmp98__; tANI_U8 tmp99__; tANI_U8 tmp100__; tANI_U8 tmp101__; + tANI_U8 tmp102__; nNeeded += 5; while ( pSrc->present ) { @@ -26205,58 +26410,58 @@ tANI_U32 dot11fPackIeRRMEnabledCap(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp97__ = 0U; - tmp97__ |= ( pSrc->LinkMeasurement << 0 ); - tmp97__ |= ( pSrc->NeighborRpt << 1 ); - tmp97__ |= ( pSrc->parallel << 2 ); - tmp97__ |= ( pSrc->repeated << 3 ); - tmp97__ |= ( pSrc->BeaconPassive << 4 ); - tmp97__ |= ( pSrc->BeaconActive << 5 ); - tmp97__ |= ( pSrc->BeaconTable << 6 ); - tmp97__ |= ( pSrc->BeaconRepCond << 7 ); - *pBuf = tmp97__; - *pnConsumed += 1; - pBuf += 1; - nBuf -= 1 ; tmp98__ = 0U; - tmp98__ |= ( pSrc->FrameMeasurement << 0 ); - tmp98__ |= ( pSrc->ChannelLoad << 1 ); - tmp98__ |= ( pSrc->NoiseHistogram << 2 ); - tmp98__ |= ( pSrc->statistics << 3 ); - tmp98__ |= ( pSrc->LCIMeasurement << 4 ); - tmp98__ |= ( pSrc->LCIAzimuth << 5 ); - tmp98__ |= ( pSrc->TCMCapability << 6 ); - tmp98__ |= ( pSrc->triggeredTCM << 7 ); + tmp98__ |= ( pSrc->LinkMeasurement << 0 ); + tmp98__ |= ( pSrc->NeighborRpt << 1 ); + tmp98__ |= ( pSrc->parallel << 2 ); + tmp98__ |= ( pSrc->repeated << 3 ); + tmp98__ |= ( pSrc->BeaconPassive << 4 ); + tmp98__ |= ( pSrc->BeaconActive << 5 ); + tmp98__ |= ( pSrc->BeaconTable << 6 ); + tmp98__ |= ( pSrc->BeaconRepCond << 7 ); *pBuf = tmp98__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; tmp99__ = 0U; - tmp99__ |= ( pSrc->APChanReport << 0 ); - tmp99__ |= ( pSrc->RRMMIBEnabled << 1 ); - tmp99__ |= ( pSrc->operatingChanMax << 2 ); - tmp99__ |= ( pSrc->nonOperatinChanMax << 5 ); + tmp99__ |= ( pSrc->FrameMeasurement << 0 ); + tmp99__ |= ( pSrc->ChannelLoad << 1 ); + tmp99__ |= ( pSrc->NoiseHistogram << 2 ); + tmp99__ |= ( pSrc->statistics << 3 ); + tmp99__ |= ( pSrc->LCIMeasurement << 4 ); + tmp99__ |= ( pSrc->LCIAzimuth << 5 ); + tmp99__ |= ( pSrc->TCMCapability << 6 ); + tmp99__ |= ( pSrc->triggeredTCM << 7 ); *pBuf = tmp99__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; tmp100__ = 0U; - tmp100__ |= ( pSrc->MeasurementPilot << 0 ); - tmp100__ |= ( pSrc->MeasurementPilotEnabled << 3 ); - tmp100__ |= ( pSrc->NeighborTSFOffset << 4 ); - tmp100__ |= ( pSrc->RCPIMeasurement << 5 ); - tmp100__ |= ( pSrc->RSNIMeasurement << 6 ); - tmp100__ |= ( pSrc->BssAvgAccessDelay << 7 ); + tmp100__ |= ( pSrc->APChanReport << 0 ); + tmp100__ |= ( pSrc->RRMMIBEnabled << 1 ); + tmp100__ |= ( pSrc->operatingChanMax << 2 ); + tmp100__ |= ( pSrc->nonOperatinChanMax << 5 ); *pBuf = tmp100__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; tmp101__ = 0U; - tmp101__ |= ( pSrc->BSSAvailAdmission << 0 ); - tmp101__ |= ( pSrc->AntennaInformation << 1 ); - tmp101__ |= ( pSrc->reserved << 2 ); + tmp101__ |= ( pSrc->MeasurementPilot << 0 ); + tmp101__ |= ( pSrc->MeasurementPilotEnabled << 3 ); + tmp101__ |= ( pSrc->NeighborTSFOffset << 4 ); + tmp101__ |= ( pSrc->RCPIMeasurement << 5 ); + tmp101__ |= ( pSrc->RSNIMeasurement << 6 ); + tmp101__ |= ( pSrc->BssAvgAccessDelay << 7 ); *pBuf = tmp101__; *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + tmp102__ = 0U; + tmp102__ |= ( pSrc->BSSAvailAdmission << 0 ); + tmp102__ |= ( pSrc->AntennaInformation << 1 ); + tmp102__ |= ( pSrc->reserved << 2 ); + *pBuf = tmp102__; + *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; break; @@ -26338,7 +26543,7 @@ tANI_U32 dot11fPackIeSchedule(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U16 tmp102__; + tANI_U16 tmp103__; nNeeded += 14; while ( pSrc->present ) { @@ -26347,12 +26552,12 @@ tANI_U32 dot11fPackIeSchedule(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp102__ = 0U; - tmp102__ |= ( pSrc->aggregation << 0 ); - tmp102__ |= ( pSrc->tsid << 1 ); - tmp102__ |= ( pSrc->direction << 5 ); - tmp102__ |= ( pSrc->reserved << 7 ); - frameshtons(pCtx, pBuf, tmp102__, 0); + tmp103__ = 0U; + tmp103__ |= ( pSrc->aggregation << 0 ); + tmp103__ |= ( pSrc->tsid << 1 ); + tmp103__ |= ( pSrc->direction << 5 ); + tmp103__ |= ( pSrc->reserved << 7 ); + frameshtons(pCtx, pBuf, tmp103__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -26552,9 +26757,9 @@ tANI_U32 dot11fPackIeTSPEC(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U16 tmp103__; - tANI_U8 tmp104__; - tANI_U16 tmp105__; + tANI_U16 tmp104__; + tANI_U8 tmp105__; + tANI_U16 tmp106__; nNeeded += 55; while ( pSrc->present ) { @@ -26563,30 +26768,30 @@ tANI_U32 dot11fPackIeTSPEC(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp103__ = 0U; - tmp103__ |= ( pSrc->traffic_type << 0 ); - tmp103__ |= ( pSrc->tsid << 1 ); - tmp103__ |= ( pSrc->direction << 5 ); - tmp103__ |= ( pSrc->access_policy << 7 ); - tmp103__ |= ( pSrc->aggregation << 9 ); - tmp103__ |= ( pSrc->psb << 10 ); - tmp103__ |= ( pSrc->user_priority << 11 ); - tmp103__ |= ( pSrc->tsinfo_ack_pol << 14 ); - frameshtons(pCtx, pBuf, tmp103__, 0); + tmp104__ = 0U; + tmp104__ |= ( pSrc->traffic_type << 0 ); + tmp104__ |= ( pSrc->tsid << 1 ); + tmp104__ |= ( pSrc->direction << 5 ); + tmp104__ |= ( pSrc->access_policy << 7 ); + tmp104__ |= ( pSrc->aggregation << 9 ); + tmp104__ |= ( pSrc->psb << 10 ); + tmp104__ |= ( pSrc->user_priority << 11 ); + tmp104__ |= ( pSrc->tsinfo_ack_pol << 14 ); + frameshtons(pCtx, pBuf, tmp104__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; - tmp104__ = 0U; - tmp104__ |= ( pSrc->schedule << 0 ); - tmp104__ |= ( pSrc->unused << 1 ); - *pBuf = tmp104__; + tmp105__ = 0U; + tmp105__ |= ( pSrc->schedule << 0 ); + tmp105__ |= ( pSrc->unused << 1 ); + *pBuf = tmp105__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - tmp105__ = 0U; - tmp105__ |= ( pSrc->size << 0 ); - tmp105__ |= ( pSrc->fixed << 15 ); - frameshtons(pCtx, pBuf, tmp105__, 0); + tmp106__ = 0U; + tmp106__ |= ( pSrc->size << 0 ); + tmp106__ |= ( pSrc->fixed << 15 ); + frameshtons(pCtx, pBuf, tmp106__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -26651,7 +26856,7 @@ tANI_U32 dot11fPackIeWMMSchedule(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U16 tmp106__; + tANI_U16 tmp107__; nNeeded += 15; while ( pSrc->present ) { @@ -26673,12 +26878,12 @@ tANI_U32 dot11fPackIeWMMSchedule(tpAniSirGlobal pCtx, *pBuf = pSrc->version; *pnConsumed += 1; pBuf += 1; - tmp106__ = 0U; - tmp106__ |= ( pSrc->aggregation << 0 ); - tmp106__ |= ( pSrc->tsid << 1 ); - tmp106__ |= ( pSrc->direction << 5 ); - tmp106__ |= ( pSrc->reserved << 7 ); - frameshtons(pCtx, pBuf, tmp106__, 0); + tmp107__ = 0U; + tmp107__ |= ( pSrc->aggregation << 0 ); + tmp107__ |= ( pSrc->tsid << 1 ); + tmp107__ |= ( pSrc->direction << 5 ); + tmp107__ |= ( pSrc->reserved << 7 ); + frameshtons(pCtx, pBuf, tmp107__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -26917,9 +27122,9 @@ tANI_U32 dot11fPackIeWMMTSPEC(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U16 tmp107__; - tANI_U8 tmp108__; - tANI_U16 tmp109__; + tANI_U16 tmp108__; + tANI_U8 tmp109__; + tANI_U16 tmp110__; nNeeded += 38; while ( pSrc->present ) { @@ -26941,30 +27146,30 @@ tANI_U32 dot11fPackIeWMMTSPEC(tpAniSirGlobal pCtx, *pBuf = pSrc->version; *pnConsumed += 1; pBuf += 1; - tmp107__ = 0U; - tmp107__ |= ( pSrc->traffic_type << 0 ); - tmp107__ |= ( pSrc->tsid << 1 ); - tmp107__ |= ( pSrc->direction << 5 ); - tmp107__ |= ( pSrc->access_policy << 7 ); - tmp107__ |= ( pSrc->aggregation << 9 ); - tmp107__ |= ( pSrc->psb << 10 ); - tmp107__ |= ( pSrc->user_priority << 11 ); - tmp107__ |= ( pSrc->tsinfo_ack_pol << 14 ); - frameshtons(pCtx, pBuf, tmp107__, 0); + tmp108__ = 0U; + tmp108__ |= ( pSrc->traffic_type << 0 ); + tmp108__ |= ( pSrc->tsid << 1 ); + tmp108__ |= ( pSrc->direction << 5 ); + tmp108__ |= ( pSrc->access_policy << 7 ); + tmp108__ |= ( pSrc->aggregation << 9 ); + tmp108__ |= ( pSrc->psb << 10 ); + tmp108__ |= ( pSrc->user_priority << 11 ); + tmp108__ |= ( pSrc->tsinfo_ack_pol << 14 ); + frameshtons(pCtx, pBuf, tmp108__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; - tmp108__ = 0U; - tmp108__ |= ( pSrc->tsinfo_rsvd << 0 ); - tmp108__ |= ( pSrc->burst_size_defn << 7 ); - *pBuf = tmp108__; + tmp109__ = 0U; + tmp109__ |= ( pSrc->tsinfo_rsvd << 0 ); + tmp109__ |= ( pSrc->burst_size_defn << 7 ); + *pBuf = tmp109__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - tmp109__ = 0U; - tmp109__ |= ( pSrc->size << 0 ); - tmp109__ |= ( pSrc->fixed << 15 ); - frameshtons(pCtx, pBuf, tmp109__, 0); + tmp110__ = 0U; + tmp110__ |= ( pSrc->size << 0 ); + tmp110__ |= ( pSrc->fixed << 15 ); + frameshtons(pCtx, pBuf, tmp110__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -27274,7 +27479,6 @@ tANI_U32 dot11fPackIeEDCAParamSet(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp110__; tANI_U8 tmp111__; tANI_U8 tmp112__; tANI_U8 tmp113__; @@ -27282,6 +27486,7 @@ tANI_U32 dot11fPackIeEDCAParamSet(tpAniSirGlobal pCtx, tANI_U8 tmp115__; tANI_U8 tmp116__; tANI_U8 tmp117__; + tANI_U8 tmp118__; nNeeded += 18; while ( pSrc->present ) { @@ -27296,79 +27501,79 @@ tANI_U32 dot11fPackIeEDCAParamSet(tpAniSirGlobal pCtx, *pBuf = pSrc->reserved; *pnConsumed += 1; pBuf += 1; - tmp110__ = 0U; - tmp110__ |= ( pSrc->acbe_aifsn << 0 ); - tmp110__ |= ( pSrc->acbe_acm << 4 ); - tmp110__ |= ( pSrc->acbe_aci << 5 ); - tmp110__ |= ( pSrc->unused1 << 7 ); - *pBuf = tmp110__; - *pnConsumed += 1; - pBuf += 1; - nBuf -= 1 ; tmp111__ = 0U; - tmp111__ |= ( pSrc->acbe_acwmin << 0 ); - tmp111__ |= ( pSrc->acbe_acwmax << 4 ); + tmp111__ |= ( pSrc->acbe_aifsn << 0 ); + tmp111__ |= ( pSrc->acbe_acm << 4 ); + tmp111__ |= ( pSrc->acbe_aci << 5 ); + tmp111__ |= ( pSrc->unused1 << 7 ); *pBuf = tmp111__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); - *pnConsumed += 2; - pBuf += 2; tmp112__ = 0U; - tmp112__ |= ( pSrc->acbk_aifsn << 0 ); - tmp112__ |= ( pSrc->acbk_acm << 4 ); - tmp112__ |= ( pSrc->acbk_aci << 5 ); - tmp112__ |= ( pSrc->unused2 << 7 ); + tmp112__ |= ( pSrc->acbe_acwmin << 0 ); + tmp112__ |= ( pSrc->acbe_acwmax << 4 ); *pBuf = tmp112__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; tmp113__ = 0U; - tmp113__ |= ( pSrc->acbk_acwmin << 0 ); - tmp113__ |= ( pSrc->acbk_acwmax << 4 ); + tmp113__ |= ( pSrc->acbk_aifsn << 0 ); + tmp113__ |= ( pSrc->acbk_acm << 4 ); + tmp113__ |= ( pSrc->acbk_aci << 5 ); + tmp113__ |= ( pSrc->unused2 << 7 ); *pBuf = tmp113__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); - *pnConsumed += 2; - pBuf += 2; tmp114__ = 0U; - tmp114__ |= ( pSrc->acvi_aifsn << 0 ); - tmp114__ |= ( pSrc->acvi_acm << 4 ); - tmp114__ |= ( pSrc->acvi_aci << 5 ); - tmp114__ |= ( pSrc->unused3 << 7 ); + tmp114__ |= ( pSrc->acbk_acwmin << 0 ); + tmp114__ |= ( pSrc->acbk_acwmax << 4 ); *pBuf = tmp114__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; tmp115__ = 0U; - tmp115__ |= ( pSrc->acvi_acwmin << 0 ); - tmp115__ |= ( pSrc->acvi_acwmax << 4 ); + tmp115__ |= ( pSrc->acvi_aifsn << 0 ); + tmp115__ |= ( pSrc->acvi_acm << 4 ); + tmp115__ |= ( pSrc->acvi_aci << 5 ); + tmp115__ |= ( pSrc->unused3 << 7 ); *pBuf = tmp115__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); - *pnConsumed += 2; - pBuf += 2; tmp116__ = 0U; - tmp116__ |= ( pSrc->acvo_aifsn << 0 ); - tmp116__ |= ( pSrc->acvo_acm << 4 ); - tmp116__ |= ( pSrc->acvo_aci << 5 ); - tmp116__ |= ( pSrc->unused4 << 7 ); + tmp116__ |= ( pSrc->acvi_acwmin << 0 ); + tmp116__ |= ( pSrc->acvi_acwmax << 4 ); *pBuf = tmp116__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; tmp117__ = 0U; - tmp117__ |= ( pSrc->acvo_acwmin << 0 ); - tmp117__ |= ( pSrc->acvo_acwmax << 4 ); + tmp117__ |= ( pSrc->acvo_aifsn << 0 ); + tmp117__ |= ( pSrc->acvo_acm << 4 ); + tmp117__ |= ( pSrc->acvo_aci << 5 ); + tmp117__ |= ( pSrc->unused4 << 7 ); *pBuf = tmp117__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + tmp118__ = 0U; + tmp118__ |= ( pSrc->acvo_acwmin << 0 ); + tmp118__ |= ( pSrc->acvo_acwmax << 4 ); + *pBuf = tmp118__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; frameshtons(pCtx, pBuf, pSrc->acvo_txoplimit, 0); *pnConsumed += 2; // fieldsEndFlag = 1 @@ -27391,7 +27596,7 @@ tANI_U32 dot11fPackIeERPInfo(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp118__; + tANI_U8 tmp119__; nNeeded += 1; while ( pSrc->present ) { @@ -27400,12 +27605,12 @@ tANI_U32 dot11fPackIeERPInfo(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp118__ = 0U; - tmp118__ |= ( pSrc->non_erp_present << 0 ); - tmp118__ |= ( pSrc->use_prot << 1 ); - tmp118__ |= ( pSrc->barker_preamble << 2 ); - tmp118__ |= ( pSrc->unused << 3 ); - *pBuf = tmp118__; + tmp119__ = 0U; + tmp119__ |= ( pSrc->non_erp_present << 0 ); + tmp119__ |= ( pSrc->use_prot << 1 ); + tmp119__ |= ( pSrc->barker_preamble << 2 ); + tmp119__ |= ( pSrc->unused << 3 ); + *pBuf = tmp119__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -27466,7 +27671,7 @@ tANI_U32 dot11fPackIeESERadMgmtCap(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp119__; + tANI_U8 tmp120__; nNeeded += 2; while ( pSrc->present ) { @@ -27486,10 +27691,10 @@ tANI_U32 dot11fPackIeESERadMgmtCap(tpAniSirGlobal pCtx, *pBuf = pSrc->mgmt_state; *pnConsumed += 1; pBuf += 1; - tmp119__ = 0U; - tmp119__ |= ( pSrc->mbssid_mask << 0 ); - tmp119__ |= ( pSrc->reserved << 3 ); - *pBuf = tmp119__; + tmp120__ = 0U; + tmp120__ |= ( pSrc->mbssid_mask << 0 ); + tmp120__ |= ( pSrc->reserved << 3 ); + *pBuf = tmp120__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -27880,7 +28085,7 @@ tANI_U32 dot11fPackIeFTInfo(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U16 tmp120__; + tANI_U16 tmp121__; tANI_U32 status = DOT11F_PARSE_SUCCESS; status = dot11fGetPackedIEFTInfo(pCtx, pSrc, &nNeeded); if ( ! DOT11F_SUCCEEDED( status ) ) return status; @@ -27891,10 +28096,10 @@ tANI_U32 dot11fPackIeFTInfo(tpAniSirGlobal pCtx, ++pBuf; --nBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; --nBuf; ++(*pnConsumed); - tmp120__ = 0U; - tmp120__ |= ( pSrc->reserved << 0 ); - tmp120__ |= ( pSrc->IECount << 8 ); - frameshtons(pCtx, pBuf, tmp120__, 0); + tmp121__ = 0U; + tmp121__ |= ( pSrc->reserved << 0 ); + tmp121__ |= ( pSrc->IECount << 8 ); + frameshtons(pCtx, pBuf, tmp121__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -27933,7 +28138,7 @@ tANI_U32 dot11fPackIeHT2040BSSCoexistence(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp121__; + tANI_U8 tmp122__; nNeeded += 1; while ( pSrc->present ) { @@ -27942,14 +28147,14 @@ tANI_U32 dot11fPackIeHT2040BSSCoexistence(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp121__ = 0U; - tmp121__ |= ( pSrc->infoRequest << 0 ); - tmp121__ |= ( pSrc->fortyMHzIntolerant << 1 ); - tmp121__ |= ( pSrc->twentyMHzBssWidthReq << 2 ); - tmp121__ |= ( pSrc->obssScanExemptionReq << 3 ); - tmp121__ |= ( pSrc->obssScanExemptionGrant << 4 ); - tmp121__ |= ( pSrc->unused << 5 ); - *pBuf = tmp121__; + tmp122__ = 0U; + tmp122__ |= ( pSrc->infoRequest << 0 ); + tmp122__ |= ( pSrc->fortyMHzIntolerant << 1 ); + tmp122__ |= ( pSrc->twentyMHzBssWidthReq << 2 ); + tmp122__ |= ( pSrc->obssScanExemptionReq << 3 ); + tmp122__ |= ( pSrc->obssScanExemptionGrant << 4 ); + tmp122__ |= ( pSrc->unused << 5 ); + *pBuf = tmp122__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -28005,11 +28210,11 @@ tANI_U32 dot11fPackIeHTCaps(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U16 tmp122__; - tANI_U8 tmp123__; - tANI_U16 tmp124__; - tANI_U32 tmp125__; - tANI_U8 tmp126__; + tANI_U16 tmp123__; + tANI_U8 tmp124__; + tANI_U16 tmp125__; + tANI_U32 tmp126__; + tANI_U8 tmp127__; nNeeded += (pSrc->num_rsvd + 26); while ( pSrc->present ) { @@ -28018,77 +28223,77 @@ tANI_U32 dot11fPackIeHTCaps(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp122__ = 0U; - tmp122__ |= ( pSrc->advCodingCap << 0 ); - tmp122__ |= ( pSrc->supportedChannelWidthSet << 1 ); - tmp122__ |= ( pSrc->mimoPowerSave << 2 ); - tmp122__ |= ( pSrc->greenField << 4 ); - tmp122__ |= ( pSrc->shortGI20MHz << 5 ); - tmp122__ |= ( pSrc->shortGI40MHz << 6 ); - tmp122__ |= ( pSrc->txSTBC << 7 ); - tmp122__ |= ( pSrc->rxSTBC << 8 ); - tmp122__ |= ( pSrc->delayedBA << 10 ); - tmp122__ |= ( pSrc->maximalAMSDUsize << 11 ); - tmp122__ |= ( pSrc->dsssCckMode40MHz << 12 ); - tmp122__ |= ( pSrc->psmp << 13 ); - tmp122__ |= ( pSrc->stbcControlFrame << 14 ); - tmp122__ |= ( pSrc->lsigTXOPProtection << 15 ); - frameshtons(pCtx, pBuf, tmp122__, 0); + tmp123__ = 0U; + tmp123__ |= ( pSrc->advCodingCap << 0 ); + tmp123__ |= ( pSrc->supportedChannelWidthSet << 1 ); + tmp123__ |= ( pSrc->mimoPowerSave << 2 ); + tmp123__ |= ( pSrc->greenField << 4 ); + tmp123__ |= ( pSrc->shortGI20MHz << 5 ); + tmp123__ |= ( pSrc->shortGI40MHz << 6 ); + tmp123__ |= ( pSrc->txSTBC << 7 ); + tmp123__ |= ( pSrc->rxSTBC << 8 ); + tmp123__ |= ( pSrc->delayedBA << 10 ); + tmp123__ |= ( pSrc->maximalAMSDUsize << 11 ); + tmp123__ |= ( pSrc->dsssCckMode40MHz << 12 ); + tmp123__ |= ( pSrc->psmp << 13 ); + tmp123__ |= ( pSrc->stbcControlFrame << 14 ); + tmp123__ |= ( pSrc->lsigTXOPProtection << 15 ); + frameshtons(pCtx, pBuf, tmp123__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; - tmp123__ = 0U; - tmp123__ |= ( pSrc->maxRxAMPDUFactor << 0 ); - tmp123__ |= ( pSrc->mpduDensity << 2 ); - tmp123__ |= ( pSrc->reserved1 << 5 ); - *pBuf = tmp123__; + tmp124__ = 0U; + tmp124__ |= ( pSrc->maxRxAMPDUFactor << 0 ); + tmp124__ |= ( pSrc->mpduDensity << 2 ); + tmp124__ |= ( pSrc->reserved1 << 5 ); + *pBuf = tmp124__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; DOT11F_MEMCPY(pCtx, pBuf, pSrc->supportedMCSSet, 16); *pnConsumed += 16; pBuf += 16; - tmp124__ = 0U; - tmp124__ |= ( pSrc->pco << 0 ); - tmp124__ |= ( pSrc->transitionTime << 1 ); - tmp124__ |= ( pSrc->reserved2 << 3 ); - tmp124__ |= ( pSrc->mcsFeedback << 8 ); - tmp124__ |= ( pSrc->reserved3 << 10 ); - frameshtons(pCtx, pBuf, tmp124__, 0); + tmp125__ = 0U; + tmp125__ |= ( pSrc->pco << 0 ); + tmp125__ |= ( pSrc->transitionTime << 1 ); + tmp125__ |= ( pSrc->reserved2 << 3 ); + tmp125__ |= ( pSrc->mcsFeedback << 8 ); + tmp125__ |= ( pSrc->reserved3 << 10 ); + frameshtons(pCtx, pBuf, tmp125__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; - tmp125__ = 0U; - tmp125__ |= ( pSrc->txBF << 0 ); - tmp125__ |= ( pSrc->rxStaggeredSounding << 1 ); - tmp125__ |= ( pSrc->txStaggeredSounding << 2 ); - tmp125__ |= ( pSrc->rxZLF << 3 ); - tmp125__ |= ( pSrc->txZLF << 4 ); - tmp125__ |= ( pSrc->implicitTxBF << 5 ); - tmp125__ |= ( pSrc->calibration << 6 ); - tmp125__ |= ( pSrc->explicitCSITxBF << 8 ); - tmp125__ |= ( pSrc->explicitUncompressedSteeringMatrix << 9 ); - tmp125__ |= ( pSrc->explicitBFCSIFeedback << 10 ); - tmp125__ |= ( pSrc->explicitUncompressedSteeringMatrixFeedback << 13 ); - tmp125__ |= ( pSrc->explicitCompressedSteeringMatrixFeedback << 16 ); - tmp125__ |= ( pSrc->csiNumBFAntennae << 19 ); - tmp125__ |= ( pSrc->uncompressedSteeringMatrixBFAntennae << 21 ); - tmp125__ |= ( pSrc->compressedSteeringMatrixBFAntennae << 23 ); - tmp125__ |= ( pSrc->reserved4 << 25 ); - frameshtonl(pCtx, pBuf, tmp125__, 0); + tmp126__ = 0U; + tmp126__ |= ( pSrc->txBF << 0 ); + tmp126__ |= ( pSrc->rxStaggeredSounding << 1 ); + tmp126__ |= ( pSrc->txStaggeredSounding << 2 ); + tmp126__ |= ( pSrc->rxZLF << 3 ); + tmp126__ |= ( pSrc->txZLF << 4 ); + tmp126__ |= ( pSrc->implicitTxBF << 5 ); + tmp126__ |= ( pSrc->calibration << 6 ); + tmp126__ |= ( pSrc->explicitCSITxBF << 8 ); + tmp126__ |= ( pSrc->explicitUncompressedSteeringMatrix << 9 ); + tmp126__ |= ( pSrc->explicitBFCSIFeedback << 10 ); + tmp126__ |= ( pSrc->explicitUncompressedSteeringMatrixFeedback << 13 ); + tmp126__ |= ( pSrc->explicitCompressedSteeringMatrixFeedback << 16 ); + tmp126__ |= ( pSrc->csiNumBFAntennae << 19 ); + tmp126__ |= ( pSrc->uncompressedSteeringMatrixBFAntennae << 21 ); + tmp126__ |= ( pSrc->compressedSteeringMatrixBFAntennae << 23 ); + tmp126__ |= ( pSrc->reserved4 << 25 ); + frameshtonl(pCtx, pBuf, tmp126__, 0); *pnConsumed += 4; pBuf += 4; nBuf -= 4 ; - tmp126__ = 0U; - tmp126__ |= ( pSrc->antennaSelection << 0 ); - tmp126__ |= ( pSrc->explicitCSIFeedbackTx << 1 ); - tmp126__ |= ( pSrc->antennaIndicesFeedbackTx << 2 ); - tmp126__ |= ( pSrc->explicitCSIFeedback << 3 ); - tmp126__ |= ( pSrc->antennaIndicesFeedback << 4 ); - tmp126__ |= ( pSrc->rxAS << 5 ); - tmp126__ |= ( pSrc->txSoundingPPDUs << 6 ); - tmp126__ |= ( pSrc->reserved5 << 7 ); - *pBuf = tmp126__; + tmp127__ = 0U; + tmp127__ |= ( pSrc->antennaSelection << 0 ); + tmp127__ |= ( pSrc->explicitCSIFeedbackTx << 1 ); + tmp127__ |= ( pSrc->antennaIndicesFeedbackTx << 2 ); + tmp127__ |= ( pSrc->explicitCSIFeedback << 3 ); + tmp127__ |= ( pSrc->antennaIndicesFeedback << 4 ); + tmp127__ |= ( pSrc->rxAS << 5 ); + tmp127__ |= ( pSrc->txSoundingPPDUs << 6 ); + tmp127__ |= ( pSrc->reserved5 << 7 ); + *pBuf = tmp127__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -28114,9 +28319,9 @@ tANI_U32 dot11fPackIeHTInfo(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp127__; - tANI_U16 tmp128__; + tANI_U8 tmp128__; tANI_U16 tmp129__; + tANI_U16 tmp130__; nNeeded += (pSrc->num_rsvd + 22); while ( pSrc->present ) { @@ -28128,35 +28333,35 @@ tANI_U32 dot11fPackIeHTInfo(tpAniSirGlobal pCtx, *pBuf = pSrc->primaryChannel; *pnConsumed += 1; pBuf += 1; - tmp127__ = 0U; - tmp127__ |= ( pSrc->secondaryChannelOffset << 0 ); - tmp127__ |= ( pSrc->recommendedTxWidthSet << 2 ); - tmp127__ |= ( pSrc->rifsMode << 3 ); - tmp127__ |= ( pSrc->controlledAccessOnly << 4 ); - tmp127__ |= ( pSrc->serviceIntervalGranularity << 5 ); - *pBuf = tmp127__; + tmp128__ = 0U; + tmp128__ |= ( pSrc->secondaryChannelOffset << 0 ); + tmp128__ |= ( pSrc->recommendedTxWidthSet << 2 ); + tmp128__ |= ( pSrc->rifsMode << 3 ); + tmp128__ |= ( pSrc->controlledAccessOnly << 4 ); + tmp128__ |= ( pSrc->serviceIntervalGranularity << 5 ); + *pBuf = tmp128__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - tmp128__ = 0U; - tmp128__ |= ( pSrc->opMode << 0 ); - tmp128__ |= ( pSrc->nonGFDevicesPresent << 2 ); - tmp128__ |= ( pSrc->transmitBurstLimit << 3 ); - tmp128__ |= ( pSrc->obssNonHTStaPresent << 4 ); - tmp128__ |= ( pSrc->reserved << 5 ); - frameshtons(pCtx, pBuf, tmp128__, 0); + tmp129__ = 0U; + tmp129__ |= ( pSrc->opMode << 0 ); + tmp129__ |= ( pSrc->nonGFDevicesPresent << 2 ); + tmp129__ |= ( pSrc->transmitBurstLimit << 3 ); + tmp129__ |= ( pSrc->obssNonHTStaPresent << 4 ); + tmp129__ |= ( pSrc->reserved << 5 ); + frameshtons(pCtx, pBuf, tmp129__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; - tmp129__ = 0U; - tmp129__ |= ( pSrc->basicSTBCMCS << 0 ); - tmp129__ |= ( pSrc->dualCTSProtection << 7 ); - tmp129__ |= ( pSrc->secondaryBeacon << 8 ); - tmp129__ |= ( pSrc->lsigTXOPProtectionFullSupport << 9 ); - tmp129__ |= ( pSrc->pcoActive << 10 ); - tmp129__ |= ( pSrc->pcoPhase << 11 ); - tmp129__ |= ( pSrc->reserved2 << 12 ); - frameshtons(pCtx, pBuf, tmp129__, 0); + tmp130__ = 0U; + tmp130__ |= ( pSrc->basicSTBCMCS << 0 ); + tmp130__ |= ( pSrc->dualCTSProtection << 7 ); + tmp130__ |= ( pSrc->secondaryBeacon << 8 ); + tmp130__ |= ( pSrc->lsigTXOPProtectionFullSupport << 9 ); + tmp130__ |= ( pSrc->pcoActive << 10 ); + tmp130__ |= ( pSrc->pcoPhase << 11 ); + tmp130__ |= ( pSrc->reserved2 << 12 ); + frameshtons(pCtx, pBuf, tmp130__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -28251,9 +28456,9 @@ tANI_U32 dot11fPackIeMeasurementReport(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp130__; tANI_U8 tmp131__; tANI_U8 tmp132__; + tANI_U8 tmp133__; tANI_U32 status = DOT11F_PARSE_SUCCESS; status = dot11fGetPackedIEMeasurementReport(pCtx, pSrc, &nNeeded); if ( ! DOT11F_SUCCEEDED( status ) ) return status; @@ -28267,12 +28472,12 @@ tANI_U32 dot11fPackIeMeasurementReport(tpAniSirGlobal pCtx, *pBuf = pSrc->token; *pnConsumed += 1; pBuf += 1; - tmp130__ = 0U; - tmp130__ |= ( pSrc->late << 0 ); - tmp130__ |= ( pSrc->incapable << 1 ); - tmp130__ |= ( pSrc->refused << 2 ); - tmp130__ |= ( pSrc->unused << 3 ); - *pBuf = tmp130__; + tmp131__ = 0U; + tmp131__ |= ( pSrc->late << 0 ); + tmp131__ |= ( pSrc->incapable << 1 ); + tmp131__ |= ( pSrc->refused << 2 ); + tmp131__ |= ( pSrc->unused << 3 ); + *pBuf = tmp131__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -28292,14 +28497,14 @@ tANI_U32 dot11fPackIeMeasurementReport(tpAniSirGlobal pCtx, frameshtons(pCtx, pBuf, pSrc->report.Basic.meas_duration, 0); *pnConsumed += 2; pBuf += 2; - tmp131__ = 0U; - tmp131__ |= ( pSrc->report.Basic.bss << 0 ); - tmp131__ |= ( pSrc->report.Basic.ofdm_preamble << 1 ); - tmp131__ |= ( pSrc->report.Basic.unid_signal << 2 ); - tmp131__ |= ( pSrc->report.Basic.rader << 3 ); - tmp131__ |= ( pSrc->report.Basic.unmeasured << 4 ); - tmp131__ |= ( pSrc->report.Basic.unused << 5 ); - *pBuf = tmp131__; + tmp132__ = 0U; + tmp132__ |= ( pSrc->report.Basic.bss << 0 ); + tmp132__ |= ( pSrc->report.Basic.ofdm_preamble << 1 ); + tmp132__ |= ( pSrc->report.Basic.unid_signal << 2 ); + tmp132__ |= ( pSrc->report.Basic.rader << 3 ); + tmp132__ |= ( pSrc->report.Basic.unmeasured << 4 ); + tmp132__ |= ( pSrc->report.Basic.unused << 5 ); + *pBuf = tmp132__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -28366,10 +28571,10 @@ tANI_U32 dot11fPackIeMeasurementReport(tpAniSirGlobal pCtx, frameshtons(pCtx, pBuf, pSrc->report.Beacon.meas_duration, 0); *pnConsumed += 2; pBuf += 2; - tmp132__ = 0U; - tmp132__ |= ( pSrc->report.Beacon.condensed_PHY << 0 ); - tmp132__ |= ( pSrc->report.Beacon.reported_frame_type << 7 ); - *pBuf = tmp132__; + tmp133__ = 0U; + tmp133__ |= ( pSrc->report.Beacon.condensed_PHY << 0 ); + tmp133__ |= ( pSrc->report.Beacon.reported_frame_type << 7 ); + *pBuf = tmp133__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -28418,7 +28623,7 @@ tANI_U32 dot11fPackIeMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp133__; + tANI_U8 tmp134__; tANI_U32 status = DOT11F_PARSE_SUCCESS; status = dot11fGetPackedIEMeasurementRequest(pCtx, pSrc, &nNeeded); if ( ! DOT11F_SUCCEEDED( status ) ) return status; @@ -28432,14 +28637,14 @@ tANI_U32 dot11fPackIeMeasurementRequest(tpAniSirGlobal pCtx, *pBuf = pSrc->measurement_token; *pnConsumed += 1; pBuf += 1; - tmp133__ = 0U; - tmp133__ |= ( pSrc->parallel << 0 ); - tmp133__ |= ( pSrc->enable << 1 ); - tmp133__ |= ( pSrc->request << 2 ); - tmp133__ |= ( pSrc->report << 3 ); - tmp133__ |= ( pSrc->durationMandatory << 4 ); - tmp133__ |= ( pSrc->unused << 5 ); - *pBuf = tmp133__; + tmp134__ = 0U; + tmp134__ |= ( pSrc->parallel << 0 ); + tmp134__ |= ( pSrc->enable << 1 ); + tmp134__ |= ( pSrc->request << 2 ); + tmp134__ |= ( pSrc->report << 3 ); + tmp134__ |= ( pSrc->durationMandatory << 4 ); + tmp134__ |= ( pSrc->unused << 5 ); + *pBuf = tmp134__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -28528,7 +28733,7 @@ tANI_U32 dot11fPackIeMobilityDomain(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp134__; + tANI_U8 tmp135__; nNeeded += 3; while ( pSrc->present ) { @@ -28540,11 +28745,11 @@ tANI_U32 dot11fPackIeMobilityDomain(tpAniSirGlobal pCtx, frameshtons(pCtx, pBuf, pSrc->MDID, 0); *pnConsumed += 2; pBuf += 2; - tmp134__ = 0U; - tmp134__ |= ( pSrc->overDSCap << 0 ); - tmp134__ |= ( pSrc->resourceReqCap << 1 ); - tmp134__ |= ( pSrc->reserved << 2 ); - *pBuf = tmp134__; + tmp135__ = 0U; + tmp135__ |= ( pSrc->overDSCap << 0 ); + tmp135__ |= ( pSrc->resourceReqCap << 1 ); + tmp135__ |= ( pSrc->reserved << 2 ); + *pBuf = tmp135__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -28567,8 +28772,8 @@ tANI_U32 dot11fPackIeNeighborReport(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp135__; tANI_U8 tmp136__; + tANI_U8 tmp137__; tANI_U32 status = DOT11F_PARSE_SUCCESS; status = dot11fGetPackedIENeighborReport(pCtx, pSrc, &nNeeded); if ( ! DOT11F_SUCCEEDED( status ) ) return status; @@ -28582,24 +28787,24 @@ tANI_U32 dot11fPackIeNeighborReport(tpAniSirGlobal pCtx, DOT11F_MEMCPY(pCtx, pBuf, pSrc->bssid, 6); *pnConsumed += 6; pBuf += 6; - tmp135__ = 0U; - tmp135__ |= ( pSrc->APReachability << 0 ); - tmp135__ |= ( pSrc->Security << 2 ); - tmp135__ |= ( pSrc->KeyScope << 3 ); - tmp135__ |= ( pSrc->SpecMgmtCap << 4 ); - tmp135__ |= ( pSrc->QosCap << 5 ); - tmp135__ |= ( pSrc->apsd << 6 ); - tmp135__ |= ( pSrc->rrm << 7 ); - *pBuf = tmp135__; + tmp136__ = 0U; + tmp136__ |= ( pSrc->APReachability << 0 ); + tmp136__ |= ( pSrc->Security << 2 ); + tmp136__ |= ( pSrc->KeyScope << 3 ); + tmp136__ |= ( pSrc->SpecMgmtCap << 4 ); + tmp136__ |= ( pSrc->QosCap << 5 ); + tmp136__ |= ( pSrc->apsd << 6 ); + tmp136__ |= ( pSrc->rrm << 7 ); + *pBuf = tmp136__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - tmp136__ = 0U; - tmp136__ |= ( pSrc->DelayedBA << 0 ); - tmp136__ |= ( pSrc->ImmBA << 1 ); - tmp136__ |= ( pSrc->MobilityDomain << 2 ); - tmp136__ |= ( pSrc->reserved << 3 ); - *pBuf = tmp136__; + tmp137__ = 0U; + tmp137__ |= ( pSrc->DelayedBA << 0 ); + tmp137__ |= ( pSrc->ImmBA << 1 ); + tmp137__ |= ( pSrc->MobilityDomain << 2 ); + tmp137__ |= ( pSrc->reserved << 3 ); + *pBuf = tmp137__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; @@ -28689,7 +28894,7 @@ tANI_U32 dot11fPackIeOperatingMode(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp137__; + tANI_U8 tmp138__; nNeeded += 1; while ( pSrc->present ) { @@ -28698,12 +28903,12 @@ tANI_U32 dot11fPackIeOperatingMode(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp137__ = 0U; - tmp137__ |= ( pSrc->chanWidth << 0 ); - tmp137__ |= ( pSrc->reserved << 2 ); - tmp137__ |= ( pSrc->rxNSS << 4 ); - tmp137__ |= ( pSrc->rxNSSType << 7 ); - *pBuf = tmp137__; + tmp138__ = 0U; + tmp138__ |= ( pSrc->chanWidth << 0 ); + tmp138__ |= ( pSrc->reserved << 2 ); + tmp138__ |= ( pSrc->rxNSS << 4 ); + tmp138__ |= ( pSrc->rxNSSType << 7 ); + *pBuf = tmp138__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -29657,7 +29862,7 @@ tANI_U32 dot11fPackIePUBufferStatus(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp138__; + tANI_U8 tmp139__; nNeeded += 1; while ( pSrc->present ) { @@ -29666,13 +29871,13 @@ tANI_U32 dot11fPackIePUBufferStatus(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp138__ = 0U; - tmp138__ |= ( pSrc->ac_bk_traffic_aval << 0 ); - tmp138__ |= ( pSrc->ac_be_traffic_aval << 1 ); - tmp138__ |= ( pSrc->ac_vi_traffic_aval << 2 ); - tmp138__ |= ( pSrc->ac_vo_traffic_aval << 3 ); - tmp138__ |= ( pSrc->reserved << 4 ); - *pBuf = tmp138__; + tmp139__ = 0U; + tmp139__ |= ( pSrc->ac_bk_traffic_aval << 0 ); + tmp139__ |= ( pSrc->ac_be_traffic_aval << 1 ); + tmp139__ |= ( pSrc->ac_vi_traffic_aval << 2 ); + tmp139__ |= ( pSrc->ac_vo_traffic_aval << 3 ); + tmp139__ |= ( pSrc->reserved << 4 ); + *pBuf = tmp139__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -29794,7 +29999,7 @@ tANI_U32 dot11fPackIeQOSCapsAp(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp139__; + tANI_U8 tmp140__; nNeeded += 1; while ( pSrc->present ) { @@ -29803,13 +30008,13 @@ tANI_U32 dot11fPackIeQOSCapsAp(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp139__ = 0U; - tmp139__ |= ( pSrc->count << 0 ); - tmp139__ |= ( pSrc->qack << 4 ); - tmp139__ |= ( pSrc->qreq << 5 ); - tmp139__ |= ( pSrc->txopreq << 6 ); - tmp139__ |= ( pSrc->reserved << 7 ); - *pBuf = tmp139__; + tmp140__ = 0U; + tmp140__ |= ( pSrc->count << 0 ); + tmp140__ |= ( pSrc->qack << 4 ); + tmp140__ |= ( pSrc->qreq << 5 ); + tmp140__ |= ( pSrc->txopreq << 6 ); + tmp140__ |= ( pSrc->reserved << 7 ); + *pBuf = tmp140__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -29832,7 +30037,7 @@ tANI_U32 dot11fPackIeQOSCapsStation(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp140__; + tANI_U8 tmp141__; nNeeded += 1; while ( pSrc->present ) { @@ -29841,15 +30046,15 @@ tANI_U32 dot11fPackIeQOSCapsStation(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp140__ = 0U; - tmp140__ |= ( pSrc->acvo_uapsd << 0 ); - tmp140__ |= ( pSrc->acvi_uapsd << 1 ); - tmp140__ |= ( pSrc->acbk_uapsd << 2 ); - tmp140__ |= ( pSrc->acbe_uapsd << 3 ); - tmp140__ |= ( pSrc->qack << 4 ); - tmp140__ |= ( pSrc->max_sp_length << 5 ); - tmp140__ |= ( pSrc->more_data_ack << 7 ); - *pBuf = tmp140__; + tmp141__ = 0U; + tmp141__ |= ( pSrc->acvo_uapsd << 0 ); + tmp141__ |= ( pSrc->acvi_uapsd << 1 ); + tmp141__ |= ( pSrc->acbk_uapsd << 2 ); + tmp141__ |= ( pSrc->acbe_uapsd << 3 ); + tmp141__ |= ( pSrc->qack << 4 ); + tmp141__ |= ( pSrc->max_sp_length << 5 ); + tmp141__ |= ( pSrc->more_data_ack << 7 ); + *pBuf = tmp141__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -30353,9 +30558,9 @@ tANI_U32 dot11fPackIeVHTCaps(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U32 tmp141__; - tANI_U16 tmp142__; + tANI_U32 tmp142__; tANI_U16 tmp143__; + tANI_U16 tmp144__; nNeeded += 12; while ( pSrc->present ) { @@ -30364,48 +30569,48 @@ tANI_U32 dot11fPackIeVHTCaps(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); pIeLen = pBuf; ++pBuf; ++(*pnConsumed); - tmp141__ = 0U; - tmp141__ |= ( pSrc->maxMPDULen << 0 ); - tmp141__ |= ( pSrc->supportedChannelWidthSet << 2 ); - tmp141__ |= ( pSrc->ldpcCodingCap << 4 ); - tmp141__ |= ( pSrc->shortGI80MHz << 5 ); - tmp141__ |= ( pSrc->shortGI160and80plus80MHz << 6 ); - tmp141__ |= ( pSrc->txSTBC << 7 ); - tmp141__ |= ( pSrc->rxSTBC << 8 ); - tmp141__ |= ( pSrc->suBeamFormerCap << 11 ); - tmp141__ |= ( pSrc->suBeamformeeCap << 12 ); - tmp141__ |= ( pSrc->csnofBeamformerAntSup << 13 ); - tmp141__ |= ( pSrc->numSoundingDim << 16 ); - tmp141__ |= ( pSrc->muBeamformerCap << 19 ); - tmp141__ |= ( pSrc->muBeamformeeCap << 20 ); - tmp141__ |= ( pSrc->vhtTXOPPS << 21 ); - tmp141__ |= ( pSrc->htcVHTCap << 22 ); - tmp141__ |= ( pSrc->maxAMPDULenExp << 23 ); - tmp141__ |= ( pSrc->vhtLinkAdaptCap << 26 ); - tmp141__ |= ( pSrc->rxAntPattern << 28 ); - tmp141__ |= ( pSrc->txAntPattern << 29 ); - tmp141__ |= ( pSrc->reserved1 << 30 ); - frameshtonl(pCtx, pBuf, tmp141__, 0); + tmp142__ = 0U; + tmp142__ |= ( pSrc->maxMPDULen << 0 ); + tmp142__ |= ( pSrc->supportedChannelWidthSet << 2 ); + tmp142__ |= ( pSrc->ldpcCodingCap << 4 ); + tmp142__ |= ( pSrc->shortGI80MHz << 5 ); + tmp142__ |= ( pSrc->shortGI160and80plus80MHz << 6 ); + tmp142__ |= ( pSrc->txSTBC << 7 ); + tmp142__ |= ( pSrc->rxSTBC << 8 ); + tmp142__ |= ( pSrc->suBeamFormerCap << 11 ); + tmp142__ |= ( pSrc->suBeamformeeCap << 12 ); + tmp142__ |= ( pSrc->csnofBeamformerAntSup << 13 ); + tmp142__ |= ( pSrc->numSoundingDim << 16 ); + tmp142__ |= ( pSrc->muBeamformerCap << 19 ); + tmp142__ |= ( pSrc->muBeamformeeCap << 20 ); + tmp142__ |= ( pSrc->vhtTXOPPS << 21 ); + tmp142__ |= ( pSrc->htcVHTCap << 22 ); + tmp142__ |= ( pSrc->maxAMPDULenExp << 23 ); + tmp142__ |= ( pSrc->vhtLinkAdaptCap << 26 ); + tmp142__ |= ( pSrc->rxAntPattern << 28 ); + tmp142__ |= ( pSrc->txAntPattern << 29 ); + tmp142__ |= ( pSrc->reserved1 << 30 ); + frameshtonl(pCtx, pBuf, tmp142__, 0); *pnConsumed += 4; pBuf += 4; nBuf -= 4 ; frameshtons(pCtx, pBuf, pSrc->rxMCSMap, 0); *pnConsumed += 2; pBuf += 2; - tmp142__ = 0U; - tmp142__ |= ( pSrc->rxHighSupDataRate << 0 ); - tmp142__ |= ( pSrc->reserved2 << 13 ); - frameshtons(pCtx, pBuf, tmp142__, 0); + tmp143__ = 0U; + tmp143__ |= ( pSrc->rxHighSupDataRate << 0 ); + tmp143__ |= ( pSrc->reserved2 << 13 ); + frameshtons(pCtx, pBuf, tmp143__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; frameshtons(pCtx, pBuf, pSrc->txMCSMap, 0); *pnConsumed += 2; pBuf += 2; - tmp143__ = 0U; - tmp143__ |= ( pSrc->txSupDataRate << 0 ); - tmp143__ |= ( pSrc->reserved3 << 13 ); - frameshtons(pCtx, pBuf, tmp143__, 0); + tmp144__ = 0U; + tmp144__ |= ( pSrc->txSupDataRate << 0 ); + tmp144__ |= ( pSrc->reserved3 << 13 ); + frameshtons(pCtx, pBuf, tmp144__, 0); *pnConsumed += 2; // fieldsEndFlag = 1 nBuf -= 2 ; @@ -30509,7 +30714,7 @@ tANI_U32 dot11fPackIeWAPI(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U16 tmp144__; + tANI_U16 tmp145__; tANI_U32 status = DOT11F_PARSE_SUCCESS; status = dot11fGetPackedIEWAPI(pCtx, pSrc, &nNeeded); if ( ! DOT11F_SUCCEEDED( status ) ) return status; @@ -30538,10 +30743,10 @@ tANI_U32 dot11fPackIeWAPI(tpAniSirGlobal pCtx, DOT11F_MEMCPY(pCtx, pBuf, pSrc->multicast_cipher_suite, 4); *pnConsumed += 4; pBuf += 4; - tmp144__ = 0U; - tmp144__ |= ( pSrc->preauth << 0 ); - tmp144__ |= ( pSrc->reserved << 1 ); - frameshtons(pCtx, pBuf, tmp144__, 0); + tmp145__ = 0U; + tmp145__ |= ( pSrc->preauth << 0 ); + tmp145__ |= ( pSrc->reserved << 1 ); + frameshtons(pCtx, pBuf, tmp145__, 0); *pnConsumed += 2; pBuf += 2; nBuf -= 2 ; @@ -30684,7 +30889,7 @@ tANI_U32 dot11fPackIeWMMCaps(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp145__; + tANI_U8 tmp146__; nNeeded += 2; while ( pSrc->present ) { @@ -30706,13 +30911,13 @@ tANI_U32 dot11fPackIeWMMCaps(tpAniSirGlobal pCtx, *pBuf = pSrc->version; *pnConsumed += 1; pBuf += 1; - tmp145__ = 0U; - tmp145__ |= ( pSrc->reserved << 0 ); - tmp145__ |= ( pSrc->qack << 4 ); - tmp145__ |= ( pSrc->queue_request << 5 ); - tmp145__ |= ( pSrc->txop_request << 6 ); - tmp145__ |= ( pSrc->more_ack << 7 ); - *pBuf = tmp145__; + tmp146__ = 0U; + tmp146__ |= ( pSrc->reserved << 0 ); + tmp146__ |= ( pSrc->qack << 4 ); + tmp146__ |= ( pSrc->queue_request << 5 ); + tmp146__ |= ( pSrc->txop_request << 6 ); + tmp146__ |= ( pSrc->more_ack << 7 ); + *pBuf = tmp146__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -30735,7 +30940,7 @@ tANI_U32 dot11fPackIeWMMInfoAp(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp146__; + tANI_U8 tmp147__; nNeeded += 2; while ( pSrc->present ) { @@ -30757,11 +30962,11 @@ tANI_U32 dot11fPackIeWMMInfoAp(tpAniSirGlobal pCtx, *pBuf = pSrc->version; *pnConsumed += 1; pBuf += 1; - tmp146__ = 0U; - tmp146__ |= ( pSrc->param_set_count << 0 ); - tmp146__ |= ( pSrc->reserved << 4 ); - tmp146__ |= ( pSrc->uapsd << 7 ); - *pBuf = tmp146__; + tmp147__ = 0U; + tmp147__ |= ( pSrc->param_set_count << 0 ); + tmp147__ |= ( pSrc->reserved << 4 ); + tmp147__ |= ( pSrc->uapsd << 7 ); + *pBuf = tmp147__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -30784,7 +30989,7 @@ tANI_U32 dot11fPackIeWMMInfoStation(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp147__; + tANI_U8 tmp148__; nNeeded += 2; while ( pSrc->present ) { @@ -30806,15 +31011,15 @@ tANI_U32 dot11fPackIeWMMInfoStation(tpAniSirGlobal pCtx, *pBuf = pSrc->version; *pnConsumed += 1; pBuf += 1; - tmp147__ = 0U; - tmp147__ |= ( pSrc->acvo_uapsd << 0 ); - tmp147__ |= ( pSrc->acvi_uapsd << 1 ); - tmp147__ |= ( pSrc->acbk_uapsd << 2 ); - tmp147__ |= ( pSrc->acbe_uapsd << 3 ); - tmp147__ |= ( pSrc->reserved1 << 4 ); - tmp147__ |= ( pSrc->max_sp_length << 5 ); - tmp147__ |= ( pSrc->reserved2 << 7 ); - *pBuf = tmp147__; + tmp148__ = 0U; + tmp148__ |= ( pSrc->acvo_uapsd << 0 ); + tmp148__ |= ( pSrc->acvi_uapsd << 1 ); + tmp148__ |= ( pSrc->acbk_uapsd << 2 ); + tmp148__ |= ( pSrc->acbe_uapsd << 3 ); + tmp148__ |= ( pSrc->reserved1 << 4 ); + tmp148__ |= ( pSrc->max_sp_length << 5 ); + tmp148__ |= ( pSrc->reserved2 << 7 ); + *pBuf = tmp148__; *pnConsumed += 1; // fieldsEndFlag = 1 nBuf -= 1 ; @@ -30837,7 +31042,6 @@ tANI_U32 dot11fPackIeWMMParams(tpAniSirGlobal pCtx, tANI_U8* pIeLen = 0; tANI_U32 nConsumedOnEntry = *pnConsumed; tANI_U32 nNeeded = 0U; - tANI_U8 tmp148__; tANI_U8 tmp149__; tANI_U8 tmp150__; tANI_U8 tmp151__; @@ -30845,6 +31049,7 @@ tANI_U32 dot11fPackIeWMMParams(tpAniSirGlobal pCtx, tANI_U8 tmp153__; tANI_U8 tmp154__; tANI_U8 tmp155__; + tANI_U8 tmp156__; nNeeded += 19; while ( pSrc->present ) { @@ -30872,79 +31077,79 @@ tANI_U32 dot11fPackIeWMMParams(tpAniSirGlobal pCtx, *pBuf = pSrc->reserved2; *pnConsumed += 1; pBuf += 1; - tmp148__ = 0U; - tmp148__ |= ( pSrc->acbe_aifsn << 0 ); - tmp148__ |= ( pSrc->acbe_acm << 4 ); - tmp148__ |= ( pSrc->acbe_aci << 5 ); - tmp148__ |= ( pSrc->unused1 << 7 ); - *pBuf = tmp148__; - *pnConsumed += 1; - pBuf += 1; - nBuf -= 1 ; tmp149__ = 0U; - tmp149__ |= ( pSrc->acbe_acwmin << 0 ); - tmp149__ |= ( pSrc->acbe_acwmax << 4 ); + tmp149__ |= ( pSrc->acbe_aifsn << 0 ); + tmp149__ |= ( pSrc->acbe_acm << 4 ); + tmp149__ |= ( pSrc->acbe_aci << 5 ); + tmp149__ |= ( pSrc->unused1 << 7 ); *pBuf = tmp149__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); - *pnConsumed += 2; - pBuf += 2; tmp150__ = 0U; - tmp150__ |= ( pSrc->acbk_aifsn << 0 ); - tmp150__ |= ( pSrc->acbk_acm << 4 ); - tmp150__ |= ( pSrc->acbk_aci << 5 ); - tmp150__ |= ( pSrc->unused2 << 7 ); + tmp150__ |= ( pSrc->acbe_acwmin << 0 ); + tmp150__ |= ( pSrc->acbe_acwmax << 4 ); *pBuf = tmp150__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbe_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; tmp151__ = 0U; - tmp151__ |= ( pSrc->acbk_acwmin << 0 ); - tmp151__ |= ( pSrc->acbk_acwmax << 4 ); + tmp151__ |= ( pSrc->acbk_aifsn << 0 ); + tmp151__ |= ( pSrc->acbk_acm << 4 ); + tmp151__ |= ( pSrc->acbk_aci << 5 ); + tmp151__ |= ( pSrc->unused2 << 7 ); *pBuf = tmp151__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); - *pnConsumed += 2; - pBuf += 2; tmp152__ = 0U; - tmp152__ |= ( pSrc->acvi_aifsn << 0 ); - tmp152__ |= ( pSrc->acvi_acm << 4 ); - tmp152__ |= ( pSrc->acvi_aci << 5 ); - tmp152__ |= ( pSrc->unused3 << 7 ); + tmp152__ |= ( pSrc->acbk_acwmin << 0 ); + tmp152__ |= ( pSrc->acbk_acwmax << 4 ); *pBuf = tmp152__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acbk_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; tmp153__ = 0U; - tmp153__ |= ( pSrc->acvi_acwmin << 0 ); - tmp153__ |= ( pSrc->acvi_acwmax << 4 ); + tmp153__ |= ( pSrc->acvi_aifsn << 0 ); + tmp153__ |= ( pSrc->acvi_acm << 4 ); + tmp153__ |= ( pSrc->acvi_aci << 5 ); + tmp153__ |= ( pSrc->unused3 << 7 ); *pBuf = tmp153__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; - frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); - *pnConsumed += 2; - pBuf += 2; tmp154__ = 0U; - tmp154__ |= ( pSrc->acvo_aifsn << 0 ); - tmp154__ |= ( pSrc->acvo_acm << 4 ); - tmp154__ |= ( pSrc->acvo_aci << 5 ); - tmp154__ |= ( pSrc->unused4 << 7 ); + tmp154__ |= ( pSrc->acvi_acwmin << 0 ); + tmp154__ |= ( pSrc->acvi_acwmax << 4 ); *pBuf = tmp154__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + frameshtons(pCtx, pBuf, pSrc->acvi_txoplimit, 0); + *pnConsumed += 2; + pBuf += 2; tmp155__ = 0U; - tmp155__ |= ( pSrc->acvo_acwmin << 0 ); - tmp155__ |= ( pSrc->acvo_acwmax << 4 ); + tmp155__ |= ( pSrc->acvo_aifsn << 0 ); + tmp155__ |= ( pSrc->acvo_acm << 4 ); + tmp155__ |= ( pSrc->acvo_aci << 5 ); + tmp155__ |= ( pSrc->unused4 << 7 ); *pBuf = tmp155__; *pnConsumed += 1; pBuf += 1; nBuf -= 1 ; + tmp156__ = 0U; + tmp156__ |= ( pSrc->acvo_acwmin << 0 ); + tmp156__ |= ( pSrc->acvo_acwmax << 4 ); + *pBuf = tmp156__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; frameshtons(pCtx, pBuf, pSrc->acvo_txoplimit, 0); *pnConsumed += 2; // fieldsEndFlag = 1 @@ -31484,6 +31689,69 @@ tANI_U32 dot11fPackIeWscReassocRes(tpAniSirGlobal pCtx, return status; } /* End dot11fPackIeWscReassocRes. */ +tANI_U32 dot11fPackIehs20vendor_ie(tpAniSirGlobal pCtx, + tDot11fIEhs20vendor_ie *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + tANI_U8 tmp157__; + tANI_U32 status = DOT11F_PARSE_SUCCESS; + status = dot11fGetPackedIEhs20vendor_ie(pCtx, pSrc, &nNeeded); + if ( ! DOT11F_SUCCEEDED( status ) ) return status; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 221; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x50; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x6f; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x9a; + ++pBuf; ++(*pnConsumed); + *pBuf = 0x10; + ++pBuf; ++(*pnConsumed); + tmp157__ = 0U; + tmp157__ |= ( pSrc->dgaf_dis << 0 ); + tmp157__ |= ( pSrc->hs_id_present << 1 ); + tmp157__ |= ( pSrc->reserved << 3 ); + tmp157__ |= ( pSrc->release_num << 4 ); + *pBuf = tmp157__; + *pnConsumed += 1; + pBuf += 1; + nBuf -= 1 ; + if ( pSrc->hs_id_present ) { + switch (pSrc->hs_id_present) + { + case 1: + frameshtons(pCtx, pBuf, pSrc->hs_id.pps_mo.pps_mo_id, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + case 2: + frameshtons(pCtx, pBuf, pSrc->hs_id.anqp_domain.anqp_domain_id, 0); + *pnConsumed += 2; + // fieldsEndFlag = 1 + break; + } + } + else break; + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return status; +} /* End dot11fPackIehs20vendor_ie. */ + tANI_U32 dot11fPackAddBAReq(tpAniSirGlobal pCtx, tDot11fAddBAReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) { tANI_U32 i = 0; @@ -32638,6 +32906,27 @@ tANI_U32 dot11fPackAssocRequest(tpAniSirGlobal pCtx, tDot11fAssocRequest *pFrm, FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("num_dscp_exceptions: %d.\n"), pFrm->QosMapSet.num_dscp_exceptions); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* ) pFrm->QosMapSet.dscp_exceptions, pFrm->QosMapSet.num_dscp_exceptions); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("to:\n")); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), pBuf, nBuf); } @@ -35196,6 +35485,27 @@ tANI_U32 dot11fPackBeacon(tpAniSirGlobal pCtx, tDot11fBeacon *pFrm, tANI_U8 *pBu FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("to:\n")); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), pBuf, nBuf); } @@ -36178,6 +36488,27 @@ tANI_U32 dot11fPackBeacon2(tpAniSirGlobal pCtx, tDot11fBeacon2 *pFrm, tANI_U8 *p FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), FRFL("to:\n")); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON2), pBuf, nBuf); } @@ -37341,6 +37672,27 @@ tANI_U32 dot11fPackBeaconIEs(tpAniSirGlobal pCtx, tDot11fBeaconIEs *pFrm, tANI_U FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("to:\n")); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), pBuf, nBuf); } @@ -40450,6 +40802,27 @@ tANI_U32 dot11fPackProbeResponse(tpAniSirGlobal pCtx, tDot11fProbeResponse *pFrm FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.bssWidthChannelTransitionDelayFactor, 2); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->OBSSScanParameters.obssScanActivityThreshold, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), FRFL("to:\n")); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_PROBERESPONSE), pBuf, nBuf); } @@ -41791,6 +42164,27 @@ tANI_U32 dot11fPackReAssocRequest(tpAniSirGlobal pCtx, tDot11fReAssocRequest *pF FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_dscp_exceptions: %d.\n"), pFrm->QosMapSet.num_dscp_exceptions); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->QosMapSet.dscp_exceptions, pFrm->QosMapSet.num_dscp_exceptions); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("hs20vendor_ie:\n")); + if (!pFrm->hs20vendor_ie.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("dgaf_dis (1): %d\n"), pFrm->hs20vendor_ie.dgaf_dis); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("hs_id_present (2): %d\n"), pFrm->hs20vendor_ie.hs_id_present); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("reserved (1): %d\n"), pFrm->hs20vendor_ie.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("release_num (4): %d\n"), pFrm->hs20vendor_ie.release_num); + switch (pFrm->hs20vendor_ie.hs_id_present) + { + case 1: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.pps_mo.pps_mo_id, 2); + break; + case 2: + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->hs20vendor_ie.hs_id.anqp_domain.anqp_domain_id, 2); + break; + } + } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("to:\n")); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), pBuf, nBuf); } @@ -45460,6 +45854,9 @@ static tANI_U32 PackCore(tpAniSirGlobal pCtx, case SigIeWscReassocRes: status |= dot11fPackIeWscReassocRes(pCtx, ( tDot11fIEWscReassocRes* )(pSrc + pIe->offset + sizeof(tDot11fIEWscReassocRes) * i ), pBufRemaining, nBufRemaining, &len); break; + case SigIehs20vendor_ie: + status |= dot11fPackIehs20vendor_ie(pCtx, ( tDot11fIEhs20vendor_ie* )(pSrc + pIe->offset + sizeof(tDot11fIEhs20vendor_ie) * i ), pBufRemaining, nBufRemaining, &len); + break; default: FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR-- I don" "'t know about the IE %d; this is most likely a b" diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c index 0da70dc30c0..ba7c97aba79 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c +++ b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -137,6 +137,9 @@ tANI_U8* macTraceGetNeighbourRoamState(tANI_U16 neighbourRoamState) CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_PREAUTHENTICATING); CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE); #endif /* WLAN_FEATURE_VOWIFI_11R */ + #ifdef WLAN_FEATURE_LFR_MBB + CASE_RETURN_STRING(eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC); + #endif CASE_RETURN_STRING(eNEIGHBOR_STATE_MAX); default: @@ -572,7 +575,13 @@ tANI_U8* macTraceGetSmeMsgString( tANI_U16 smeMsg ) CASE_RETURN_STRING(eWNI_SME_UPDATE_MAX_RATE_IND); CASE_RETURN_STRING(eWNI_SME_SET_TDLS_2040_BSSCOEX_REQ); CASE_RETURN_STRING(eWNI_SME_REGISTER_MGMT_FRAME_CB); +#ifdef WLAN_FEATURE_LFR_MBB + CASE_RETURN_STRING(eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ); + CASE_RETURN_STRING(eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP); +#endif CASE_RETURN_STRING(eWNI_SME_MSG_TYPES_END); + CASE_RETURN_STRING(eWNI_SME_CAP_TSF_REQ); + CASE_RETURN_STRING(eWNI_SME_GET_TSF_REQ); default: return( (tANI_U8*)"UNKNOWN" ); break; @@ -906,10 +915,19 @@ tANI_U8* macTraceGetWdaMsgString( tANI_U16 wdaMsg ) CASE_RETURN_STRING(WDA_MON_STOP_REQ); CASE_RETURN_STRING(WDA_SPOOF_MAC_ADDR_REQ); CASE_RETURN_STRING(WDA_LOST_LINK_PARAMS_IND); +#ifdef DHCP_SERVER_OFFLOAD + CASE_RETURN_STRING(WDA_SET_DHCP_SERVER_OFFLOAD_REQ); +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + CASE_RETURN_STRING(WDA_SET_MDNS_OFFLOAD_CMD); + CASE_RETURN_STRING(WDA_SET_MDNS_FQDN_CMD); + CASE_RETURN_STRING(WDA_SET_MDNS_RESPONSE_CMD); + CASE_RETURN_STRING(WDA_GET_MDNS_STATUS_CMD); +#endif + CASE_RETURN_STRING(WDA_CAP_TSF_REQ); + CASE_RETURN_STRING(WDA_GET_TSF_REQ); CASE_RETURN_STRING(WDA_SET_ARP_STATS_REQ); CASE_RETURN_STRING(WDA_GET_ARP_STATS_REQ); - CASE_RETURN_STRING(WDA_TRIGGER_ADD_BA_REQ); - CASE_RETURN_STRING(WDA_GET_CON_STATUS); default: return((tANI_U8*) "UNKNOWN" ); break; @@ -971,7 +989,15 @@ tANI_U8* macTraceGetLimMsgString( tANI_U16 limMsg ) CASE_RETURN_STRING(SIR_LIM_DISASSOC_ACK_TIMEOUT); CASE_RETURN_STRING(SIR_LIM_DEAUTH_ACK_TIMEOUT); CASE_RETURN_STRING(SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT); + +#ifdef WLAN_FEATURE_LFR_MBB + CASE_RETURN_STRING(SIR_LIM_PREAUTH_MBB_RSP_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_REASSOC_MBB_RSP_TIMEOUT); + +#endif + CASE_RETURN_STRING(SIR_LIM_AUTH_RETRY_TIMEOUT); + CASE_RETURN_STRING(SIR_LIM_MSG_TYPES_END); CASE_RETURN_STRING(LIM_MLM_SCAN_REQ); CASE_RETURN_STRING(LIM_MLM_SCAN_CNF); diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/parserApi.c b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/parserApi.c index a3f30f0653f..142be12bda6 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/parserApi.c +++ b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/parserApi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -50,6 +50,30 @@ #include "rrmApi.h" #endif +#define DOT11F_RSN_VERSION 1 /* current supported version */ +#define DOT11F_RSN_OUI_SIZE 4 +#define DOT11F_RSN_CSE_NULL 0x00 +#define DOT11F_RSN_CSE_WEP40 0x01 +#define DOT11F_RSN_CSE_TKIP 0x02 +#define DOT11F_RSN_CSE_WRAP 0x03 +#define DOT11F_RSN_CSE_CCMP 0x04 +#define DOT11F_RSN_CSE_WEP104 0x05 +#define DOT11F_RSN_CSE_AES_CMAC 0x06 + +static const tANI_U8 sirRSNOui[][ DOT11F_RSN_OUI_SIZE ] = { + { 0x00, 0x0F, 0xAC, 0x00 }, /* group cipher */ + { 0x00, 0x0F, 0xAC, 0x01 }, /* WEP-40 or RSN */ + { 0x00, 0x0F, 0xAC, 0x02 }, /* TKIP or RSN-PSK */ + { 0x00, 0x0F, 0xAC, 0x03 }, /* Reserved */ + { 0x00, 0x0F, 0xAC, 0x04 }, /* AES-CCMP */ + { 0x00, 0x0F, 0xAC, 0x05 }, /* WEP-104 */ + { 0x00, 0x40, 0x96, 0x00 }, /* CCKM */ + /* BIP (encryption type) or RSN-PSK-SHA256 (authentication type) */ + { 0x00, 0x0F, 0xAC, 0x06 }, + /* RSN-8021X-SHA256 (authentication type) */ + { 0x00, 0x0F, 0xAC, 0x05 } +}; + //////////////////////////////////////////////////////////////////////// @@ -2380,6 +2404,7 @@ tSirRetStatus sirConvertProbeFrame2Struct(tpAniSirGlobal pMac, vos_mem_copy( &pProbeResp->VHTExtBssLoad, &pr->VHTExtBssLoad, sizeof( tDot11fIEVHTExtBssLoad) ); } #endif + sir_copy_hs20_ie(&pProbeResp->hs20vendor_ie, &pr->hs20vendor_ie); vos_mem_vfree(pr); return eSIR_SUCCESS; @@ -2708,7 +2733,7 @@ sirConvertAssocRespFrame2Struct(tpAniSirGlobal pMac, #endif #ifdef WLAN_FEATURE_VOWIFI_11R - if (ar.num_RICDataDesc <= 2) { + if (ar.num_RICDataDesc && ar.num_RICDataDesc <= 2) { for (cnt=0; cnt < ar.num_RICDataDesc; cnt++) { if (ar.RICDataDesc[cnt].present) { vos_mem_copy( &pAssocRsp->RICData[cnt], &ar.RICDataDesc[cnt], @@ -3493,6 +3518,8 @@ sirParseBeaconIE(tpAniSirGlobal pMac, vos_mem_copy( &pBeaconStruct->ExtCap, &pBies->ExtCap, sizeof(tDot11fIEExtCap)); } + sir_copy_hs20_ie(&pBeaconStruct->hs20vendor_ie, &pBies->hs20vendor_ie); + vos_mem_free(pBies); @@ -3798,6 +3825,7 @@ sirConvertBeaconFrame2Struct(tpAniSirGlobal pMac, &pBeacon->OBSSScanParameters, sizeof( tDot11fIEOBSSScanParameters)); } + sir_copy_hs20_ie(&pBeaconStruct->hs20vendor_ie, &pBeacon->hs20vendor_ie); vos_mem_vfree(pBeacon); return eSIR_SUCCESS; @@ -5456,4 +5484,137 @@ void PopulateDot11fTimeoutInterval( tpAniSirGlobal pMac, pDot11f->timeoutType = type; pDot11f->timeoutValue = value; } +#ifdef SAP_AUTH_OFFLOAD +tSirRetStatus +sap_auth_offload_construct_rsn_opaque( tDot11fIERSN *pdot11f_rsn, + tDot11fIERSNOpaque *pdot11f) +{ + tANI_U32 data_len=0; + tANI_U8 *ptr; + tANI_U32 element_len=0; + tANI_U32 count=0; + ptr = (tANI_U8 *)pdot11f->data; + if (pdot11f_rsn->present) + { + pdot11f->present = pdot11f_rsn->present; + element_len = sizeof(pdot11f_rsn->version); + vos_mem_copy(ptr, &pdot11f_rsn->version, element_len); + ptr += element_len; + data_len += element_len; + element_len = sizeof(pdot11f_rsn->gp_cipher_suite); + vos_mem_copy(ptr, pdot11f_rsn->gp_cipher_suite, element_len); + ptr += element_len; + data_len += element_len; + + if (pdot11f_rsn->pwise_cipher_suite_count) + { + element_len = sizeof(pdot11f_rsn->pwise_cipher_suite_count); + vos_mem_copy(ptr, + &pdot11f_rsn->pwise_cipher_suite_count, + element_len); + ptr += element_len; + data_len += element_len; + for (count = 0; count < pdot11f_rsn->pwise_cipher_suite_count; + count++) + { + element_len = DOT11F_RSN_OUI_SIZE; + vos_mem_copy(ptr, + &pdot11f_rsn->pwise_cipher_suites[count][0], + element_len); + ptr += element_len; + data_len += element_len; + } + } + + if (pdot11f_rsn->akm_suite_count) + { + element_len = sizeof(pdot11f_rsn->akm_suite_count); + vos_mem_copy(ptr, &pdot11f_rsn->akm_suite_count, element_len); + ptr += element_len; + data_len += element_len; + for (count = 0; count < pdot11f_rsn->akm_suite_count; count++) + { + element_len = DOT11F_RSN_OUI_SIZE; + vos_mem_copy(ptr, + &pdot11f_rsn->akm_suites[count][0], + element_len); + ptr += element_len; + data_len += element_len; + } + } + + element_len = sizeof(pdot11f_rsn->RSN_Cap); + vos_mem_copy(ptr, pdot11f_rsn->RSN_Cap, element_len); + ptr += element_len; + data_len += element_len; + } + pdot11f->num_data = data_len; + return eSIR_SUCCESS; +} + +void +sap_auth_offload_update_rsn_ie( tpAniSirGlobal pmac, + tDot11fIERSNOpaque *pdot11f) +{ + tDot11fIERSN *pdot11f_rsn; + pdot11f_rsn = vos_mem_malloc(sizeof(tDot11fIERSN)); + vos_mem_set(pdot11f_rsn, sizeof(tDot11fIERSN), 0); + /* Assign RSN IE for Software AP Authentication offload security */ + if (pmac->sap_auth_offload && pmac->sap_auth_offload_sec_type) + { + switch (pmac->sap_auth_offload_sec_type) + { + case eSIR_OFFLOAD_WPA2PSK_CCMP: + /* Only Support one kind of Cipher Suit for + * Software AP authentication offload + */ + pdot11f_rsn->present = 1; + pdot11f_rsn->version = 1; + vos_mem_copy(pdot11f_rsn->gp_cipher_suite, + &sirRSNOui[DOT11F_RSN_CSE_CCMP][0], + DOT11F_RSN_OUI_SIZE); + pdot11f_rsn->pwise_cipher_suite_count = 1; + vos_mem_copy(&(pdot11f_rsn->pwise_cipher_suites[0][0]), + &sirRSNOui[DOT11F_RSN_CSE_CCMP][0], + DOT11F_RSN_OUI_SIZE); + pdot11f_rsn->akm_suite_count = 1; + vos_mem_copy(&(pdot11f_rsn->akm_suites[0][0]), + &sirRSNOui[DOT11F_RSN_CSE_TKIP][0], + DOT11F_RSN_OUI_SIZE); + pdot11f_rsn->pmkid_count = 0; + /* Construct RSN IE into RSNOpaque*/ + sap_auth_offload_construct_rsn_opaque(pdot11f_rsn, pdot11f); + break; + default: + dot11fLog( pmac, LOGE, + FL("The security type is not definied for " + "Software AP authentication offload!\n")); + break; + } + } +} +#endif /* SAP_AUTH_OFFLOAD */ + +/** + * sir_copy_hs20_ie() - Update HS 2.0 Information Element. + * @dest: dest HS IE buffer to be updated + * @src: src HS IE buffer + * + * Update HS2.0 IE info from src to dest + * + * Return: void + */ +void sir_copy_hs20_ie(tDot11fIEhs20vendor_ie *dest, tDot11fIEhs20vendor_ie *src) +{ + if (src->present) { + vos_mem_copy(dest, src, + sizeof(tDot11fIEhs20vendor_ie) - + sizeof(src->hs_id)); + if (src->hs_id_present) + vos_mem_copy(&dest->hs_id, + &src->hs_id, + sizeof(src->hs_id)); + } +} + // parserApi.c ends here. diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/utilsParser.c b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/utilsParser.c index 3292b5c4f72..32f19925b22 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/utilsParser.c +++ b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/utilsParser.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2015, 2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -691,6 +691,8 @@ void ConvertQosMapsetFrame(tpAniSirGlobal pMac, tSirQosMapSet* Qos, tDot11fIEQos tANI_U8 i,j=0; if (dot11fIE->num_dscp_exceptions > 58) dot11fIE->num_dscp_exceptions = 58; + if (dot11fIE->num_dscp_exceptions < 16) + return; Qos->num_dscp_exceptions = (dot11fIE->num_dscp_exceptions - 16)/2; for (i=0;i<Qos->num_dscp_exceptions;i++) { diff --git a/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h b/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h index 35d9f7d976b..45f3b9db2f4 100644 --- a/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h +++ b/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -721,7 +721,16 @@ typedef VOS_STATUS (*WLANTL_STARxCBType)( v_PVOID_t pvosGCtx, vos_pkt_t* vosDataBuff, v_U8_t ucSTAId, WLANTL_RxMetaInfoType* pRxMetaInfo); - +/** + * WLANTL_FwdEapolCBType() - Call back to forward Eapol packet + * @pvosGCtx : pointer to vos global context + * @vosDataBuff: pointer to vos packet + * + * Return: None + * + */ +typedef void (*WLANTL_FwdEapolCBType) (v_PVOID_t pvosGCtx, + vos_pkt_t* vosDataBuff); /*---------------------------------------------------------------------------- INTERACTION WITH BAP @@ -3378,6 +3387,39 @@ void WLANTL_ResetRxSSN(v_PVOID_t pvosGCtx, uint8_t ucSTAId); void WLANTL_SetDataPktFilter(v_PVOID_t pvosGCtx, uint8_t ucSTAId, bool flag); /** + * WLANTL_SampleTx() - collect tx samples + * @data: TL context pointer + * + * This function records the frames fetched from stations + * during TX sample interval + * + * Return: void + */ +void WLANTL_SampleTx(void *data); + +/* + * WLANTL_EnablePreAssocCaching - Enable caching during pre-assoc + * @staid: sta client where frames are cached + * + * Return: none + */ +void WLANTL_EnablePreAssocCaching(void); + +/* + * WLANTL_PreAssocForward - Forward the cached packets + * + * This function forwards or flushes the packets after + * pre assoc success/failure. + * + * Return: none + */ +void WLANTL_PreAssocForward(bool flag); + +/* make before break */ +void WLANTL_RegisterFwdEapol(v_PVOID_t pvosGCtx, + WLANTL_FwdEapolCBType pfnFwdEapol); + +/** * WLANTL_SetARPFWDatapath() - keep or remove FW in data path for ARP * @pvosGCtx: global vos context * @flag: value to keep or remove FW from data path diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c index 09754b8a967..e5786c036f9 100644..100755 --- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c +++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -243,6 +243,12 @@ int bdPduInterruptGetThreshold = WLANTL_BD_PDU_INTERRUPT_GET_THRESHOLD; #define ENABLE_ARP_TOGGLE 1 #define SEND_ARP_ON_WQ5 2 +#define WLANTL_RATE_RATIO_THRESHOLD 2 +#define WLANTL_PER_THRESHOLD 5 +#define WLANTL_QUEUE_THRESHOLD 60 +#define WLANTL_GOOD_STA_WEIGHT 1 +#define WLANTL_WEIGHT_THRESHOLD 50 + /*---------------------------------------------------------------------------- * Type Declarations * -------------------------------------------------------------------------*/ @@ -692,10 +698,12 @@ WLANTL_Open } // scheduling init to be the last one of previous round - pTLCb->uCurServedAC = WLANTL_AC_BK; - pTLCb->ucCurLeftWeight = 1; + pTLCb->uCurServedAC = WLANTL_AC_VO; + pTLCb->ucCurLeftWeight = pTLCb->tlConfigInfo.ucAcWeights[pTLCb->uCurServedAC]; pTLCb->ucCurrentSTA = WLAN_MAX_STA_COUNT-1; + vos_timer_init(&pTLCb->tx_frames_timer, VOS_TIMER_TYPE_SW, + WLANTL_SampleTx, (void *)pTLCb); #if 0 //flow control field init vos_mem_zero(&pTLCb->tlFCInfo, sizeof(tFcTxParams_type)); @@ -833,8 +841,10 @@ WLANTL_Start /* Enable transmission */ vos_atomic_set_U8( &pTLCb->ucTxSuspended, 0); - pTLCb->uResCount = uResCount; + + vos_timer_start(&pTLCb->tx_frames_timer, WLANTL_SAMPLE_INTERVAL); + return VOS_STATUS_SUCCESS; }/* WLANTL_Start */ @@ -917,6 +927,10 @@ WLANTL_Stop } #endif + if (VOS_TIMER_STATE_STOPPED != + vos_timer_getCurrentState(&pTLCb->tx_frames_timer)) + vos_timer_stop(&pTLCb->tx_frames_timer); + /*------------------------------------------------------------------------- Clean client stations -------------------------------------------------------------------------*/ @@ -1011,6 +1025,15 @@ WLANTL_Close } #endif + if (VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&pTLCb->tx_frames_timer)) { + vos_timer_stop(&pTLCb->tx_frames_timer); + } + if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(&pTLCb->tx_frames_timer))) { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "%s: Cannot deallocate TX frames sample timer", __func__)); + } + /*------------------------------------------------------------------------ Cleanup TL control block. ------------------------------------------------------------------------*/ @@ -4912,6 +4935,8 @@ WLANTL_GetFrames pClientSTA->uBuffThresholdMax = (pClientSTA->uBuffThresholdMax >= uResLen) ? (pClientSTA->uBuffThresholdMax - uResLen) : 0; + pClientSTA->tx_frames ++; + } else { @@ -5950,6 +5975,153 @@ WLANTL_ProcessFCFrame return VOS_STATUS_SUCCESS; } +/** + * WLANTL_FlowControl() - TX Flow control + * @pTLCb: TL context pointer + * @pvosDataBuff: Firmware indication data buffer + * + * This function implenets the algorithm to flow control TX traffic in case + * of SAP and SAP + STA concurrency. + * + * Algorithm goal is to fetch more packets from good peer than bad peer by + * introducing weights for each station connected. Weight of each station is + * calcutated by taking ratio of max RA rate of the peers to its rate. If the + * ratio is less than two based on number of queued frames in the station BTQM + * weight is modified. If the queued frames reaches the defined threshold weight + * is assigned as four. Here weight is inversely proportional to the number of + * packets fetch. + * + * Return true if flow controlled or false otherwise. + */ +static bool WLANTL_FlowControl(WLANTL_CbType* pTLCb, vos_pkt_t* pvosDataBuff) +{ + WLANTL_FlowControlInfo *fc_data = NULL; + WLANTL_PerStaFlowControlParam *sta_fc_params = NULL; + uint8_t num_stas; + struct sk_buff *skb = NULL; + uint16_t data_len; + uint8_t *staid; + uint16_t max_rate = 0; + uint8_t i; + + vos_pkt_get_packet_length(pvosDataBuff, &data_len); + if (!data_len) { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "%s: Null fw indication data", __func__)); + return false; + } + + vos_pkt_get_os_packet(pvosDataBuff, (v_VOID_t **)&skb, 0); + fc_data = (WLANTL_FlowControlInfo *)skb->data; + num_stas = fc_data->num_stas; + if (!num_stas) { + TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, + "%s: No connected stations", __func__)); + return true; + } + + /* Skip flow control for one connected station */ + if (1 == num_stas) + return true; + + staid = (uint8_t *)vos_mem_malloc(WLAN_MAX_STA_COUNT); + if (!staid) { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "%s: mem allocation failure", __func__)); + return false; + } + vos_mem_set((uint8_t *)staid, WLAN_MAX_STA_COUNT, 0); + + sta_fc_params = (WLANTL_PerStaFlowControlParam *)(&fc_data->num_stas + 1); + + for(i = 0; i < num_stas; i ++, sta_fc_params ++) { + staid[i] = sta_fc_params->sta_id; + + if (!pTLCb->atlSTAClients[staid[i]]) + continue; + + pTLCb->atlSTAClients[staid[i]]->per = sta_fc_params->avg_per; + pTLCb->atlSTAClients[staid[i]]->queue = sta_fc_params->queue_len; + pTLCb->atlSTAClients[staid[i]]->trate = sta_fc_params->rate; + max_rate = max_rate > pTLCb->atlSTAClients[staid[i]]->trate ? + max_rate : pTLCb->atlSTAClients[staid[i]]->trate; + + TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: sta_id:%d in:%d queue:%d avg_per:%d rate:%d", __func__, + staid[i], pTLCb->atlSTAClients[staid[i]]->tx_samples_sum, + pTLCb->atlSTAClients[staid[i]]->queue, + pTLCb->atlSTAClients[staid[i]]->per, + pTLCb->atlSTAClients[staid[i]]->trate)); + } + + for (i = 0; i < num_stas; i++) { + pTLCb->atlSTAClients[staid[i]]->weight = + max_rate/pTLCb->atlSTAClients[staid[i]]->trate; + if (pTLCb->atlSTAClients[staid[i]]->weight >= + WLANTL_RATE_RATIO_THRESHOLD) { + if (!pTLCb->atlSTAClients[staid[i]]->set_flag) { + vos_set_hdd_bad_sta(staid[i]); + pTLCb->atlSTAClients[staid[i]]->set_flag = true; + } + /** + * If station's link becomes very bad rssi below -90dbm then because + * of high PER rate high number of packets are stuck in BTQM which is + * affecting the good peers throughput. So throttle further the bad + * link traffic. + */ + if ((pTLCb->atlSTAClients[staid[i]]->weight > + WLANTL_WEIGHT_THRESHOLD) && + (pTLCb->atlSTAClients[staid[i]]->queue > + WLANTL_QUEUE_THRESHOLD)) + pTLCb->atlSTAClients[staid[i]]->weight *= 2; + } + if (pTLCb->atlSTAClients[staid[i]]->weight < + WLANTL_RATE_RATIO_THRESHOLD) { + if (pTLCb->atlSTAClients[staid[i]]->per >= WLANTL_PER_THRESHOLD && + pTLCb->atlSTAClients[staid[i]]->queue > WLANTL_QUEUE_THRESHOLD + && !pTLCb->atlSTAClients[staid[i]]->set_flag) { + pTLCb->atlSTAClients[staid[i]]->weight *= 2; + vos_set_hdd_bad_sta(staid[i]); + pTLCb->atlSTAClients[staid[i]]->set_flag = true; + } + else if (pTLCb->atlSTAClients[staid[i]]->set_flag) { + vos_reset_hdd_bad_sta(staid[i]); + pTLCb->atlSTAClients[staid[i]]->set_flag = false; + } + } + } + vos_mem_free(staid); + return true; +} + +/** + * WLANTL_CacheEapol() - cache eapol frames + * @pTLCb : pointer to TL context + * @vosTempBuff: pointer to vos packet buff + * + * Return: None + * + */ +static void WLANTL_CacheEapol(WLANTL_CbType* pTLCb, vos_pkt_t* vosTempBuff) +{ + if ((NULL == pTLCb) || (NULL == vosTempBuff)) + { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid input pointer", __func__)); + return; + } + + if (NULL == pTLCb->vosEapolCachedFrame) { + TLLOG1(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, + "%s: Cache Eapol frame", __func__)); + pTLCb->vosEapolCachedFrame = vosTempBuff; + } + else { + TLLOG1(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, + "%s: Drop duplicate EAPOL frame", __func__)); + vos_pkt_return_packet(vosTempBuff); + } +} /*========================================================================== @@ -6014,8 +6186,10 @@ WLANTL_RxFrames #ifdef WLAN_FEATURE_LINK_LAYER_STATS v_S7_t currentAvgRSSI = 0; v_U8_t ac; - #endif + uint8_t ucMPDUHLen; + uint16_t seq_no; + uint16_t usEtherType = 0; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ @@ -6053,7 +6227,7 @@ WLANTL_RxFrames ---------------------------------------------------------------------*/ vosTempBuff = vosDataBuff; - while ( NULL != vosTempBuff ) + while (NULL != vosDataBuff) { broadcast = VOS_FALSE; selfBcastLoopback = VOS_FALSE; @@ -6094,7 +6268,8 @@ WLANTL_RxFrames TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, "WLAN TL:receive one FC frame")); - WLANTL_ProcessFCFrame(pvosGCtx, vosTempBuff, pvBDHeader); + WLANTL_FlowControl(pTLCb, vosTempBuff); + /* Drop packet */ vos_pkt_return_packet(vosTempBuff); vosTempBuff = vosDataBuff; @@ -6194,6 +6369,9 @@ WLANTL_RxFrames { ucSTAId = (v_U8_t)WDA_GET_RX_STAID( pvBDHeader ); ucTid = (v_U8_t)WDA_GET_RX_TID( pvBDHeader ); + uDPUSig = WDA_GET_RX_DPUSIG(pvBDHeader); + ucMPDUHLen = (uint8_t)WDA_GET_RX_MPDU_HEADER_LEN(pvBDHeader); + seq_no = (uint16_t)WDA_GET_RX_REORDER_CUR_PKT_SEQ_NO(pvBDHeader); TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, "WLAN TL:Data packet received for STA %d", ucSTAId)); @@ -6218,6 +6396,28 @@ WLANTL_RxFrames } }/*if bcast*/ + /* Pre assoc cache eapol */ + if (pTLCb->preassoc_caching) + { + WLANTL_GetEtherType(pvBDHeader,vosTempBuff, ucMPDUHLen, &usEtherType); + if (WLANTL_LLC_8021X_TYPE != usEtherType) + { + VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, + "%s: RX Frame not EAPOL EtherType %d", + __func__, usEtherType); + vos_pkt_return_packet(vosTempBuff); + } + else + { + WLANTL_CacheEapol(pTLCb, vosTempBuff); + TLLOG1(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, + "WLAN TL:TL preassoc_caching is enabled seq No: %d", seq_no)); + } + + vosTempBuff = vosDataBuff; + continue; + } + if (WLANTL_STA_ID_INVALID(ucSTAId)) { TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, @@ -6328,8 +6528,7 @@ WLANTL_RxFrames vosTempBuff = vosDataBuff; continue; } - uDPUSig = WDA_GET_RX_DPUSIG( pvBDHeader ); - //Station has not yet been registered with TL - cache the frame + /* Station has not yet been registered with TL - cache the frame */ TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, "%s: staId %d exist %d tlState %d cache rx frame", __func__, ucSTAId, pClientSTA->ucExists, pClientSTA->tlState)); @@ -6941,6 +7140,47 @@ WLANTL_RxCachedFrames return VOS_STATUS_SUCCESS; }/* WLANTL_RxCachedFrames */ +/** + * WLANTL_ForwardPkts() - forward cached eapol frames + * @pvosGCtx: pointer to vos global context + * @data: value to indicate either forward or flush + * + * Return: None + * + */ +static VOS_STATUS WLANTL_ForwardPkts(void* pvosGCtx, uint32_t data) +{ + WLANTL_CbType* pTLCb = NULL; + + pTLCb = VOS_GET_TL_CB(pvosGCtx); + if (NULL == pTLCb) { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid input pointer", __func__)); + return VOS_STATUS_E_FAULT; + } + + if (!data) { + TLLOG2(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Pre assoc fail flush cache", __func__)); + WLANTL_FlushCachedFrames(pTLCb->vosEapolCachedFrame); + goto done; + } + + /* forward packets to HDD */ + if (NULL != pTLCb->vosEapolCachedFrame) { + TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: forward pre assoc cached frames", __func__)); + WLANTL_MonTranslate80211To8023Header(pTLCb->vosEapolCachedFrame, pTLCb); + pTLCb->pfnEapolFwd(pvosGCtx, pTLCb->vosEapolCachedFrame); + } + +done: + pTLCb->vosEapolCachedFrame = NULL; + pTLCb->preassoc_caching = false; + + return VOS_STATUS_SUCCESS; +} + /*========================================================================== FUNCTION WLANTL_RxProcessMsg @@ -7018,6 +7258,11 @@ WLANTL_RxProcessMsg ucUcastSig, ucBcastSig); break; + case WLANTL_RX_FWD_PRE_ASSOC_CACHED: + uData = message->bodyval; + vosStatus = WLANTL_ForwardPkts(pvosGCtx, uData); + break; + default: /*no processing for now*/ break; @@ -8309,13 +8554,11 @@ WLANTL_STATxAuth { if (pTLCb->track_arp) { - if (vos_check_arp_req_target_ip(vosDataBuff->pSkb, true)) + if (vos_check_arp_target_ip(vosDataBuff)) { ucTxFlag |= HAL_USE_FW_IN_TX_PATH; ucTxFlag |= HAL_TXCOMP_REQUESTED_MASK; tlMetaInfo.ucTxBdToken = ++ pTLCb->txbd_token; - TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, - "%s: ARP packet FW in data path", __func__)); } } @@ -11428,12 +11671,15 @@ WLAN_TLAPGetNextTxIds { WLANTL_CbType* pTLCb; v_U8_t ucACFilter = 1; - v_U8_t ucNextSTA ; + v_U8_t ucNextSTA, ucTempSTA; v_BOOL_t isServed = TRUE; //current round has find a packet or not v_U8_t ucACLoopNum = WLANTL_AC_HIGH_PRIO + 1; //number of loop to go v_U8_t uFlowMask; // TX FlowMask from WDA uint8 ucACMask; - uint8 i = 0; + uint8 i = 0; + uint8 j; + uint8 minWeightSta; + uint32_t sta_bitmask = 0; /*------------------------------------------------------------------------ Extract TL control block ------------------------------------------------------------------------*/ @@ -11475,10 +11721,8 @@ WLAN_TLAPGetNextTxIds ++ucNextSTA; if ( WLAN_MAX_STA_COUNT <= ucNextSTA ) - { - //one round is done. ucNextSTA = 0; - pTLCb->ucCurLeftWeight--; + isServed = FALSE; if ( 0 == pTLCb->ucCurLeftWeight ) { @@ -11496,7 +11740,9 @@ WLAN_TLAPGetNextTxIds pTLCb->ucCurLeftWeight = pTLCb->tlConfigInfo.ucAcWeights[pTLCb->uCurServedAC]; } // (0 == pTLCb->ucCurLeftWeight) - } //( WLAN_MAX_STA_COUNT == ucNextSTA ) + + ucTempSTA = ucNextSTA; + minWeightSta = ucNextSTA; //decide how many loops to go. if current loop is partial, do one extra to make sure //we cover every station @@ -11554,6 +11800,30 @@ WLAN_TLAPGetNextTxIds continue; } + /* + * Initial weight is 0 is for all the stations. As part of FW TX stats + * indication to host, good peer weight is updated to one and the + * remaining peers weight is updated based on their RA rates and BTQM + * queued frames length. TL skips fetching the packet until the station + * has got chances equal to its weight. + */ + if (pTLCb->atlSTAClients[ucNextSTA]->weight > WLANTL_GOOD_STA_WEIGHT) { + if (pTLCb->atlSTAClients[ucNextSTA]->weight_count <= + pTLCb->atlSTAClients[ucNextSTA]->weight) + { + if (pTLCb->atlSTAClients[minWeightSta]->weight <= 1) + minWeightSta = ucNextSTA; + else if (pTLCb->atlSTAClients[ucNextSTA]->weight < + pTLCb->atlSTAClients[minWeightSta]->weight) { + minWeightSta = ucNextSTA; + } + sta_bitmask |= (1 << ucNextSTA); + pTLCb->atlSTAClients[ucNextSTA]->weight_count++; + continue; + } + else + pTLCb->atlSTAClients[ucNextSTA]->weight_count = 0; + } // Find a station. Weight is updated already. *pucSTAId = ucNextSTA; @@ -11564,9 +11834,92 @@ WLAN_TLAPGetNextTxIds " TL serve one station AC: %d W: %d StaId: %d", pTLCb->uCurServedAC, pTLCb->ucCurLeftWeight, pTLCb->ucCurrentSTA )); + pTLCb->ucCurLeftWeight--; return VOS_STATUS_SUCCESS; } //STA loop + for (j = 0; j < ucTempSTA; j++) { + if (NULL == pTLCb->atlSTAClients[j]) + continue; + + WLAN_TL_AC_ARRAY_2_MASK (pTLCb->atlSTAClients[j], ucACMask, i); + + if ((0 == pTLCb->atlSTAClients[j]->ucExists) || + ((0 == pTLCb->atlSTAClients[j]->ucPktPending) && !(ucACMask)) || + (0 == (ucACMask & ucACFilter))) + continue; + + if ((WLANTL_STA_AUTHENTICATED != pTLCb->atlSTAClients[j]->tlState) || + (pTLCb->atlSTAClients[j]->disassoc_progress == VOS_TRUE)) { + TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, + "%s Sta %d not in auth state so skipping it.", + __func__, ucNextSTA)); + continue; + } + + if ((TRUE == pTLCb->atlSTAClients[j]->ucLwmModeEnabled) && + ((FALSE == pTLCb->atlSTAClients[j]->ucLwmEventReported) || + (0 < pTLCb->atlSTAClients[j]->uBuffThresholdMax))) + continue; + + if (pTLCb->atlSTAClients[j]->weight > WLANTL_GOOD_STA_WEIGHT) { + if (pTLCb->atlSTAClients[j]->weight_count <= + pTLCb->atlSTAClients[j]->weight) + { + if (pTLCb->atlSTAClients[minWeightSta]->weight <= 1) + minWeightSta = j; + else if (pTLCb->atlSTAClients[j]->weight < + pTLCb->atlSTAClients[minWeightSta]->weight) { + minWeightSta = j; + } + sta_bitmask |= (1 << j); + pTLCb->atlSTAClients[j]->weight_count++; + continue; + } + else + pTLCb->atlSTAClients[j]->weight_count = 0; + } + + *pucSTAId = j; + pTLCb->ucCurrentSTA = j; + pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC = pTLCb->uCurServedAC; + + TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW, + " TL serve one station AC: %d W: %d StaId: %d", + pTLCb->uCurServedAC, pTLCb->ucCurLeftWeight, pTLCb->ucCurrentSTA )); + pTLCb->ucCurLeftWeight--; + return VOS_STATUS_SUCCESS; + } + + /* Fecth packet from the stations with minimum weight among them */ + if (pTLCb->atlSTAClients[minWeightSta] && + pTLCb->atlSTAClients[minWeightSta]->ucPktPending) + { + *pucSTAId = minWeightSta; + pTLCb->ucCurrentSTA = minWeightSta; + pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC = pTLCb->uCurServedAC; + + for (j = 0; sta_bitmask != 0; sta_bitmask >>= 1, j++) + { + if (0 == (sta_bitmask & 0x1)) + continue; + + if (minWeightSta == j) + continue; + /* To ensure fairness between stations */ + pTLCb->atlSTAClients[j]->weight_count += + pTLCb->atlSTAClients[minWeightSta]->weight - + pTLCb->atlSTAClients[minWeightSta]->weight_count; + } + pTLCb->atlSTAClients[minWeightSta]->weight_count = 0; + + TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW, + " TL serve one station AC: %d W: %d StaId: %d", + pTLCb->uCurServedAC, pTLCb->ucCurLeftWeight, pTLCb->ucCurrentSTA )); + pTLCb->ucCurLeftWeight--; + return VOS_STATUS_SUCCESS; + } + ucNextSTA = 0; if ( FALSE == isServed ) { @@ -11722,6 +12075,18 @@ WLAN_TLGetNextTxIds { continue; } + + if ((pTLCb->atlSTAClients[ucNextSTA]->weight > WLANTL_GOOD_STA_WEIGHT) && + (pTLCb->atlSTAClients[ucNextSTA]->ucPktPending)) { + if (pTLCb->atlSTAClients[ucNextSTA]->weight_count <= + pTLCb->atlSTAClients[ucNextSTA]->weight) { + pTLCb->atlSTAClients[ucNextSTA]->weight_count++; + continue; + } + else + pTLCb->atlSTAClients[ucNextSTA]->weight_count = 0; + } + if (( pTLCb->atlSTAClients[ucNextSTA]->ucExists ) && ( pTLCb->atlSTAClients[ucNextSTA]->ucPktPending )) { @@ -13828,7 +14193,169 @@ void WLANTL_ResetRxSSN(v_PVOID_t pvosGCtx, uint8_t ucSTAId) } } +void WLANTL_SetDataPktFilter(v_PVOID_t pvosGCtx, uint8_t ucSTAId, bool flag) +{ + WLANTL_CbType* pTLCb = NULL; + WLANTL_STAClientType* pClientSTA = NULL; + uint8_t i; + + if (WLANTL_STA_ID_INVALID(ucSTAId)) { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid station id requested", __func__)); + return; + } + + pTLCb = VOS_GET_TL_CB(pvosGCtx); + if (NULL == pTLCb) { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid TL pointer from pvosGCtx", __func__)); + return; + } + + pClientSTA = pTLCb->atlSTAClients[ucSTAId]; + + for (i = 0; i < WLAN_MAX_TID ; i++) { + if (0 == pClientSTA->atlBAReorderInfo[i].ucExists) + continue; + + TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, + "WLAN TL: Last RxSSN reset to zero for tid %d", i)); + pClientSTA->atlBAReorderInfo[i].set_data_filter = flag; + } +} + +/** + * WLANTL_ShiftArrByOne() - utility function to shift array by one + * @arr: pointer to array + * @len: length of the array + * + * Caller responsibility to provide the correct length of the array + * other may leads to bugs. + * + * Return: void + */ +static void WLANTL_ShiftArrByOne(uint32_t *arr, uint8_t len) +{ + int i; + for (i = 0; i < len - 1; i ++) + arr[i] = arr[i + 1]; + arr[i] = 0; +} + +/** + * WLANTL_SampleTx() - collect tx samples + * @data: TL context pointer + * + * This function records the last five tx bytes sent samples + * collected after tx_bytes_timer expire. + * + * Return: void + */ +void WLANTL_SampleTx(void *data) +{ + WLANTL_CbType* pTLCb = (WLANTL_CbType *)data; + WLANTL_STAClientType* pClientSTA = NULL; + uint8_t count = pTLCb->sample_count; + uint8_t i; + + for ( i = 0; i < WLAN_MAX_STA_COUNT; i++) { + if (NULL != pTLCb->atlSTAClients[i] && + pTLCb->atlSTAClients[i]->ucExists) { + pClientSTA = pTLCb->atlSTAClients[i]; + + if (count > (WLANTL_SAMPLE_COUNT - 1)) { + count = WLANTL_SAMPLE_COUNT - 1; + pClientSTA->tx_samples_sum -= pClientSTA->tx_sample[0]; + WLANTL_ShiftArrByOne(pClientSTA->tx_sample, WLANTL_SAMPLE_COUNT); + } + + pClientSTA->tx_sample[count] = pClientSTA->tx_frames; + pClientSTA->tx_samples_sum += pClientSTA->tx_sample[count]; + pClientSTA->tx_frames = 0; + count++; + pTLCb->sample_count = count; + } + } + + vos_timer_start(&pTLCb->tx_frames_timer, WLANTL_SAMPLE_INTERVAL); +} + /** + * WLANTL_EnablePreAssocCaching() - Enable caching EAPOL frames + * + * Return: None + * + */ +void WLANTL_EnablePreAssocCaching(void) +{ + v_PVOID_t pvosGCtx= vos_get_global_context(VOS_MODULE_ID_TL,NULL); + WLANTL_CbType* pTLCb = VOS_GET_TL_CB(pvosGCtx); + if (NULL == pTLCb ) { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid TL pointer for global context", __func__)); + return; + } + + pTLCb->vosEapolCachedFrame = NULL; + pTLCb->preassoc_caching = true; +} + +/** + * WLANTL_ForwardPreAssoc() - forward cached eapol frames + * @flag: Value to forward or flush + * + * Return: vos status + * + */ +static VOS_STATUS WLANTL_ForwardPreAssoc(bool flag) +{ + vos_msg_t sMessage; + + VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + " ---- Serializing TL for forwarding pre assoc cache frames"); + + vos_mem_zero( &sMessage, sizeof(vos_msg_t)); + sMessage.type = WLANTL_RX_FWD_PRE_ASSOC_CACHED; + sMessage.bodyval = flag; + + return vos_rx_mq_serialize(VOS_MQ_ID_TL, &sMessage); +} + +/** + * WLANTL_PreAssocForward() - forward cached eapol frames + * @flag: Value to forward or flush + * + * Return: None + * + */ +void WLANTL_PreAssocForward(bool flag) +{ + if(!VOS_IS_STATUS_SUCCESS(WLANTL_ForwardPreAssoc(flag))) + { + VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + " %s fails to forward packets", __func__); + } +} + +/** + * WLANTL_RegisterFwdEapol() - register call back to forward cached eapol frame + * @pvosGCtx : pointer to vos global context + * @pfnFwdEapol: call back function pointer + * + * Return: None + * + */ +void WLANTL_RegisterFwdEapol(v_PVOID_t pvosGCtx, + WLANTL_FwdEapolCBType pfnFwdEapol) +{ + WLANTL_CbType* pTLCb = NULL; + pTLCb = VOS_GET_TL_CB(pvosGCtx); + + pTLCb->pfnEapolFwd = pfnFwdEapol; + +} + + /** * WLANTL_SetARPFWDatapath() - keep or remove FW in data path for ARP * * @flag: value to keep or remove FW from data path @@ -14464,34 +14991,3 @@ WLANTL_SetMcastDuplicateDetection } #endif /* WLAN_FEATURE_RMC */ - -void WLANTL_SetDataPktFilter(v_PVOID_t pvosGCtx, uint8_t ucSTAId, bool flag) -{ - WLANTL_CbType* pTLCb = NULL; - WLANTL_STAClientType* pClientSTA = NULL; - uint8_t i; - - if (WLANTL_STA_ID_INVALID(ucSTAId)) { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "%s: Invalid station id requested", __func__)); - return; - } - - pTLCb = VOS_GET_TL_CB(pvosGCtx); - if (NULL == pTLCb) { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "%s: Invalid TL pointer from pvosGCtx", __func__)); - return; - } - - pClientSTA = pTLCb->atlSTAClients[ucSTAId]; - - for (i = 0; i < WLAN_MAX_TID ; i++) { - if (0 == pClientSTA->atlBAReorderInfo[i].ucExists) - continue; - - TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, - "WLAN TL: Last RxSSN reset to zero for tid %d", i)); - pClientSTA->atlBAReorderInfo[i].set_data_filter = flag; - } -} diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c index ccfcfb0c699..b97af6cfdf1 100644 --- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c +++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c @@ -1166,10 +1166,7 @@ VOS_STATUS WLANTL_MSDUReorder "(QCUR_FWDBUF) dropping old frame, SN=%d LastSN=%d", CSN, currentReorderInfo->LastSN)); if (vos_is_arp_pkt((*vosDataBuff)->pSkb, true)) - { - if (vos_check_arp_rsp_src_ip((*vosDataBuff)->pSkb, true)) - vos_update_arp_rx_drop_reorder(); - } + vos_update_arp_rx_drop_reorder(); status = vos_pkt_return_packet(*vosDataBuff); if (!VOS_IS_STATUS_SUCCESS(status)) diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h b/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h index fdb5898b8fb..cb6414a6143 100644 --- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h +++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -190,6 +190,9 @@ when who what, where, why #define WLANTL_RMC_HASH_TABLE_SIZE (32) #endif +#define WLANTL_SAMPLE_INTERVAL 50 +#define WLANTL_SAMPLE_COUNT 2 + /*------------------------------------------------------------------------- BT-AMP related definition - !!! should probably be moved to BT-AMP header ---------------------------------------------------------------------------*/ @@ -302,6 +305,8 @@ typedef enum /* Forwarding RX cached frames */ WLANTL_RX_FWD_CACHED = 0, + /* Forward pre assoc cached frames */ + WLANTL_RX_FWD_PRE_ASSOC_CACHED = 1, }WLANTL_RxSignalsType; /*--------------------------------------------------------------------------- @@ -727,6 +732,20 @@ typedef struct /* Disassoc in progress */ v_BOOL_t disassoc_progress; + + /* sample timer Tx frames */ + uint64_t tx_frames; + uint32_t tx_sample[WLANTL_SAMPLE_COUNT]; + uint64_t tx_samples_sum; + + /* flow control */ + uint8_t weight; + uint8_t weight_count; + uint8_t per; + uint8_t set_flag; + uint16_t queue; + uint16_t trate; + }WLANTL_STAClientType; /*--------------------------------------------------------------------------- @@ -811,6 +830,19 @@ typedef struct vos_lock_t hosLock; } WLANTL_HO_SUPPORT_TYPE; +typedef struct { + uint8 sta_id; + uint8 avg_per; + uint16 queue_len; + uint16_t rate; + uint16_t reserved; +} WLANTL_PerStaFlowControlParam; + +typedef struct { + uint8 num_stas; + WLANTL_PerStaFlowControlParam *sta_fc_info; +} WLANTL_FlowControlInfo; + #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD #define ROAM_MAX_INDEX_NUM 50 #define ROAM_PER_INDEX_TIME 500 /* (msec) */ @@ -967,8 +999,17 @@ typedef struct WLANTL_RoamMonitorType gDsRxRoamStats; #endif + /* TX sample data timer */ + vos_timer_t tx_frames_timer; + uint8_t sample_count; + + bool preassoc_caching; + vos_pkt_t* vosEapolCachedFrame; + WLANTL_FwdEapolCBType pfnEapolFwd; + uint8_t track_arp; uint32_t txbd_token; + }WLANTL_CbType; diff --git a/drivers/staging/prima/CORE/VOSS/inc/event_defs.h b/drivers/staging/prima/CORE/VOSS/inc/event_defs.h index 690745667e7..869017202a4 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/event_defs.h +++ b/drivers/staging/prima/CORE/VOSS/inc/event_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -1911,6 +1911,8 @@ typedef enum EVENT_OFFLOAD_REQ = 0xAB8, EVENT_TDLS_SCAN_BLOCK = 0xAB9, EVENT_WLAN_TX_RX_MGMT = 0xABA, + EVENT_WLAN_SSR_REINIT_SUBSYSTEM = 0xB3C, + EVENT_WLAN_SSR_SHUTDOWN_SUBSYSTEM = 0xB3D, EVENT_NEXT_UNUSED_EVENT, EVENT_RSVD_START = 0x0800, EVENT_RSVD_END = 0x083F, diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_api.h b/drivers/staging/prima/CORE/VOSS/inc/vos_api.h index 4e5882db702..5c7fd8c0e7c 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/vos_api.h +++ b/drivers/staging/prima/CORE/VOSS/inc/vos_api.h @@ -517,21 +517,21 @@ v_BOOL_t vos_isLoadUnloadInProgress(void); bool vos_get_rx_wow_dump(void); void vos_set_rx_wow_dump(bool value); +void vos_set_hdd_bad_sta(uint8_t sta_id); +void vos_reset_hdd_bad_sta(uint8_t sta_id); + void vos_probe_threads(void); void vos_per_pkt_stats_to_user(void *perPktStat); void vos_updatePktStatsInfo(void * pktStat); bool vos_is_wlan_logging_enabled(void); v_BOOL_t vos_is_probe_rsp_offload_enabled(void); +void vos_set_snoc_high_freq_voting(bool enable); void vos_smd_dump_stats(void); void vos_log_wdi_event(uint16 msg, vos_wdi_trace_event_type event); void vos_dump_wdi_events(void); -bool vos_check_arp_target_ip(void *pSkb, bool conversion); -bool vos_check_arp_req_target_ip(void *pSkb, bool conversion); -bool vos_check_arp_src_ip(void *pSkb, bool conversion); -bool vos_check_arp_rsp_src_ip(void *pSkb, bool conversion); +bool vos_check_arp_target_ip(vos_pkt_t *pPacket); void vos_update_arp_fw_tx_delivered(void); void vos_update_arp_rx_drop_reorder(void); -void vos_set_snoc_high_freq_voting(bool enable); #endif // if !defined __VOS_NVITEM_H diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_diag_core_event.h b/drivers/staging/prima/CORE/VOSS/inc/vos_diag_core_event.h index c52a6f56033..ac7b39b2aea 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/vos_diag_core_event.h +++ b/drivers/staging/prima/CORE/VOSS/inc/vos_diag_core_event.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -385,6 +385,47 @@ struct vos_event_wlan_log_complete { uint32_t reserved; }; +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_SSR_REINIT_SUBSYSTEM + ------------------------------------------------------------------------*/ +/** + * struct host_event_wlan_css - Holds diag event details + * @status: Indicates the status of event + * + * This structure holds the host diag event related information + */ + +struct host_event_wlan_ssr_reinit { + uint32_t status; +}; + +/*------------------------------------------------------------------------- + Event ID: EVENT_WLAN_SSR_SHUTDOWN_SUBSYSTEM + ------------------------------------------------------------------------*/ +/** + * struct host_event_wlan_ssr_shutdown - Holds diag event details + * @status: Indicates the status of event + * + * This structure holds the host diag event related information + */ + +struct host_event_wlan_ssr_shutdown { + uint32_t status; +}; + +/*------------------------------------------------------------------------- + Function declarations and documenation + ------------------------------------------------------------------------*/ +/** + * enum host_ssr_events - Enum containing ssr subtype + * @SSR_SUB_SYSTEM_REINIT: Indicate ssr reinit state + * @SSR_SUB_SYSTEM_SHUTDOWN: Indicate ssr shutdown state + * + */ +enum host_ssr_events { + SSR_SUB_SYSTEM_REINIT, + SSR_SUB_SYSTEM_SHUTDOWN, +}; /*------------------------------------------------------------------------- Function declarations and documenation @@ -413,6 +454,7 @@ enum wake_lock_reason { WIFI_POWER_EVENT_WAKELOCK_ROC, WIFI_POWER_EVENT_WAKELOCK_HOLD_RX, WIFI_POWER_EVENT_WAKELOCK_SAP, + WIFI_POWER_EVENT_WAKELOCK_FIND_AP_INDICATION, }; #ifdef __cplusplus diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h b/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h index 06e8e2c9ef2..ad838d7bcf9 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h +++ b/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h @@ -53,16 +53,6 @@ #define VOS_PKT_PROTO_TYPE_EAPOL 0x02 #define VOS_PKT_PROTO_TYPE_DHCP 0x04 #define VOS_PKT_PROTO_TYPE_ARP 0x08 - -/* ARP packet offset values */ -#define VOS_PKT_ARP_OPCODE_OFFSET 20 -#define VOS_PKT_ARPOP_REQUEST 1 -#define VOS_PKT_ARPOP_REPLY 2 -#define VOS_ARP_TARGET_IP_OFFSET 38 -#define VOS_ARP_SRC_IP_OFFSET 28 - -#define VOS_80211_8023_HEADER_OFFSET 20 - /*-------------------------------------------------------------------------- Type declarations ------------------------------------------------------------------------*/ diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_timer.h b/drivers/staging/prima/CORE/VOSS/inc/vos_timer.h index 70a09772169..12e2f7cc13c 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/vos_timer.h +++ b/drivers/staging/prima/CORE/VOSS/inc/vos_timer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -326,6 +326,20 @@ VOS_STATUS vos_timer_stop( vos_timer_t *timer ); ------------------------------------------------------------------------*/ v_TIME_t vos_timer_get_system_ticks( v_VOID_t ); +/** + * vos_system_time_after() - Check if a is later than b + * @a: Time stamp value a + * @b: Time stamp value b + * + * Return: + * true if a is after b else false + */ +static inline bool vos_system_time_after(v_TIME_t a, v_TIME_t b) +{ + return (long)(b) - (long)(a) < 0; +} + + /*-------------------------------------------------------------------------- diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_api.c b/drivers/staging/prima/CORE/VOSS/src/vos_api.c index bfff2cc16d7..8e048bad193 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_api.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_api.c @@ -103,6 +103,9 @@ /* Trace index for WDI Read/Write */ #define VOS_TRACE_INDEX_MAX 256 +/* ARP Target IP offset */ +#define VOS_ARP_TARGET_IP_OFFSET 58 + /*--------------------------------------------------------------------------- * Data definitions * ------------------------------------------------------------------------*/ @@ -1848,7 +1851,7 @@ VOS_STATUS __vos_fatal_event_logs_req( uint32_t is_fatal, return VOS_STATUS_E_FAILURE; } - if(!pHddCtx->cfg_ini->enableFatalEvent) + if (!pHddCtx->cfg_ini->enableFatalEvent || !pHddCtx->is_fatal_event_log_sup) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "%s: Fatal event not enabled", __func__); @@ -3287,6 +3290,59 @@ void vos_set_rx_wow_dump(bool value) } /** + * vos_set_hdd_bad_sta() - Set bad link peer sta id + * @sta_id: sta id of the bad peer + * + * Return none. + */ +void vos_set_hdd_bad_sta(uint8_t sta_id) +{ + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if(!pVosContext) + { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__); + return; + } + + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + if(!pHddCtx) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: HDD context is Null", __func__); + return; + } + + pHddCtx->bad_sta[sta_id] = 1; +} + +/** + * vos_reset_hdd_bad_sta() - Reset the bad peer sta_id + * @sta_id: sta id of the peer + * + * Return none. + */ +void vos_reset_hdd_bad_sta(uint8_t sta_id) +{ + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if(!pVosContext) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__); + return; + } + + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + if(!pHddCtx) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, + "%s: HDD context is Null", __func__); + return; + } + + pHddCtx->bad_sta[sta_id] = 0; +} + +/** * vos_probe_threads() - VOS API to post messages * to all the threads to detect if they are active or not * @@ -3632,6 +3688,46 @@ v_BOOL_t vos_is_probe_rsp_offload_enabled(void) return pHddCtx->cfg_ini->sap_probe_resp_offload; } + +/** + * vos_set_snoc_high_freq_voting() - enable/disable high freq voting + * @enable: true if need to be enabled + * + * enable/disable high freq voting + * + * Return: Void + */ +#ifdef HAVE_WCNSS_SNOC_HIGH_FREQ_VOTING +void vos_set_snoc_high_freq_voting(bool enable) +{ + VosContextType *vos_ctx = NULL; + + /* Get the Global VOSS Context */ + vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if (!vos_ctx) { + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: vos context is NULL", __func__); + return; + } + + spin_lock(&vos_ctx->freq_voting_lock); + if (vos_ctx->snoc_high_freq_voting != enable) + { + vos_ctx->snoc_high_freq_voting = enable; + spin_unlock(&vos_ctx->freq_voting_lock); + wcnss_snoc_vote(enable); + return; + } + spin_unlock(&vos_ctx->freq_voting_lock); +} +#else +void vos_set_snoc_high_freq_voting(bool enable) +{ + return; +} +#endif + void vos_smd_dump_stats(void) { WCTS_Dump_Smd_status(); @@ -3666,19 +3762,18 @@ void vos_dump_wdi_events(void) gvos_wdi_msg_trace[i].message); } } + /** * vos_check_arp_target_ip() - check if the Target IP is gateway IP * @pPacket: pointer to vos packet - * @conversion: 802.3 to 802.11 frame conversion * * Return: true if the IP is of gateway or false otherwise */ -bool vos_check_arp_target_ip(void *pSkb, bool conversion) +bool vos_check_arp_target_ip(vos_pkt_t *pPacket) { v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); hdd_context_t *pHddCtx = NULL; struct sk_buff *skb; - uint8_t offset; if(!pVosContext) { @@ -3693,164 +3788,29 @@ bool vos_check_arp_target_ip(void *pSkb, bool conversion) return false; } - if (unlikely(NULL == pSkb)) - { - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, - "%s: NULL pointer", __func__); - return false; - } - - skb = (struct sk_buff *)pSkb; - - if (conversion) - offset = VOS_ARP_TARGET_IP_OFFSET + VOS_80211_8023_HEADER_OFFSET; - else - offset = VOS_ARP_TARGET_IP_OFFSET; - - if (pHddCtx->track_arp_ip == - (v_U32_t)(*(v_U32_t *)(skb->data + offset))) - return true; - - return false; -} - -/** - * vos_check_arp_req_target_ip() - check if the ARP is request and - target IP is gateway - * @pPacket: pointer to vos packet - * @conversion: 802.3 to 802.11 frame conversion - * - * Return: true if the IP is of gateway or false otherwise - */ -bool vos_check_arp_req_target_ip(void *pSkb, bool conversion) -{ - v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); - struct sk_buff *skb; - uint8_t offset; - - if(!pVosContext) - { - hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__); - return false; - } - - if (unlikely(NULL == pSkb)) + if (unlikely(NULL == pPacket)) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, "%s: NULL pointer", __func__); return false; } - skb = (struct sk_buff *)pSkb; - - if (conversion) - offset = VOS_PKT_ARP_OPCODE_OFFSET + VOS_80211_8023_HEADER_OFFSET; - else - offset = VOS_PKT_ARP_OPCODE_OFFSET; - - if (htons(VOS_PKT_ARPOP_REQUEST) == - (uint16_t)(*(uint16_t *)(skb->data + offset))) - { - if (vos_check_arp_target_ip(skb, conversion)) - return true; - } - - return false; -} - -/** - * vos_check_arp_src_ip() - check if the ARP response src IP is gateway IP - * @pPacket: pointer to vos packet - * @conversion: 802.3 to 802.11 frame conversion - * - * Return: true if the IP is of gateway or false otherwise - */ -bool vos_check_arp_src_ip(void *pSkb, bool conversion) -{ - v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); - hdd_context_t *pHddCtx = NULL; - struct sk_buff *skb; - uint8_t offset; - - if(!pVosContext) - { - hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__); - return false; - } - - pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); - if(!pHddCtx) { - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, - "%s: HDD context is Null", __func__); - return false; - } - - if (unlikely(NULL == pSkb)) + if ( VOS_STATUS_SUCCESS != + vos_pkt_get_os_packet(pPacket, (void**)&skb, VOS_FALSE )) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, - "%s: NULL pointer", __func__); + "%s: OS PKT pointer is NULL", __func__); return false; } - skb = (struct sk_buff *)pSkb; - - if (conversion) - offset = VOS_ARP_SRC_IP_OFFSET + VOS_80211_8023_HEADER_OFFSET; - else - offset = VOS_ARP_SRC_IP_OFFSET; - if (pHddCtx->track_arp_ip == - (v_U32_t)(*(v_U32_t *)(skb->data + offset))) + (v_U32_t)(*(v_U32_t *)(skb->data + VOS_ARP_TARGET_IP_OFFSET))) return true; return false; } /** - * vos_check_arp_rsp_src_ip() - check if the ARP is request and - target IP is gateway - * @pPacket: pointer to vos packet - * @conversion: 802.3 to 802.11 frame conversion - * - * Return: true if the IP is of gateway or false otherwise - */ -bool vos_check_arp_rsp_src_ip(void *pSkb, bool conversion) -{ - v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); - struct sk_buff *skb; - uint8_t offset; - - if(!pVosContext) - { - hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__); - return false; - } - - if (unlikely(NULL == pSkb)) - { - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL, - "%s: NULL pointer", __func__); - return false; - } - - skb = (struct sk_buff *)pSkb; - - if (conversion) - offset = VOS_PKT_ARP_OPCODE_OFFSET + VOS_80211_8023_HEADER_OFFSET; - else - offset = VOS_PKT_ARP_OPCODE_OFFSET; - - if (htons(VOS_PKT_ARPOP_REPLY) == - (uint16_t)(*(uint16_t *)(skb->data + offset))) - { - if (vos_check_arp_src_ip(skb, conversion)) - return true; - } - - return false; -} - -/** * vos_update_arp_fw_tx_delivered() - update the ARP stats host to FW deliver * count * @@ -3931,42 +3891,3 @@ void vos_update_arp_rx_drop_reorder(void) pAdapter->hdd_stats.hddArpStats.rx_host_drop_reorder++; } - -/** - * vos_set_snoc_high_freq_voting() - enable/disable high freq voting - * @enable: true if need to be enabled - * - * enable/disable high freq voting - * - * Return: Void - */ -#ifdef HAVE_WCNSS_SNOC_HIGH_FREQ_VOTING -void vos_set_snoc_high_freq_voting(bool enable) -{ - VosContextType *vos_ctx = NULL; - - /* Get the Global VOSS Context */ - vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); - - if (!vos_ctx) { - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "%s: vos context is NULL", __func__); - return; - } - - spin_lock(&vos_ctx->freq_voting_lock); - if (vos_ctx->snoc_high_freq_voting != enable) - { - vos_ctx->snoc_high_freq_voting = enable; - spin_unlock(&vos_ctx->freq_voting_lock); - wcnss_snoc_vote(enable); - return; - } - spin_unlock(&vos_ctx->freq_voting_lock); -} -#else -void vos_set_snoc_high_freq_voting(bool enable) -{ - return; -} -#endif diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_diag.c b/drivers/staging/prima/CORE/VOSS/src/vos_diag.c index 496ae473492..dbc2a5cae21 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_diag.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_diag.c @@ -318,7 +318,7 @@ void vos_event_report_payload(v_U16_t event_Id, v_U16_t length, v_VOID_t *pPaylo if( ptt_sock_send_msg_to_app(wmsg, 0, ANI_NL_MSG_PUMAC, INVALID_PID, MSG_DONTWAIT) < 0) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, ("Ptt Socket error sending message to the app!!")); vos_mem_free((v_VOID_t*)wmsg); return; diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_sched.h b/drivers/staging/prima/CORE/VOSS/src/vos_sched.h index 031809dac74..09b8038e1a9 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_sched.h +++ b/drivers/staging/prima/CORE/VOSS/src/vos_sched.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * diff --git a/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h b/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h index 2711451ee74..83d0267f8df 100644 --- a/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h +++ b/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -73,6 +73,10 @@ //invalid channel id. #define HAL_INVALID_CHANNEL_ID 0 +#ifdef SAP_AUTH_OFFLOAD +#define MAX_CONNECT_REQ_LENGTH 512 +#endif + /* BSS index used when no BSS is associated with the station. For example, * driver creates only one self station without valid BSS while scanning. * Then this index is used to tell softmac that BSS is not valid. @@ -288,6 +292,13 @@ typedef struct tANI_U8 htLdpcCapable; tANI_U8 vhtLdpcCapable; +#ifdef SAP_AUTH_OFFLOAD + tANI_U8 dpuIndex; + tANI_U8 bcastDpuIndex; + tANI_U8 bcastMgmtDpuIdx; + tANI_U8 ucMgmtSig; +#endif + } tAddStaParams, *tpAddStaParams; @@ -1417,5 +1428,22 @@ typedef struct sNanRequest tANI_U8 request_data[1]; } tNanRequest, *tpNanRequest; + +#ifdef SAP_AUTH_OFFLOAD +struct sap_offload_add_sta_req +{ + tANI_U32 assoc_id; + tANI_U32 conn_req_len; + tANI_U8 conn_req[MAX_CONNECT_REQ_LENGTH]; +}; +struct sap_offload_del_sta_req +{ + tANI_U32 assoc_id; + tANI_U32 reason_code; + tANI_U32 flags; + tSirMacAddr sta_mac; +}; +#endif /* SAP_AUTH_OFFLOAD */ + #endif /* _HALMSGAPI_H_ */ diff --git a/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h b/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h index 804925a4f93..67becef9bcf 100644 --- a/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h +++ b/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h @@ -219,6 +219,12 @@ typedef enum #endif //CMD not Queued in SME eHAL_STATUS_CMD_NOT_QUEUED, + +#ifdef WLAN_FEATURE_LFR_MBB + eHAL_STATUS_MBB_DEL_BSS_FAIL, + eHAL_STATUS_MBB_ADD_BSS_FAIL, +#endif + // not a real status. Just a way to mark the maximum in the enum. eHAL_STATUS_MAX @@ -352,7 +358,7 @@ typedef enum * supported by rome/prima hardware */ #define MIN_TX_PWR_CAP 8 -#define MAX_TX_PWR_CAP 30 +#define MAX_TX_PWR_CAP 22 /* Moving the miscellaneous defination required by UMAC are moved here from * volansdefs.h */ diff --git a/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h b/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h index fdc768d8ca4..997c80d5fcb 100644 --- a/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h +++ b/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h @@ -385,6 +385,8 @@ typedef eHalStatus (*pWDAAckFnTxComp)(tpAniSirGlobal, void *pData); typedef void (*WDA_txFailIndCallback)(tANI_U8 *, tANI_U8); #endif /* WLAN_FEATURE_RMC */ +typedef void (*WDA_suspend_req_callback)(tANI_U8 *, tANI_U8); + typedef struct { tANI_U16 ucValidStaIndex ; @@ -525,10 +527,6 @@ typedef struct uint8_t mgmt_pktfree_fail; vos_lock_t mgmt_pkt_lock; - /* debug connection status */ - bool tx_aggr; - uint8_t sta_id; - uint8_t tid; } tWDA_CbContext ; typedef struct @@ -820,6 +818,11 @@ tBssSystemRole wdaGetGlobalSystemRole(tpAniSirGlobal pMac); #ifdef WLAN_FEATURE_EXTSCAN #define WDA_GET_EXTSCANFULLSCANRESIND(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->extscanBuffer) #endif + +#ifdef SAP_AUTH_OFFLOAD +#define WDA_GET_SAP_AUTHOFFLOADIND(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->indType) +#endif + /* WDA_GET_RX_RSSI_DB ********************************************************/ // Volans RF # define WDA_RSSI_OFFSET 100 @@ -1295,11 +1298,19 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_START_RSSI_MONITOR_REQ SIR_HAL_RSSI_MON_START_REQ #define WDA_STOP_RSSI_MONITOR_REQ SIR_HAL_RSSI_MON_STOP_REQ +#ifdef DHCP_SERVER_OFFLOAD +#define WDA_SET_DHCP_SERVER_OFFLOAD_REQ SIR_HAL_SET_DHCP_SERVER_OFFLOAD_REQ +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD +#define WDA_SET_MDNS_OFFLOAD_CMD SIR_HAL_SET_MDNS_OFFLOAD +#define WDA_SET_MDNS_FQDN_CMD SIR_HAL_SET_MDNS_FQDN +#define WDA_SET_MDNS_RESPONSE_CMD SIR_HAL_SET_MDNS_RESPONSE +#define WDA_GET_MDNS_STATUS_CMD SIR_HAL_GET_MDNS_STATUS +#endif /* MDNS_OFFLOAD */ + /* ARP Debug */ #define WDA_SET_ARP_STATS_REQ SIR_HAL_SET_ARP_STATS_REQ #define WDA_GET_ARP_STATS_REQ SIR_HAL_GET_ARP_STATS_REQ -#define WDA_TRIGGER_ADD_BA_REQ SIR_HAL_TRIGGER_ADD_BA_REQ -#define WDA_GET_CON_STATUS SIR_HAL_GET_CON_STATUS tSirRetStatus wdaPostCtrlMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg); @@ -1362,6 +1373,21 @@ eHalStatus WDA_SetRegDomain(void * clientCtxt, v_REGDOMAIN_t regId, #define WDA_PAUSE_TL_IND SIR_HAL_PAUSE_TL_IND +#ifdef SAP_AUTH_OFFLOAD +#define WDA_SAP_OFL_ADD_STA SIR_HAL_SAP_OFL_ADD_STA +#define WDA_SAP_OFL_DEL_STA SIR_HAL_SAP_OFL_DEL_STA +#define WDA_SET_SAP_AUTH_OFL SIR_HAL_SET_SAP_AUTH_OFL +#endif /* SAP_AUTH_OFFLOAD */ + +#ifdef WLAN_FEATURE_APFIND +#define WDA_APFIND_SET_CMD SIR_HAL_APFIND_SET_CMD +#define WDA_AP_FIND_IND SIR_HAL_AP_FIND_IND +#endif /* WLAN_FEATURE_APFIND */ + +#define WDA_CAP_TSF_REQ SIR_HAL_CAP_TSF_REQ +#define WDA_GET_TSF_REQ SIR_HAL_GET_TSF_REQ + + #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 // Bit 6 will be used to control BD rate for Management frames #define halTxFrame(hHal, pFrmBuf, frmLen, frmType, txDir, tid, pCompFunc, pData, txFlag) \ @@ -2183,4 +2209,9 @@ void WDA_FWLoggingDXEdoneInd(v_U32_t logType); void WDA_SetMgmtPktViaWQ5(v_BOOL_t sendMgmtPktViaWQ5); +#define CAP_TSF_REQUEST 0 +#define GET_TSF_REQUEST 1 + +VOS_STATUS WDA_ProcessCapTsfReq(tWDA_CbContext *pWDA, tSirCapTsfParams *params); +VOS_STATUS WDA_ProcessGetTsfReq(tWDA_CbContext *pWDA, tSirCapTsfParams *params); #endif diff --git a/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c b/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c index 83a5229007c..a26f81b875d 100644 --- a/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c +++ b/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c @@ -165,12 +165,7 @@ void WDA_lowLevelIndCallback(WDI_LowLevelIndType *wdiLowLevelInd, static VOS_STATUS wdaCreateTimers(tWDA_CbContext *pWDA) ; static VOS_STATUS wdaDestroyTimers(tWDA_CbContext *pWDA); bool WDA_AllowAddBA(tpAniSirGlobal pMAc, tANI_U8 staId, tANI_U8 tid); -void WDA_BaCheckActivity(tWDA_CbContext *pWDA, bool test_con); - -/* check connection status */ -void WDA_GetConnectionStatus(tWDA_CbContext *pWDA, - getConStatusParams *conStatusParams); - +void WDA_BaCheckActivity(tWDA_CbContext *pWDA) ; void WDA_TimerTrafficStatsInd(tWDA_CbContext *pWDA); void WDA_HALDumpCmdCallback(WDI_HALDumpCmdRspParamsType *wdiRspParams, void* pUserData); #ifdef WLAN_FEATURE_VOWIFI_11R @@ -2399,6 +2394,37 @@ VOS_STATUS WDA_prepareConfigTLV(v_PVOID_t pVosContext, } tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + sizeof(tHalCfg) + tlvStruct->length) ; + /* QWLAN_HAL_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL */ + tlvStruct->type = QWLAN_HAL_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL ; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + + if (wlan_cfgGetInt(pMac, WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL, + configDataValue ) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get value for WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL"); + goto handle_failure; + } + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length) ; + + wdiStartParams->usConfigBufferLen = (tANI_U8 *)tlvStruct - tlvStructStart ; + + /* QWLAN_HAL_CFG_DISABLE_SCAN_DURING_SCO */ + tlvStruct->type = QWLAN_HAL_CFG_DISABLE_SCAN_DURING_SCO ; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + + if (wlan_cfgGetInt(pMac, WNI_CFG_DISABLE_SCAN_DURING_SCO, + configDataValue ) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get value for WNI_CFG_DISABLE_SCAN_DURING_SCO"); + goto handle_failure; + } + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length) ; /* QWLAN_HAL_CFG_CONS_BCNMISS_COUNT */ tlvStruct->type = QWLAN_HAL_CFG_CONS_BCNMISS_COUNT; @@ -2430,22 +2456,20 @@ VOS_STATUS WDA_prepareConfigTLV(v_PVOID_t pVosContext, tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + sizeof(tHalCfg) + tlvStruct->length); - wdiStartParams->usConfigBufferLen = (tANI_U8 *)tlvStruct - tlvStructStart ; - - /* QWLAN_HAL_CFG_DISABLE_SCAN_DURING_SCO */ - tlvStruct->type = QWLAN_HAL_CFG_DISABLE_SCAN_DURING_SCO ; + /* QWLAN_HAL_CFG_TRIGGER_NULLFRAME_BEFORE_HB */ + tlvStruct->type = QWLAN_HAL_CFG_TRIGGER_NULLFRAME_BEFORE_HB; tlvStruct->length = sizeof(tANI_U32); configDataValue = (tANI_U32 *)(tlvStruct + 1); - - if (wlan_cfgGetInt(pMac, WNI_CFG_DISABLE_SCAN_DURING_SCO, - configDataValue ) != eSIR_SUCCESS) + if(wlan_cfgGetInt(pMac, WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB, + configDataValue) != eSIR_SUCCESS) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "Failed to get value for WNI_CFG_DISABLE_SCAN_DURING_SCO"); + "Failed to get WNI_CFG_TRIGGER_NULLFRAME_BEFORE_HB"); goto handle_failure; } + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct - + sizeof(tHalCfg) + tlvStruct->length) ; + + sizeof(tHalCfg) + tlvStruct->length); #ifdef WLAN_DEBUG { int i; @@ -2479,10 +2503,339 @@ handle_failure: vos_mem_free(configParam); return VOS_STATUS_E_FAILURE; } + +#ifdef DHCP_SERVER_OFFLOAD +/** + * wda_dhcp_server_offload_rsp_callback() - response to the dhcp server offload + * @wdi_rsp: pointer to the dhcp server offload response + * @user_data: pointer to user data + * + * Return: None + */ +void wda_dhcp_server_offload_rsp_callback(wdi_dhcp_server_offload_rsp_param_t* + wdi_rsp, + void* user_data) +{ + tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data; + sir_dhcp_srv_offload_info_t *dhcp_srv_offload_info; + VOS_STATUS status; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s " ,__func__); + + if(NULL == wda_params) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(NULL == wda_params->wdaMsgParam) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams->wdaMsgParam is NULL", __func__); + VOS_ASSERT(0); + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params); + return; + } + + dhcp_srv_offload_info = (sir_dhcp_srv_offload_info_t *) + wda_params->wdaMsgParam; + + if(dhcp_srv_offload_info->dhcp_offload_callback) + { + dhcp_srv_offload_info->dhcp_offload_callback( + dhcp_srv_offload_info->dhcp_server_offload_cb_context, + CONVERT_WDI2VOS_STATUS(wdi_rsp->status)); + } + else + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pFWLoggingInitParams callback is NULL", __func__); + } + + status = CONVERT_WDI2VOS_STATUS(wdi_rsp->status); + if (status) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: DHCP server offload failed with status=%d", __func__, status); + VOS_ASSERT(0); + } + + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + return; +} +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +/** + * wda_mdns_enable_rsp_callback() - response to the mdns enable server offload + * @wdi_rsp: pointer to the mdns enable offload response + * @user_data: pointer to user data + * + * Return: None + */ +void wda_mdns_enable_rsp_callback(wdi_mdns_enable_offload_rsp_param_t* + wdi_rsp, + void* user_data) +{ + tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data; + sir_mdns_offload_info_t *mdns_offload_info; + VOS_STATUS status; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s " ,__func__); + + if(NULL == wda_params) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return ; + } + + if(NULL == wda_params->wdaMsgParam) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams->wdaMsgParam is NULL", __func__); + VOS_ASSERT(0); + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params); + return ; + } + + mdns_offload_info = (sir_mdns_offload_info_t *) + wda_params->wdaMsgParam; + + if(mdns_offload_info->mdns_enable_callback) + { + mdns_offload_info->mdns_enable_callback(mdns_offload_info-> + mdns_enable_cb_context, + CONVERT_WDI2VOS_STATUS(wdi_rsp-> + status)); + } + else + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: mdns_enable callback is NULL", __func__); + } + + status = CONVERT_WDI2VOS_STATUS(wdi_rsp->status); + if (status) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: MDNS offload failed with status=%d", __func__, status); + VOS_ASSERT(0); + } + + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + + return; +} + +/** + * wda_mdns_fqdn_rsp_callback() - response to the mdns fqdn offload + * @wdi_rsp: pointer to the mdns fqdn offload response + * @user_data: pointer to user data + * + * Return: None + */ +void wda_mdns_fqdn_rsp_callback(wdi_mdns_set_fqdn_rsp_param_t* + wdi_rsp, + void* user_data) +{ + tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data; + sir_mdns_fqdn_info_t *mdns_fqdn_info; + VOS_STATUS status; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s " ,__func__); + + if(NULL == wda_params) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return ; + } + + if(NULL == wda_params->wdaMsgParam) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams->wdaMsgParam is NULL", __func__); + VOS_ASSERT(0); + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params); + return ; + } + + mdns_fqdn_info = (sir_mdns_fqdn_info_t *) + wda_params->wdaMsgParam; + + if(mdns_fqdn_info->mdns_fqdn_callback) + { + mdns_fqdn_info->mdns_fqdn_callback(mdns_fqdn_info-> + mdns_fqdn_cb_context, + CONVERT_WDI2VOS_STATUS(wdi_rsp-> + status)); + } + else + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: mdns_fqdn callback is NULL", __func__); + } + + status = CONVERT_WDI2VOS_STATUS(wdi_rsp->status); + if (status) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: MDNS FQDN offload failed with status=%d", __func__, status); + VOS_ASSERT(0); + } + + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + + return; +} + +/** + * wda_mdns_resp_rsp_callback() - response to the mdns resp offload + * @wdi_rsp: pointer to the mdns fqdn offload response + * @user_data: pointer to user data + * + * Return: None + */ +void wda_mdns_resp_rsp_callback +( + wdi_mdns_set_rsp_param_t* + wdi_rsp, + void* user_data) +{ + tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data; + sir_mdns_resp_info_t *mdns_resp_info; + VOS_STATUS status; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s " ,__func__); + + if(NULL == wda_params) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return ; + } + + if(NULL == wda_params->wdaMsgParam) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams->wdaMsgParam is NULL", __func__); + VOS_ASSERT(0); + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params); + return ; + } + + mdns_resp_info = (sir_mdns_resp_info_t *) + wda_params->wdaMsgParam; + + if(mdns_resp_info->mdns_resp_callback) + { + mdns_resp_info->mdns_resp_callback(mdns_resp_info-> + mdns_resp_cb_context, + CONVERT_WDI2VOS_STATUS(wdi_rsp-> + status)); + } + else + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: mdns_fqdn callback is NULL", __func__); + } + + status = CONVERT_WDI2VOS_STATUS(wdi_rsp->status); + if (status) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: MDNS FQDN offload failed with status=%d", __func__, status); + VOS_ASSERT(0); + } + + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + + return; +} + +/** + * wda_get_stats_rsp_callback() - response to the mdns stats offload + * @wdi_rsp: pointer to the mdns fqdn offload response + * @user_data: pointer to user data + * + * Return: None + */ +void wda_get_stats_rsp_callback +( + wdi_mdns_stats_rsp_param_t* + wdi_rsp, + void* user_data) +{ + tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data; + sir_get_mdns_stats_info_t *mdns_stats_info; + VOS_STATUS status; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s " ,__func__); + + if(NULL == wda_params) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return ; + } + + if(NULL == wda_params->wdaMsgParam) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams->wdaMsgParam is NULL", __func__); + VOS_ASSERT(0); + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params); + return ; + } + + mdns_stats_info = (sir_get_mdns_stats_info_t *) + wda_params->wdaMsgParam; + + status = CONVERT_WDI2VOS_STATUS(wdi_rsp->status); + if (status) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: MDNS FQDN offload failed with status=%d", __func__, status); + VOS_ASSERT(0); + } + + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + + return; +} +#endif /* MDNS_OFFLOAD */ + /* * FUNCTION: WDA_wdiCompleteCB * call the voss call back function - */ + */ void WDA_stopCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; @@ -4370,7 +4723,95 @@ VOS_STATUS WDA_ProcessAddStaReq(tWDA_CbContext *pWDA, } return CONVERT_WDI2VOS_STATUS(status) ; } +#ifdef SAP_AUTH_OFFLOAD + +/** + * WDA_ProcessSapAuthOffloadAddStaReq(): process add sta command. + * + * @pWDA: WDA Call back context + * @addStaReqParam: Add sta request params + * + * This function process sta params and store them to WDA layer. + * It will register station entry to mempool as well. + * As station is already in associated state in firmware this + * function doesnt send any request to firmware and wait for response, + * instead of that this function will send response from here. + * + * Return: Return VOS_STATUS + */ +VOS_STATUS WDA_ProcessSapAuthOffloadAddStaReq(tWDA_CbContext *pWDA, + tAddStaParams *addStaReqParam) +{ + WDI_Status status = WDI_STATUS_SUCCESS ; + WDI_AddStaParams wdiAddSTAParam = {0}; + WDI_ConfigSTAReqParamsType *wdiConfigStaReqParam = + (WDI_ConfigSTAReqParamsType *)vos_mem_malloc( + sizeof(WDI_ConfigSTAReqParamsType)) ; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "------> %s " ,__func__); + if (NULL == wdiConfigStaReqParam) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_NOMEM; + } + + vos_mem_set(wdiConfigStaReqParam, sizeof(WDI_ConfigSTAReqParamsType), 0); + /* update STA params into WDI structure */ + WDA_UpdateSTAParams(pWDA, &wdiConfigStaReqParam->wdiReqInfo, + addStaReqParam); + wdiAddSTAParam.ucSTAIdx = wdiConfigStaReqParam->wdiReqInfo.staIdx; + wdiAddSTAParam.ucStaType = WDI_STA_ENTRY_PEER; + /* MAC Address of STA */ + wpalMemoryCopy(wdiAddSTAParam.staMacAddr, + wdiConfigStaReqParam->wdiReqInfo.macSTA, + WDI_MAC_ADDR_LEN); + + wpalMemoryCopy(wdiAddSTAParam.macBSSID, + wdiConfigStaReqParam->wdiReqInfo.macBSSID, + WDI_MAC_ADDR_LEN); + + wdiAddSTAParam.dpuIndex = addStaReqParam->dpuIndex; + wdiAddSTAParam.dpuSig = addStaReqParam->ucUcastSig; + wdiAddSTAParam.bcastDpuIndex = addStaReqParam->bcastDpuIndex; + wdiAddSTAParam.bcastDpuSignature = addStaReqParam->ucBcastSig; + wdiAddSTAParam.bcastMgmtDpuIndex = addStaReqParam->bcastMgmtDpuIdx; + wdiAddSTAParam.bcastMgmtDpuSignature = addStaReqParam->ucMgmtSig; + wdiAddSTAParam.ucWmmEnabled = addStaReqParam->wmmEnabled; + wdiAddSTAParam.ucRmfEnabled = addStaReqParam->rmfEnabled; + wdiAddSTAParam.ucBSSIdx = addStaReqParam->bssIdx; + wdiAddSTAParam.ucHTCapable = addStaReqParam->htCapable; + + + WDI_STATableAddSta(pWDA->pWdiContext, &wdiAddSTAParam); + pWDA->wdaStaInfo[wdiConfigStaReqParam->wdiReqInfo.staIdx].ucValidStaIndex = + WDA_VALID_STA_INDEX; + pWDA->wdaStaInfo[wdiConfigStaReqParam->wdiReqInfo.staIdx].currentOperChan = + addStaReqParam->currentOperChan; + + if (WDI_STATUS_SUCCESS != + WDI_STATableFindStaidByAddr(pWDA->pWdiContext, + wdiConfigStaReqParam->wdiReqInfo.macSTA, + (wpt_uint8 *)&wdiConfigStaReqParam->wdiReqInfo.staIdx)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to get selfStaIdx!", __func__); + } + if (WDI_DS_AddSTAMemPool(pWDA->pWdiContext, + wdiConfigStaReqParam->wdiReqInfo.staIdx)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: add STA into mempool fail", __func__); + VOS_ASSERT(0) ; + } + vos_mem_free(wdiConfigStaReqParam); + WDA_SendMsg(pWDA, WDA_ADD_STA_RSP, (void *)addStaReqParam, 0) ; + return status; +} +#endif /* * FUNCTION: WDA_DelBSSRspCallback * Dens DEL BSS RSP back to PE @@ -4636,6 +5077,45 @@ void WDA_DelSTAReqCallback(WDI_Status wdiStatus, return ; } +#ifdef SAP_AUTH_OFFLOAD +/** + * WDA_ProcessSapAuthOffloadDelStaReq(): process del sta command. + * + * @pWDA: WDA Call back context + * @delStaParam: Del sta request params + * + * This function process sta params and remove entry from WDA layer. + * It will unregister station entry from mempool as well. + * As station is already in disassociated state in firmware this + * function doesn't send any request to firmware and wait for response, + * instead of that this function will send response from here. + * + * Return: Return VOS_STATUS + */ +void WDA_ProcessSapAuthOffloadDelStaReq(tWDA_CbContext *pWDA, + tDeleteStaParams *delStaParam) + +{ + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "------> %s " ,__func__); + + if (WDI_DS_DelSTAMemPool(pWDA->pWdiContext, delStaParam->staIdx)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: DEL STA from MemPool Fail", __func__); + // VOS_ASSERT(0) ; + } + WLANTL_StartForwarding(delStaParam->staIdx, 0, 0); + WDI_STATableDelSta(pWDA->pWdiContext, delStaParam->staIdx); + pWDA->wdaStaInfo[delStaParam->staIdx].ucValidStaIndex = + WDA_INVALID_STA_INDEX; + pWDA->wdaStaInfo[delStaParam->staIdx].currentOperChan = 0; + pWDA->wdaStaInfo[delStaParam->staIdx].ucUseBaBitmap = 0; + WDA_SendMsg(pWDA, WDA_DELETE_STA_RSP, (void *)delStaParam, 0); + return ; +} +#endif + /* * FUNCTION: WDA_ProcessDelStaReq * Init DEL STA req with WDI @@ -5362,6 +5842,9 @@ static inline tANI_U16 WDA_ConvertWniCfgIdToHALCfgId(v_U32_t wniCfgId) return QWLAN_HAL_CFG_ENABLE_RTSCTS_HTVHT; case WNI_CFG_ENABLE_MC_ADDR_LIST: return QWLAN_HAL_CFG_ENABLE_MC_ADDR_LIST; + case WNI_CFG_HEART_BEAT_THRESHOLD: + return QWLAN_HAL_CFG_PS_HEART_BEAT_THRESHOLD; + default: { VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -11060,6 +11543,55 @@ void WDA_WdiIndicationCallback( WDI_Status wdiStatus, VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "<------ %s " ,__func__); } + +/** + * WDA_ProcessWlanSuspendIndCallback: callback API for WDA_ProcessWlanSuspendInd + * @wdiStatus: wdi status + * @pUserData: suspend params + * + * Return: None + */ +void WDA_ProcessWlanSuspendIndCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tSirWlanSuspendParam *pWlanSuspendParam; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + return; + } + + pWlanSuspendParam = (tSirWlanSuspendParam *)pWdaParams->wdaMsgParam; + if (pWlanSuspendParam == NULL) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: suspend params NULL", __func__); + vos_mem_free(pWdaParams); + return; + } + if (pWlanSuspendParam->wlan_sus_callback) + { + pWlanSuspendParam->wlan_sus_callback(pWlanSuspendParam->context, + CONVERT_WDI2VOS_STATUS(wdiStatus)); + } + else + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: wlan suspend callback is NULL", __func__); + } + if (pWdaParams->wdaMsgParam) { + vos_mem_free(pWdaParams->wdaMsgParam); + pWdaParams->wdaMsgParam = NULL; + } + vos_mem_free(pWdaParams); + return; +} + /* * FUNCTION: WDA_ProcessWlanSuspendInd * @@ -11069,12 +11601,22 @@ VOS_STATUS WDA_ProcessWlanSuspendInd(tWDA_CbContext *pWDA, { WDI_Status wdiStatus; WDI_SuspendParamsType wdiSuspendParams; + tWDA_ReqParams *pWdaParams; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "------> %s " ,__func__); wdiSuspendParams.wdiSuspendParams.ucConfiguredMcstBcstFilterSetting = pWlanSuspendParam->configuredMcstBcstFilterSetting; - wdiSuspendParams.wdiReqStatusCB = WDA_WdiIndicationCallback; - wdiSuspendParams.pUserData = pWDA; + wdiSuspendParams.wdiReqStatusCB = WDA_ProcessWlanSuspendIndCallback; + + pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)); + if (!pWdaParams) + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s memory allocation failed" ,__func__); + pWdaParams->pWdaContext = pWDA; + pWdaParams->wdaMsgParam = pWlanSuspendParam; + wdiSuspendParams.pUserData = pWdaParams; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "%s: %d" ,__func__, pWlanSuspendParam->configuredMcstBcstFilterSetting); wdiStatus = WDI_HostSuspendInd(&wdiSuspendParams); if(WDI_STATUS_PENDING == wdiStatus) @@ -11087,7 +11629,6 @@ VOS_STATUS WDA_ProcessWlanSuspendInd(tWDA_CbContext *pWDA, VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "Failure in %s:%d ",__func__,__LINE__ ); } - vos_mem_free(pWlanSuspendParam); return CONVERT_WDI2VOS_STATUS(wdiStatus) ; } @@ -11764,7 +12305,7 @@ VOS_STATUS WDA_ProcessHostOffloadReq(tWDA_CbContext *pWDA, if(IS_WDI_STATUS_FAILURE(wstatus)) { - VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_WARN, "Failure in host offload REQ WDI API, free all the memory %d", wstatus); status = CONVERT_WDI2VOS_STATUS(wstatus); @@ -14951,6 +15492,50 @@ WDA_ProcessIbssPeerInfoReq(tWDA_CbContext *pWDA, } +#ifdef WLAN_FEATURE_APFIND +/* + * FUNCTION: WDA_Process_apfind_set_cmd + * Forward AP find config request to WDI + */ +VOS_STATUS WDA_Process_apfind_set_cmd(tWDA_CbContext *pWDA, + struct hal_apfind_request *ap_find_req) +{ + WDI_Status status; + struct WDI_APFind_cmd *wdi_ap_find_cmd; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "------> %s " ,__func__); + if (NULL == ap_find_req) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: apfind_req info received NULL", __func__); + VOS_ASSERT(0) ; + return VOS_STATUS_E_FAULT; + } + + wdi_ap_find_cmd = (struct WDI_APFind_cmd *)vos_mem_malloc( + sizeof(struct hal_apfind_request) + ap_find_req->request_data_len); + + wdi_ap_find_cmd->data_len = ap_find_req->request_data_len; + vos_mem_copy(wdi_ap_find_cmd->data, ap_find_req->request_data, + ap_find_req->request_data_len); + + status = WDI_process_ap_find_cmd(wdi_ap_find_cmd); + if (WDI_STATUS_PENDING == status) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + FL("pending status received")); + } else if (WDI_STATUS_SUCCESS_SYNC != status && + (WDI_STATUS_SUCCESS != status)) { + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + FL("Failure in process_sap_auth_offload API %d"), status); + + } + vos_mem_free(wdi_ap_find_cmd); + return CONVERT_WDI2VOS_STATUS(status) ; +} +#endif + /* * FUNCTION: WDA_ProcessTXFailMonitorInd * Forward TX Fail Monitor to WDI @@ -15303,6 +15888,74 @@ VOS_STATUS wda_process_set_allowed_action_frames_ind(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } +#ifdef SAP_AUTH_OFFLOAD +VOS_STATUS wda_process_sap_auth_offload(tWDA_CbContext *pWDA, + struct tSirSapOffloadInfo *sap_auth_offload_info) +{ + WDI_Status status = WDI_STATUS_SUCCESS; + struct WDI_sap_ofl_enable_params *sap_ofl_enable_cmd; + v_U16_t psk_len, psk_len_padded; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "------> %s " ,__func__); + + if(NULL == sap_auth_offload_info) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: sap_auth_offload_info received NULL", __func__); + VOS_ASSERT(0) ; + return VOS_STATUS_E_FAULT; + } + psk_len = sap_auth_offload_info->key_len; + psk_len_padded = roundup(psk_len, sizeof(v_U32_t)); + + sap_ofl_enable_cmd = (struct WDI_sap_ofl_enable_params*) + vos_mem_malloc(sizeof + (*sap_ofl_enable_cmd)); + if (!sap_ofl_enable_cmd) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + vos_mem_free(sap_auth_offload_info); + return VOS_STATUS_E_NOMEM; + } + vos_mem_zero(sap_ofl_enable_cmd, sizeof(*sap_ofl_enable_cmd)); + vos_mem_copy(sap_ofl_enable_cmd->macAddr, + sap_auth_offload_info->macAddr, VOS_MAC_ADDRESS_LEN); + + sap_ofl_enable_cmd->enable = sap_auth_offload_info->sap_auth_offload_enable; + sap_ofl_enable_cmd->psk_len = psk_len; + switch (sap_auth_offload_info->sap_auth_offload_sec_type) { + case eSIR_OFFLOAD_WPA2PSK_CCMP: + sap_ofl_enable_cmd->rsn_authmode = WDI_AUTH_TYPE_RSN_PSK; + sap_ofl_enable_cmd->rsn_mcastcipherset = WDI_ED_CCMP; + sap_ofl_enable_cmd->rsn_ucastcipherset = WDI_ED_CCMP; + break; + case eSIR_OFFLOAD_NONE: + default: + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "Set SAP AP Auth offload with none support security type\n"); + break; + } + vos_mem_copy(sap_ofl_enable_cmd->key, sap_auth_offload_info->key, psk_len); + + status = WDI_process_sap_auth_offload(sap_ofl_enable_cmd); + + if (WDI_STATUS_PENDING == status) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + FL("pending status received")); + } else if (WDI_STATUS_SUCCESS_SYNC != status && + (WDI_STATUS_SUCCESS != status)) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + FL("Failure in process_sap_auth_offload API %d"), status); + } + + vos_mem_free(sap_ofl_enable_cmd); + vos_mem_free(sap_auth_offload_info); + return CONVERT_WDI2VOS_STATUS(status) ; + +} +#endif + /* * FUNCTION: WDA_ProcessBcnMissPenaltyCount * Request to WDI. @@ -15590,6 +16243,409 @@ VOS_STATUS WDA_ProcessGetARPStatsReq(tWDA_CbContext *pWDA, return wdi_status; } + +#ifdef DHCP_SERVER_OFFLOAD +/** + * wda_process_dhcpserver_offload_req() - wda api to set dhcp server offload + * @wda_handle: pointer to wda handle + * @dhcp_server_offload_info: dhcp server offload info + * + * Return: status + * 0 - success or else failure + */ +static int wda_process_dhcpserver_offload_req(tWDA_CbContext *wda_handle, + sir_dhcp_srv_offload_info_t + *dhcp_server_offload_info) +{ + wdi_set_dhcp_server_offload_t *dhcp_info; + tWDA_ReqParams *wda_params; + WDI_Status wstatus; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + FL("---> %s"), __func__); + + if(NULL == dhcp_server_offload_info) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: dhcp_server_offload_info received NULL", + __func__); + VOS_ASSERT(0) ; + return VOS_STATUS_E_FAULT; + } + + dhcp_info = (wdi_set_dhcp_server_offload_t *) + vos_mem_malloc(sizeof(*dhcp_info)); + if (!dhcp_info) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to allocate buffer to send " + "set_dhcp_server_offload cmd"); + vos_mem_free(dhcp_server_offload_info); + return VOS_STATUS_E_NOMEM; + } + + vos_mem_zero(dhcp_info, sizeof(*dhcp_info)); + + wda_params = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ; + if(NULL == wda_params) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(dhcp_info); + vos_mem_free(dhcp_server_offload_info); + return VOS_STATUS_E_NOMEM; + } + + dhcp_info->bssidx = dhcp_server_offload_info->bssidx; + dhcp_info->enable = dhcp_server_offload_info->dhcp_srv_offload_enabled; + dhcp_info->num_client = dhcp_server_offload_info->dhcp_client_num; + dhcp_info->srv_ipv4 = dhcp_server_offload_info->dhcp_srv_ip; + dhcp_info->start_lsb = dhcp_server_offload_info->start_lsb; + + wda_params->pWdaContext = wda_handle; + wda_params->wdaMsgParam = dhcp_server_offload_info; + wda_params->wdaWdiApiMsgParam = (void *)dhcp_info; + + wstatus = wdi_process_dhcpserver_offload_req(dhcp_info, + (wdi_dhcp_srv_offload_rsp_cb) + wda_dhcp_server_offload_rsp_callback, + wda_params); + if(IS_WDI_STATUS_FAILURE(wstatus)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to send set_dhcp_server_offload cmd" ); + status = CONVERT_WDI2VOS_STATUS(wstatus); + vos_mem_free(wda_params->wdaWdiApiMsgParam) ; + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + } + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "Set dhcp server offload"); + return status; +} +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +/** + * wda_set_mdns_offload_req() - wda api to set mdns offload + * @wda_handle: wda handle + * @mdns_offload_info: mdns offload info + * + * Return - 0 for success or else failure + */ +static int +wda_set_mdns_offload_req(tWDA_CbContext *wda_handle, + sir_mdns_offload_info_t *mdns_offload_info) +{ + wdi_mdns_enable_offload_cmd_req *mdns_info; + tWDA_ReqParams *wda_params; + WDI_Status wstatus; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + FL("---> %s"), __func__); + + if(NULL == mdns_offload_info) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: set_mdns_offload received NULL", + __func__); + VOS_ASSERT(0) ; + return VOS_STATUS_E_FAULT; + } + + mdns_info = (wdi_mdns_enable_offload_cmd_req *) + vos_mem_malloc(sizeof(*mdns_info)); + if (!mdns_info) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to allocate buffer to send " + "set_mdns_offload cmd"); + vos_mem_free(mdns_offload_info); + return VOS_STATUS_E_NOMEM; + } + + vos_mem_zero(mdns_info, sizeof(*mdns_info)); + + wda_params = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ; + if(NULL == wda_params) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(mdns_info); + vos_mem_free(mdns_offload_info); + return VOS_STATUS_E_NOMEM; + } + + mdns_info->bss_idx = mdns_offload_info->bss_idx; + mdns_info->enable = mdns_offload_info->enable; + + wda_params->pWdaContext = wda_handle; + wda_params->wdaMsgParam = mdns_offload_info; + wda_params->wdaWdiApiMsgParam = (void *)mdns_info; + + wstatus = wdi_set_mdns_offload_req(mdns_info, + (wdi_mdns_enable_rsp_cb) + wda_mdns_enable_rsp_callback, + wda_params); + if(IS_WDI_STATUS_FAILURE(wstatus)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to send wdi_set_mdns_offload_req cmd" ); + status = CONVERT_WDI2VOS_STATUS(wstatus); + vos_mem_free(wda_params->wdaWdiApiMsgParam) ; + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + } + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "mdns enabled!"); + return status; + +} + +/** + * wda_set_mdns_fqdn_req() - wda api to set mdns fqdn offload + * @wda_handle: wda handle + * @mdns_fqdn_info: mdns fqdn offload info + * + * Return - 0 for success or else failure + */ +static int +wda_set_mdns_fqdn_req(tWDA_CbContext *wda_handle, + sir_mdns_fqdn_info_t *mdns_fqdn_info) +{ + wdi_mdns_set_fqdn_cmd_req *fqdn_info; + tWDA_ReqParams *wda_params; + WDI_Status wstatus; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + FL("---> %s"), __func__); + + if(NULL == mdns_fqdn_info) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: set_mdns_fqdn received NULL", + __func__); + VOS_ASSERT(0) ; + return VOS_STATUS_E_FAULT; + } + + fqdn_info = (wdi_mdns_set_fqdn_cmd_req *) + vos_mem_malloc(sizeof(*fqdn_info)); + if (!fqdn_info) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to allocate buffer to send " + "set_mdns_fqdn cmd"); + vos_mem_free(mdns_fqdn_info); + return VOS_STATUS_E_NOMEM; + } + + vos_mem_zero(fqdn_info, sizeof(*fqdn_info)); + + wda_params = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)); + if(NULL == wda_params) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(fqdn_info); + vos_mem_free(mdns_fqdn_info); + return VOS_STATUS_E_NOMEM; + } + + fqdn_info->bss_idx = mdns_fqdn_info->bss_idx; + fqdn_info->type = mdns_fqdn_info->fqdn_type; + fqdn_info->fqdn_len = mdns_fqdn_info->fqdn_len; + vos_mem_copy(fqdn_info->fqdn_data, mdns_fqdn_info->fqdn_data, + mdns_fqdn_info->fqdn_len); + fqdn_info->fqdn_data[mdns_fqdn_info->fqdn_len] = '\0'; + + wda_params->pWdaContext = wda_handle; + wda_params->wdaMsgParam = mdns_fqdn_info; + wda_params->wdaWdiApiMsgParam = (void *)fqdn_info; + + wstatus = wdi_set_mdns_fqdn_req(fqdn_info, + (wdi_mdns_fqdn_rsp_cb) + wda_mdns_fqdn_rsp_callback, + wda_params); + if(IS_WDI_STATUS_FAILURE(wstatus)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to send wdi_set_mdns_fqdn_req cmd" ); + status = CONVERT_WDI2VOS_STATUS(wstatus); + vos_mem_free(wda_params->wdaWdiApiMsgParam) ; + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + } + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "mDNS FQDN set"); + return status; +} + +/** + * wda_set_mdns_response_req() - wda api to set mdns resp offload + * @wda_handle: wda handle + * @mdns_rsp_info: mdns resp offload info + * + * Return - 0 for success or else failure + */ +static int +wda_set_mdns_response_req(tWDA_CbContext *wda_handle, + sir_mdns_resp_info_t *mdns_rsp_info) +{ + wdi_mdns_set_resp_req *rsp_info; + tWDA_ReqParams *wda_params; + WDI_Status wstatus; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + FL("---> %s"), __func__); + + if(NULL == mdns_rsp_info) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: dhcp_server_offload_info received NULL", + __func__); + VOS_ASSERT(0) ; + return VOS_STATUS_E_FAULT; + } + + rsp_info = (wdi_mdns_set_resp_req *) + vos_mem_malloc(sizeof(*rsp_info)); + if (!rsp_info) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to allocate buffer to send " + "wdi_set_mdns_response_req cmd"); + vos_mem_free(mdns_rsp_info); + return VOS_STATUS_E_NOMEM; + } + + vos_mem_zero(rsp_info, sizeof(*rsp_info)); + + wda_params = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ; + if(NULL == wda_params) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(rsp_info); + vos_mem_free(mdns_rsp_info); + return VOS_STATUS_E_NOMEM; + } + + rsp_info->bss_idx = mdns_rsp_info->bss_idx; + rsp_info->ar_count = mdns_rsp_info->resourceRecord_count; + rsp_info->resp_len = mdns_rsp_info->resp_len; + vos_mem_copy(rsp_info->resp_data, mdns_rsp_info->resp_data, + mdns_rsp_info->resp_len); + rsp_info->resp_data[mdns_rsp_info->resp_len] = '\0'; + + wda_params->pWdaContext = wda_handle; + wda_params->wdaMsgParam = mdns_rsp_info; + wda_params->wdaWdiApiMsgParam = (void *)rsp_info; + + wstatus = wdi_set_mdns_response_req(rsp_info, + (wdi_mdns_resp_rsp_cb) + wda_mdns_resp_rsp_callback, + wda_params); + if(IS_WDI_STATUS_FAILURE(wstatus)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to send wdi_set_mdns_response_req cmd" ); + status = CONVERT_WDI2VOS_STATUS(wstatus); + vos_mem_free(wda_params->wdaWdiApiMsgParam) ; + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + } + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "mDNS Response set!"); + return status; +} + +/** + * wda_get_mdns_stats_req() - wda api to get mdns stats + * @wda_handle: wda handle + * @mdns_info: mdns info + * + * Return - 0 for success or else failure + */ +static int +wda_get_mdns_stats_req(tWDA_CbContext *wda_handle, + sir_get_mdns_stats_info_t *mdns_info) +{ + wdi_mdns_get_stats_req *status_info; + tWDA_ReqParams *wda_params; + WDI_Status wstatus; + + VOS_STATUS status = VOS_STATUS_SUCCESS; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + FL("---> %s"), __func__); + + if(NULL == mdns_info) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: dhcp_server_offload_info received NULL", + __func__); + VOS_ASSERT(0) ; + return VOS_STATUS_E_FAULT; + } + + status_info = (wdi_mdns_get_stats_req *) + vos_mem_malloc(sizeof(*status_info)); + if (!status_info) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to allocate buffer to send " + "wdi_set_mdns_response_req cmd"); + vos_mem_free(mdns_info); + return VOS_STATUS_E_NOMEM; + } + + vos_mem_zero(status_info, sizeof(*status_info)); + + wda_params = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ; + if(NULL == wda_params) + { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(status_info); + vos_mem_free(mdns_info); + return VOS_STATUS_E_NOMEM; + } + + status_info->bss_idx = mdns_info->bss_idx; + + wda_params->pWdaContext = wda_handle; + wda_params->wdaMsgParam = mdns_info; + wda_params->wdaWdiApiMsgParam = (void *)status_info; + + wstatus = wdi_get_mdns_stats_req(status_info, + (wdi_get_stats_rsp_cb) + wda_get_stats_rsp_callback, + wda_params); + if(IS_WDI_STATUS_FAILURE(wstatus)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to send wdi_set_mdns_response_req cmd" ); + status = CONVERT_WDI2VOS_STATUS(wstatus); + vos_mem_free(wda_params->wdaWdiApiMsgParam) ; + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + } + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "Get mDNS stats"); + return status; +} +#endif /* MDNS_OFFLOAD */ + /* * FUNCTION: WDA_McProcessMsg * Trigger DAL-AL to start CFG download @@ -16200,26 +17256,16 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) /* timer related messages */ case WDA_TIMER_BA_ACTIVITY_REQ: { - WDA_BaCheckActivity(pWDA, false); + WDA_BaCheckActivity(pWDA) ; break ; } + /* timer related messages */ case WDA_TIMER_TRAFFIC_STATS_IND: { WDA_TimerTrafficStatsInd(pWDA); break; } - /* Connection status related messages */ - case WDA_TRIGGER_ADD_BA_REQ: - { - WDA_BaCheckActivity(pWDA, true); - break; - } - case WDA_GET_CON_STATUS: - { - WDA_GetConnectionStatus(pWDA, (getConStatusParams *)pMsg->bodyptr); - break; - } #ifdef WLAN_FEATURE_VOWIFI_11R case WDA_AGGR_QOS_REQ: { @@ -16513,7 +17559,32 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) WDA_ProcessEncryptMsgReq(pWDA, (u8 *)pMsg->bodyptr); break; } - +#ifdef DHCP_SERVER_OFFLOAD + case WDA_SET_DHCP_SERVER_OFFLOAD_REQ: + { + wda_process_dhcpserver_offload_req(pWDA, + (sir_dhcp_srv_offload_info_t *)pMsg->bodyptr); + break; + } +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + case WDA_SET_MDNS_OFFLOAD_CMD: + wda_set_mdns_offload_req(pWDA, + (sir_mdns_offload_info_t *)pMsg->bodyptr); + break; + case WDA_SET_MDNS_FQDN_CMD: + wda_set_mdns_fqdn_req(pWDA, + (sir_mdns_fqdn_info_t *)pMsg->bodyptr); + break; + case WDA_SET_MDNS_RESPONSE_CMD: + wda_set_mdns_response_req(pWDA, + (sir_mdns_resp_info_t *)pMsg->bodyptr); + break; + case WDA_GET_MDNS_STATUS_CMD: + wda_get_mdns_stats_req(pWDA, + (sir_get_mdns_stats_info_t *) pMsg->bodyptr); + break; +#endif /* MDNS_OFFLOAD */ case WDA_NAN_REQUEST: { WDA_ProcessNanRequest( pWDA, (tNanRequest *)pMsg->bodyptr); @@ -16576,6 +17647,44 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) WDA_ProcessTLPauseInd(pWDA, pMsg->bodyval); break; } +#ifdef WLAN_FEATURE_APFIND + case WDA_APFIND_SET_CMD: + { + WDA_Process_apfind_set_cmd(pWDA, + (struct hal_apfind_request *)pMsg->bodyptr); + } +#endif +#ifdef SAP_AUTH_OFFLOAD + case WDA_SET_SAP_AUTH_OFL: + { + wda_process_sap_auth_offload(pWDA, + (struct tSirSapOffloadInfo*)pMsg->bodyptr); + break; + } + case WDA_SAP_OFL_ADD_STA: + { + WDA_ProcessSapAuthOffloadAddStaReq(pWDA, + (tAddStaParams *)pMsg->bodyptr); + break; + } + case WDA_SAP_OFL_DEL_STA: + { + WDA_ProcessSapAuthOffloadDelStaReq(pWDA, + (tDeleteStaParams *)pMsg->bodyptr); + break; + } +#endif + case WDA_CAP_TSF_REQ: + { + WDA_ProcessCapTsfReq(pWDA, (tSirCapTsfParams *) + pMsg->bodyptr); + break; + } + case WDA_GET_TSF_REQ: + { + WDA_ProcessGetTsfReq(pWDA, (tSirCapTsfParams *)pMsg->bodyptr); + break; + } case WDA_SET_ARP_STATS_REQ: { WDA_ProcessSetARPStatsReq(pWDA, (setArpStatsParams *)pMsg->bodyptr); @@ -16670,6 +17779,13 @@ void WDA_lowLevelIndCallback(WDI_LowLevelIndType *wdiLowLevelInd, WDA_SendMsg(pWDA, WDA_MISSED_BEACON_IND, (void *)pMissBeacInd , 0) ; break ; } +#ifdef WLAN_FEATURE_APFIND + case WDI_AP_FOUND_IND: + { + WDA_SendMsg(pWDA, WDA_AP_FIND_IND, NULL, 0) ; + break ; + } +#endif case WDI_UNKNOWN_ADDR2_FRAME_RX_IND: { /* TODO: Decode Ind and send Ind to PE */ @@ -17926,55 +19042,19 @@ bool WDA_AllowAddBA(tpAniSirGlobal pMac, tANI_U8 staId, tANI_U8 tid) return true; } -void WDA_GetConnectionStatus(tWDA_CbContext *pWDA, - getConStatusParams *conStatusParams) -{ - tpAniSirGlobal pMac; - uint8_t sta_id, tid; - bool tx_aggr; - bool status = false; - - pMac = (tpAniSirGlobal)VOS_GET_MAC_CTXT(pWDA->pVosContext); - if (NULL == pMac) - { - VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "%s: pMac is NULL",__func__); - return; - } - - tx_aggr= pMac->lim.test_status_bainfo.tx_aggr; - sta_id = pMac->lim.test_status_bainfo.sta_id; - tid = pMac->lim.test_status_bainfo.tid; - - if (tx_aggr && WDA_GET_BA_TXFLAG(pWDA, sta_id, tid)) - status = true; - - if (conStatusParams->rsp_cb_fn) - conStatusParams->rsp_cb_fn(conStatusParams->data_ctx, status); -} - -static void WDA_StoreTestBAInfo(tpAniSirGlobal pMac, bool tx_aggr, - uint8_t sta_id, uint8_t tid) -{ - pMac->lim.test_status_bainfo.tx_aggr = tx_aggr; - pMac->lim.test_status_bainfo.sta_id= sta_id; - pMac->lim.test_status_bainfo.tid = tid; -} - /* * BA Activity check timer handler */ -void WDA_BaCheckActivity(tWDA_CbContext *pWDA, bool test_con) +void WDA_BaCheckActivity(tWDA_CbContext *pWDA) { tANI_U8 curSta = 0 ; tANI_U8 tid = 0 ; tANI_U8 size = 0 ; tANI_U8 baCandidateCount = 0 ; tANI_U8 newBaCandidate = 0 ; - tANI_U32 val; + tANI_U32 val, val1; WDI_TriggerBAReqCandidateType baCandidate[WDA_MAX_STA] = {{0}} ; tpAniSirGlobal pMac; - bool found = false; if (NULL == pWDA) { @@ -18014,16 +19094,18 @@ void WDA_BaCheckActivity(tWDA_CbContext *pWDA, bool test_con) val = 0; } + if (wlan_cfgGetInt(pMac, + WNI_CFG_ENABLE_TX_RX_AGGREGATION, &val1) != + eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Unable to get WNI_CFG_ENABLE_TX_RX_AGGREGATION"); + val1 = 1; + } /* walk through all STA entries and find out TX packet count */ for(curSta = 0 ; curSta < pWDA->wdaMaxSta ; curSta++) { tANI_U32 currentOperChan = pWDA->wdaStaInfo[curSta].currentOperChan; - WLANTL_STAStateType tlSTAState; - tANI_U8 validStaIndex = pWDA->wdaStaInfo[curSta].ucValidStaIndex; - - if (found) - break; - #ifdef WLAN_SOFTAP_VSTA_FEATURE // We can only do BA on "hard" STAs. if (!(IS_HWSTA_IDX(curSta))) @@ -18031,47 +19113,47 @@ void WDA_BaCheckActivity(tWDA_CbContext *pWDA, bool test_con) continue; } #endif //WLAN_SOFTAP_VSTA_FEATURE - - if (!((WDA_VALID_STA_INDEX == validStaIndex) && - (VOS_STATUS_SUCCESS == WDA_TL_GET_STA_STATE(pWDA->pVosContext, - curSta, &tlSTAState)))) - continue; - - if (WLANTL_STA_AUTHENTICATED != tlSTAState) - continue; - - if(val && ((currentOperChan >= SIR_11B_CHANNEL_BEGIN) && - (currentOperChan <= SIR_11B_CHANNEL_END))) { - VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "%s: BTC disabled aggregation - dont start" - "TX ADDBA req",__func__); - continue; - } - for(tid = 0 ; tid < STACFG_MAX_TC ; tid++) { + WLANTL_STAStateType tlSTAState ; tANI_U32 txPktCount = 0 ; - if (VOS_STATUS_SUCCESS == WDA_TL_GET_TX_PKTCOUNT( pWDA->pVosContext, - curSta, tid, &txPktCount)) + tANI_U8 validStaIndex = pWDA->wdaStaInfo[curSta].ucValidStaIndex ; + if((WDA_VALID_STA_INDEX == validStaIndex) && + (VOS_STATUS_SUCCESS == WDA_TL_GET_STA_STATE( pWDA->pVosContext, + curSta, &tlSTAState)) && + (VOS_STATUS_SUCCESS == WDA_TL_GET_TX_PKTCOUNT( pWDA->pVosContext, + curSta, tid, &txPktCount))) { - if(!WDA_GET_BA_TXFLAG(pWDA, curSta, tid) && - WDA_AllowAddBA(pMac, curSta, tid) && - (((eSYSTEM_STA_IN_IBSS_ROLE == pWDA->wdaGlobalSystemRole) - && txPktCount) || - (txPktCount >= WDA_LAST_POLLED_THRESHOLD(pWDA, curSta, tid)) || - test_con)) +#if 0 + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_LOW, + "************* %d:%d, %d ",curSta, txPktCount, + pWDA->wdaStaInfo[curSta].framesTxed[tid]); +#endif + if(val && ( (currentOperChan >= SIR_11B_CHANNEL_BEGIN) && + (currentOperChan <= SIR_11B_CHANNEL_END))) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "%s: BTC disabled aggregation - dont start " + "TX ADDBA req",__func__); + } + else if (!val1) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "%s: aggregation disabled- dont start " + "TX ADDBA req",__func__); + } + else if(!WDA_GET_BA_TXFLAG(pWDA, curSta, tid) + && (WLANTL_STA_AUTHENTICATED == tlSTAState) + && WDA_AllowAddBA(pMac, curSta, tid) + && (((eSYSTEM_STA_IN_IBSS_ROLE == + pWDA->wdaGlobalSystemRole) && txPktCount ) + || (txPktCount >= WDA_LAST_POLLED_THRESHOLD(pWDA, + curSta, tid)))) { /* get prepare for sending message to HAL */ //baCandidate[baCandidateCount].staIdx = curSta ; baCandidate[baCandidateCount].ucTidBitmap |= 1 << tid ; newBaCandidate = WDA_ENABLE_BA ; - - /* Trigger only one BA request to check connection status */ - if (test_con) { - WDA_StoreTestBAInfo(pMac, true, curSta, tid); - found = true; - break; - } } pWDA->wdaStaInfo[curSta].framesTxed[tid] = txPktCount ; } @@ -18140,14 +19222,6 @@ void WDA_BaCheckActivity(tWDA_CbContext *pWDA, bool test_con) } else { - if (test_con) - { - WDA_StoreTestBAInfo(pMac, false, pWDA->wdaMaxSta, STACFG_MAX_TC); - VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "%s: ADDBA to test connection status no valid Tid found", - __func__); - } - VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_LOW, "There is no TID for initiating BA"); } @@ -18167,7 +19241,6 @@ void WDA_BaCheckActivity(tWDA_CbContext *pWDA, bool test_con) } return ; } - /* * WDA common routine to create timer used by WDA. */ @@ -18251,7 +19324,6 @@ static VOS_STATUS wdaCreateTimers(tWDA_CbContext *pWDA) } return VOS_STATUS_SUCCESS ; } - /* * WDA common routine to destroy timer used by WDA. */ @@ -18860,6 +19932,8 @@ VOS_STATUS WDA_ProcessRoamScanOffloadReq(tWDA_CbContext *pWDA, pRoamOffloadScanReqParams->nProbes; pwdiRoamOffloadScanInfo->HomeAwayTime = pRoamOffloadScanReqParams->HomeAwayTime; + pwdiRoamOffloadScanInfo->WeakZoneRssiThresholdForRoam = + pRoamOffloadScanReqParams->WeakZoneRssiThresholdForRoam; pwdiRoamScanOffloadReqParams->wdiReqStatusCB = NULL; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiRoamScanOffloadReqParams; @@ -22177,5 +23251,274 @@ VOS_STATUS WDA_ProcessBcnMissPenaltyCount(tWDA_CbContext *pWDA, vos_mem_free(params); return CONVERT_WDI2VOS_STATUS(status) ; } - #endif +/* + * WDA_CapTsfRspCb : handle response for tsf requests + * @wdi_rsp : Response from WDI for tsf requests + * @user_data: pointer to user data + * Returns: None + */ +void WDA_CapTsfRspCb (wdi_cap_tsf_rsp_t *wdi_rsp, void *user_data) +{ + + tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data; + tSirCapTsfParams *cap_tsf_params; + struct stsf *stsf_temp; + VOS_STATUS status; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s " ,__func__); + + if (NULL == wda_params) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if (NULL == wda_params->wdaMsgParam) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams->wdaMsgParam is NULL", __func__); + VOS_ASSERT(0); + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params); + return; + } + + stsf_temp = (struct stsf *)vos_mem_malloc(sizeof(*stsf_temp)); + if (NULL == stsf_temp) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: Unable to allocate tsf struct", __func__); + VOS_ASSERT(0); + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + return; + } + cap_tsf_params = (tSirCapTsfParams *)wda_params->wdaMsgParam; + stsf_temp->session_id = cap_tsf_params->bss_idx; + stsf_temp->set_tsf_req = true; + stsf_temp->tsf_req_status = wdi_rsp->status; + + if (cap_tsf_params->tsf_rsp_cb_func) { + cap_tsf_params->tsf_rsp_cb_func ( + cap_tsf_params->tsf_rsp_cb_ctx, stsf_temp); + } + else { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: tsf callback is NULL", __func__); + vos_mem_free(stsf_temp); + } + status = CONVERT_WDI2VOS_STATUS(wdi_rsp->status); + if (status) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: Capture TSF failed with status=%d", __func__, + status); + VOS_ASSERT(0); + } + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + return; +} + +/* + * WDA_GetTsfRspCb : handle response for get tsf request + * @wdi_rsp : Response from WDI for tsf requests + * @user_data: pointer to user data + * Returns: None + */ +void WDA_GetTsfRspCb (wdi_cap_tsf_rsp_t *wdi_rsp, void *user_data) +{ + + tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data; + tSirCapTsfParams *cap_tsf_params; + struct stsf *stsf_temp; + VOS_STATUS status; + + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s " ,__func__); + + if (NULL == wda_params) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if (NULL == wda_params->wdaMsgParam) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams->wdaMsgParam is NULL", __func__); + VOS_ASSERT(0); + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params); + return; + } + + stsf_temp = (struct stsf *)vos_mem_malloc(sizeof(*stsf_temp)); + if (NULL == stsf_temp) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: Unable to allocate tsf struct", __func__); + VOS_ASSERT(0); + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + return; + } + cap_tsf_params = (tSirCapTsfParams *)wda_params->wdaMsgParam; + stsf_temp->session_id = cap_tsf_params->bss_idx; + /* Indicate to upper layer that this is a get request */ + stsf_temp->set_tsf_req = false; + stsf_temp->tsf_low = wdi_rsp->tsf_lo; + stsf_temp->tsf_high = wdi_rsp->tsf_hi; + stsf_temp->tsf_req_status = wdi_rsp->status; + + if (cap_tsf_params->tsf_rsp_cb_func) { + cap_tsf_params->tsf_rsp_cb_func ( + cap_tsf_params->tsf_rsp_cb_ctx, stsf_temp); + } + else { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: tsf callback is NULL", __func__); + vos_mem_free(stsf_temp); + } + status = CONVERT_WDI2VOS_STATUS(wdi_rsp->status); + if (status) { + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: Capture TSF failed with status=%d", __func__, + status); + VOS_ASSERT(0); + } + vos_mem_free(wda_params->wdaWdiApiMsgParam); + vos_mem_free(wda_params->wdaMsgParam); + vos_mem_free(wda_params); + return; +} +/* + * FUNCTION: WDA_ProcessCapTsfReq + * Send capture tsf request to FW. + */ +VOS_STATUS WDA_ProcessCapTsfReq(tWDA_CbContext *pWDA, tSirCapTsfParams *params) +{ + WDI_Status status = WDI_STATUS_SUCCESS; + wdi_cap_tsf_params_t *pWDICapTsfReqType; + tWDA_ReqParams *pWdaParams ; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s " ,__func__); + if(NULL == params) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: cap tsf params NULL", __func__); + VOS_ASSERT(0) ; + return -EINVAL; + } + + pWDICapTsfReqType = (wdi_cap_tsf_params_t *)vos_mem_malloc( + sizeof(*pWDICapTsfReqType)); + if(NULL == pWDICapTsfReqType) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(params); + return VOS_STATUS_E_NOMEM; + } + pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(*pWdaParams)) ; + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(pWDICapTsfReqType); + vos_mem_free(params); + return VOS_STATUS_E_NOMEM; + } + + pWDICapTsfReqType->bss_idx = params->bss_idx; + pWDICapTsfReqType->capTSFget = CAP_TSF_REQUEST; + + pWdaParams->pWdaContext = pWDA; + pWdaParams->wdaMsgParam = params; + pWdaParams->wdaWdiApiMsgParam = (void *)pWDICapTsfReqType; + + status = wdi_process_cap_tsf_req(pWDICapTsfReqType, + (wdi_tsf_rsp_cb)WDA_CapTsfRspCb, + pWdaParams); + + if(IS_WDI_STATUS_FAILURE(status)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failure in sendind WifiConfigReq, free all the memory" ); + vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ; + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + vos_mem_free(params); + } + return CONVERT_WDI2VOS_STATUS(status) ; +} + +/* + * FUNCTION: WDA_ProcessGetTsfReq + * Send capture tsf request to FW. + */ +VOS_STATUS WDA_ProcessGetTsfReq(tWDA_CbContext *pWDA, tSirCapTsfParams *params) +{ + WDI_Status status = WDI_STATUS_SUCCESS; + wdi_cap_tsf_params_t *pWDIGetTsfReqType; + tWDA_ReqParams *pWdaParams ; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s " ,__func__); + if(NULL == params) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: cap tsf params NULL", __func__); + VOS_ASSERT(0) ; + return VOS_STATUS_E_INVAL; + } + + pWDIGetTsfReqType = (wdi_cap_tsf_params_t *)vos_mem_malloc( + sizeof(wdi_cap_tsf_params_t)); + if(NULL == pWDIGetTsfReqType) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(params); + return VOS_STATUS_E_INVAL; + } + pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ; + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(pWDIGetTsfReqType); + vos_mem_free(params); + return VOS_STATUS_E_NOMEM; + } + + pWDIGetTsfReqType->bss_idx = params->bss_idx; + /* Indicate that this is a get request */ + pWDIGetTsfReqType->capTSFget = GET_TSF_REQUEST; + + pWdaParams->pWdaContext = pWDA; + pWdaParams->wdaMsgParam = params; + pWdaParams->wdaWdiApiMsgParam = (void *)pWDIGetTsfReqType; + + status = wdi_process_get_tsf_req(pWDIGetTsfReqType, + (wdi_tsf_rsp_cb)WDA_GetTsfRspCb, + pWdaParams); + + if(IS_WDI_STATUS_FAILURE(status)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failure in sendind WifiConfigReq, free all the memory" ); + vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ; + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + vos_mem_free(params); + } + return CONVERT_WDI2VOS_STATUS(status) ; +} diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h index 65461f720c6..297fba64905 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -430,6 +430,9 @@ typedef enum #ifdef FEATURE_OEM_DATA_SUPPORT WDI_START_OEM_DATA_RSP_IND_NEW, #endif +#ifdef WLAN_FEATURE_APFIND + WDI_AP_FOUND_IND, +#endif WDI_MAX_IND }WDI_LowLevelIndEnumType; @@ -3303,6 +3306,9 @@ typedef enum WDI_LINK_FINISH_CAL_STATE = 13, WDI_LINK_LISTEN_STATE = 14, WDI_LINK_SEND_ACTION_STATE = 15, +#ifdef WLAN_FEATURE_LFR_MBB + WDI_LINK_PRE_AUTH_REASSOC_STATE = 17, +#endif WDI_LINK_MAX = 0x7FFFFFFF } WDI_LinkStateType; @@ -5567,6 +5573,7 @@ typedef struct WDI_MobilityDomainInfo MDID; wpt_uint8 nProbes; wpt_uint16 HomeAwayTime; + wpt_uint8 WeakZoneRssiThresholdForRoam; } WDI_RoamOffloadScanInfo; typedef struct @@ -6416,6 +6423,157 @@ typedef struct wpt_macAddr bssId; }WDI_WifiConfigSetReqType; +#ifdef DHCP_SERVER_OFFLOAD +/** + * wdi_set_dhcp_server_offload_t - dhcp server offload info + * @bssidx: bss index + * @enable: enable od disable + * @srv_ipv4: server ip address + * @start_lsb: starting lsb addredd of pool + * @num_client: number of clients supported + */ +typedef struct { + wpt_uint8 bssidx; + wpt_uint32 enable; + wpt_uint32 srv_ipv4; /* server IP */ + wpt_uint32 start_lsb; /* starting address assigned to client */ + wpt_uint32 num_client; /* number of clients we support */ +} wdi_set_dhcp_server_offload_t; + +/** + * wdi_dhcp_server_offload_rsp_param_t - dhcp server offload response + * @status: status for the command success or failure + */ +typedef struct +{ + /* wdi status */ + wpt_uint32 status; +} wdi_dhcp_server_offload_rsp_param_t; +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +/** + * The purpose of the multicast Domain Name System (mDNS) is to resolve host + * names to IP addresses within small networks that do not include a local + * name server. It utilizes essentially the same programming interfaces, packet + * formats and operating semantics as the unicast DNS, and the advantage is + * zero configuration service while no need for central or global server. + * Based on mDNS, the DNS-SD (Service Discovery) allows clients to discover a + * named list of services by type in a specified domain using standard + * DNS queries. Here, we provide the ability to advertise the available + * services by responding to mDNS queries. + */ + +/** + * wdi_mdns_enable_offload_cmd_req - mdns enable request + * @bss_idx: bss index + * @enable: enable + */ +typedef struct { + wpt_uint8 bss_idx; + wpt_uint32 enable; +} wdi_mdns_enable_offload_cmd_req; + +/** + * wdi_mdns_enable_offload_rsp_param_t - mDNS enable offload response + * @status: status for the command success or failure + */ +typedef struct +{ + wpt_uint32 status; +} wdi_mdns_enable_offload_rsp_param_t; + +#define WMI_MAX_MDNS_FQDN_LEN 64 +#define WMI_MAX_MDNS_RESP_LEN 512 +#define WMI_MDNS_FQDN_TYPE_GENERAL 0 +#define WMI_MDNS_FQDN_TYPE_UNIQUE 1 + +/** + * wdi_mdns_set_fqdn_cmd_req - set fqdn request + * @bss_idx: bss index + * @type: type of fqdn, general or unique + * @fqdn_len: length of fqdn + * @fqdn_data: TLV byte stream of fqdn data of length fqdn_len fully-qualified + * domain name to check if match with the received queries + */ +typedef struct { + wpt_uint8 bss_idx; + wpt_uint32 type; + wpt_uint32 fqdn_len; + wpt_uint8 fqdn_data[WMI_MAX_MDNS_FQDN_LEN]; +} wdi_mdns_set_fqdn_cmd_req; + +/** + * wdi_mdns_set_fqdn_rsp_param_t - mDNS set fqdn response + * @status: status for the command success or failure + */ +typedef struct +{ + wpt_uint32 status; +} wdi_mdns_set_fqdn_rsp_param_t; + +/** + * wdi_mdns_set_resp_req - mDNS response request + * @bss_idx: bss index + * @ar_count: Answer Resource Record count + * @resp_len: length of response + * @resp_data: TLV byte stream of resp data of length resp_len responses consisits of Resource Records + */ +typedef struct { + wpt_uint8 bss_idx; + wpt_uint32 ar_count; + wpt_uint32 resp_len; + wpt_uint8 resp_data[WMI_MAX_MDNS_RESP_LEN]; +} wdi_mdns_set_resp_req; + +/** + * wdi_mdns_set_rsp_param_t - mDNS set response rsp + * @status: status for the command success or failure + */ +typedef struct +{ + wpt_uint32 status; +} wdi_mdns_set_rsp_param_t; + +/** + * wdi_mdns_get_stats_req - get mdns stats request + * @bss_idx: bss index + */ +typedef struct { + wpt_uint8 bss_idx; +} wdi_mdns_get_stats_req; + +/** + * wdi_mdns_stats_rsp_t - mdns stats + * @bss_idx: bss index + * @current_ts: curTimestamp in milliseconds + * @last_querry_ts: last received Query in milliseconds + * @last_resp_ts: last sent Response in milliseconds + * @tot_queries: stats of received queries + * @tot_matches: stats of macth queries + * @tot_rsp: stats of responses + * @status: indicate the current status of mDNS offload + */ +typedef struct { + wpt_uint8 bss_idx; + wpt_uint32 current_ts; + wpt_uint32 last_querry_ts; + wpt_uint32 last_resp_ts; + wpt_uint32 tot_queries; + wpt_uint32 tot_matches; + wpt_uint32 tot_rsp; + wpt_uint32 status; +} wdi_mdns_stats_rsp_param_t; +#endif /* MDNS_OFFLOAD */ + +#ifdef WLAN_FEATURE_APFIND +struct WDI_APFind_cmd +{ + wpt_uint32 data_len; + wpt_uint8 data[]; +}; +#endif + /** * struct WDI_FwrMemDumpReqType - firmware memory dump request details. .*.@FWMemDumpReqCb - Associated Callback @@ -6464,6 +6622,50 @@ struct WDI_AllowedActionFramesInd { wpt_uint32 bitmask; wpt_uint32 reserved; }; + +struct WDI_sap_ofl_enable_params{ + + wpt_macAddr macAddr; + /** enable/disable sap auth offload */ + wpt_uint32 enable; + /** authentication mode (defined above) */ + wpt_uint32 rsn_authmode; + /** unicast cipher set */ + wpt_uint32 rsn_ucastcipherset; + /** mcast/group cipher set */ + wpt_uint32 rsn_mcastcipherset; + /** mcast/group management frames cipher set */ + wpt_uint32 rsn_mcastmgmtcipherset; + /** sap channel */ + wpt_uint32 channel; + /** length of psk */ + wpt_uint32 psk_len; + wpt_uint8 key[64]; +}; + +/** + * wdi_cap_tsf_params_t - wdi capture tsf params + * @bssidx: bss index + * @capTSFget: whether get/set request + * + */ + typedef struct { + wpt_uint8 bss_idx; + wpt_uint8 capTSFget; +} wdi_cap_tsf_params_t; + +/** + * wdi_cap_tsf_rsp_t - capture tsf response + * @bssidx: bss index + * @capTSFget: whether get/set request + * + */ + typedef struct { + wpt_uint32 status; + wpt_uint32 tsf_lo; + wpt_uint32 tsf_hi; +} wdi_cap_tsf_rsp_t; + /*---------------------------------------------------------------------------- * WDI callback types *--------------------------------------------------------------------------*/ @@ -8425,6 +8627,19 @@ typedef void (*WDI_AntennaDivSelRspCb)(WDI_Status status, typedef void (*wdi_nud_set_arp_rsp_cb)(void *event_data,void *user_data); typedef void (*wdi_nud_get_arp_rsp_cb)(void *event_data,void *user_data); +#ifdef DHCP_SERVER_OFFLOAD +typedef void (*wdi_dhcp_srv_offload_rsp_cb)(void *event_data,void *user_data); +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD +typedef void (*wdi_mdns_enable_rsp_cb)(void *event_data,void *user_data); +typedef void (*wdi_mdns_fqdn_rsp_cb)(void *event_data,void *user_data); +typedef void (*wdi_mdns_resp_rsp_cb)(void *event_data,void *user_data); +typedef void (*wdi_get_stats_rsp_cb)(void *event_data,void *user_data); +#endif /* MDNS_OFFLOAD */ + +typedef void (*wdi_tsf_rsp_cb)(void *event_data,void *user_data); + + /*======================================================================== * Function Declarations and Documentation ==========================================================================*/ @@ -12229,4 +12444,67 @@ WDI_GetARPStatsReq WDI_GetARPStatsRspCb wdiGetARPStatsRspCb, void* pUserData ); + +WDI_Status +WDI_process_sap_auth_offload( + struct WDI_sap_ofl_enable_params *sap_ofl_enable_cmd +); +#ifdef WLAN_FEATURE_APFIND +WDI_Status WDI_process_ap_find_cmd(struct WDI_APFind_cmd *params); +#endif +#ifdef DHCP_SERVER_OFFLOAD +WDI_Status +wdi_process_dhcpserver_offload_req +( + wdi_set_dhcp_server_offload_t *dhcp_info, + wdi_dhcp_srv_offload_rsp_cb wdi_dhcp_srv_offload_rsp_callback, + void *user_data +); +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +WDI_Status +wdi_set_mdns_offload_req +( + wdi_mdns_enable_offload_cmd_req *mdns_info, + wdi_mdns_enable_rsp_cb wdi_mdns_enable_rsp_callback, + void *user_data +); + +WDI_Status +wdi_set_mdns_fqdn_req +( + wdi_mdns_set_fqdn_cmd_req *mdns_info, + wdi_mdns_fqdn_rsp_cb wdi_mdns_fqdn_rsp_callback, + void *user_data +); + +WDI_Status +wdi_set_mdns_response_req +( + wdi_mdns_set_resp_req *mdns_info, + wdi_mdns_resp_rsp_cb wdi_mdns_resp_rsp_callback, + void *user_data +); + +WDI_Status +wdi_get_mdns_stats_req +( + wdi_mdns_get_stats_req *mdns_info, + wdi_get_stats_rsp_cb wdi_get_stats_rsp_callback, + void *user_data +); +#endif /* MDNS_OFFLOAD */ + +WDI_Status +wdi_process_cap_tsf_req (wdi_cap_tsf_params_t *wdi_cap_tsf_req, + wdi_tsf_rsp_cb wdi_tsf_rsp_callback, + void *user_data); + +WDI_Status +wdi_process_get_tsf_req (wdi_cap_tsf_params_t *wdi_get_tsf_req, + wdi_tsf_rsp_cb wdi_tsf_rsp_callback, + void *user_data); + + #endif /* #ifndef WLAN_QCT_WDI_H */ diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h index c828c4b2ea5..4ca3a656472 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h @@ -325,9 +325,16 @@ typedef struct this field is set to zero. */ wpt_uint32 tid:4; - wpt_uint32 reserved4:8; + wpt_uint32 indType:2; + wpt_uint32 reserved4:4; + wpt_uint32 htt_t2h_msg:1; + wpt_uint32 fc:1; + #else - wpt_uint32 reserved4:8; + wpt_uint32 fc:1; + wpt_uint32 htt_t2h_msg:1; + wpt_uint32 reserved4:4; + wpt_uint32 indType:2; wpt_uint32 tid:4; #ifdef WCN_PRONTO wpt_uint32 rxDXEPriorityRouting:1; diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h index 85446f1b6dd..ca1b403af0f 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h @@ -226,6 +226,8 @@ when who what, where, why #endif +#define WDI_RXBD_MLME_STA_STATUS 0x1 +#define WDI_RXBD_SAP_TX_STATS 0x2 /*-------------------------------------------------------------------------- BD header macros - used by the data path to get or set various values inside the packet BD @@ -312,6 +314,8 @@ when who what, where, why #define WDI_RX_BD_GET_EXTSCANFULLSCANRESIND( _pvBDHeader ) (((WDI_RxBdType*)_pvBDHeader)->extscanBuffer) #endif +#define WDI_RX_BD_GET_PER_SAPOFFLOAD( _pvBDHeader ) (((WDI_RxBdType*)_pvBDHeader)->indType) + /*------------ RSSI and SNR Information extraction -------------*/ #define WDI_RX_BD_GET_RSSI0( _pvBDHeader ) \ (((((WDI_RxBdType*)_pvBDHeader)->phyStats0) >> 24) & 0xff) diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h index d0faaf04697..5fb24ba0722 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h @@ -491,9 +491,19 @@ typedef enum WDI_PER_ROAM_SCAN_OFFLOAD_REQ = 116, WDI_PER_ROAM_SCAN_TRIGGER_REQ = 117, #endif -/* ARP DEBUG STATS */ - WDI_FW_ARP_STATS_REQ = 118, - WDI_FW_GET_ARP_STATS_REQ = 119, + + WDI_DHCP_SERVER_OFFLOAD_REQ = 118, + WDI_MDNS_ENABLE_OFFLOAD_REQ = 119, + WDI_MDNS_FQDN_OFFLOAD_REQ = 120, + WDI_MDNS_RESP_OFFLOAD_REQ = 121, + WDI_MDNS_STATS_OFFLOAD_REQ = 122, + + WDI_CAP_TSF_REQ = 123, + WDI_GET_TSF_REQ = 124, + + /* ARP DEBUG STATS */ + WDI_FW_ARP_STATS_REQ = 125, + WDI_FW_GET_ARP_STATS_REQ = 126, WDI_MAX_REQ, @@ -558,8 +568,12 @@ typedef enum WDI_ANTENNA_DIVERSITY_SELECTION_REQ = WDI_MAX_REQ + 21, WDI_MODIFY_ROAM_PARAMS_IND = WDI_MAX_REQ + 22, WDI_SET_ALLOWED_ACTION_FRAMES_IND = WDI_MAX_REQ + 23, +#ifdef SAP_AUTH_OFFLOAD + WDI_PROCESS_SAP_AUTH_OFFLOAD_IND = WDI_MAX_REQ +24, +#endif - WDI_MAX_UMAC_IND = WDI_MAX_REQ + 24 + WDI_SET_AP_FIND_IND = WDI_MAX_REQ + 25, + WDI_MAX_UMAC_IND = WDI_MAX_REQ + 26 }WDI_RequestEnumType; @@ -869,8 +883,15 @@ typedef enum WDI_PER_ROAM_SCAN_OFFLOAD_RSP = 116, WDI_PER_ROAM_SCAN_TRIGGER_RSP = 117, #endif - WDI_FW_ARP_STATS_RSP = 118, - WDI_FW_GET_ARP_STATS_RSP = 119, + WDI_DHCP_SERVER_OFFLOAD_RSP = 118, + WDI_MDNS_ENABLE_OFFLOAD_RSP = 119, + WDI_MDNS_FQDN_OFFLOAD_RSP = 120, + WDI_MDNS_RESP_OFFLOAD_RSP = 121, + WDI_MDNS_STATS_OFFLOAD_RSP = 122, + WDI_CAPTURE_GET_TSF_TSTAMP_RSP = 123, + WDI_FW_ARP_STATS_RSP = 124, + WDI_FW_GET_ARP_STATS_RSP = 125, + /*------------------------------------------------------------------------- Indications @@ -962,6 +983,9 @@ typedef enum WDI_HAL_RSSI_BREACHED_IND = WDI_HAL_IND_MIN + 32, WDI_HAL_START_OEM_DATA_RSP_IND_NEW = WDI_HAL_IND_MIN + 33, WDI_ANTENNA_DIVERSITY_SELECTION_RSP = WDI_HAL_IND_MIN + 34, +#ifdef WLAN_FEATURE_APFIND + WDI_HAL_QRF_PREF_NETWORK_FOUND_IND = WDI_HAL_IND_MIN + 35, +#endif WDI_MAX_RESP }WDI_ResponseEnumType; @@ -1327,6 +1351,8 @@ typedef struct wpt_uint8 roamDelayStatsEnabled; /* enable/disable sendMgmtPktViaWQ5 params in ini */ wpt_boolean sendMgmtPktViaWQ5; + /* Wake lock for keep device in awake once host gets a find AP indication */ + vos_wake_lock_t find_ap_lock; }WDI_ControlBlockType; @@ -5914,6 +5940,15 @@ WDI_Status WDI_ProcessLphbCfgRsp ); #endif /* FEATURE_WLAN_LPHB */ +#ifdef WLAN_FEATURE_APFIND +WDI_Status +WDI_ProcessQRFPrefNetworkFoundInd +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +); +#endif + /** @brief Process Rate Update Indication and post it to HAL @@ -6640,6 +6675,131 @@ WDI_ProcessSetAllowedActionFramesInd WDI_ControlBlockType* pWDICtx, WDI_EventInfoType* pEventData ); +#ifdef SAP_AUTH_OFFLOAD +/** + * WDI_ProcessSapAuthOffloadInd - Process Set sap offload enable + * command + * + * @pWDICtx: pointer to the WLAN DAL context + * @pEventData: pointer to the event information structure + * + */ +WDI_Status +WDI_ProcessSapAuthOffloadInd +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData + ); +#endif + +#ifdef DHCP_SERVER_OFFLOAD +WDI_Status +wdi_dhcp_server_offload_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); + +WDI_Status +wdi_dhcp_server_offload_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +WDI_Status +wdi_mdns_enable_offload_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); + +WDI_Status +wdi_mdns_enable_offload_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); + +WDI_Status +wdi_mdns_fqdn_offload_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); + +WDI_Status +wdi_mdns_fqdn_offload_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); + +WDI_Status +wdi_mdns_resp_offload_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); + +WDI_Status +wdi_mdns_resp_offload_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); + +WDI_Status +wdi_get_mdns_stats_offload_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); + +WDI_Status +wdi_get_mdns_stats_offload_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); +#endif /* MDNS_OFFLOAD */ +#ifdef WLAN_FEATURE_APFIND +/** + * WDI_ProcessApFindInd - Process AP find command command + * + * @pWDICtx: pointer to the WLAN DAL context + * @pEventData: pointer to the event information structure + * + */ +WDI_Status +WDI_ProcessApFindInd +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +); +#endif + +WDI_Status +wdi_cap_tsf_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); + +WDI_Status +wdi_get_tsf_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); +WDI_Status +wdi_get_tsf_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +); WDI_Status WDI_ProcessSetArpStatsReq @@ -6668,5 +6828,6 @@ WDI_ProcessGetArpStatsResp WDI_ControlBlockType* pWDICtx, WDI_EventInfoType* pEventData ); + #endif /*WLAN_QCT_WDI_I_H*/ diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_sta.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_sta.h index 44cd97dc6f9..f62bbff6b80 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_sta.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_sta.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -71,45 +71,6 @@ when who what, where, why #define WDI_STA_INVALID_IDX 0xFF /*---------------------------------------------------------------------------- - WDI_AddStaParams - -------------------------------------------------------------------------*/ -typedef struct -{ - wpt_uint8 ucSTAIdx; - wpt_uint8 ucWmmEnabled; - wpt_uint8 ucHTCapable; - - /* MAC Address of STA */ - wpt_macAddr staMacAddr; - - /*MAC Address of the BSS*/ - wpt_macAddr macBSSID; - - /* Field to indicate if this is sta entry for itself STA adding entry for itself - or remote (AP adding STA after successful association. - This may or may not be required in production driver. - 0 - Self, 1 other/remote, 2 - bssid */ - wpt_uint8 ucStaType; - - - /*DPU Information*/ - wpt_uint8 dpuIndex; // DPU table index - wpt_uint8 dpuSig; // DPU signature - wpt_uint8 bcastDpuIndex; - wpt_uint8 bcastDpuSignature; - wpt_uint8 bcastMgmtDpuIndex; - wpt_uint8 bcastMgmtDpuSignature; - - - /*RMF enabled/disabled*/ - wpt_uint8 ucRmfEnabled; - - /* Index into the BSS Session table */ - wpt_uint8 ucBSSIdx; - -}WDI_AddStaParams; - -/*---------------------------------------------------------------------------- WDI_StaStruct -------------------------------------------------------------------------*/ typedef struct @@ -206,41 +167,6 @@ WDI_STATableClose WDI_ControlBlockType* pWDICtx ); - -/** - @brief WDI_STATableAddSta - Function to Add Station - - - @param pWDICtx: pointer to the WLAN DAL context - pwdiParam: station parameters - - @see - @return Result of the function call -*/ -WDI_Status -WDI_STATableAddSta -( - WDI_ControlBlockType* pWDICtx, - WDI_AddStaParams* pwdiParam -); - -/** - @brief WDI_STATableDelSta - Function to Delete a Station - - - @param pWDICtx: pointer to the WLAN DAL context - ucSTAIdx: station to be deleted - - @see - @return Result of the function call -*/ -WDI_Status -WDI_STATableDelSta -( - WDI_ControlBlockType* pWDICtx, - wpt_uint8 ucSTAIdx -); - /** @brief WDI_STATableBSSDelSta - Function to Delete Stations in this BSS @@ -356,25 +282,6 @@ WDI_STATableSetStaType /** - @brief WDI_STATableFindStaidByAddr - Given a station mac address, search - for the corresponding station index from the Station Table. - - @param pWDICtx: WDI Context pointer - staAddr: station address - pucStaId: output station id - - @see - @return Result of the function call -*/ -WDI_Status -WDI_STATableFindStaidByAddr -( - WDI_ControlBlockType* pWDICtx, - wpt_macAddr staAddr, - wpt_uint8* pucStaId -); - -/** @brief WDI_STATableGetStaAddr - get station address @param pWDICtx: WDI Context pointer diff --git a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c index 4dd8722b888..4aed25df745 100644 --- a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c +++ b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c @@ -90,6 +90,7 @@ #include "pttMsgApi.h" #include "vos_trace.h" +#include "vos_diag_core_event.h" #include "vos_api.h" @@ -220,10 +221,10 @@ static placeHolderInCapBitmap supportEnabledFeatures[] = ,WIFI_CONFIG //61 ,ANTENNA_DIVERSITY_SELECTION //62 ,PER_BASED_ROAMING //63 - ,FEATURE_NOT_SUPPORTED //64 - ,FEATURE_NOT_SUPPORTED //65 - ,FEATURE_NOT_SUPPORTED //66 - ,FEATURE_NOT_SUPPORTED //67 + ,SAP_MODE_WOW //64 + ,SAP_OFFLOADS //65 + ,SAP_BUFF_ALLOC //66 + ,MAKE_BEFORE_BREAK //67 ,NUD_DEBUG //68 ,FEATURE_NOT_SUPPORTED //69 reserved for FATAL_EVENT_LOGGING ,FEATURE_NOT_SUPPORTED //70 reserved for WIFI_DUAL_BAND_ENABLE @@ -524,9 +525,27 @@ WDI_ReqProcFuncType pfnReqProcTbl[WDI_MAX_UMAC_IND] = NULL, NULL, #endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */ +#ifdef DHCP_SERVER_OFFLOAD + wdi_dhcp_server_offload_req, /* WDI_DHCP_SERVER_OFFLOAD_REQ */ +#else + NULL, +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + wdi_mdns_enable_offload_req, /* WDI_MDNS_ENABLE_OFFLOAD_REQ */ + wdi_mdns_fqdn_offload_req, /* WDI_MDNS_FQDN_OFFLOAD_REQ */ + wdi_mdns_resp_offload_req, /* WDI_MDNS_RESP_OFFLOAD_REQ */ + wdi_get_mdns_stats_offload_req, /* WDI_GET_MDNS_STATS_OFFLOAD_REQ */ +#else + NULL, + NULL, + NULL, + NULL, +#endif /* MDNS_OFFLOAD */ + wdi_cap_tsf_req, /* WDI_CAP_TSF_REQ */ + wdi_get_tsf_req, /* WDI_GET_TSF_REQ */ - WDI_ProcessSetArpStatsReq, /* WDI_FW_ARP_STATS_REQ */ - WDI_ProcessGetArpStatsReq, /* WDI_FW_GET_ARP_STATS_REQ */ + WDI_ProcessSetArpStatsReq, /* WDI_FW_ARP_STATS_REQ */ + WDI_ProcessGetArpStatsReq, /* WDI_FW_GET_ARP_STATS_REQ */ /*------------------------------------------------------------------------- Indications @@ -588,6 +607,12 @@ WDI_ReqProcFuncType pfnReqProcTbl[WDI_MAX_UMAC_IND] = WDI_ProcessGetCurrentAntennaIndex, /* WDI_ANTENNA_DIVERSITY_SELECTION_REQ */ WDI_ProcessBcnMissPenaltyCount, /* WDI_MODIFY_ROAM_PARAMS_IND */ WDI_ProcessSetAllowedActionFramesInd, /* WDI_SET_ALLOWED_ACTION_FRAMES_IND */ +#ifdef SAP_AUTH_OFFLOAD + WDI_ProcessSapAuthOffloadInd, /* WDI_PROCESS_SAP_AUTH_OFFLOAD_IND */ +#endif +#ifdef WLAN_FEATURE_APFIND + WDI_ProcessApFindInd, /* WDI_SET_AP_FIND_IND */ +#endif }; @@ -849,9 +874,28 @@ WDI_RspProcFuncType pfnRspProcTbl[WDI_MAX_RESP] = NULL, NULL, #endif -/* ARP Debug Stats*/ +#ifdef DHCP_SERVER_OFFLOAD + wdi_dhcp_server_offload_rsp, /* WDI_DHCP_SERVER_OFFLOAD_RSP */ +#else + NULL, +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + wdi_mdns_enable_offload_rsp, /* WDI_MDNS_ENABLE_OFFLOAD_RSP */ + wdi_mdns_fqdn_offload_rsp, /* WDI_MDNS_FQDN_OFFLOAD_RSP */ + wdi_mdns_resp_offload_rsp, /* WDI_MDNS_RESP_OFFLOAD_RSP */ + wdi_get_mdns_stats_offload_rsp, /* WDI_MDNS_STATS_OFFLOAD_RSP */ +#else + NULL, + NULL, + NULL, + NULL, +#endif /* MDNS_OFFLOAD */ + wdi_get_tsf_rsp, /* WDI_CAPTURE_GET_TSF_TSTAMP_RSP */ + + /* ARP Debug Stats*/ WDI_ProcessSetArpStatsResp, /* WDI_FW_ARP_STATS_RSP */ WDI_ProcessGetArpStatsResp, /* WDI_FW_GET_ARP_STATS_RSP */ + /*--------------------------------------------------------------------- Indications ---------------------------------------------------------------------*/ @@ -957,6 +1001,11 @@ WDI_RspProcFuncType pfnRspProcTbl[WDI_MAX_RESP] = NULL, #endif WDI_ProcessGetCurrentAntennaIndexRsp, /* WDI_ANTENNA_DIVERSITY_SELECTION_RSP */ +#ifdef WLAN_FEATURE_APFIND + WDI_ProcessQRFPrefNetworkFoundInd, /* WDI_HAL_QRF_PREF_NETWORK_FOUND_IND */ +#else + NULL, +#endif }; @@ -1310,17 +1359,225 @@ static char *WDI_getReqMsgString(wpt_uint16 wdiReqMsgId) CASE_RETURN_STRING( WDI_ANTENNA_DIVERSITY_SELECTION_REQ ); CASE_RETURN_STRING( WDI_MODIFY_ROAM_PARAMS_IND ); CASE_RETURN_STRING( WDI_SET_ALLOWED_ACTION_FRAMES_IND ); - CASE_RETURN_STRING( WDI_FW_ARP_STATS_REQ ); - CASE_RETURN_STRING( WDI_FW_GET_ARP_STATS_REQ ); +#ifdef SAP_AUTH_OFFLOAD + CASE_RETURN_STRING( WDI_PROCESS_SAP_AUTH_OFFLOAD_IND); +#endif +#ifdef DHCP_SERVER_OFFLOAD + CASE_RETURN_STRING( WDI_DHCP_SERVER_OFFLOAD_REQ ); +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + CASE_RETURN_STRING( WDI_MDNS_ENABLE_OFFLOAD_REQ ); + CASE_RETURN_STRING( WDI_MDNS_FQDN_OFFLOAD_REQ ); + CASE_RETURN_STRING( WDI_MDNS_RESP_OFFLOAD_REQ ); + CASE_RETURN_STRING( WDI_MDNS_STATS_OFFLOAD_REQ ); +#endif /* MDNS_OFFLOAD */ #ifdef WLAN_FEATURE_APFIND CASE_RETURN_STRING( WDI_SET_AP_FIND_IND ); #endif + CASE_RETURN_STRING( WDI_FW_ARP_STATS_REQ ); + CASE_RETURN_STRING( WDI_FW_GET_ARP_STATS_REQ ); + default: return "Unknown WDI MessageId"; } } +#ifdef DHCP_SERVER_OFFLOAD +/** + * wdi_process_dhcpserver_offload_req() - wdi api to set dhcp server offload + * @dhcp_info: pointer to dhcp server offload + * @wdi_dhcp_srv_offload_rsp_callback: response callback + * @user_data: pointer to user data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_process_dhcpserver_offload_req +( + wdi_set_dhcp_server_offload_t *dhcp_info, + wdi_dhcp_srv_offload_rsp_cb wdi_dhcp_srv_offload_rsp_callback, + void *user_data +) +{ + WDI_EventInfoType wdi_event_data; + + if ( eWLAN_PAL_FALSE == gWDIInitialized ) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail request"); + return WDI_STATUS_E_NOT_ALLOWED; + } + + /*------------------------------------------------------------------- + Fill in Event data and post to the Main FSM + -----------------------------------------------------------------*/ + wdi_event_data.wdiRequest = WDI_DHCP_SERVER_OFFLOAD_REQ; + wdi_event_data.pEventData = dhcp_info; + wdi_event_data.uEventDataSize = sizeof(*dhcp_info); + wdi_event_data.pCBfnc = wdi_dhcp_srv_offload_rsp_callback; + wdi_event_data.pUserData = user_data; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdi_event_data); +} +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +/** + * wdi_set_mdns_offload_req() - wdi api to set mdns enable offload + * @mdns_info: pointer to dhcp server offload + * @wdi_mdns_enable_offload_rsp_callback: response callback + * @user_data: pointer to user data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_set_mdns_offload_req + +( + wdi_mdns_enable_offload_cmd_req *mdns_info, + wdi_mdns_enable_rsp_cb wdi_mdns_enable_offload_rsp_callback, + void *user_data +) +{ + WDI_EventInfoType wdi_event_data; + + if ( eWLAN_PAL_FALSE == gWDIInitialized ) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail request"); + return WDI_STATUS_E_NOT_ALLOWED; + } + + /*------------------------------------------------------------------- + Fill in Event data and post to the Main FSM + -----------------------------------------------------------------*/ + wdi_event_data.wdiRequest = WDI_MDNS_ENABLE_OFFLOAD_REQ; + wdi_event_data.pEventData = mdns_info; + wdi_event_data.uEventDataSize = sizeof(*mdns_info); + wdi_event_data.pCBfnc = wdi_mdns_enable_offload_rsp_callback; + wdi_event_data.pUserData = user_data; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdi_event_data); +} + +/** + * wdi_set_mdns_fqdn_req() - wdi api to set mdns fqdn request + * @fqdn_info: pointer to dhcp server offload + * @wdi_mdns_fqdn_offload_rsp_callback: response callback + * @user_data: pointer to user data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_set_mdns_fqdn_req + +( + wdi_mdns_set_fqdn_cmd_req *fqdn_info, + wdi_mdns_fqdn_rsp_cb wdi_mdns_fqdn_offload_rsp_callback, + void *user_data +) +{ + WDI_EventInfoType wdi_event_data; + + if ( eWLAN_PAL_FALSE == gWDIInitialized ) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail request"); + return WDI_STATUS_E_NOT_ALLOWED; + } + + /*------------------------------------------------------------------- + Fill in Event data and post to the Main FSM + -----------------------------------------------------------------*/ + wdi_event_data.wdiRequest = WDI_MDNS_FQDN_OFFLOAD_REQ; + wdi_event_data.pEventData = fqdn_info; + wdi_event_data.uEventDataSize = sizeof(*fqdn_info); + wdi_event_data.pCBfnc = wdi_mdns_fqdn_offload_rsp_callback; + wdi_event_data.pUserData = user_data; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdi_event_data); +} + +/** + * wdi_set_mdns_response_req() - wdi api to mdns response + * @resp_info: pointer to mdns response + * @wdi_mdns_resp_offload_rsp_callback: response callback + * @user_data: pointer to user data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_set_mdns_response_req + +( + wdi_mdns_set_resp_req *resp_info, + wdi_mdns_resp_rsp_cb wdi_mdns_resp_offload_rsp_callback, + void *user_data +) +{ + WDI_EventInfoType wdi_event_data; + + if ( eWLAN_PAL_FALSE == gWDIInitialized ) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail request"); + return WDI_STATUS_E_NOT_ALLOWED; + } + + /*------------------------------------------------------------------- + Fill in Event data and post to the Main FSM + -----------------------------------------------------------------*/ + wdi_event_data.wdiRequest = WDI_MDNS_RESP_OFFLOAD_REQ; + wdi_event_data.pEventData = resp_info; + wdi_event_data.uEventDataSize = sizeof(*resp_info); + wdi_event_data.pCBfnc = wdi_mdns_resp_offload_rsp_callback; + wdi_event_data.pUserData = user_data; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdi_event_data); +} + +/** + * wdi_get_mdns_stats_req() - wdi api to get mdns stats + * @stats_info: pointer to mdns stats info + * @wdi_get_stats_offload_rsp_callback: response callback + * @user_data: pointer to user data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_get_mdns_stats_req +( + wdi_mdns_get_stats_req *stats_info, + wdi_get_stats_rsp_cb wdi_get_stats_offload_rsp_callback, + void *user_data +) +{ + WDI_EventInfoType wdi_event_data; + if ( eWLAN_PAL_FALSE == gWDIInitialized ) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail request"); + return WDI_STATUS_E_NOT_ALLOWED; + } + + /*------------------------------------------------------------------- + Fill in Event data and post to the Main FSM + -----------------------------------------------------------------*/ + wdi_event_data.wdiRequest = WDI_MDNS_STATS_OFFLOAD_REQ; + wdi_event_data.pEventData = stats_info; + wdi_event_data.uEventDataSize = sizeof(*stats_info); + wdi_event_data.pCBfnc = wdi_get_stats_offload_rsp_callback; + wdi_event_data.pUserData = user_data; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdi_event_data); +} +#endif /* MDNS_OFFLOAD */ /** * WDI_ProcessSetArpStatsResp() - WDI api to process set arp stats response @@ -1400,6 +1657,7 @@ WDI_ProcessGetArpStatsResp return WDI_STATUS_SUCCESS; } + /** @brief WDI_getRespMsgString prints the WDI resonse message in string. @@ -1543,6 +1801,10 @@ static char *WDI_getRespMsgString(wpt_uint16 wdiRespMsgId) CASE_RETURN_STRING (WDI_PER_ROAM_SCAN_OFFLOAD_RSP); CASE_RETURN_STRING (WDI_PER_ROAM_SCAN_TRIGGER_RSP); #endif +#ifdef DHCP_SERVER_OFFLOAD + CASE_RETURN_STRING (WDI_DHCP_SERVER_OFFLOAD_RSP); +#endif /* DHCP_SERVER_OFFLOAD */ + CASE_RETURN_STRING (WDI_CAPTURE_GET_TSF_TSTAMP_RSP); default: return "Unknown WDI MessageId"; } @@ -1734,6 +1996,29 @@ void WDI_TraceHostFWCapabilities(tANI_U32 *capabilityBitmap) "%s", "PER_BASED_ROAMING"); pCapStr += strlen("PER_BASED_ROAMING"); break; + case SAP_MODE_WOW: + snprintf(pCapStr, sizeof("SAP_MODE_WOW"), + "%s", "SAP_MODE_WOW"); + pCapStr += strlen("SAP_MODE_WOW"); + break; + case SAP_OFFLOADS: + snprintf(pCapStr, sizeof("SAP_OFFLOADS"), + "%s", "SAP_OFFLOADS"); + pCapStr += strlen("SAP_OFFLOADS"); + break; + + case SAP_BUFF_ALLOC: + snprintf(pCapStr, sizeof("SAP_BUFF_ALLOC"), + "%s", "SAP_BUFF_ALLOC"); + pCapStr += strlen("SAP_BUFF_ALLOC"); + break; + + case MAKE_BEFORE_BREAK: + snprintf(pCapStr, sizeof("MAKE_BEFORE_BREAK"), + "%s", "MAKE_BEFORE_BREAK"); + pCapStr += strlen("MAKE_BEFORE_BREAK"); + break; + case NUD_DEBUG: snprintf(pCapStr, sizeof("NUD_DEBUG"), "%s", "NUD_DEBUG"); @@ -2058,7 +2343,6 @@ WDI_Init goto fail_wdts_open; } } - /*The WDI is initialized - set state to init */ gWDICb.uGlobalState = WDI_INIT_ST; gWDICb.roamDelayStatsEnabled = vos_get_roam_delay_stats_enabled(); @@ -2072,6 +2356,8 @@ WDI_Init wdi_register_debug_callback(); + vos_wake_lock_init(&gWDICb.find_ap_lock, "find_ap_lock"); + return WDI_STATUS_SUCCESS; /* ERROR handlers @@ -2419,7 +2705,7 @@ WDI_Close "Failed to delete mutex %d", wptStatus); WDI_ASSERT(0); } - + vos_wake_lock_destroy(&gWDICb.find_ap_lock); /*Clear control block. note that this will clear the "magic" which will inhibit all asynchronous callbacks*/ WDI_CleanCB(&gWDICb); @@ -2535,6 +2821,7 @@ WDI_Shutdown "%s: Failed to delete mutex %d", __func__, wptStatus); WDI_ASSERT(0); } + vos_wake_lock_destroy(&gWDICb.find_ap_lock); /* Free the global variables */ wpalMemoryFree(gpHostWlanFeatCaps); wpalMemoryFree(gpFwWlanFeatCaps); @@ -16911,12 +17198,6 @@ WDI_ProcessInitScanRsp "Error returned WDI_ProcessInitScanRspi:%d BMPS%d", wdiStatus, pWDICtx->bInBmps); } - else - { - WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, - "Error returned WDI_ProcessInitScanRspi:%d BMPS%d", - wdiStatus, pWDICtx->bInBmps); - } /*Notify UMAC*/ wdiInitScanRspCb( wdiStatus, pWDICtx->pRspCBUserData); @@ -23148,6 +23429,7 @@ WDI_SendIndication */ pWDICtx->wdiReqStatusCB( ((uStatus != eWLAN_PAL_STATUS_SUCCESS) && (uStatus != eWLAN_PAL_STATUS_E_RESOURCES)) ? WDI_STATUS_E_FAILURE: WDI_STATUS_SUCCESS, pWDICtx->pReqStatusUserData); + pWDICtx->wdiReqStatusCB = NULL; } /*If sending of the message failed - it is considered catastrophic and @@ -24560,6 +24842,8 @@ WDI_HAL_2_WDI_STATUS /*The rest of the HAL error codes must be kept hidden from the UMAC as they refer to specific internal modules of our device*/ default: + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "Fwr halStatus:%d", halStatus); return WDI_STATUS_DEV_INTERNAL_FAILURE; } @@ -24887,12 +25171,36 @@ WDI_2_HAL_REQ_TYPE return WLAN_HAL_MODIFY_ROAM_PARAMS_IND; case WDI_SET_ALLOWED_ACTION_FRAMES_IND: return WLAN_HAL_SET_ALLOWED_ACTION_FRAMES_IND; + case WDI_SET_AP_FIND_IND: + return WLAN_HAL_QRF_AP_FIND_COMMAND; #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD case WDI_PER_ROAM_SCAN_OFFLOAD_REQ: return WLAN_HAL_SET_PER_ROAM_CONFIG_REQ; case WDI_PER_ROAM_SCAN_TRIGGER_REQ: return WLAN_HAL_PER_ROAM_SCAN_TRIGGER_REQ; #endif +#ifdef SAP_AUTH_OFFLOAD + case WDI_PROCESS_SAP_AUTH_OFFLOAD_IND: + return WLAN_HAL_SAP_AUTH_OFFLOAD_IND; +#endif +#ifdef DHCP_SERVER_OFFLOAD + case WDI_DHCP_SERVER_OFFLOAD_REQ: + return WLAN_HAL_DHCP_SERVER_OFFLOAD_REQ; +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + case WDI_MDNS_ENABLE_OFFLOAD_REQ: + return WLAN_HAL_MDNS_ENABLE_OFFLOAD_REQ; + case WDI_MDNS_FQDN_OFFLOAD_REQ: + return WLAN_HAL_MDNS_FQDN_OFFLOAD_REQ; + case WDI_MDNS_RESP_OFFLOAD_REQ: + return WLAN_HAL_MDNS_RESP_OFFLOAD_REQ; + case WDI_MDNS_STATS_OFFLOAD_REQ: + return WLAN_HAL_MDNS_STATS_OFFLOAD_REQ; +#endif /* MDNS_OFFLOAD */ + case WDI_CAP_TSF_REQ: + return WLAN_HAL_CAPTURE_GET_TSF_TSTAMP; + case WDI_GET_TSF_REQ: + return WLAN_HAL_CAPTURE_GET_TSF_TSTAMP; case WDI_FW_ARP_STATS_REQ: return WLAN_HAL_FW_SET_CLEAR_ARP_STATS_REQ; case WDI_FW_GET_ARP_STATS_REQ: @@ -25260,6 +25568,26 @@ case WLAN_HAL_DEL_STA_SELF_RSP: case WLAN_HAL_PER_ROAM_SCAN_TRIGGER_RSP: return WDI_PER_ROAM_SCAN_TRIGGER_RSP; #endif +#ifdef DHCP_SERVER_OFFLOAD + case WLAN_HAL_DHCP_SERVER_OFFLOAD_RSP: + return WDI_DHCP_SERVER_OFFLOAD_RSP; +#endif /* DHCP_SERVER_OFFLOAD */ +#ifdef MDNS_OFFLOAD + case WLAN_HAL_MDNS_ENABLE_OFFLOAD_RSP: + return WDI_MDNS_ENABLE_OFFLOAD_RSP; + case WLAN_HAL_MDNS_FQDN_OFFLOAD_RSP: + return WDI_MDNS_FQDN_OFFLOAD_RSP; + case WLAN_HAL_MDNS_RESP_OFFLOAD_RSP: + return WDI_MDNS_RESP_OFFLOAD_RSP; + case WLAN_HAL_MDNS_STATS_OFFLOAD_RSP: + return WDI_MDNS_STATS_OFFLOAD_RSP; +#endif /* MDNS_OFFLOAD */ +#ifdef WLAN_FEATURE_APFIND + case WLAN_HAL_QRF_PREF_NETW_FOUND_IND: + return WDI_HAL_QRF_PREF_NETWORK_FOUND_IND; +#endif + case WLAN_HAL_CAPTURE_GET_TSF_TSTAMP_RSP: + return WDI_CAPTURE_GET_TSF_TSTAMP_RSP; case WLAN_HAL_FW_SET_CLEAR_ARP_STATS_RSP: return WDI_FW_ARP_STATS_RSP; case WLAN_HAL_FW_GET_ARP_STATS_RSP: @@ -25647,6 +25975,11 @@ WDI_2_HAL_LINK_STATE case WDI_LINK_SEND_ACTION_STATE: return eSIR_LINK_SEND_ACTION_STATE; +#ifdef WLAN_FEATURE_LFR_MBB + case WDI_LINK_PRE_AUTH_REASSOC_STATE: + return eSIR_LINK_PRE_AUTH_REASSOC_STATE; +#endif + default: return eSIR_LINK_MAX; } @@ -26855,17 +27188,18 @@ WDI_ProcessSetPreferredNetworkReq WDI_ASSERT(0); return WDI_STATUS_E_FAILURE; } - /*---------------------------------------------------------------------- Avoid Enable PNO during any active session or an ongoing session - ----------------------------------------------------------------------*/ - if ( (pwdiPNOScanReqParams->wdiPNOScanInfo.bEnable && - WDI_GetActiveSessionsCount(pWDICtx, NULL, eWLAN_PAL_FALSE)) ) + Allow only if SAP auth offload feature is enabled + ----------------------------------------------------------------------*/ + if ((pwdiPNOScanReqParams->wdiPNOScanInfo.bEnable && + WDI_GetActiveSessionsCount(pWDICtx, NULL, eWLAN_PAL_FALSE)) && + !WDI_getFwWlanFeatCaps(SAP_OFFLOADS)) { - WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s:(Active/Ongoing Session) - Fail request", __func__); - return WDI_STATUS_E_FAILURE; + return WDI_STATUS_E_FAILURE; } /*------------------------------------------------------------------------- @@ -27187,6 +27521,8 @@ WDI_PackRoamScanOffloadParams pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ValidChannelList, pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ValidChannelCount); pRoamCandidateListParams->ValidChannelCount = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ValidChannelCount; + pRoamCandidateListParams->WeakZoneRssiThresholdForRoam = + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.WeakZoneRssiThresholdForRoam; WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH, "Values are ssid = %s, RoamOffloadScan=%d,Command=%d," @@ -27194,7 +27530,7 @@ WDI_PackRoamScanOffloadParams "NeighborRoamScanRefreshPeriod=%d,NeighborScanChannelMinTime=%d," "NeighborScanChannelMaxTime = %d,EmptyRefreshScanPeriod=%d," "mdiePresent=%d,MDID=%d, auth=%d, uce=%d, mce=%d, nProbes=%d," - "HomeAwayTime=%d", + "HomeAwayTime=%d RssiThesholdForRoam=%d", pRoamCandidateListParams->ConnectedNetwork.ssId.ssId, pRoamCandidateListParams->RoamScanOffloadEnabled, pRoamCandidateListParams->Command, @@ -27210,7 +27546,8 @@ WDI_PackRoamScanOffloadParams pRoamCandidateListParams->ConnectedNetwork.encryption, pRoamCandidateListParams->ConnectedNetwork.mcencryption, pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.nProbes, - pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.HomeAwayTime); + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.HomeAwayTime, + pRoamCandidateListParams->WeakZoneRssiThresholdForRoam); pRoamCandidateListParams->us24GProbeSize = (pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.us24GProbeSize< WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE)? @@ -27550,6 +27887,54 @@ WDI_ProcessPERRoamScanTriggerRsp }/* WDI_ProcessPERRoamScanTriggerRsp */ #endif +#ifdef WLAN_FEATURE_APFIND +#define FIND_AP_WAKELOCK_TIMEOUT 1000 +/** + @brief Process QRF Preferred Network Found Indication function + + @param pWDICtx: pointer to the WLAN DAL context + pEventData: pointer to the event information structure + + @see + @return Result of the function call +*/ +WDI_Status +WDI_ProcessQRFPrefNetworkFoundInd +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +) +{ + WDI_LowLevelIndType wdiInd; + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "%s:%d Enter", __func__, __LINE__); + + /*------------------------------------------------------------------------- + Sanity check + -------------------------------------------------------------------------*/ + if (NULL == pWDICtx) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT( 0 ); + return WDI_STATUS_E_FAILURE; + } + vos_wake_lock_timeout_release(&pWDICtx->find_ap_lock, + FIND_AP_WAKELOCK_TIMEOUT, + WIFI_POWER_EVENT_WAKELOCK_FIND_AP_INDICATION); + /*Fill in the indication parameters*/ + wdiInd.wdiIndicationType = WDI_AP_FOUND_IND; + if ( pWDICtx->wdiLowLevelIndCB ) + { + /*Notify UMAC*/ + pWDICtx->wdiLowLevelIndCB( &wdiInd, pWDICtx->pIndUserData ); + } + + return WDI_STATUS_SUCCESS; +} +#endif + /** @brief Process Update Scan Params function @@ -27926,6 +28311,8 @@ WDI_ProcessPrefNetworkFoundInd /*Notify UMAC*/ pWDICtx->wdiLowLevelIndCB( &wdiInd, pWDICtx->pIndUserData ); } + else + vos_mem_free( wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.pData); return WDI_STATUS_SUCCESS; } @@ -33918,6 +34305,210 @@ WDI_ProcessMonStartReq WDI_MON_START_RSP); } +#ifdef DHCP_SERVER_OFFLOAD +/** + * wdi_dhcp_server_offload_rsp() - wdi api for the dhcp server response + * @wdi_ctx: pointer to the wdi context + * @event_data: pointer to the event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_dhcp_server_offload_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +) +{ + wdi_dhcp_srv_offload_rsp_cb wdi_dhcp_srv_offload_rsp_callback; + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, + "%s: Enter ", __func__); + /*------------------------------------------------------------------- + Sanity check + -----------------------------------------------------------------*/ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_dhcp_srv_offload_rsp_callback = + (wdi_dhcp_srv_offload_rsp_cb)wdi_ctx->pfncRspCB; + + wdi_dhcp_srv_offload_rsp_callback((void *) event_data->pEventData, + wdi_ctx->pRspCBUserData); + + return WDI_STATUS_SUCCESS; +} +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +/** + * wdi_mdns_enable_offload_rsp() - wdi api for the mdns enable response + * @wdi_ctx: pointer to the wdi context + * @event_data: pointer to the event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_mdns_enable_offload_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +) +{ + wdi_mdns_enable_rsp_cb wdi_mdns_rsp_callback; + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, + "%s: Enter ", __func__); + /*------------------------------------------------------------------- + Sanity check + -----------------------------------------------------------------*/ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_mdns_rsp_callback = + (wdi_mdns_enable_rsp_cb)wdi_ctx->pfncRspCB; + + wdi_mdns_rsp_callback((void *) event_data->pEventData, + wdi_ctx->pRspCBUserData); + + return WDI_STATUS_SUCCESS; +} + +/** + * wdi_mdns_fqdn_offload_rsp() - wdi api for the mdns fqdn response + * @wdi_ctx: pointer to the wdi context + * @event_data: pointer to the event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_mdns_fqdn_offload_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +) +{ + wdi_mdns_enable_rsp_cb wdi_mdns_rsp_callback; + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, + "%s: Enter ", __func__); + /*------------------------------------------------------------------- + Sanity check + -----------------------------------------------------------------*/ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_mdns_rsp_callback = + (wdi_mdns_enable_rsp_cb)wdi_ctx->pfncRspCB; + + wdi_mdns_rsp_callback((void *) event_data->pEventData, + wdi_ctx->pRspCBUserData); + + return WDI_STATUS_SUCCESS; +} + +/** + * wdi_mdns_resp_offload_rsp() - wdi api for the mdns resp response + * @wdi_ctx: pointer to the wdi context + * @event_data: pointer to the event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_mdns_resp_offload_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +) +{ + wdi_mdns_resp_rsp_cb wdi_mdns_rsp_callback; + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, + "%s: Enter ", __func__); + /*------------------------------------------------------------------- + Sanity check + -----------------------------------------------------------------*/ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_mdns_rsp_callback = + (wdi_mdns_resp_rsp_cb)wdi_ctx->pfncRspCB; + + wdi_mdns_rsp_callback((void *) event_data->pEventData, + wdi_ctx->pRspCBUserData); + + return WDI_STATUS_SUCCESS; +} + +/** + * wdi_get_mdns_stats_offload_rsp() - wdi api for the mdns stats response + * @wdi_ctx: pointer to the wdi context + * @event_data: pointer to the event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_get_mdns_stats_offload_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +) +{ + wdi_get_stats_rsp_cb wdi_mdns_rsp_callback; + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "%s: Enter ", __func__); + /*------------------------------------------------------------------- + Sanity check + -----------------------------------------------------------------*/ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_mdns_rsp_callback = + (wdi_get_stats_rsp_cb)wdi_ctx->pfncRspCB; + + wdi_mdns_rsp_callback((void *) event_data->pEventData, + wdi_ctx->pRspCBUserData); + + return WDI_STATUS_SUCCESS; +} +#endif /* MDNS_OFFLOAD */ + WDI_Status WDI_ProcessMonStartRsp ( @@ -36412,6 +37003,457 @@ WDI_ProcessFatalEventLogsReq } +#ifdef DHCP_SERVER_OFFLOAD +/** + * wdi_dhcp_server_offload_req() - wdi api for dhcp server offload + * @wdi_ctx: pointer to wdi context + * @event_data: pointer to event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_dhcp_server_offload_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +) +{ + wdi_set_dhcp_server_offload_t *wdi_dhcp_server_info; + wpt_uint8 *buff = NULL; + wpt_uint16 data_offset = 0; + wpt_uint16 size = 0; + WDI_Status wdi_status; + hal_dhcp_srv_offload_req_msg_t dhcp_srv_offload_req; + wdi_dhcp_srv_offload_rsp_cb wdi_dhcp_srv_offload_rsp_callback; + + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: %d Enter",__func__, __LINE__); + + /*------------------------------------------------------------------ + Sanity check + ------------------------------------------------------------------*/ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_dhcp_server_info = (wdi_set_dhcp_server_offload_t *) + event_data->pEventData; + + /*------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------*/ + if (( WDI_STATUS_SUCCESS != + WDI_GetMessageBuffer(wdi_ctx, + WDI_DHCP_SERVER_OFFLOAD_REQ, + sizeof(dhcp_srv_offload_req. + dhcp_srv_offload_req_params), + &buff, &data_offset, &size))|| + (size < (data_offset + + sizeof(dhcp_srv_offload_req.dhcp_srv_offload_req_params)))) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "Unable to get send buffer in GetFrameLog Req"); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + dhcp_srv_offload_req.dhcp_srv_offload_req_params.bss_idx = + wdi_dhcp_server_info->bssidx; + dhcp_srv_offload_req.dhcp_srv_offload_req_params.enable = + wdi_dhcp_server_info->enable; + dhcp_srv_offload_req.dhcp_srv_offload_req_params.srv_ipv4 = + wdi_dhcp_server_info->srv_ipv4; + dhcp_srv_offload_req.dhcp_srv_offload_req_params.start_lsb = + wdi_dhcp_server_info->start_lsb; + dhcp_srv_offload_req.dhcp_srv_offload_req_params.num_client = + wdi_dhcp_server_info->num_client; + + wdi_dhcp_srv_offload_rsp_callback = (wdi_dhcp_srv_offload_rsp_cb) + event_data->pCBfnc; + + wpalMemoryCopy(buff+data_offset, + &dhcp_srv_offload_req.dhcp_srv_offload_req_params, + sizeof(dhcp_srv_offload_req. + dhcp_srv_offload_req_params)); + + /*------------------------------------------------------------------- + Send Suspend Request to HAL + -----------------------------------------------------------------*/ + wdi_status = WDI_SendMsg(wdi_ctx, buff, size, + wdi_dhcp_srv_offload_rsp_callback, + event_data->pUserData, + WDI_DHCP_SERVER_OFFLOAD_RSP); + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: %d Exit",__func__, __LINE__); + return wdi_status; +} +#endif /* DHCP_SERVER_OFFLOAD */ + +#ifdef MDNS_OFFLOAD +/** + * wdi_mdns_enable_offload_req() - wdi api for dhcp server offload + * @wdi_ctx: pointer to wdi context + * @event_data: pointer to event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_mdns_enable_offload_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data + ) +{ + wdi_mdns_enable_offload_cmd_req *wdi_mdns_enable_info; + wpt_uint8 *buff = NULL; + wpt_uint16 data_offset = 0; + wpt_uint16 size = 0; + WDI_Status wdi_status; + hal_mdns_enable_offload_req_msg_t mdns_enable_req; + wdi_mdns_enable_rsp_cb wdi_mdns_enable_rsp_callback;; + + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: %d Enter",__func__, __LINE__); + + /*------------------------------------------------------------------ + Sanity check + ------------------------------------------------------------------*/ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_mdns_enable_info = (wdi_mdns_enable_offload_cmd_req *) + event_data->pEventData; + + /*------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------*/ + if (( WDI_STATUS_SUCCESS != + WDI_GetMessageBuffer(wdi_ctx, + WDI_MDNS_ENABLE_OFFLOAD_REQ, + sizeof(mdns_enable_req. + mdns_enable_req_params), + &buff, &data_offset, &size))|| + (size < (data_offset + + sizeof(mdns_enable_req.mdns_enable_req_params)))) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "Unable to get send buffer in GetFrameLog Req"); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + mdns_enable_req.mdns_enable_req_params.bss_idx = + wdi_mdns_enable_info->bss_idx; + mdns_enable_req.mdns_enable_req_params.enable = + wdi_mdns_enable_info->enable; + + wdi_mdns_enable_rsp_callback = (wdi_mdns_enable_rsp_cb) + event_data->pCBfnc; + + wpalMemoryCopy(buff+data_offset, + &mdns_enable_req.mdns_enable_req_params, + sizeof(mdns_enable_req. + mdns_enable_req_params)); + + /*------------------------------------------------------------------- + Send Suspend Request to HAL + -----------------------------------------------------------------*/ + wdi_status = WDI_SendMsg(wdi_ctx, buff, size, + wdi_mdns_enable_rsp_callback, + event_data->pUserData, + WDI_MDNS_ENABLE_OFFLOAD_RSP); + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: %d Exit",__func__, __LINE__); + return wdi_status; +} + +/** + * wdi_mdns_fqdn_offload_req() - wdi api for mdns fqdn offload + * @wdi_ctx: pointer to wdi context + * @event_data: pointer to event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_mdns_fqdn_offload_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data + ) +{ + wdi_mdns_set_fqdn_cmd_req *wdi_mdns_fqdn_info; + wpt_uint8 *buff = NULL; + wpt_uint16 buf_size, data_offset = 0; + wpt_uint16 temp_size, size = 0; + WDI_Status wdi_status; + hal_mdns_fqdn_offload_req_param_t mdns_fqdn; + wdi_mdns_fqdn_rsp_cb wdi_mdns_fqdn_rsp_callback;; + + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: %d Enter",__func__, __LINE__); + + /*------------------------------------------------------------------ + Sanity check + ------------------------------------------------------------------*/ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_mdns_fqdn_info = (wdi_mdns_set_fqdn_cmd_req *) + event_data->pEventData; + + mdns_fqdn.bss_idx = wdi_mdns_fqdn_info->bss_idx; + mdns_fqdn.type = wdi_mdns_fqdn_info->type; + mdns_fqdn.fqdn_len = wdi_mdns_fqdn_info->fqdn_len; + + buf_size = sizeof(mdns_fqdn) + mdns_fqdn.fqdn_len - + sizeof(mdns_fqdn.fqdn_data[1]); + + /*------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------*/ + if (( WDI_STATUS_SUCCESS != + WDI_GetMessageBuffer(wdi_ctx, + WDI_MDNS_FQDN_OFFLOAD_REQ, + buf_size, + &buff, &data_offset, &size))|| + (size < (data_offset + buf_size))) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "Unable to get send buffer in GetFrameLog Req"); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_mdns_fqdn_rsp_callback = (wdi_mdns_fqdn_rsp_cb) + event_data->pCBfnc; + + temp_size = 0; + wpalMemoryCopy(buff+data_offset+temp_size, + &mdns_fqdn.bss_idx, + sizeof(mdns_fqdn.bss_idx)); + temp_size += sizeof(mdns_fqdn.bss_idx); + wpalMemoryCopy(buff+data_offset+temp_size, + &mdns_fqdn.type, + sizeof(mdns_fqdn.type)); + temp_size += sizeof(mdns_fqdn.type); + wpalMemoryCopy(buff+data_offset+temp_size, + &mdns_fqdn.fqdn_len, + sizeof(mdns_fqdn.fqdn_len)); + temp_size += sizeof(mdns_fqdn.fqdn_len); + wpalMemoryCopy(buff+data_offset+temp_size, + wdi_mdns_fqdn_info->fqdn_data, + wdi_mdns_fqdn_info->fqdn_len); + + /*------------------------------------------------------------------- + Send Suspend Request to HAL + -----------------------------------------------------------------*/ + wdi_status = WDI_SendMsg(wdi_ctx, buff, size, + wdi_mdns_fqdn_rsp_callback, + event_data->pUserData, + WDI_MDNS_FQDN_OFFLOAD_RSP); + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: %d Exit",__func__, __LINE__); + return wdi_status; +} + +/** + * wdi_mdns_resp_offload_req() - wdi api for mdns response offload + * @wdi_ctx: pointer to wdi context + * @event_data: pointer to event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_mdns_resp_offload_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data + ) +{ + wdi_mdns_set_resp_req *wdi_mdns_resp_info; + wpt_uint8 *buff = NULL; + wpt_uint16 buf_size, data_offset = 0; + wpt_uint16 temp_size, size = 0; + WDI_Status wdi_status; + hal_mdns_resp_offload_req_param_t mdns_resp; + wdi_mdns_resp_rsp_cb wdi_mdns_resp_rsp_callback;; + + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: %d Enter",__func__, __LINE__); + + /*------------------------------------------------------------------ + Sanity check + ------------------------------------------------------------------*/ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_mdns_resp_info = (wdi_mdns_set_resp_req *) + event_data->pEventData; + + mdns_resp.bss_idx = wdi_mdns_resp_info->bss_idx; + mdns_resp.ar_count = wdi_mdns_resp_info->ar_count; + mdns_resp.resp_len = wdi_mdns_resp_info->resp_len; + + buf_size = sizeof(mdns_resp) + mdns_resp.resp_len - + sizeof(mdns_resp.resp_data[1]); + + /*------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------*/ + if (( WDI_STATUS_SUCCESS != + WDI_GetMessageBuffer(wdi_ctx, + WDI_MDNS_RESP_OFFLOAD_REQ, + buf_size, + &buff, &data_offset, &size))|| + (size < (data_offset + buf_size))) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "Unable to get send buffer in GetFrameLog Req"); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_mdns_resp_rsp_callback = (wdi_mdns_resp_rsp_cb) + event_data->pCBfnc; + + temp_size = 0; + wpalMemoryCopy(buff+data_offset+temp_size, + &mdns_resp.bss_idx, + sizeof(mdns_resp.bss_idx)); + temp_size += sizeof(mdns_resp.bss_idx); + wpalMemoryCopy(buff+data_offset+temp_size, + &mdns_resp.ar_count, + sizeof(mdns_resp.ar_count)); + temp_size += sizeof(mdns_resp.ar_count); + wpalMemoryCopy(buff+data_offset+temp_size, + &mdns_resp.resp_len, + sizeof(mdns_resp.resp_len)); + temp_size += sizeof(mdns_resp.resp_len); + wpalMemoryCopy(buff+data_offset+temp_size, + &wdi_mdns_resp_info->resp_data, + wdi_mdns_resp_info->resp_len); + + /*------------------------------------------------------------------- + Send Suspend Request to HAL + -----------------------------------------------------------------*/ + wdi_status = WDI_SendMsg(wdi_ctx, buff, size, + wdi_mdns_resp_rsp_callback, + event_data->pUserData, + WDI_MDNS_RESP_OFFLOAD_RSP); + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: %d Exit",__func__, __LINE__); + return wdi_status; +} + +/** + * wdi_get_mdns_stats_offload_req() - wdi api for mdns stats offload + * @wdi_ctx: pointer to wdi context + * @event_data: pointer to event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_get_mdns_stats_offload_req +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data + ) +{ + wdi_mdns_get_stats_req *wdi_mdns_stats_info; + wpt_uint8 *buff = NULL; + wpt_uint16 data_offset = 0; + wpt_uint16 size = 0; + WDI_Status wdi_status; + hal_mdns_stats_offload_req_msg_t mdns_stats_req; + wdi_get_stats_rsp_cb wdi_mdns_stats_rsp_callback;; + + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: %d Enter",__func__, __LINE__); + + /*------------------------------------------------------------------ + Sanity check + ------------------------------------------------------------------*/ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_mdns_stats_info = (wdi_mdns_get_stats_req *) + event_data->pEventData; + + /*------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------*/ + if (( WDI_STATUS_SUCCESS != + WDI_GetMessageBuffer(wdi_ctx, + WDI_MDNS_STATS_OFFLOAD_REQ, + sizeof(mdns_stats_req. + mdns_stats_req_params), + &buff, &data_offset, &size))|| + (size < (data_offset + + sizeof(mdns_stats_req.mdns_stats_req_params)))) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "Unable to get send buffer in GetFrameLog Req"); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + mdns_stats_req.mdns_stats_req_params.bss_idx = + wdi_mdns_stats_info->bss_idx; + + wdi_mdns_stats_rsp_callback = (wdi_get_stats_rsp_cb) + event_data->pCBfnc; + + wpalMemoryCopy(buff+data_offset, + &mdns_stats_req.mdns_stats_req_params, + sizeof(mdns_stats_req. + mdns_stats_req_params)); + + /*------------------------------------------------------------------- + Send Suspend Request to HAL + -----------------------------------------------------------------*/ + wdi_status = WDI_SendMsg(wdi_ctx, buff, size, + wdi_mdns_stats_rsp_callback, + event_data->pUserData, + WDI_MDNS_STATS_OFFLOAD_RSP); + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: %d Exit",__func__, __LINE__); + return wdi_status; +} +#endif /* MDNS_OFFLOAD */ /** @brief Process FWLoggingInit Request @@ -37816,6 +38858,92 @@ WDI_SetBcnMissPenaltyCount #endif +#ifdef WLAN_FEATURE_APFIND +WDI_Status WDI_ProcessApFindInd(WDI_ControlBlockType *pWDICtx, + WDI_EventInfoType *pEventData) +{ + wpt_uint8* pSendBuffer = NULL; + wpt_uint16 usDataOffset = 0; + wpt_uint16 usSendSize = 0; + struct WDI_APFind_cmd *pwdiapFindRequestInd; + tQRFPrefNetwListParams *phalAPFindRequestParam; + WDI_Status wdiStatus = WDI_STATUS_SUCCESS; + wpt_uint16 buffer_len = 0; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "%s", __func__); + + /*------------------------------------------------------------------------- + Sanity check + ------------------------------------------------------------------------*/ + if (( NULL == pEventData ) || ( NULL == pEventData->pEventData )) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + pwdiapFindRequestInd = (struct WDI_APFind_cmd *)pEventData->pEventData; + if (pwdiapFindRequestInd->data_len) + buffer_len = sizeof(tQRFPrefNetwListParams); + /*----------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------------*/ + if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer(pWDICtx, + WDI_SET_AP_FIND_IND, + buffer_len, + &pSendBuffer, &usDataOffset, &usSendSize))|| + ( usSendSize < (usDataOffset + sizeof(tQRFPrefNetwListParams) ))) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "Unable to get send buffer in QRF command %p ", + pEventData); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + phalAPFindRequestParam = + (tQRFPrefNetwListParams *)(pSendBuffer + usDataOffset); + + wpalMemoryCopy(phalAPFindRequestParam, + &pwdiapFindRequestInd->data[0], + pwdiapFindRequestInd->data_len); + + pWDICtx->pReqStatusUserData = NULL; + pWDICtx->pfncRspCB = NULL; + /*------------------------------------------------------------------------- + Send WDI_SET_AP_FIND_IND Indication to HAL + -------------------------------------------------------------------------*/ + + wdiStatus = WDI_SendIndication( pWDICtx, pSendBuffer, usSendSize); + + return (wdiStatus != WDI_STATUS_SUCCESS) ? wdiStatus:WDI_STATUS_SUCCESS_SYNC; + +} + +WDI_Status WDI_process_ap_find_cmd(struct WDI_APFind_cmd *params) +{ + WDI_EventInfoType wdiEventData; + + if (eWLAN_PAL_FALSE == gWDIInitialized) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail req"); + return WDI_STATUS_E_NOT_ALLOWED; + } + + wdiEventData.wdiRequest = WDI_SET_AP_FIND_IND; + wdiEventData.pEventData = params; + wdiEventData.uEventDataSize = sizeof(*params); + wdiEventData.pCBfnc = NULL; + wdiEventData.pUserData = NULL; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); + +} +#endif + /** * WDI_ProcessSetAllowedActionFramesInd() - Process Allowed action frames * Indication message and post it to HAL @@ -38111,3 +39239,372 @@ WDI_GetARPStatsReq return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); }/*WDI_GetARPStatsReq*/ + + +#ifdef SAP_AUTH_OFFLOAD +/** + * WDI_ProcessSapAuthOffloadInd() - Process SAP AUTH ofload + * Indication message and post it to HAL + * + * @pWDICtx: pointer to the WLAN DAL context + * @pEventData: pointer to the event information structure + * + * Return: WDI_Status enumeration + */ +WDI_Status +WDI_ProcessSapAuthOffloadInd +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData + ) +{ + wpt_uint8* pSendBuffer = NULL; + wpt_uint16 usDataOffset = 0; + wpt_uint16 usSendSize = 0; + tSapOffloadEnableMsg *sapOffloadEnableIndParam; + struct WDI_sap_ofl_enable_params *pwdiSapOflEnableParams; + WDI_Status wdiStatus = WDI_STATUS_SUCCESS; + int buffer_len = 0; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, + "%s", __func__); + + /*------------------------------------------------------------------------- + Sanity check + -------------------------------------------------------------------------*/ + if (( NULL == pEventData ) || ( NULL == pEventData->pEventData )) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + /*----------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------------*/ + pwdiSapOflEnableParams = + (struct WDI_sap_ofl_enable_params*)pEventData->pEventData; + + if (pwdiSapOflEnableParams->psk_len) + buffer_len = pwdiSapOflEnableParams->psk_len + + sizeof(tSapOffloadEnableMsg) - sizeof(tANI_U8); + else + buffer_len = sizeof(tSapOffloadEnableMsg); + + if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx, + WDI_PROCESS_SAP_AUTH_OFFLOAD_IND, + buffer_len, + &pSendBuffer, &usDataOffset, &usSendSize))|| + ( usSendSize < (usDataOffset + sizeof(tSapOffloadEnableMsg) ))) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "Unable to get send buffer in SAP Auth offload Ind %p ", + pEventData); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + pwdiSapOflEnableParams = + (struct WDI_sap_ofl_enable_params*)pEventData->pEventData; + sapOffloadEnableIndParam = + (tSapOffloadEnableMsg*)(pSendBuffer + usDataOffset); + wpalMemoryCopy(&sapOffloadEnableIndParam->selfMacAddr, + &pwdiSapOflEnableParams->macAddr, sizeof(wpt_macAddr)); + + sapOffloadEnableIndParam->enable = pwdiSapOflEnableParams->enable; + sapOffloadEnableIndParam->rsn_authmode = + pwdiSapOflEnableParams->rsn_authmode; + sapOffloadEnableIndParam->rsn_ucastcipherset = + pwdiSapOflEnableParams->rsn_ucastcipherset; + sapOffloadEnableIndParam->rsn_mcastcipherset = + pwdiSapOflEnableParams->rsn_mcastcipherset; + sapOffloadEnableIndParam->psk_len = pwdiSapOflEnableParams->psk_len; + wpalMemoryCopy(&sapOffloadEnableIndParam->psk, &pwdiSapOflEnableParams->key, + pwdiSapOflEnableParams->psk_len); + pWDICtx->pReqStatusUserData = NULL; + pWDICtx->pfncRspCB = NULL; + /*------------------------------------------------------------------------- + Send SAP_AUTH_OFFLOAD_IND Indication to HAL + -------------------------------------------------------------------------*/ + wdiStatus = WDI_SendIndication( pWDICtx, pSendBuffer, usSendSize); + return (wdiStatus != WDI_STATUS_SUCCESS) ? + wdiStatus:WDI_STATUS_SUCCESS_SYNC; + +} + +/** + * WDI_process_sap_auth_offload() - Process SAP AUTH offload + * Indication message and post it to HAL + * + * @pWDICtx: pointer to the WLAN DAL context + * @pEventData: pointer to the event information structure + * + * Return: WDI_Status enumeration + */ +WDI_Status WDI_process_sap_auth_offload( + struct WDI_sap_ofl_enable_params *params) +{ + WDI_EventInfoType wdiEventData; + + if (eWLAN_PAL_FALSE == gWDIInitialized) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail req"); + return WDI_STATUS_E_NOT_ALLOWED; + } + + wdiEventData.wdiRequest = WDI_PROCESS_SAP_AUTH_OFFLOAD_IND; + wdiEventData.pEventData = params; + wdiEventData.uEventDataSize = sizeof(*params); + wdiEventData.pCBfnc = NULL; + wdiEventData.pUserData = NULL; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); +} + +/** + * wdi_process_cap_tsf_req() - Send Capture tsf request to FW. + * + * @pWDICtx: pointer to the WLAN DAL context + * @pEventData: pointer to the event information structure + * + * Return: WDI_Status enumeration + */ +WDI_Status wdi_process_cap_tsf_req(wdi_cap_tsf_params_t *wdi_cap_tsf_req, + wdi_tsf_rsp_cb wdi_cap_tsf_rsp_callback, + void *user_data) +{ + WDI_EventInfoType wdiEventData; + + if (eWLAN_PAL_FALSE == gWDIInitialized) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail req"); + return WDI_STATUS_E_NOT_ALLOWED; + } + + wdiEventData.wdiRequest = WDI_CAP_TSF_REQ; + wdiEventData.pEventData = wdi_cap_tsf_req; + wdiEventData.uEventDataSize = sizeof(*wdi_cap_tsf_req); + wdiEventData.pCBfnc = wdi_cap_tsf_rsp_callback; + wdiEventData.pUserData = user_data; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); +} +/** + * wdi_process_get_tsf_req() - Send Get tsf request to FW. + * + * @pWDICtx: pointer to the WLAN DAL context + * @pEventData: pointer to the event information structure + * + * Return: WDI_Status enumeration + */ +WDI_Status wdi_process_get_tsf_req(wdi_cap_tsf_params_t *wdi_get_tsf_req, + wdi_tsf_rsp_cb wdi_tsf_rsp_callback, + void *user_data) +{ + WDI_EventInfoType wdiEventData; + + if (eWLAN_PAL_FALSE == gWDIInitialized) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail req"); + return WDI_STATUS_E_NOT_ALLOWED; + } + + wdiEventData.wdiRequest = WDI_GET_TSF_REQ; + wdiEventData.pEventData = wdi_get_tsf_req; + wdiEventData.uEventDataSize = sizeof(*wdi_get_tsf_req); + wdiEventData.pCBfnc = wdi_tsf_rsp_callback; + wdiEventData.pUserData = user_data; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); +} + +/** + * wdi_cap_tsf_req() - wdi api for capture tsf request + * @wdi_ctx: pointer to wdi context + * @event_data: pointer to event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status wdi_cap_tsf_req (WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data) +{ + + wdi_cap_tsf_params_t *wdi_cap_tsf_req_info; + wpt_uint8 *buff = NULL; + wpt_uint16 data_offset = 0; + wpt_uint16 size = 0; + WDI_Status wdi_status; + tHalCapTSFgetReqInd hal_cap_tsf_req; + wdi_tsf_rsp_cb wdi_tsf_rsp_callback; + + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: Enter",__func__ ); + /* Sanity check */ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) { + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_cap_tsf_req_info = (wdi_cap_tsf_params_t *) + event_data->pEventData; + + /* Get message buffer */ + if (( WDI_STATUS_SUCCESS != + WDI_GetMessageBuffer(wdi_ctx, + WDI_CAP_TSF_REQ, + sizeof(hal_cap_tsf_req. + capTSFget), + &buff, &data_offset, &size))|| + (size < (data_offset + + sizeof(hal_cap_tsf_req.capTSFget)))) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "Unable to get send buffer in GetTsfFrame Req"); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + hal_cap_tsf_req.capTSFget.uBssIdx = wdi_cap_tsf_req_info->bss_idx; + hal_cap_tsf_req.capTSFget.capTSFget = wdi_cap_tsf_req_info->capTSFget; + + wdi_tsf_rsp_callback = (wdi_tsf_rsp_cb)event_data->pCBfnc; + + wpalMemoryCopy(buff+data_offset, + &hal_cap_tsf_req.capTSFget, + sizeof(hal_cap_tsf_req.capTSFget)); + + wdi_status = WDI_SendMsg(wdi_ctx, buff, size, + wdi_tsf_rsp_callback, + event_data->pUserData, + WDI_CAPTURE_GET_TSF_TSTAMP_RSP); + + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: Exit",__func__); + + return wdi_status; +} + +/** + * wdi_get_tsf_req() - wdi api for get tsf request + * @wdi_ctx: pointer to wdi context + * @event_data: pointer to event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status wdi_get_tsf_req (WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data) +{ + + wdi_cap_tsf_params_t *wdi_cap_tsf_req_info; + wpt_uint8 *buff = NULL; + wpt_uint16 data_offset = 0; + wpt_uint16 size = 0; + WDI_Status wdi_status; + tHalCapTSFgetReqInd hal_cap_tsf_req; + wdi_tsf_rsp_cb wdi_tsf_rsp_callback; + + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: Enter",__func__ ); + /* Sanity check */ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) { + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_cap_tsf_req_info = (wdi_cap_tsf_params_t *) + event_data->pEventData; + + /* Get message buffer */ + if (( WDI_STATUS_SUCCESS != + WDI_GetMessageBuffer(wdi_ctx, + WDI_CAP_TSF_REQ, + sizeof(hal_cap_tsf_req. + capTSFget), + &buff, &data_offset, &size))|| + (size < (data_offset + + sizeof(hal_cap_tsf_req.capTSFget)))) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "Unable to get send buffer in GetTsfFrame Req"); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + hal_cap_tsf_req.capTSFget.uBssIdx = wdi_cap_tsf_req_info->bss_idx; + hal_cap_tsf_req.capTSFget.capTSFget = wdi_cap_tsf_req_info->capTSFget; + + wdi_tsf_rsp_callback = (wdi_tsf_rsp_cb)event_data->pCBfnc; + + wpalMemoryCopy(buff+data_offset, + &hal_cap_tsf_req.capTSFget, + sizeof(hal_cap_tsf_req.capTSFget)); + + wdi_status = WDI_SendMsg(wdi_ctx, buff, size, + wdi_tsf_rsp_callback, + event_data->pUserData, + WDI_CAPTURE_GET_TSF_TSTAMP_RSP); + + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, + "%s: Exit",__func__); + + return wdi_status; +} + +/** + * wdi_get_tsf_rsp() - wdi api for the get tsf response + * @wdi_ctx: pointer to the wdi context + * @event_data: pointer to the event data + * + * Return: WDI_Status + * WDI_STATUS_SUCCESS - success or else failure status + */ +WDI_Status +wdi_get_tsf_rsp +( + WDI_ControlBlockType *wdi_ctx, + WDI_EventInfoType *event_data +) +{ + wdi_tsf_rsp_cb wdi_tsf_rsp_callback; + + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, + "%s: Enter ", __func__); + /*------------------------------------------------------------------- + Sanity check + -----------------------------------------------------------------*/ + if ((NULL == wdi_ctx) || (NULL == event_data) || + (NULL == event_data->pEventData)) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + wdi_tsf_rsp_callback = + (wdi_tsf_rsp_cb)wdi_ctx->pfncRspCB; + + if (wdi_tsf_rsp_callback) + wdi_tsf_rsp_callback((void *) event_data->pEventData, + wdi_ctx->pRspCBUserData); + else { + VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR, + "wdi_tsf_rsp_callback is NULL!"); + return WDI_STATUS_E_FAILURE; + } + + return WDI_STATUS_SUCCESS; +} +#endif diff --git a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_sta.c b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_sta.c index 9b8aa788bf8..0038a7b3009 100644 --- a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_sta.c +++ b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_sta.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -206,7 +206,7 @@ WDI_STATableClose @brief WDI_STATableAddSta - Function to Add Station - @param pWDICtx: pointer to the WLAN DAL context + @param pWDICtx: pointer to the WLAN DAL context pwdiParam: station parameters @see @@ -215,11 +215,12 @@ WDI_STATableClose WDI_Status WDI_STATableAddSta ( - WDI_ControlBlockType* pWDICtx, + void* ctx, WDI_AddStaParams* pwdiParam ) { wpt_uint8 ucSTAIdx = 0; + WDI_ControlBlockType* pWDICtx = ctx; WDI_StaStruct* pSTATable = (WDI_StaStruct*) pWDICtx->staTable; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ @@ -302,7 +303,7 @@ WDI_STATableAddSta @brief WDI_STATableDelSta - Function to Delete a Station - @param pWDICtx: pointer to the WLAN DAL context + @param void: pointer to the WLAN DAL context ucSTAIdx: station to be deleted @see @@ -311,10 +312,11 @@ WDI_STATableAddSta WDI_Status WDI_STATableDelSta ( - WDI_ControlBlockType* pWDICtx, + void* ctx, wpt_uint8 ucSTAIdx ) { + WDI_ControlBlockType* pWDICtx = ctx; WDI_StaStruct* pSTATable = (WDI_StaStruct*) pWDICtx->staTable; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ @@ -341,7 +343,7 @@ WDI_STATableDelSta @brief WDI_STATableBSSDelSta - Function to Delete Stations in this BSS - @param pWDICtx: pointer to the WLAN DAL context + @param pWDICtx: pointer to the WLAN DAL context ucBSSIdx: BSS index @see @@ -584,12 +586,13 @@ WDI_CompareMacAddr WDI_Status WDI_STATableFindStaidByAddr ( - WDI_ControlBlockType* pWDICtx, + void * context, wpt_macAddr staAddr, wpt_uint8* pucStaId ) { WDI_Status wdiStatus = WDI_STATUS_E_FAILURE; + WDI_ControlBlockType* pWDICtx = context; wpt_uint8 i; WDI_StaStruct* pSTATable = (WDI_StaStruct*) pWDICtx->staTable; diff --git a/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h b/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h index 2acb5cec4cd..4f88b99f6c0 100644 --- a/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h +++ b/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h @@ -175,6 +175,7 @@ typedef struct wpt_uint32 extscanBuffer; #endif wpt_uint32 loggingData; + wpt_uint32 indType; } WDI_DS_RxMetaInfoType; typedef struct sPktMetaInfo @@ -199,6 +200,48 @@ typedef struct wpt_uint16 reasonCode; } WDI_DS_LoggingSessionType; + +/*---------------------------------------------------------------------------- + * WDI_AddStaParams + * -------------------------------------------------------------------------*/ +typedef struct +{ + wpt_uint8 ucSTAIdx; + wpt_uint8 ucWmmEnabled; + wpt_uint8 ucHTCapable; + + /* MAC Address of STA */ + wpt_macAddr staMacAddr; + + /*MAC Address of the BSS*/ + wpt_macAddr macBSSID; + + /* Field to indicate if this is sta entry for itself STA adding entry for itself + * or remote (AP adding STA after successful association. + * This may or may not be required in production driver. + * 0 - Self, 1 other/remote, 2 - bssid + */ + wpt_uint8 ucStaType; + + + /*DPU Information*/ + wpt_uint8 dpuIndex; // DPU table index + wpt_uint8 dpuSig; // DPU signature + wpt_uint8 bcastDpuIndex; + wpt_uint8 bcastDpuSignature; + wpt_uint8 bcastMgmtDpuIndex; + wpt_uint8 bcastMgmtDpuSignature; + + + /*RMF enabled/disabled*/ + wpt_uint8 ucRmfEnabled; + + /* Index into the BSS Session table */ + wpt_uint8 ucBSSIdx; + +}WDI_AddStaParams; + + WPT_STATIC WPT_INLINE WDI_DS_RxMetaInfoType* WDI_DS_ExtractRxMetaData (wpt_packet *pFrame) { WDI_DS_RxMetaInfoType * pRxMetadata = @@ -317,6 +360,59 @@ wpt_uint32 WDI_DS_GetReservedResCountPerSTA(void *pContext, * */ WDI_Status WDI_DS_AddSTAMemPool(void *pContext, wpt_uint8 staIndex); +/** + @brief WDI_STATableFindStaidByAddr - Given a station mac address, search + for the corresponding station index from the Station Table. + + @param pWDICtx: Context pointer +staAddr: station address +pucStaId: output station id + +@see +@return Result of the function call +*/ +WDI_Status +WDI_STATableFindStaidByAddr +( + void* pWDICtx, + wpt_macAddr staAddr, + wpt_uint8* pucStaId + ); + +/** + * @brief WDI_STATableAddSta - Function to Add Station + * + * + * @param pWDICtx: pointer to the WLAN DAL context + * pwdiParam: station parameters + * + * @see + * @return Result of the function call + * */ +WDI_Status +WDI_STATableAddSta +( + void* pWDICtx, + WDI_AddStaParams* pwdiParam + ); + + +/** + * @brief WDI_STATableDelSta - Function to Delete a Station + * + * + * @param pWDICtx: pointer to the WLAN DAL context + * ucSTAIdx: station to be deleted + * + * @see + * @return Result of the function call + */ +WDI_Status +WDI_STATableDelSta +( + void* pWDICtx, + wpt_uint8 ucSTAIdx + ); /* DAL Remove STA from memPool * Parameters: diff --git a/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c b/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c index a43656a1b41..15a44bcec9f 100644 --- a/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c +++ b/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c @@ -668,6 +668,7 @@ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType c wpt_uint8 isFcBd = 0; WDI_DS_LoggingSessionType *pLoggingSession; tPerPacketStats rxStats = {0}; + wpt_uint8 indType = 0; tpSirMacFrameCtl pMacFrameCtl; // Do Sanity checks @@ -724,6 +725,7 @@ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType c bFSF = WDI_RX_BD_GET_ESF(pBDHeader); bLSF = WDI_RX_BD_GET_LSF(pBDHeader); isFcBd = WDI_RX_FC_BD_GET_FC(pBDHeader); + indType = WDI_RX_BD_GET_PER_SAPOFFLOAD(pBDHeader); DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WLAN TL:BD header processing data: HO %d DO %d Len %d HLen %d" @@ -733,7 +735,6 @@ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType c pRxMetadata = WDI_DS_ExtractRxMetaData(pFrame); - // Special handling for frames which contain logging information if (WDTS_CHANNEL_RX_LOG == channel) { if (VPKT_SIZE_BUFFER_ALIGNED < (usMPDULen+ucMPDUHOffset)) @@ -768,10 +769,20 @@ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType c wpalPacketSetRxLength(pFrame, usMPDULen+ucMPDUHOffset); wpalPacketRawTrimHead(pFrame, ucMPDUHOffset); - // Invoke Rx complete callback - wpalLogPktSerialize(pFrame); - - return eWLAN_PAL_STATUS_SUCCESS; + if(indType) { + DTI_TRACE(DTI_TRACE_LEVEL_INFO, "indtype is %d size of pacekt is %lu", + indType, sizeof(WDI_RxBdType)); + if (WDI_RXBD_SAP_TX_STATS == indType) { + pRxMetadata->fc = 1; + pClientData->receiveFrameCB(pClientData->pCallbackContext, pFrame); + return eWLAN_PAL_STATUS_SUCCESS; + } + } + else { + // Invoke Rx complete callback + wpalLogPktSerialize(pFrame); + return eWLAN_PAL_STATUS_SUCCESS; + } } else { @@ -780,7 +791,9 @@ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType c if(!isFcBd) { - if(usMPDUDOffset <= ucMPDUHOffset || usMPDULen < ucMPDUHLen) { + /* When channel is WDTS_CHANNEL_RX_LOG firmware doesn't send MPDU header*/ + if ((usMPDUDOffset <= ucMPDUHOffset || usMPDULen < ucMPDUHLen) && + (WDTS_CHANNEL_RX_LOG != channel)) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "WLAN TL:BD header corrupted - dropping packet"); /* Drop packet ???? */ @@ -866,6 +879,30 @@ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType c pRxMetadata->roamCandidateInd = WDI_RX_BD_GET_ROAMCANDIDATEIND(pBDHeader); pRxMetadata->perRoamCndInd = WDI_RX_BD_GET_PER_ROAMCANDIDATEIND(pBDHeader); #endif +#ifdef SAP_AUTH_OFFLOAD + /* Currently firmware use WDTS_CHANNEL_RX_LOG channel for two purpose. + * 1) For firmare logging information: driver will do special handling + * for those message. + * 2) When SAP offload is enabled: In this case, indication type is stored + * in pRxMetadata which will be used by LIM later. + */ + if (WDTS_CHANNEL_RX_LOG == channel) + { + pRxMetadata->indType = + (wpt_uint32)WDI_RX_BD_GET_PER_SAPOFFLOAD(pBDHeader); + if (pRxMetadata->indType == WDI_RXBD_MLME_STA_STATUS) + { + DTI_TRACE( DTI_TRACE_LEVEL_INFO, "%s: Indtype is %d\n", + __func__, pRxMetadata->indType); + pRxMetadata->type = WDI_MAC_MGMT_FRAME; + } + } + else + { + pRxMetadata->indType = 0; + } +#endif + #ifdef WLAN_FEATURE_EXTSCAN pRxMetadata->extscanBuffer = WDI_RX_BD_GET_EXTSCANFULLSCANRESIND(pBDHeader); #endif diff --git a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_api.c b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_api.c index ee70505da23..a6019cbdbbf 100644 --- a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_api.c +++ b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_api.c @@ -546,13 +546,7 @@ bool wpalIsArpPkt(void *pPacket) { vos_pkt_t *pkt = (vos_pkt_t*)pPacket; - if (vos_is_arp_pkt(pkt->pSkb, true)) - { - if (vos_check_arp_req_target_ip(pkt->pSkb, true)) - return true; - } - - return false; + return vos_is_arp_pkt(pkt->pSkb, true); } void wpalUpdateTXArpFWdeliveredStats(void) diff --git a/drivers/staging/prima/Kbuild b/drivers/staging/prima/Kbuild index b7c1f72644e..dfa683e6784 100644 --- a/drivers/staging/prima/Kbuild +++ b/drivers/staging/prima/Kbuild @@ -23,12 +23,18 @@ ifeq ($(KERNEL_BUILD), 0) #Flag to enable Legacy Fast Roaming(LFR) CONFIG_PRIMA_WLAN_LFR := y +#Flag to enable Legacy Fast Roaming(LFR) Make Before Break + CONFIG_PRIMA_WLAN_LFR_MBB := y + #JB kernel has PMKSA patches, hence enabling this flag CONFIG_PRIMA_WLAN_OKC := y # JB kernel has CPU enablement patches, so enable CONFIG_PRIMA_WLAN_11AC_HIGH_TP := y +#Flag to enable mDNS feature + CONFIG_MDNS_OFFLOAD_SUPPORT := y + #Flag to enable TDLS feature CONFIG_QCOM_TDLS := y @@ -47,6 +53,11 @@ ifneq ($(CONFIG_PRONTO_WLAN),) CONFIG_WLAN_OFFLOAD_PACKETS := y endif +#Flag to enable AP Find feature +CONFIG_WLAN_FEATURE_AP_FIND := y + +# Flag to enable feature Software AP Authentication Offload +SAP_AUTH_OFFLOAD := y # To enable CONFIG_QCOM_ESE_UPLOAD, dependent config # CONFIG_QCOM_ESE must be enabled. @@ -225,6 +236,10 @@ ifeq ($(CONFIG_QCOM_TDLS),y) MAC_LIM_OBJS += $(MAC_SRC_DIR)/pe/lim/limProcessTdls.o endif +ifeq ($(CONFIG_PRIMA_WLAN_LFR_MBB),y) +MAC_LIM_OBJS += $(MAC_SRC_DIR)/pe/lim/lim_mbb.o +endif + MAC_PMM_OBJS := $(MAC_SRC_DIR)/pe/pmm/pmmAP.o \ $(MAC_SRC_DIR)/pe/pmm/pmmApi.o \ $(MAC_SRC_DIR)/pe/pmm/pmmDebug.o @@ -286,6 +301,10 @@ ifeq ($(CONFIG_QCOM_TDLS),y) SME_CSR_OBJS += $(SME_SRC_DIR)/csr/csrTdlsProcess.o endif +ifeq ($(CONFIG_PRIMA_WLAN_LFR_MBB),y) +SME_CSR_OBJS += $(SME_SRC_DIR)/csr/csr_roam_mbb.o +endif + SME_PMC_OBJS := $(SME_SRC_DIR)/pmc/pmcApi.o \ $(SME_SRC_DIR)/pmc/pmc.o \ $(SME_SRC_DIR)/pmc/pmcLogDump.o @@ -564,7 +583,9 @@ CDEFINES := -DANI_BUS_TYPE_PLATFORM=1 \ -DWLAN_FEATURE_LINK_LAYER_STATS \ -DWLAN_FEATURE_EXTSCAN \ -DFEATURE_EXT_LL_STAT \ - -DWLAN_VOWIFI_DEBUG + -DWLAN_VOWIFI_DEBUG \ + -DDHCP_SERVER_OFFLOAD \ + -DWLAN_FEATURE_TSF ifneq ($(CONFIG_PRONTO_WLAN),) CDEFINES += -DWCN_PRONTO @@ -617,6 +638,10 @@ ifeq ($(CONFIG_PRIMA_WLAN_LFR),y) CDEFINES += -DFEATURE_WLAN_LFR endif +ifeq ($(CONFIG_PRIMA_WLAN_LFR_MBB),y) +CDEFINES += -DWLAN_FEATURE_LFR_MBB +endif + ifeq ($(CONFIG_PRIMA_WLAN_OKC),y) CDEFINES += -DFEATURE_WLAN_OKC endif @@ -658,6 +683,15 @@ ifeq ($(CONFIG_ENABLE_LINUX_REG), y) CDEFINES += -DCONFIG_ENABLE_LINUX_REG endif +# Enable feature SAP Authentication Offload +ifeq ($(SAP_AUTH_OFFLOAD), y) +CDEFINES += -DSAP_AUTH_OFFLOAD +endif + +ifeq ($(CONFIG_WLAN_FEATURE_AP_FIND), y) +CDEFINES += -DWLAN_FEATURE_APFIND +endif + CDEFINES += -DFEATURE_WLAN_CH_AVOID CDEFINES += -DWLAN_FEATURE_AP_HT40_24G @@ -679,6 +713,10 @@ ifeq ($(CONFIG_WLAN_OFFLOAD_PACKETS),y) CDEFINES += -DWLAN_FEATURE_OFFLOAD_PACKETS endif +ifeq ($(CONFIG_MDNS_OFFLOAD_SUPPORT), y) +CDEFINES += -DMDNS_OFFLOAD +endif + KBUILD_CPPFLAGS += $(CDEFINES) # Module information used by KBuild framework diff --git a/drivers/staging/prima/Kconfig b/drivers/staging/prima/Kconfig index e3cf3f3477e..e3fcf736961 100644 --- a/drivers/staging/prima/Kconfig +++ b/drivers/staging/prima/Kconfig @@ -54,7 +54,7 @@ config WLAN_OFFLOAD_PACKETS default n config QCOM_TDLS - bool "Enable TDLS feature" - default n + bool "Enable TDLS feature" + default n endif # PRIMA_WLAN || PRONTO_WLAN diff --git a/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini b/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini index 97b61e9b4f7..dbb09688542 100644 --- a/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini +++ b/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini @@ -477,6 +477,52 @@ gTcpDelAckThresholdHigh=17000 #Delack set lower limit gTcpDelAckThresholdLow=12000 +# Enable or Disable DHCP Server offload +# 1=Enable, 0=Disable (default) +gDHCPServerOffloadEnable=0 + +# Set max number of DHCP Clients +# Its value could not be greater than 2(default) +#gDHCPMaxNumClients=2 + +# Set DHCP server IP +# 4th field could not be greater than 99, that is xxx.xxx.xxx.0 ~ xxx.xxx.xxx.99 +# 1st field could not be within the range of 224 ~ 239 (multicast IP address) +# 192.168.1.2(default) +#gDHCPServerIP=192.168.1.2 + +# Set DHCP pool start Lsb +# min 100 (default) +# max 255 +gDHCPStartLsb=100 + +# mDNS enable +gMDNSOffloadEnable=1 +# mDNS FQDN query +gMDNSFqdn="_GoProRemote._tcp.local" +# mDNS UFQDN query +gMDNSUniqueFqdn="service._GoProRemote._tcp.local" +# mDNS response typeA +gMDNSResponseTypeA="goprobp-D89685121212.local" +# mDNS response typeAIpv4Addr +gMDNSResponseTypeAIpv4Addr=0xc0a80102 +# mDNS response typeTXT +gMDNSResponseTypeTXT="GoProBP-D89685121212._GoProRemote._tcp.local" +# mDNS response typeTXTContent +gMDNSResponseTypeTXTContent="Device=HERO 3+-BAWA Model=BAWA Version=HD3.11.02.00 Wifi Version=4.0.36.0 Protocol Version=2" +# mDNS response typePTR +gMDNSResponseTypePTR="_GoProRemote._tcp.local" +# mDNS response typePTRDomainName +gMDNSResponseTypePTRDomainName="GoProBP-D89685121212._GoProRemote._tcp.local" +# mDNS response typeSRV +gMDNSResponseTypeSRV="GoProBP-D89685121212._GoProRemote._tcp.local" +# mDNS response typeSRVTarget +gMDNSResponseTypeSRVTarget="goprobp-D89685121212.local" +# mDNS response typeSRVPriority +gMDNSResponseTypeSRVPriority=0 +# mDNS response typeSRVWeight +gMDNSResponseTypeSRVWeight=0 + END # Note: Configuration parser would not read anything past the END marker diff --git a/drivers/staging/prima/riva/inc/wlan_hal_cfg.h b/drivers/staging/prima/riva/inc/wlan_hal_cfg.h index 31f59ee3dc4..8c4f277c045 100644 --- a/drivers/staging/prima/riva/inc/wlan_hal_cfg.h +++ b/drivers/staging/prima/riva/inc/wlan_hal_cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013,2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013,2016,2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -278,12 +278,14 @@ #define QWLAN_HAL_CFG_SAR_BOFFSET_CORRECTION_ENABLE 220 #define QWLAN_HAL_CFG_UNITS_OF_BCN_WAIT_TIME 221 #define QWLAN_HAL_CFG_CONS_BCNMISS_COUNT 222 +#define QWLAN_HAL_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL 223 #define QWLAN_HAL_CFG_DISABLE_SCAN_DURING_SCO 224 +#define QWLAN_HAL_CFG_TRIGGER_NULLFRAME_BEFORE_HB 225 -#define QWLAN_HAL_CFG_MAX_PARAMS 225 +#define QWLAN_HAL_CFG_MAX_PARAMS 226 /* Total number of Integer CFGs. This is used while allocating the memory for TLV */ -#define QWLAN_HAL_CFG_INTEGER_PARAM 225 +#define QWLAN_HAL_CFG_INTEGER_PARAM 226 /*------------------------------------------------------------------------- Configuration Parameter min, max, defaults @@ -1106,4 +1108,9 @@ #define QWLAN_HAL_CFG_BAR_WAKEUP_HOST_DISABLE_MAX 1 #define QWLAN_HAL_CFG_BAR_WAKEUP_HOST_DISABLE_DEF 0 +/* QWLAN_HAL_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL */ +#define QWLAN_HAL_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_MIN 0 +#define QWLAN_HAL_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_MAX 1 +#define QWLAN_HAL_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL_DEF 0 + #endif //__WLAN_HAL_CFG_H__ diff --git a/drivers/staging/prima/riva/inc/wlan_hal_msg.h b/drivers/staging/prima/riva/inc/wlan_hal_msg.h index 482adfc380d..64b090a26ff 100644 --- a/drivers/staging/prima/riva/inc/wlan_hal_msg.h +++ b/drivers/staging/prima/riva/inc/wlan_hal_msg.h @@ -123,7 +123,7 @@ typedef tANI_U8 tHalIpv4Addr[4]; /* 80 is actually NUM_RF_CHANNELS_V2, but beyond V2, this number will be ignored by FW */ #define WLAN_HAL_ROAM_SCAN_MAX_CHANNELS 80 #define WLAN_HAL_ROAM_SACN_PMK_SIZE 32 -#define WLAN_HAL_ROAM_SCAN_RESERVED_BYTES 20 +#define WLAN_HAL_ROAM_SCAN_RESERVED_BYTES 19 #define WLAN_HAL_EXT_SCAN_MAX_CHANNELS 16 #define WLAN_HAL_EXT_SCAN_MAX_BUCKETS 16 @@ -605,6 +605,24 @@ typedef enum WLAN_HAL_PER_ROAM_SCAN_TRIGGER_REQ = 336, WLAN_HAL_PER_ROAM_SCAN_TRIGGER_RSP = 337, + WLAN_HAL_DHCP_SERVER_OFFLOAD_REQ = 339, + WLAN_HAL_DHCP_SERVER_OFFLOAD_RSP = 340, + WLAN_HAL_SAP_AUTH_OFFLOAD_IND = 341, + WLAN_HAL_MDNS_ENABLE_OFFLOAD_REQ = 342, + WLAN_HAL_MDNS_ENABLE_OFFLOAD_RSP = 343, + WLAN_HAL_MDNS_FQDN_OFFLOAD_REQ = 344, + WLAN_HAL_MDNS_FQDN_OFFLOAD_RSP = 345, + WLAN_HAL_MDNS_RESP_OFFLOAD_REQ = 346, + WLAN_HAL_MDNS_RESP_OFFLOAD_RSP = 347, + WLAN_HAL_MDNS_STATS_OFFLOAD_REQ = 348, + WLAN_HAL_MDNS_STATS_OFFLOAD_RSP = 349, + + /* QRF Support */ + WLAN_HAL_QRF_AP_FIND_COMMAND = 350, + WLAN_HAL_QRF_PREF_NETW_FOUND_IND = 351, + WLAN_HAL_CAPTURE_GET_TSF_TSTAMP = 352, + WLAN_HAL_CAPTURE_GET_TSF_TSTAMP_RSP = 353, + /* ARP DEBUG stats*/ WLAN_HAL_FW_SET_CLEAR_ARP_STATS_REQ = 354, WLAN_HAL_FW_SET_CLEAR_ARP_STATS_RSP = 355, WLAN_HAL_FW_GET_ARP_STATS_REQ = 356, @@ -824,6 +842,9 @@ typedef enum eSriLinkState { #ifdef WLAN_FEATURE_ROAM_OFFLOAD eSIR_LINK_FT_PREASSOC_STATE = 16, #endif +#ifdef WLAN_FEATURE_LFR_MBB + eSIR_LINK_PRE_AUTH_REASSOC_STATE = 17, +#endif eSIR_LINK_MAX = WLAN_HAL_MAX_ENUM_SIZE } tSirLinkState; @@ -6370,6 +6391,7 @@ typedef PACKED_PRE struct PACKED_POST { tANI_U8 Prefer5GHz; tANI_U8 RoamRssiCatGap; tANI_U8 Select5GHzMargin; + tANI_U8 WeakZoneRssiThresholdForRoam; tANI_U8 ReservedBytes[WLAN_HAL_ROAM_SCAN_RESERVED_BYTES]; tRoamNetworkType ConnectedNetwork; tMobilityDomainInfo MDID; @@ -6897,6 +6919,10 @@ typedef enum { WIFI_CONFIG = 61, ANTENNA_DIVERSITY_SELECTION = 62, PER_BASED_ROAMING = 63, + SAP_MODE_WOW = 64, + SAP_OFFLOADS = 65, + SAP_BUFF_ALLOC = 66, + MAKE_BEFORE_BREAK = 67, NUD_DEBUG = 68, /* 69 reserved for FATAL_EVENT_LOGGING */ /* 70 reserved for WIFI_DUAL_BAND_ENABLE */ @@ -9089,6 +9115,39 @@ typedef PACKED_PRE struct PACKED_POST tConfigRoamScanRspParams configRoamScanRspParams; } tSetRoamScanConfigRsp, * tpSetRoamScanConfigRsp; +/*--------------------------------------------------------------------------- +* WLAN_HAL_CAPTURE_GET_TSF_TSTAMP +*-------------------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + uint8 uBssIdx; + boolean capTSFget; +}tHalCapTSFget, *tptHalCapTSFget; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + tHalCapTSFget capTSFget; +}tHalCapTSFgetReqInd, *tpHalCapTSFgetReqInd; + +/*--------------------------------------------------------------------------- + WLAN_HAL_CAPTURE_GET_TSF_TSTAMP_RSP +---------------------------------------------------------------------------*/ + +typedef PACKED_PRE struct PACKED_POST +{ + /* Success /Failure / Nil result */ + tANI_U32 status; + tANI_U32 tsf_lo; + tANI_U32 tsf_hi; +} tConfigcapTSFgetRspParams, * tptConfigcapTSFgetRspParams; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + tConfigcapTSFgetRspParams configcapTSFgetRspParams; +} tcapGetTSFConfigRsp, * tpcapGetTSFConfigRsp; + #define PER_ROAM_MAX_AP_CNT 30 #define PER_ROAM_MAX_CANDIDATE_CNT 15 @@ -9128,6 +9187,75 @@ typedef PACKED_PRE struct PACKED_POST } tFWLoggingDxeDoneIndMsg, * tpFWLoggingDxeDoneIndMsg; /*--------------------------------------------------------------------------- + * WLAN_HAL_APFIND_CMDID + * ---------------------------------------------------------------------------*/ + +#define MAX_ARRAY_SIZE 1000 +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U16 msg_version:4; + tANI_U16 msg_id:12; + tANI_U16 msg_len:16; + tANI_U16 handle; + tANI_U16 transaction_id; +} tApfindMsgHeader, *tpApfindMsgHeader; + +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U16 type; + tANI_U16 length; + tANI_U8* value; +} tApfindTlv, *tpApfindTlv; + +typedef PACKED_PRE struct PACKED_POST +{ + tApfindMsgHeader apFindHeader; + tANI_U8 ptlv[MAX_ARRAY_SIZE]; +} tQRFPrefNetwListParams, *tpQRFPrefNetwListParams; + +typedef enum +{ + APFIND_MSG_ID_ERROR_RSP = 0, + APFIND_MSG_ID_ENABLE_REQ = 1, + APFIND_MSG_ID_SET_SSID = 2, + APFIND_MSG_ID_SET_MAC = 3, + APFIND_MSG_ID_SET_PARAMS = 4, +} tApfindMsgId; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + tQRFPrefNetwListParams qRFprefNetwListParams; +} tQRFSetPrefNetwListReq, *tpQRFSetPrefNetwListReq; + +#define QRF_MAX_SUPPORTED_NETWORKS 10 + +typedef PACKED_PRE struct PACKED_POST { + /*Network that was found with the highest RSSI*/ + tSirMacSSid ssId; + /*Indicates the RSSI */ + tANI_U8 rssi; + /* The MPDU frame length of a beacon or probe rsp. + * data is the start of the frame + */ + tANI_U16 frameLength; +} tQrfNetwFoundParam, *tpQrfNetwFoundParam; + +typedef PACKED_PRE struct PACKED_POST { + uint8 netwCount; + tQrfNetwFoundParam qrfNetwParams[QRF_MAX_SUPPORTED_NETWORKS]; +} tQrfPrefNetwFoundParams, * tpQrfPrefNetwFoundParams; + +/* + * Preferred network found indication + */ +typedef PACKED_PRE struct PACKED_POST { + tHalMsgHeader header; + tQrfPrefNetwFoundParams qrfPrefNetwFoundParams; +} tQrfPrefNetwFoundInd, *tpQrfPrefNetwFoundInd; + + +/*--------------------------------------------------------------------------- * Logging mail box structure *-------------------------------------------------------------------------*/ @@ -9327,6 +9455,184 @@ typedef PACKED_PRE struct PACKED_POST tHalModifyRoamParamsIndParams modifyRoamParamsReqParams; } tHalModifyRoamParamsInd, *tpHalModifyRoamParamsInd; +typedef PACKED_PRE struct PACKED_POST +{ + tSirMacAddr selfMacAddr; + tANI_U32 enable; + tSirMacSSid ssId; + tANI_U32 rsn_authmode; + tANI_U32 rsn_ucastcipherset; + tANI_U32 rsn_mcastcipherset; + tANI_U32 rsn_mcastmgmtcipherset; + tANI_U32 channel; + tANI_U32 psk_len; + tANI_U8 psk[1]; +} tSapOffloadEnableMsg, *tpSapOffloadEnableMsg; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + tSapOffloadEnableMsg SapOffloadEnableMsg; +} tHalSapoffloadEnable, *tpHalSapoffloadEnable; + +/*--------------------------------------------------------------------------- + * WLAN_HAL_DHCP_SERVER_OFFLOAD_REQ + *--------------------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U8 bss_idx; + tANI_U32 enable; + tANI_U32 srv_ipv4; /* server IP */ + tANI_U32 start_lsb; /* starting address assigned to client */ + tANI_U32 num_client; /* number of clients we support */ +} hal_dhcp_srv_offload_req_param_t, *hal_dhcp_srv_offload_req_params; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + hal_dhcp_srv_offload_req_param_t dhcp_srv_offload_req_params; +} hal_dhcp_srv_offload_req_msg_t; + +/*--------------------------------------------------------------------------- + * WLAN_HAL_DHCP_SERVER_OFFLOAD_RSP + *--------------------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U32 status; +} hal_dhcp_srv_offload_rsp_param_t, *hal_dhcp_srv_offload_rsp_params; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + hal_dhcp_srv_offload_rsp_param_t dhcp_srv_offload_rsp_params; +} hal_dhcp_srv_offload_rsp_msg_t, *hal_dhcp_srv_offload_rsp_msg; + +/*--------------------------------------------------------------------------- + * WLAN_HAL_MDNS_ENABLE_OFFLOAD_REQ + *--------------------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U8 bss_idx; + tANI_U32 enable; +} hal_mdns_enable_offload_req_param_t, *hal_mdns_enable_offload_req_params; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + hal_mdns_enable_offload_req_param_t mdns_enable_req_params; +} hal_mdns_enable_offload_req_msg_t; + +/*--------------------------------------------------------------------------- + * WLAN_HAL_MDNS_ENABLE_OFFLOAD_RSP + *--------------------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U32 status; +} hal_mdns_enable_offload_rsp_param_t, *hal_mdns_enable_offload_rsp_params; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + hal_mdns_enable_offload_rsp_param_t mdns_enable_rsp_params; +} hal_mdns_enable_offload_rsp_msg_t, *hal_mdns_enable_offload_rsp_msg; + +/*--------------------------------------------------------------------------- + * WLAN_HAL_MDNS_FQDN_OFFLOAD_REQ + *--------------------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U8 bss_idx; + tANI_U32 type; + tANI_U32 fqdn_len; + tANI_U8 fqdn_data[1]; +} hal_mdns_fqdn_offload_req_param_t, *hal_mdns_fqdn_offload_req_params; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + hal_mdns_fqdn_offload_req_param_t mdns_fqdn_req_params; +} hal_mdns_fqdn_offload_req_msg_t; + +/*--------------------------------------------------------------------------- + * WLAN_HAL_MDNS_FQDN_OFFLOAD_RSP + *--------------------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U32 status; +} hal_mdns_fqdn_offload_rsp_param_t, *hal_mdns_fqdn_offload_rsp_params; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + hal_mdns_fqdn_offload_rsp_param_t mdns_fqdn_rsp_params; +} hal_mdns_fqdn_offload_rsp_msg_t, *hal_mdns_fqdn_offload_rsp_msg; + +/*--------------------------------------------------------------------------- + * WLAN_HAL_MDNS_RESP_OFFLOAD_REQ + *--------------------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U8 bss_idx; + tANI_U32 ar_count; + tANI_U32 resp_len; + tANI_U8 resp_data[1]; +} hal_mdns_resp_offload_req_param_t, *hal_mdns_resp_offload_req_params; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + hal_mdns_resp_offload_req_param_t mdns_resp_req_params; +} hal_mdns_resp_offload_req_msg_t; + +/*--------------------------------------------------------------------------- + * WLAN_HAL_MDNS_RESP_OFFLOAD_RSP + *--------------------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U32 status; +} hal_mdns_resp_offload_rsp_param_t, *hal_mdns_resp_offload_rsp_params; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + hal_mdns_resp_offload_rsp_param_t mdns_rsp_params; +} hal_mdns_resp_offload_rsp_msg_t, *hal_mdns_resp_offload_rsp_msg; + +/*--------------------------------------------------------------------------- + * WLAN_HAL_MDNS_STATS_OFFLOAD_REQ + *--------------------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U8 bss_idx; +} hal_mdns_stats_offload_req_param_t, *hal_mdns_stats_offload_req_params; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + hal_mdns_stats_offload_req_param_t mdns_stats_req_params; +} hal_mdns_stats_offload_req_msg_t; + +/*--------------------------------------------------------------------------- + * WLAN_HAL_MDNS_STATS_OFFLOAD_RSP + *--------------------------------------------------------------------------*/ +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U8 bss_idx; + tANI_U32 current_ts; + tANI_U32 last_query_ts; + tANI_U32 last_rsp_ts; + tANI_U32 tot_queries; + tANI_U32 tot_matches; + tANI_U32 tot_rsp; + tANI_U32 status; +} hal_mdns_stats_offload_rsp_param_t, *hal_mdns_stats_offload_rsp_params; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + hal_mdns_stats_offload_rsp_param_t mdns_stats_rsp_params; +} hal_mdns_stats_offload_rsp_msg_t, *hal_mdns_stats_offload_rsp_msg; + /*--------------------------------------------------------------------------- * WLAN_HAL_FW_SET_CLEAR_ARP_STATS_REQ *--------------------------------------------------------------------------*/ diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 04c775cb3e6..179f7810d39 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -84,6 +84,11 @@ static int target_fabric_mappedlun_link( "_tpg does not exist\n"); return -EINVAL; } + if (lun->lun_shutdown) { + pr_err("Unable to create mappedlun symlink because" + " lun->lun_shutdown=true\n"); + return -EINVAL; + } se_tpg = lun->lun_sep->sep_tpg; nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item; diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index 8572207e3d4..bc3092f032b 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -839,6 +839,8 @@ static void core_tpg_shutdown_lun( struct se_portal_group *tpg, struct se_lun *lun) { + lun->lun_shutdown = true; + core_clear_lun_from_tpg(lun, tpg); transport_clear_lun_from_sessions(lun); } @@ -868,6 +870,7 @@ struct se_lun *core_tpg_pre_dellun( spin_unlock(&tpg->tpg_lun_lock); return ERR_PTR(-ENODEV); } + lun->lun_shutdown = false; spin_unlock(&tpg->tpg_lun_lock); return lun; diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index 7d199c8e1a7..c9635f1c710 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -27,6 +27,7 @@ #define UARTn_FRAME 0x04 #define UARTn_FRAME_DATABITS__MASK 0x000f #define UARTn_FRAME_DATABITS(n) ((n) - 3) +#define UARTn_FRAME_PARITY__MASK 0x0300 #define UARTn_FRAME_PARITY_NONE 0x0000 #define UARTn_FRAME_PARITY_EVEN 0x0200 #define UARTn_FRAME_PARITY_ODD 0x0300 @@ -578,12 +579,16 @@ static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port, 16 * (4 + (clkdiv >> 6))); frame = efm32_uart_read32(efm_port, UARTn_FRAME); - if (frame & UARTn_FRAME_PARITY_ODD) + switch (frame & UARTn_FRAME_PARITY__MASK) { + case UARTn_FRAME_PARITY_ODD: *parity = 'o'; - else if (frame & UARTn_FRAME_PARITY_EVEN) + break; + case UARTn_FRAME_PARITY_EVEN: *parity = 'e'; - else + break; + default: *parity = 'n'; + } *bits = (frame & UARTn_FRAME_DATABITS__MASK) - UARTn_FRAME_DATABITS(4) + 4; diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 8b1534c424a..be3dc751dfb 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -1379,9 +1379,9 @@ static struct spi_driver ifx_spi_driver = { static void __exit ifx_spi_exit(void) { /* unregister */ + spi_unregister_driver((void *)&ifx_spi_driver); tty_unregister_driver(tty_drv); put_tty_driver(tty_drv); - spi_unregister_driver((void *)&ifx_spi_driver); unregister_reboot_notifier(&ifx_modem_reboot_notifier_block); } diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 010ec70d59f..3390a39f5a7 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2601,13 +2601,13 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) * related to the kernel should not use this. */ data = vt_get_shift_state(); - ret = __put_user(data, p); + ret = put_user(data, p); break; case TIOCL_GETMOUSEREPORTING: console_lock(); /* May be overkill */ data = mouse_reporting(); console_unlock(); - ret = __put_user(data, p); + ret = put_user(data, p); break; case TIOCL_SETVESABLANK: console_lock(); @@ -2616,7 +2616,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) break; case TIOCL_GETKMSGREDIRECT: data = vt_get_kmsg_redirect(); - ret = __put_user(data, p); + ret = put_user(data, p); break; case TIOCL_SETKMSGREDIRECT: if (!capable(CAP_SYS_ADMIN)) { diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index 0ac843abce8..9b3a925110e 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -242,7 +242,8 @@ static int ci_role_show(struct seq_file *s, void *data) { struct ci13xxx *ci = s->private; - seq_printf(s, "%s\n", ci_role(ci)->name); + if (ci->role != CI_ROLE_END) + seq_printf(s, "%s\n", ci_role(ci)->name); return 0; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c8555041373..a1748841d56 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -511,8 +511,7 @@ static void led_work (struct work_struct *work) changed++; } if (changed) - queue_delayed_work(system_power_efficient_wq, - &hub->leds, LED_CYCLE_PERIOD); + schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); } /* use a short timeout for hub/port status fetches */ @@ -1080,9 +1079,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) if (hdev->bus->is_b_host) goto init2; #endif - INIT_DELAYED_WORK(&hub->init_work, hub_init_func2); - queue_delayed_work(system_power_efficient_wq, - &hub->init_work, + PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2); + schedule_delayed_work(&hub->init_work, msecs_to_jiffies(delay)); /* Suppress autosuspend until init is done */ @@ -1243,9 +1241,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) /* Don't do a long sleep inside a workqueue routine */ if (type == HUB_INIT2) { - INIT_DELAYED_WORK(&hub->init_work, hub_init_func3); - queue_delayed_work(system_power_efficient_wq, - &hub->init_work, + PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3); + schedule_delayed_work(&hub->init_work, msecs_to_jiffies(delay)); device_unlock(hub->intfdev); return; /* Continues at init3: below */ @@ -1260,8 +1257,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) if (status < 0) dev_err(hub->intfdev, "activate --> %d\n", status); if (hub->has_indicators && blinkenlights) - queue_delayed_work(system_power_efficient_wq, - &hub->leds, LED_CYCLE_PERIOD); + schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); /* Scan all ports that need attention */ kick_khubd(hub); @@ -4494,8 +4490,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1) /* hub LEDs are probably harder to miss than syslog */ if (hub->has_indicators) { hub->indicator[port1-1] = INDICATOR_GREEN_BLINK; - queue_delayed_work(system_power_efficient_wq, - &hub->leds, 0); + schedule_delayed_work (&hub->leds, 0); } } kfree(qual); @@ -4724,9 +4719,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (hub->has_indicators) { hub->indicator[port1-1] = INDICATOR_AMBER_BLINK; - queue_delayed_work( - system_power_efficient_wq, - &hub->leds, 0); + schedule_delayed_work (&hub->leds, 0); } status = -ENOTCONN; /* Don't retry */ goto loop_disable; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index d88a7b2dda6..ab21645e988 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2549,6 +2549,14 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, s_pkt = 1; } + /* + * We assume here we will always receive the entire data block + * which we should receive. Meaning, if we program RX to + * receive 4K but we receive only 2K, we assume that's all we + * should receive and we simply bounce the request back to the + * gadget driver for further processing. + */ + req->request.actual += length - count; if (s_pkt) return 1; if ((event->status & DEPEVT_STATUS_LST) && @@ -2569,7 +2577,6 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, unsigned int slot; unsigned int i; unsigned int trb_len; - int count = 0; int ret; do { @@ -2598,8 +2605,6 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, slot++; slot %= DWC3_TRB_NUM; trb = &dep->trb_pool[slot]; - count += trb->size & DWC3_TRB_SIZE_MASK; - if (req->request.num_mapped_sgs) trb_len = sg_dma_len(&req->request.sg[i]); @@ -2612,14 +2617,6 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, break; }while (++i < req->request.num_mapped_sgs); - /* - * We assume here we will always receive the entire data block - * which we should receive. Meaning, if we program RX to - * receive 4K but we receive only 2K, we assume that's all we - * should receive and we simply bounce the request back to the - * gadget driver for further processing. - */ - req->request.actual += req->request.length - count; if (req->ztrb) { trb = req->ztrb; if ((event->status & DEPEVT_STATUS_LST) && diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index ef499470679..33da16834e4 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1662,6 +1662,8 @@ static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL); static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver) { struct usb_composite_dev *cdev = get_gadget_data(gadget); + struct usb_gadget_strings *gstr = cdev->driver->strings[0]; + struct usb_string *dev_str = gstr->strings; /* composite_disconnect() must already have been called * by the underlying peripheral controller driver! @@ -1682,6 +1684,9 @@ static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver) composite_dev_cleanup(cdev); + if (dev_str[USB_GADGET_MANUFACTURER_IDX].s == cdev->def_manufacturer) + dev_str[USB_GADGET_MANUFACTURER_IDX].s = ""; + kfree(cdev->def_manufacturer); kfree(cdev); set_gadget_data(gadget, NULL); diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 6656dfda566..0fa139081b1 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1270,7 +1270,7 @@ static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td) time = 30; break; default: - time = 300; + time = 50; break; } @@ -1786,6 +1786,7 @@ static void r8a66597_td_timer(unsigned long _r8a66597) pipe = td->pipe; pipe_stop(r8a66597, pipe); + /* Select a different address or endpoint */ new_td = td; do { list_move_tail(&new_td->queue, @@ -1795,7 +1796,8 @@ static void r8a66597_td_timer(unsigned long _r8a66597) new_td = td; break; } - } while (td != new_td && td->address == new_td->address); + } while (td != new_td && td->address == new_td->address && + td->pipe->info.epnum == new_td->pipe->info.epnum); start_transfer(r8a66597, new_td); diff --git a/drivers/usb/misc/ks_bridge.c b/drivers/usb/misc/ks_bridge.c index 4018c6225df..cad74d62195 100644 --- a/drivers/usb/misc/ks_bridge.c +++ b/drivers/usb/misc/ks_bridge.c @@ -117,7 +117,7 @@ struct ks_bridge { struct ks_bridge *__ksb[NO_BRIDGE_INSTANCES]; /* by default debugging is enabled */ -static unsigned int enable_dbg = 0; +static unsigned int enable_dbg = 1; module_param(enable_dbg, uint, S_IRUGO | S_IWUSR); static void diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index cfd205036ab..a4b02734258 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -600,8 +600,10 @@ static int usbhsc_resume(struct device *dev) struct usbhs_priv *priv = dev_get_drvdata(dev); struct platform_device *pdev = usbhs_priv_to_pdev(priv); - if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) + if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) { usbhsc_power_ctrl(priv, 1); + usbhs_mod_autonomy_mode(priv); + } usbhs_platform_call(priv, phy_reset, pdev); diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 157a9f9afc2..0c962ff5eed 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -261,11 +261,26 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + int ret = 0; - if (!usbhs_pipe_is_dcp(pipe)) - usbhsf_fifo_barrier(priv, fifo); + if (!usbhs_pipe_is_dcp(pipe)) { + /* + * This driver checks the pipe condition first to avoid -EBUSY + * from usbhsf_fifo_barrier() with about 10 msec delay in + * the interrupt handler if the pipe is RX direction and empty. + */ + if (usbhs_pipe_is_dir_in(pipe)) + ret = usbhs_pipe_is_accessible(pipe); + if (!ret) + ret = usbhsf_fifo_barrier(priv, fifo); + } - usbhs_write(priv, fifo->ctr, BCLR); + /* + * if non-DCP pipe, this driver should set BCLR when + * usbhsf_fifo_barrier() returns 0. + */ + if (!ret) + usbhs_write(priv, fifo->ctr, BCLR); } static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, @@ -545,6 +560,7 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) usbhsf_send_terminator(pipe, fifo); usbhsf_tx_irq_ctrl(pipe, !*is_done); + usbhs_pipe_running(pipe, !*is_done); usbhs_pipe_enable(pipe); dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", @@ -571,12 +587,21 @@ usbhs_fifo_write_busy: * retry in interrupt */ usbhsf_tx_irq_ctrl(pipe, 1); + usbhs_pipe_running(pipe, 1); return ret; } +static int usbhsf_pio_prepare_push(struct usbhs_pkt *pkt, int *is_done) +{ + if (usbhs_pipe_is_running(pkt->pipe)) + return 0; + + return usbhsf_pio_try_push(pkt, is_done); +} + struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { - .prepare = usbhsf_pio_try_push, + .prepare = usbhsf_pio_prepare_push, .try_run = usbhsf_pio_try_push, }; @@ -590,6 +615,9 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) if (usbhs_pipe_is_busy(pipe)) return 0; + if (usbhs_pipe_is_running(pipe)) + return 0; + /* * pipe enable to prepare packet receive */ @@ -598,6 +626,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length); usbhs_pipe_enable(pipe); + usbhs_pipe_running(pipe, 1); usbhsf_rx_irq_ctrl(pipe, 1); return 0; @@ -643,6 +672,7 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done) (total_len < maxp)) { /* short packet */ *is_done = 1; usbhsf_rx_irq_ctrl(pipe, 0); + usbhs_pipe_running(pipe, 0); usbhs_pipe_disable(pipe); /* disable pipe first */ } @@ -798,10 +828,11 @@ static void xfer_work(struct work_struct *work) dev_dbg(dev, " %s %d (%d/ %d)\n", fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); + usbhs_pipe_running(pipe, 1); usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans); - usbhs_pipe_enable(pipe); - usbhsf_dma_start(pipe, fifo); dma_async_issue_pending(chan); + usbhsf_dma_start(pipe, fifo); + usbhs_pipe_enable(pipe); } /* @@ -829,6 +860,10 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ goto usbhsf_pio_prepare_push; + /* return at this time if the pipe is running */ + if (usbhs_pipe_is_running(pipe)) + return 0; + /* get enable DMA fifo */ fifo = usbhsf_get_dma_fifo(priv, pkt); if (!fifo) @@ -866,6 +901,7 @@ static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done) pkt->actual = pkt->trans; *is_done = !pkt->zero; /* send zero packet ? */ + usbhs_pipe_running(pipe, !*is_done); usbhsf_dma_stop(pipe, pipe->fifo); usbhsf_dma_unmap(pkt); @@ -966,8 +1002,10 @@ static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done) if ((pkt->actual == pkt->length) || /* receive all data */ (pkt->trans < maxp)) { /* short packet */ *is_done = 1; + usbhs_pipe_running(pipe, 0); } else { /* re-enable */ + usbhs_pipe_running(pipe, 0); usbhsf_prepare_pop(pkt, is_done); } diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 7926e1c700f..85e30e1d5e8 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -578,6 +578,19 @@ int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe) return usbhsp_flags_has(pipe, IS_DIR_HOST); } +int usbhs_pipe_is_running(struct usbhs_pipe *pipe) +{ + return usbhsp_flags_has(pipe, IS_RUNNING); +} + +void usbhs_pipe_running(struct usbhs_pipe *pipe, int running) +{ + if (running) + usbhsp_flags_set(pipe, IS_RUNNING); + else + usbhsp_flags_clr(pipe, IS_RUNNING); +} + void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence) { u16 mask = (SQCLR | SQSET); diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index b476fde955b..b18a794922d 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -36,6 +36,7 @@ struct usbhs_pipe { #define USBHS_PIPE_FLAGS_IS_USED (1 << 0) #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1) #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) +#define USBHS_PIPE_FLAGS_IS_RUNNING (1 << 3) struct usbhs_pkt_handle *handler; @@ -79,6 +80,9 @@ int usbhs_pipe_probe(struct usbhs_priv *priv); void usbhs_pipe_remove(struct usbhs_priv *priv); int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe); +int usbhs_pipe_is_running(struct usbhs_pipe *pipe); +void usbhs_pipe_running(struct usbhs_pipe *pipe, int running); + void usbhs_pipe_init(struct usbhs_priv *priv, int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)); int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 5f3bcd31e20..f3bbe210119 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -188,6 +188,7 @@ static int usb_console_setup(struct console *co, char *options) kfree(tty); reset_open_count: port->port.count = 0; + info->port = NULL; usb_autopm_put_interface(serial->interface); error_get_interface: usb_serial_put(serial); diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index 39b71e0ad0b..baed57d3cff 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -28,11 +28,6 @@ * * Also need to add code to deal with cards endians that are different than * the native cpu endians. I also need to deal with MSB position in the word. - * Modified by Harm Hanemaaijer (fgenfb@yahoo.com) 2013: - * - Provide optimized versions of fast_imageblit for 16 and 32bpp that are - * significantly faster than the previous implementation. - * - Simplify the fast/slow_imageblit selection code, avoiding integer - * divides. */ #include <linux/module.h> #include <linux/string.h> @@ -267,133 +262,6 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * } } -/* - * Optimized fast_imageblit for bpp == 16. ppw = 2, bit_mask = 3 folded - * into the code, main loop unrolled. - */ - -static inline void fast_imageblit16(const struct fb_image *image, - struct fb_info *p, u8 __iomem * dst1, - u32 fgcolor, u32 bgcolor) -{ - u32 fgx = fgcolor, bgx = bgcolor; - u32 spitch = (image->width + 7) / 8; - u32 end_mask, eorx; - const char *s = image->data, *src; - u32 __iomem *dst; - const u32 *tab = NULL; - int i, j, k; - - tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; - - fgx <<= 16; - bgx <<= 16; - fgx |= fgcolor; - bgx |= bgcolor; - - eorx = fgx ^ bgx; - k = image->width / 2; - - for (i = image->height; i--;) { - dst = (u32 __iomem *) dst1; - src = s; - - j = k; - while (j >= 4) { - u8 bits = *src; - end_mask = tab[(bits >> 6) & 3]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - end_mask = tab[(bits >> 4) & 3]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - end_mask = tab[(bits >> 2) & 3]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - end_mask = tab[bits & 3]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - src++; - j -= 4; - } - if (j != 0) { - u8 bits = *src; - end_mask = tab[(bits >> 6) & 3]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - if (j >= 2) { - end_mask = tab[(bits >> 4) & 3]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - if (j == 3) { - end_mask = tab[(bits >> 2) & 3]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst); - } - } - } - dst1 += p->fix.line_length; - s += spitch; - } -} - -/* - * Optimized fast_imageblit for bpp == 32. ppw = 1, bit_mask = 1 folded - * into the code, main loop unrolled. - */ - -static inline void fast_imageblit32(const struct fb_image *image, - struct fb_info *p, u8 __iomem * dst1, - u32 fgcolor, u32 bgcolor) -{ - u32 fgx = fgcolor, bgx = bgcolor; - u32 spitch = (image->width + 7) / 8; - u32 end_mask, eorx; - const char *s = image->data, *src; - u32 __iomem *dst; - const u32 *tab = NULL; - int i, j, k; - - tab = cfb_tab32; - - eorx = fgx ^ bgx; - k = image->width; - - for (i = image->height; i--;) { - dst = (u32 __iomem *) dst1; - src = s; - - j = k; - while (j >= 8) { - u8 bits = *src; - end_mask = tab[(bits >> 7) & 1]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - end_mask = tab[(bits >> 6) & 1]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - end_mask = tab[(bits >> 5) & 1]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - end_mask = tab[(bits >> 4) & 1]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - end_mask = tab[(bits >> 3) & 1]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - end_mask = tab[(bits >> 2) & 1]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - end_mask = tab[(bits >> 1) & 1]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - end_mask = tab[bits & 1]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - src++; - j -= 8; - } - if (j != 0) { - u32 bits = (u32) * src; - while (j > 1) { - end_mask = tab[(bits >> 7) & 1]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst++); - bits <<= 1; - j--; - } - end_mask = tab[(bits >> 7) & 1]; - FB_WRITEL((end_mask & eorx) ^ bgx, dst); - } - dst1 += p->fix.line_length; - s += spitch; - } -} - void cfb_imageblit(struct fb_info *p, const struct fb_image *image) { u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; @@ -426,21 +294,11 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image) bgcolor = image->bg_color; } - if (!start_index && !pitch_index) { - if (bpp == 32) - fast_imageblit32(image, p, dst1, fgcolor, - bgcolor); - else if (bpp == 16 && (width & 1) == 0) - fast_imageblit16(image, p, dst1, fgcolor, - bgcolor); - else if (bpp == 8 && (width & 3) == 0) - fast_imageblit(image, p, dst1, fgcolor, - bgcolor); - else - slow_imageblit(image, p, dst1, fgcolor, - bgcolor, - start_index, pitch_index); - } else + if (32 % bpp == 0 && !start_index && !pitch_index && + ((width & (32/bpp-1)) == 0) && + bpp >= 8 && bpp <= 32) + fast_imageblit(image, p, dst1, fgcolor, bgcolor); + else slow_imageblit(image, p, dst1, fgcolor, bgcolor, start_index, pitch_index); } else @@ -453,4 +311,3 @@ MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); MODULE_DESCRIPTION("Generic software accelerated imaging drawing"); MODULE_LICENSE("GPL"); - diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index e3a9fb5bd2f..e432d363db6 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1087,6 +1087,13 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, void __user *argp = (void __user *)arg; long ret = 0; + memset(&var, 0, sizeof(var)); + memset(&fix, 0, sizeof(fix)); + memset(&con2fb, 0, sizeof(con2fb)); + memset(&cmap_from, 0, sizeof(cmap_from)); + memset(&cmap, 0, sizeof(cmap)); + memset(&event, 0, sizeof(event)); + switch (cmd) { case FBIOGET_VSCREENINFO: if (!lock_fb_info(info)) diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c index 772ee197785..2e8cb4e46ca 100644 --- a/drivers/video/msm/mdss/mdp3_ppp.c +++ b/drivers/video/msm/mdss/mdp3_ppp.c @@ -37,6 +37,7 @@ #define MDP_PPP_MAX_BPP 4 #define MDP_PPP_DYNAMIC_FACTOR 3 #define MDP_PPP_MAX_READ_WRITE 3 +#define MDP_PPP_MAX_WIDTH 0xFFF #define ENABLE_SOLID_FILL 0x2 #define DISABLE_SOLID_FILL 0x0 #define BLEND_LATENCY 3 @@ -148,6 +149,11 @@ int mdp3_ppp_get_img(struct mdp_img *img, struct mdp_blit_req *req, return -EINVAL; } + if (img->width > MDP_PPP_MAX_WIDTH) { + pr_err("%s incorrect width %d\n", __func__, img->width); + return -EINVAL; + } + fb_data.flags = img->priv; fb_data.memory_id = img->memory_id; fb_data.offset = 0; diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c index 668522527bd..1ed8eabdcb3 100644 --- a/drivers/video/msm/mdss/mdss_edp.c +++ b/drivers/video/msm/mdss/mdss_edp.c @@ -897,20 +897,11 @@ static int edp_event_thread(void *data) struct mdss_edp_drv_pdata *ep; unsigned long flag; u32 todo = 0; - int ret; ep = (struct mdss_edp_drv_pdata *)data; while (1) { - ret = wait_event_interruptible(ep->event_q, - (ep->event_pndx != ep->event_gndx) || - kthread_should_stop()); - - if (ret) { - pr_debug("%s: interrupted", __func__); - continue; - } - + wait_event(ep->event_q, (ep->event_pndx != ep->event_gndx)); spin_lock_irqsave(&ep->event_lock, flag); if (ep->event_pndx == ep->event_gndx) { spin_unlock_irqrestore(&ep->event_lock, flag); diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index 21e2e60a61a..be86411ec38 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -3348,6 +3348,7 @@ static void mdss_fb_var_to_panelinfo(struct fb_var_screeninfo *var, static void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo, struct fb_var_screeninfo *var) { + u32 frame_rate; struct mdss_panel_data *pdata = container_of(pinfo, struct mdss_panel_data, panel_info); @@ -3359,7 +3360,21 @@ static void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo, var->right_margin = pinfo->lcdc.h_front_porch; var->left_margin = pinfo->lcdc.h_back_porch; var->hsync_len = pinfo->lcdc.h_pulse_width; - var->pixclock = pinfo->clk_rate; + + frame_rate = mdss_panel_get_framerate(pinfo); + if (frame_rate) { + unsigned long clk_rate, h_total, v_total; + + h_total = var->xres + var->left_margin + + var->right_margin + var->hsync_len; + v_total = var->yres + var->lower_margin + + var->upper_margin + var->vsync_len; + clk_rate = h_total * v_total * frame_rate; + var->pixclock = KHZ2PICOS(clk_rate / 1000); + } else if (pinfo->clk_rate) { + var->pixclock = KHZ2PICOS( + (unsigned long int) pinfo->clk_rate / 1000); + } } /** @@ -3446,15 +3461,10 @@ static int __mdss_fb_display_thread(void *data) mfd->index); while (1) { - ret = wait_event_interruptible(mfd->commit_wait_q, + wait_event(mfd->commit_wait_q, (atomic_read(&mfd->commits_pending) || kthread_should_stop())); - if (ret) { - pr_info("%s: interrupted", __func__); - continue; - } - if (kthread_should_stop()) break; diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c index 0db7286d59a..27737f081e8 100644 --- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c +++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1196,8 +1196,9 @@ static void mdss_mdp_handoff_programmable_fetch(struct mdss_mdp_ctl *ctl, MDSS_MDP_REG_INTF_HSYNC_CTL) >> 16; v_total_handoff = mdp_video_read(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0)/h_total_handoff; - ctl->prg_fet = v_total_handoff - - ((fetch_start_handoff - 1)/h_total_handoff); + if (h_total_handoff) + ctl->prg_fet = v_total_handoff - + ((fetch_start_handoff - 1)/h_total_handoff); pr_debug("programmable fetch lines %d start:%d\n", ctl->prg_fet, fetch_start_handoff); } diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c index 2400e149345..f41390a5069 100644 --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -3854,6 +3854,11 @@ static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd, if (cursor->set & FB_CUR_SETIMAGE) { u32 cursor_addr; + if (img->width * img->height * 4 > cursor_frame_size) { + pr_err("cursor image size is too large\n"); + ret = -EINVAL; + goto done; + } ret = copy_from_user(mfd->cursor_buf, img->data, img->width * img->height * 4); if (ret) { @@ -4191,12 +4196,16 @@ static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd, ret = mdss_fb_get_hw_caps(mfd, &metadata->data.caps); break; case metadata_op_get_ion_fd: - if (mfd->fb_ion_handle) { + if (mfd->fb_ion_handle && mfd->fb_ion_client) { + get_dma_buf(mfd->fbmem_buf); metadata->data.fbmem_ionfd = - dma_buf_fd(mfd->fbmem_buf, 0); - if (metadata->data.fbmem_ionfd < 0) + ion_share_dma_buf_fd(mfd->fb_ion_client, + mfd->fb_ion_handle); + if (metadata->data.fbmem_ionfd < 0) { + dma_buf_put(mfd->fbmem_buf); pr_err("fd allocation failed. fd = %d\n", metadata->data.fbmem_ionfd); + } } break; case metadata_op_crc: diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c index 5cbf523472e..b092728525f 100644 --- a/drivers/video/msm/mdss/mdss_mdp_pp.c +++ b/drivers/video/msm/mdss/mdss_mdp_pp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -5916,9 +5916,6 @@ static int is_valid_calib_addr(void *addr, u32 operation) int ret = 0; char __iomem *ptr = addr; char __iomem *mixer_base = mdss_res->mixer_intf->base; - char __iomem *rgb_base = mdss_res->rgb_pipes->base; - char __iomem *dma_base = mdss_res->dma_pipes->base; - char __iomem *vig_base = mdss_res->vig_pipes->base; char __iomem *ctl_base = mdss_res->ctl_off->base; char __iomem *dspp_base = mdss_res->mixer_intf->dspp_base; @@ -5950,17 +5947,20 @@ static int is_valid_calib_addr(void *addr, u32 operation) if (ret) goto valid_addr; } - if (ptr >= vig_base) { + if (mdss_res->vig_pipes && + ptr >= mdss_res->vig_pipes->base) { ret = is_valid_calib_vig_addr(ptr); if (ret) goto valid_addr; } - if (ptr >= rgb_base) { + if (mdss_res->rgb_pipes && + ptr >= mdss_res->rgb_pipes->base) { ret = is_valid_calib_rgb_addr(ptr); if (ret) goto valid_addr; } - if (ptr >= dma_base) { + if (mdss_res->dma_pipes && + ptr >= mdss_res->dma_pipes->base) { ret = is_valid_calib_dma_addr(ptr); if (ret) goto valid_addr; diff --git a/fs/9p/acl.c b/fs/9p/acl.c index c19a66472d2..6b951d1140d 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -323,7 +323,8 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, struct iattr iattr; struct posix_acl *old_acl = acl; - retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); + retval = posix_acl_update_mode(inode, + &iattr.ia_mode, &acl); if (retval) goto err_out; if (!acl) { @@ -1161,6 +1161,7 @@ long do_io_submit(aio_context_t ctx_id, long nr, struct kioctx *ctx; long ret = 0; int i = 0; + struct blk_plug plug; if (unlikely(nr < 0)) return -EINVAL; @@ -1177,6 +1178,8 @@ long do_io_submit(aio_context_t ctx_id, long nr, return -EINVAL; } + blk_start_plug(&plug); + /* * AKPM: should this return a partial result if some of the IOs were * successfully submitted? @@ -1199,6 +1202,7 @@ long do_io_submit(aio_context_t ctx_id, long nr, if (ret) break; } + blk_finish_plug(&plug); put_ioctx(ctx); return i ? i : ret; diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index d6d53e5e794..1fc4626becc 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -118,7 +118,8 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans, case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; if (acl) { - ret = posix_acl_update_mode(inode, &inode->i_mode, &acl); + ret = posix_acl_update_mode(inode, + &inode->i_mode, &acl); if (ret) return ret; } diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 296cc1b4944..7831e6865f1 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2974,6 +2974,10 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) ret = PTR_ERR(new_root); goto out; } + if (!is_fstree(new_root->objectid)) { + ret = -ENOENT; + goto out; + } if (btrfs_root_refs(&new_root->root_item) == 0) { ret = -ENOENT; diff --git a/fs/direct-io.c b/fs/direct-io.c index 0fe3d65403d..1396937f715 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -774,7 +774,8 @@ out: */ if (sdio->boundary) { ret = dio_send_cur_page(dio, sdio, map_bh); - dio_bio_submit(dio, sdio); + if (sdio->bio) + dio_bio_submit(dio, sdio); page_cache_release(sdio->cur_page); sdio->cur_page = NULL; } @@ -948,6 +949,7 @@ do_holes: i_size_aligned >> blkbits) { /* We hit eof */ page_cache_release(page); + dio_cleanup(dio, sdio); goto out; } zero_user(page, block_in_page << blkbits, diff --git a/fs/eventpoll.c b/fs/eventpoll.c index deecc7294a6..0cff4434880 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -34,6 +34,7 @@ #include <linux/mutex.h> #include <linux/anon_inodes.h> #include <linux/device.h> +#include <linux/freezer.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/mman.h> @@ -1602,7 +1603,8 @@ fetch_events: } spin_unlock_irqrestore(&ep->lock, flags); - if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS)) + if (!freezable_schedule_hrtimeout_range(to, slack, + HRTIMER_MODE_ABS)) timed_out = 1; spin_lock_irqsave(&ep->lock, flags); diff --git a/fs/exec.c b/fs/exec.c index 0b31a8040c6..d84c14880e1 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -197,8 +197,26 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, if (write) { unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; + unsigned long ptr_size; struct rlimit *rlim; + /* + * Since the stack will hold pointers to the strings, we + * must account for them as well. + * + * The size calculation is the entire vma while each arg page is + * built, so each time we get here it's calculating how far it + * is currently (rather than each call being just the newly + * added size from the arg page). As a result, we need to + * always add the entire size of the pointers, so that on the + * last call to get_arg_page() we'll actually have the entire + * correct size. + */ + ptr_size = (bprm->argc + bprm->envc) * sizeof(void *); + if (ptr_size > ULONG_MAX - size) + goto fail; + size += ptr_size; + acct_arg_size(bprm, size / PAGE_SIZE); /* @@ -216,13 +234,15 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, * to work from. */ rlim = current->signal->rlim; - if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) { - put_page(page); - return NULL; - } + if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) + goto fail; } return page; + +fail: + put_page(page); + return NULL; } static void put_arg_page(struct page *page) diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 48c3c2d7d26..36ad07b03e0 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -206,7 +206,8 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) case ACL_TYPE_ACCESS: name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); + error = posix_acl_update_mode(inode, + &inode->i_mode, &acl); if (error) return error; inode->i_ctime = CURRENT_TIME_SEC; diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index bb2f60a62d8..dbb5ad59a7f 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -205,11 +205,15 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type, case ACL_TYPE_ACCESS: name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); - if (error) + error = posix_acl_equiv_mode(acl, &inode->i_mode); + if (error < 0) return error; - inode->i_ctime = CURRENT_TIME_SEC; - ext3_mark_inode_dirty(handle, inode); + else { + inode->i_ctime = CURRENT_TIME_SEC; + ext3_mark_inode_dirty(handle, inode); + if (error == 0) + acl = NULL; + } } break; diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index efea5d5c44c..af1a90a8b22 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -64,6 +64,24 @@ config EXT4_FS_SECURITY If you are not using a security module that requires using extended attributes for file security labels, say N. +config EXT4_FS_ENCRYPTION + bool "Ext4 Encryption" + depends on EXT4_FS + select CRYPTO_AES + select CRYPTO_CBC + select CRYPTO_ECB + select CRYPTO_XTS + select CRYPTO_CTS + select CRYPTO_CTR + select CRYPTO_SHA256 + select KEYS + select ENCRYPTED_KEYS + help + Enable encryption of ext4 files and directories. This + feature is similar to ecryptfs, but it is more memory + efficient since it avoids caching the encrypted and + decrypted pages in the page cache. + config EXT4_DEBUG bool "EXT4 debugging support" depends on EXT4_FS diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile index 0310fec2ee3..cd6f50fce27 100644 --- a/fs/ext4/Makefile +++ b/fs/ext4/Makefile @@ -8,7 +8,7 @@ ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \ ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \ mmp.o indirect.o extents_status.o xattr.o xattr_user.o \ - xattr_trusted.o inline.o + xattr_trusted.o inline.o readpage.o ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index c844f1bfb45..9bbdc384768 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -211,7 +211,8 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type, case ACL_TYPE_ACCESS: name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); + error = posix_acl_update_mode(inode, + &inode->i_mode, &acl); if (error) return error; inode->i_ctime = ext4_current_time(inode); diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 79b9210c119..2e8b010aff7 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -246,6 +246,7 @@ struct ext4_io_submit { #define EXT4_MAX_BLOCK_SIZE 65536 #define EXT4_MIN_BLOCK_LOG_SIZE 10 #define EXT4_MAX_BLOCK_LOG_SIZE 16 +#define EXT4_MAX_CLUSTER_LOG_SIZE 30 #ifdef __KERNEL__ # define EXT4_BLOCK_SIZE(s) ((s)->s_blocksize) #else @@ -2651,6 +2652,10 @@ static inline void ext4_set_de_type(struct super_block *sb, de->file_type = ext4_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; } +/* readpages.c */ +extern int ext4_mpage_readpages(struct address_space *mapping, + struct list_head *pages, struct page *page, + unsigned nr_pages); /* symlink.c */ extern const struct inode_operations ext4_symlink_inode_operations; diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index 3517d5af257..1be3996b594 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c @@ -75,14 +75,8 @@ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) ext4_put_nojournal(handle); return 0; } - - err = handle->h_err; - if (!handle->h_transaction) { - rc = jbd2_journal_stop(handle); - return err ? err : rc; - } - sb = handle->h_transaction->t_journal->j_private; + err = handle->h_err; rc = jbd2_journal_stop(handle); if (!err) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index ec9770f4253..ed2badabebf 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -325,47 +325,27 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, num = min_t(pgoff_t, end - index, PAGEVEC_SIZE); nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index, (pgoff_t)num); - if (nr_pages == 0) { - if (whence == SEEK_DATA) - break; - - BUG_ON(whence != SEEK_HOLE); - /* - * If this is the first time to go into the loop and - * offset is not beyond the end offset, it will be a - * hole at this offset - */ - if (lastoff == startoff || lastoff < endoff) - found = 1; + if (nr_pages == 0) break; - } - - /* - * If this is the first time to go into the loop and - * offset is smaller than the first page offset, it will be a - * hole at this offset. - */ - if (lastoff == startoff && whence == SEEK_HOLE && - lastoff < page_offset(pvec.pages[0])) { - found = 1; - break; - } for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; struct buffer_head *bh, *head; /* - * If the current offset is not beyond the end of given - * range, it will be a hole. + * If current offset is smaller than the page offset, + * there is a hole at this offset. */ - if (lastoff < endoff && whence == SEEK_HOLE && - page->index > end) { + if (whence == SEEK_HOLE && lastoff < endoff && + lastoff < page_offset(pvec.pages[i])) { found = 1; *offset = lastoff; goto out; } + if (page->index > end) + goto out; + lock_page(page); if (unlikely(page->mapping != inode->i_mapping)) { @@ -382,6 +362,8 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, lastoff = page_offset(page); bh = head = page_buffers(page); do { + if (lastoff + bh->b_size <= startoff) + goto next; if (buffer_uptodate(bh) || buffer_unwritten(bh)) { if (whence == SEEK_DATA) @@ -396,6 +378,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, unlock_page(page); goto out; } +next: lastoff += bh->b_size; bh = bh->b_this_page; } while (bh != head); @@ -405,20 +388,18 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, unlock_page(page); } - /* - * The no. of pages is less than our desired, that would be a - * hole in there. - */ - if (nr_pages < num && whence == SEEK_HOLE) { - found = 1; - *offset = lastoff; + /* The no. of pages is less than our desired, we are done. */ + if (nr_pages < num) break; - } index = pvec.pages[i - 1]->index + 1; pagevec_release(&pvec); } while (index <= end); + if (whence == SEEK_HOLE && lastoff < endoff) { + found = 1; + *offset = lastoff; + } out: pagevec_release(&pvec); return found; @@ -440,7 +421,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) mutex_lock(&inode->i_mutex); isize = i_size_read(inode); - if (offset >= isize) { + if (offset < 0 || offset >= isize) { mutex_unlock(&inode->i_mutex); return -ENXIO; } @@ -523,7 +504,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) mutex_lock(&inode->i_mutex); isize = i_size_read(inode); - if (offset >= isize) { + if (offset < 0 || offset >= isize) { mutex_unlock(&inode->i_mutex); return -ENXIO; } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 6bcadebeef2..6d5f9690fc2 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3015,7 +3015,7 @@ static int ext4_readpage(struct file *file, struct page *page) ret = ext4_readpage_inline(inode, page); if (ret == -EAGAIN) - return mpage_readpage(page, ext4_get_block); + return ext4_mpage_readpages(page->mapping, NULL, page, 1); return ret; } @@ -3030,7 +3030,7 @@ ext4_readpages(struct file *file, struct address_space *mapping, if (ext4_has_inline_data(inode)) return 0; - return mpage_readpages(mapping, pages, nr_pages, ext4_get_block); + return ext4_mpage_readpages(mapping, pages, NULL, nr_pages); } static void ext4_invalidatepage(struct page *page, unsigned long offset) @@ -5061,8 +5061,9 @@ static int ext4_expand_extra_isize(struct inode *inode, /* No extended attributes present */ if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) || header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) { - memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0, - new_extra_isize); + memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE + + EXT4_I(inode)->i_extra_isize, 0, + new_extra_isize - EXT4_I(inode)->i_extra_isize); EXT4_I(inode)->i_extra_isize = new_extra_isize; return 0; } @@ -5113,8 +5114,6 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) sbi->s_want_extra_isize, iloc, handle); if (ret) { - ext4_set_inode_state(inode, - EXT4_STATE_NO_EXPAND); if (mnt_count != le16_to_cpu(sbi->s_es->s_mnt_count)) { ext4_warning(inode->i_sb, diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 407bcf79aa3..55014e9603e 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2253,9 +2253,20 @@ retry: inode->i_op = &ext4_file_inode_operations; inode->i_fop = &ext4_file_operations; ext4_set_aops(inode); - err = ext4_add_nondir(handle, dentry, inode); + err = 0; +#ifdef CONFIG_EXT4_FS_ENCRYPTION + if (!err && ext4_encrypted_inode(dir)) + err = ext4_inherit_context(dir, inode); +#endif + if (!err) + err = ext4_add_nondir(handle, dentry, inode); if (!err && IS_DIRSYNC(dir)) ext4_handle_sync(handle); + if (err) { + clear_nlink(inode); + unlock_new_inode(inode); + iput(inode); + } } if (handle) ext4_journal_stop(handle); @@ -2401,6 +2412,13 @@ retry: err = ext4_init_new_dir(handle, dir, inode); if (err) goto out_clear_inode; +#ifdef CONFIG_EXT4_FS_ENCRYPTION + if (ext4_encrypted_inode(dir)) { + err = ext4_inherit_context(dir, inode); + if (err) + goto out_clear_inode; + } +#endif err = ext4_mark_inode_dirty(handle, inode); if (!err) err = ext4_add_entry(handle, dentry, inode); diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c new file mode 100644 index 00000000000..ae7c56984e3 --- /dev/null +++ b/fs/ext4/readpage.c @@ -0,0 +1,264 @@ +/* + * linux/fs/ext4/readpage.c + * + * Copyright (C) 2002, Linus Torvalds. + * Copyright (C) 2015, Google, Inc. + * + * This was originally taken from fs/mpage.c + * + * The intent is the ext4_mpage_readpages() function here is intended + * to replace mpage_readpages() in the general case, not just for + * encrypted files. It has some limitations (see below), where it + * will fall back to read_block_full_page(), but these limitations + * should only be hit when page_size != block_size. + * + * This will allow us to attach a callback function to support ext4 + * encryption. + * + * If anything unusual happens, such as: + * + * - encountering a page which has buffers + * - encountering a page which has a non-hole after a hole + * - encountering a page with non-contiguous blocks + * + * then this code just gives up and calls the buffer_head-based read function. + * It does handle a page which has holes at the end - that is a common case: + * the end-of-file on blocksize < PAGE_CACHE_SIZE setups. + * + */ + +#include <linux/kernel.h> +#include <linux/export.h> +#include <linux/mm.h> +#include <linux/kdev_t.h> +#include <linux/gfp.h> +#include <linux/bio.h> +#include <linux/fs.h> +#include <linux/buffer_head.h> +#include <linux/blkdev.h> +#include <linux/highmem.h> +#include <linux/prefetch.h> +#include <linux/mpage.h> +#include <linux/writeback.h> +#include <linux/backing-dev.h> +#include <linux/pagevec.h> +#include <linux/cleancache.h> + +#include "ext4.h" + +/* + * I/O completion handler for multipage BIOs. + * + * The mpage code never puts partial pages into a BIO (except for end-of-file). + * If a page does not map to a contiguous run of blocks then it simply falls + * back to block_read_full_page(). + * + * Why is this? If a page's completion depends on a number of different BIOs + * which can complete in any order (or at the same time) then determining the + * status of that page is hard. See end_buffer_async_read() for the details. + * There is no point in duplicating all that complexity. + */ +static void mpage_end_io(struct bio *bio, int err) +{ + struct bio_vec *bv; + int i; + + bio_for_each_segment_all(bv, bio, i) { + struct page *page = bv->bv_page; + + if (!err) { + SetPageUptodate(page); + } else { + ClearPageUptodate(page); + SetPageError(page); + } + unlock_page(page); + } + + bio_put(bio); +} + +int ext4_mpage_readpages(struct address_space *mapping, + struct list_head *pages, struct page *page, + unsigned nr_pages) +{ + struct bio *bio = NULL; + unsigned page_idx; + sector_t last_block_in_bio = 0; + + struct inode *inode = mapping->host; + const unsigned blkbits = inode->i_blkbits; + const unsigned blocks_per_page = PAGE_CACHE_SIZE >> blkbits; + const unsigned blocksize = 1 << blkbits; + sector_t block_in_file; + sector_t last_block; + sector_t last_block_in_file; + sector_t blocks[MAX_BUF_PER_PAGE]; + unsigned page_block; + struct block_device *bdev = inode->i_sb->s_bdev; + int length; + unsigned relative_block = 0; + struct ext4_map_blocks map; + + map.m_pblk = 0; + map.m_lblk = 0; + map.m_len = 0; + map.m_flags = 0; + + for (page_idx = 0; nr_pages; page_idx++, nr_pages--) { + int fully_mapped = 1; + unsigned first_hole = blocks_per_page; + + prefetchw(&page->flags); + if (pages) { + page = list_entry(pages->prev, struct page, lru); + list_del(&page->lru); + if (add_to_page_cache_lru(page, mapping, + page->index, GFP_KERNEL)) + goto next_page; + } + + if (page_has_buffers(page)) + goto confused; + + block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits); + last_block = block_in_file + nr_pages * blocks_per_page; + last_block_in_file = (i_size_read(inode) + blocksize - 1) >> blkbits; + if (last_block > last_block_in_file) + last_block = last_block_in_file; + page_block = 0; + + /* + * Map blocks using the previous result first. + */ + if ((map.m_flags & EXT4_MAP_MAPPED) && + block_in_file > map.m_lblk && + block_in_file < (map.m_lblk + map.m_len)) { + unsigned map_offset = block_in_file - map.m_lblk; + unsigned last = map.m_len - map_offset; + + for (relative_block = 0; ; relative_block++) { + if (relative_block == last) { + /* needed? */ + map.m_flags &= ~EXT4_MAP_MAPPED; + break; + } + if (page_block == blocks_per_page) + break; + blocks[page_block] = map.m_pblk + map_offset + + relative_block; + page_block++; + block_in_file++; + } + } + + /* + * Then do more ext4_map_blocks() calls until we are + * done with this page. + */ + while (page_block < blocks_per_page) { + if (block_in_file < last_block) { + map.m_lblk = block_in_file; + map.m_len = last_block - block_in_file; + + if (ext4_map_blocks(NULL, inode, &map, 0) < 0) { + set_error_page: + SetPageError(page); + zero_user_segment(page, 0, + PAGE_CACHE_SIZE); + unlock_page(page); + goto next_page; + } + } + if ((map.m_flags & EXT4_MAP_MAPPED) == 0) { + fully_mapped = 0; + if (first_hole == blocks_per_page) + first_hole = page_block; + page_block++; + block_in_file++; + continue; + } + if (first_hole != blocks_per_page) + goto confused; /* hole -> non-hole */ + + /* Contiguous blocks? */ + if (page_block && blocks[page_block-1] != map.m_pblk-1) + goto confused; + for (relative_block = 0; ; relative_block++) { + if (relative_block == map.m_len) { + /* needed? */ + map.m_flags &= ~EXT4_MAP_MAPPED; + break; + } else if (page_block == blocks_per_page) + break; + blocks[page_block] = map.m_pblk+relative_block; + page_block++; + block_in_file++; + } + } + if (first_hole != blocks_per_page) { + zero_user_segment(page, first_hole << blkbits, + PAGE_CACHE_SIZE); + if (first_hole == 0) { + SetPageUptodate(page); + unlock_page(page); + goto next_page; + } + } else if (fully_mapped) { + SetPageMappedToDisk(page); + } + if (fully_mapped && blocks_per_page == 1 && + !PageUptodate(page) && cleancache_get_page(page) == 0) { + SetPageUptodate(page); + goto confused; + } + + /* + * This page will go to BIO. Do we need to send this + * BIO off first? + */ + if (bio && (last_block_in_bio != blocks[0] - 1)) { + submit_and_realloc: + submit_bio(READ, bio); + bio = NULL; + } + if (bio == NULL) { + bio = bio_alloc(GFP_KERNEL, + min_t(int, nr_pages, bio_get_nr_vecs(bdev))); + if (!bio) + goto set_error_page; + bio->bi_bdev = bdev; + bio->bi_sector = blocks[0] << (blkbits - 9); + bio->bi_end_io = mpage_end_io; + } + + length = first_hole << blkbits; + if (bio_add_page(bio, page, length, 0) < length) + goto submit_and_realloc; + + if (((map.m_flags & EXT4_MAP_BOUNDARY) && + (relative_block == map.m_len)) || + (first_hole != blocks_per_page)) { + submit_bio(READ, bio); + bio = NULL; + } else + last_block_in_bio = blocks[blocks_per_page - 1]; + goto next_page; + confused: + if (bio) { + submit_bio(READ, bio); + bio = NULL; + } + if (!PageUptodate(page)) + block_read_full_page(page, ext4_get_block); + else + unlock_page(page); + next_page: + if (pages) + page_cache_release(page); + } + BUG_ON(pages && !list_empty(pages)); + if (bio) + submit_bio(READ, bio); + return 0; +} diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 04f7fc1a523..26ee4e1a4ed 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -1911,7 +1911,8 @@ retry: n_desc_blocks = o_desc_blocks + le16_to_cpu(es->s_reserved_gdt_blocks); n_group = n_desc_blocks * EXT4_DESC_PER_BLOCK(sb); - n_blocks_count = n_group * EXT4_BLOCKS_PER_GROUP(sb); + n_blocks_count = (ext4_fsblk_t)n_group * + EXT4_BLOCKS_PER_GROUP(sb); n_group--; /* set to last group number */ } diff --git a/fs/ext4/super.c b/fs/ext4/super.c index ad3dd732495..46e73254b52 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -305,6 +305,8 @@ static void __save_error_info(struct super_block *sb, const char *func, struct ext4_super_block *es = EXT4_SB(sb)->s_es; EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; + if (bdev_read_only(sb->s_bdev)) + return; es->s_state |= cpu_to_le16(EXT4_ERROR_FS); es->s_last_error_time = cpu_to_le32(get_seconds()); strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func)); @@ -3552,7 +3554,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) if (blocksize < EXT4_MIN_BLOCK_SIZE || blocksize > EXT4_MAX_BLOCK_SIZE) { ext4_msg(sb, KERN_ERR, - "Unsupported filesystem blocksize %d", blocksize); + "Unsupported filesystem blocksize %d (%d log_block_size)", + blocksize, le32_to_cpu(es->s_log_block_size)); + goto failed_mount; + } + if (le32_to_cpu(es->s_log_block_size) > + (EXT4_MAX_BLOCK_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) { + ext4_msg(sb, KERN_ERR, + "Invalid log block size: %u", + le32_to_cpu(es->s_log_block_size)); goto failed_mount; } @@ -3671,6 +3681,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) "block size (%d)", clustersize, blocksize); goto failed_mount; } + if (le32_to_cpu(es->s_log_cluster_size) > + (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) { + ext4_msg(sb, KERN_ERR, + "Invalid log cluster size: %u", + le32_to_cpu(es->s_log_cluster_size)); + goto failed_mount; + } sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) - le32_to_cpu(es->s_log_block_size); sbi->s_clusters_per_group = diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 92850bab451..dde00d1e299 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1266,11 +1266,13 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize); down_write(&EXT4_I(inode)->xattr_sem); + /* + * Set EXT4_STATE_NO_EXPAND to avoid recursion when marking inode dirty + */ + ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND); retry: - if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) { - up_write(&EXT4_I(inode)->xattr_sem); - return 0; - } + if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) + goto out; header = IHDR(inode, raw_inode); entry = IFIRST(header); @@ -1295,8 +1297,7 @@ retry: (void *)header, total_ino, inode->i_sb->s_blocksize); EXT4_I(inode)->i_extra_isize = new_extra_isize; - error = 0; - goto cleanup; + goto out; } /* @@ -1457,6 +1458,8 @@ retry: kfree(bs); } brelse(bh); +out: + ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); up_write(&EXT4_I(inode)->xattr_sem); return 0; @@ -1468,6 +1471,10 @@ cleanup: kfree(is); kfree(bs); brelse(bh); + /* + * We deliberately leave EXT4_STATE_NO_EXPAND set here since inode + * size expansion failed. + */ up_write(&EXT4_I(inode)->xattr_sem); return error; } diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index c767dbdd7fc..7037e910944 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h @@ -23,6 +23,7 @@ #define EXT4_XATTR_INDEX_SECURITY 6 #define EXT4_XATTR_INDEX_SYSTEM 7 #define EXT4_XATTR_INDEX_RICHACL 8 +#define EXT4_XATTR_INDEX_ENCRYPTION 9 struct ext4_xattr_header { __le32 h_magic; /* magic number for identification */ @@ -100,6 +101,8 @@ extern const struct xattr_handler ext4_xattr_acl_access_handler; extern const struct xattr_handler ext4_xattr_acl_default_handler; extern const struct xattr_handler ext4_xattr_security_handler; +#define EXT4_XATTR_NAME_ENCRYPTION_CONTEXT "c" + extern ssize_t ext4_listxattr(struct dentry *, char *, size_t); extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t); diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index 9ae61eca788..5b952c05903 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c @@ -228,10 +228,12 @@ static int f2fs_set_acl(struct inode *inode, int type, case ACL_TYPE_ACCESS: name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); - if (error) + error = posix_acl_equiv_mode(acl, &inode->i_mode); + if (error < 0) return error; set_acl_inode(fi, inode->i_mode); + if (error == 0) + acl = NULL; } break; diff --git a/fs/f2fs~a6f9f264ace7... fs: use motorola_kernel b/fs/f2fs~a6f9f264ace7... fs: use motorola_kernel new file mode 120000 index 00000000000..e3e532097e4 --- /dev/null +++ b/fs/f2fs~a6f9f264ace7... fs: use motorola_kernel @@ -0,0 +1 @@ +../../motorola/kernel/fs/f2fs/
\ No newline at end of file diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 2ca61f1daf3..908f87e88c2 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1170,7 +1170,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) if ((inode->i_state & flags) == flags) return; - if (unlikely(block_dump)) + if (unlikely(block_dump > 1)) block_dump___mark_inode_dirty(inode); spin_lock(&inode->i_lock); diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c index f27c89d1788..e7cf8c5f267 100644 --- a/fs/fscache/object-list.c +++ b/fs/fscache/object-list.c @@ -338,6 +338,13 @@ static void fscache_objlist_config(struct fscache_objlist_data *data) rcu_read_lock(); confkey = key->payload.data; + if (!confkey) { + /* key was revoked */ + rcu_read_unlock(); + key_put(key); + goto no_config; + } + buf = confkey->data; for (len = confkey->datalen - 1; len >= 0; len--) { diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 28eb26b9291..33841db8b4c 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -60,7 +60,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) { struct fuse_file *ff; - ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); + ff = kzalloc(sizeof(struct fuse_file), GFP_KERNEL); if (unlikely(!ff)) return NULL; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index f1162e1dfe4..a7bc3582ef0 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -941,7 +941,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | - FUSE_FLOCK_LOCKS | FUSE_HAS_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | + FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | FUSE_WRITEBACK_CACHE; req->in.h.opcode = FUSE_INIT; diff --git a/fs/generic_acl.c b/fs/generic_acl.c index 21408084c3b..7855cfb938f 100644 --- a/fs/generic_acl.c +++ b/fs/generic_acl.c @@ -82,14 +82,20 @@ generic_acl_set(struct dentry *dentry, const char *name, const void *value, return PTR_ERR(acl); } if (acl) { + struct posix_acl *old_acl; + error = posix_acl_valid(acl); if (error) goto failed; switch (type) { case ACL_TYPE_ACCESS: - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); - if (error) + old_acl = acl; + error = posix_acl_update_mode(inode, &inode->i_mode, + &acl); + if (error < 0) goto failed; + if (!acl) + posix_acl_release(old_acl); inode->i_ctime = CURRENT_TIME; break; case ACL_TYPE_DEFAULT: diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index db243db4403..d4b2bbd7cf4 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -267,10 +267,10 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, goto out_release; if (type == ACL_TYPE_ACCESS) { - umode_t mode = inode->i_mode; + umode_t mode; struct posix_acl *old_acl = acl; - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); + error = posix_acl_update_mode(inode, &mode, &acl); if (!acl) posix_acl_release(old_acl); if (error) diff --git a/fs/inode.c b/fs/inode.c index eb66712897d..6b164e9d84d 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1935,3 +1935,34 @@ void inode_dio_done(struct inode *inode) wake_up_bit(&inode->i_state, __I_DIO_WAKEUP); } EXPORT_SYMBOL(inode_dio_done); + +/* + * inode_set_flags - atomically set some inode flags + * + * Note: the caller should be holding i_mutex, or else be sure that + * they have exclusive access to the inode structure (i.e., while the + * inode is being instantiated). The reason for the cmpxchg() loop + * --- which wouldn't be necessary if all code paths which modify + * i_flags actually followed this rule, is that there is at least one + * code path which doesn't today --- for example, + * __generic_file_aio_write() calls file_remove_suid() without holding + * i_mutex --- so we use cmpxchg() out of an abundance of caution. + * + * In the long run, i_mutex is overkill, and we should probably look + * at using the i_lock spinlock to protect i_flags, and then make sure + * it is so documented in include/linux/fs.h and that all code follows + * the locking convention!! + */ +void inode_set_flags(struct inode *inode, unsigned int flags, + unsigned int mask) +{ + unsigned int old_flags, new_flags; + + WARN_ON_ONCE(flags & ~mask); + do { + old_flags = ACCESS_ONCE(inode->i_flags); + new_flags = (old_flags & ~mask) | flags; + } while (unlikely(cmpxchg(&inode->i_flags, old_flags, + new_flags) != old_flags)); +} +EXPORT_SYMBOL(inode_set_flags); diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 02bdfe007aa..7adb97da7b2 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -694,9 +694,10 @@ static int can_set_system_xattr(struct inode *inode, const char *name, } if (acl) { struct posix_acl *old_acl = acl; + rc = posix_acl_update_mode(inode, &inode->i_mode, &acl); posix_acl_release(old_acl); - if (rc) { + if (rc < 0) { printk(KERN_ERR "posix_acl_update_mode returned %d\n", rc); diff --git a/fs/namespace.c b/fs/namespace.c index a8af5666a9e..d7e655a82f2 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -188,6 +188,7 @@ static struct mount *alloc_vfsmnt(const char *name) mnt->mnt_count = 1; mnt->mnt_writers = 0; #endif + mnt->mnt.data = NULL; INIT_LIST_HEAD(&mnt->mnt_hash); INIT_LIST_HEAD(&mnt->mnt_child); @@ -785,7 +786,6 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void if (!mnt) return ERR_PTR(-ENOMEM); - mnt->mnt.data = NULL; if (type->alloc_mnt_data) { mnt->mnt.data = type->alloc_mnt_data(); if (!mnt->mnt.data) { @@ -799,7 +799,6 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void root = mount_fs(type, flags, name, &mnt->mnt, data); if (IS_ERR(root)) { - kfree(mnt->mnt.data); free_vfsmnt(mnt); return ERR_CAST(root); } @@ -897,7 +896,6 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, return mnt; out_free: - kfree(mnt->mnt.data); free_vfsmnt(mnt); return ERR_PTR(err); } @@ -2365,9 +2363,9 @@ long do_mount(const char *dev_name, const char *dir_name, if (retval) goto dput_out; - /* Default to noatime/nodiratime unless overriden */ - if (!(flags & MS_RELATIME)) - mnt_flags |= MNT_NOATIME; + /* Default to relatime unless overriden */ + if (!(flags & MS_NOATIME)) + mnt_flags |= MNT_RELATIME; /* Separate the per-mountpoint flags */ if (flags & MS_NOSUID) @@ -2376,9 +2374,9 @@ long do_mount(const char *dev_name, const char *dir_name, mnt_flags |= MNT_NODEV; if (flags & MS_NOEXEC) mnt_flags |= MNT_NOEXEC; - //if (flags & MS_NOATIME) + if (flags & MS_NOATIME) mnt_flags |= MNT_NOATIME; - //if (flags & MS_NODIRATIME) + if (flags & MS_NODIRATIME) mnt_flags |= MNT_NODIRATIME; if (flags & MS_STRICTATIME) mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME); diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 2fe643160cf..713f87d3f1e 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -274,14 +274,20 @@ static int ocfs2_set_acl(handle_t *handle, case ACL_TYPE_ACCESS: name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { - umode_t mode = inode->i_mode; + umode_t mode; + ret = posix_acl_update_mode(inode, &mode, &acl); if (ret) return ret; - ret = ocfs2_acl_set_mode(inode, di_bh, - handle, mode); - if (ret) - return ret; + else { + if (ret == 0) + acl = NULL; + + ret = ocfs2_acl_set_mode(inode, di_bh, + handle, mode); + if (ret) + return ret; + } } break; case ACL_TYPE_DEFAULT: diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 35cc1f40b82..2bc32c0b30c 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -341,37 +341,6 @@ static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) return not_equiv; } -/** - * posix_acl_update_mode - update mode in set_acl - * - * Update the file mode when setting an ACL: compute the new file permission - * bits based on the ACL. In addition, if the ACL is equivalent to the new - * file mode, set *acl to NULL to indicate that no ACL should be set. - * - * As with chmod, clear the setgit bit if the caller is not in the owning group - * or capable of CAP_FSETID (see inode_change_ok). - * - * Called from set_acl inode operations. - */ -int posix_acl_update_mode(struct inode *inode, umode_t *mode_p, - struct posix_acl **acl) -{ - umode_t mode = inode->i_mode; - int error; - - error = posix_acl_equiv_mode(*acl, &mode); - if (error < 0) - return error; - if (error == 0) - *acl = NULL; - if (!in_group_p(inode->i_gid) && - !capable_wrt_inode_uidgid(inode, CAP_FSETID)) - mode &= ~S_ISGID; - *mode_p = mode; - return 0; -} -EXPORT_SYMBOL(posix_acl_update_mode); - /* * Modify the ACL for the chmod syscall. */ @@ -455,3 +424,34 @@ posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode) return err; } EXPORT_SYMBOL(posix_acl_chmod); + +/** + * posix_acl_update_mode - update mode in set_acl + * + * Update the file mode when setting an ACL: compute the new file permission + * bits based on the ACL. In addition, if the ACL is equivalent to the new + * file mode, set *acl to NULL to indicate that no ACL should be set. + * + * As with chmod, clear the setgit bit if the caller is not in the owning group + * or capable of CAP_FSETID (see inode_change_ok). + * + * Called from set_acl inode operations. + */ +int posix_acl_update_mode(struct inode *inode, umode_t *mode_p, + struct posix_acl **acl) +{ + umode_t mode = inode->i_mode; + int error; + + error = posix_acl_equiv_mode(*acl, &mode); + if (error < 0) + return error; + if (error == 0) + *acl = NULL; + if (!in_group_p(inode->i_gid) && + !capable_wrt_inode_uidgid(inode, CAP_FSETID)) + mode &= ~S_ISGID; + *mode_p = mode; + return 0; +} +EXPORT_SYMBOL(posix_acl_update_mode); diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index 5fd5d6a899b..a48f623d9a3 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -58,7 +58,7 @@ static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) old = atomic_read(&prz->buffer->start); new = old + a; - while (unlikely(new > prz->buffer_size)) + while (unlikely(new >= prz->buffer_size)) new -= prz->buffer_size; atomic_set(&prz->buffer->start, new); diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 2d73589f37d..df5ad557481 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -286,7 +286,8 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; if (acl) { - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); + error = posix_acl_update_mode(inode, + &inode->i_mode, &acl); if (error) return error; } diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c index 64f188f8488..75beeff149f 100755 --- a/fs/sdcardfs/derived_perm.c +++ b/fs/sdcardfs/derived_perm.c @@ -175,6 +175,9 @@ void fixup_lower_ownership(struct dentry *dentry, const char *name) gid_t gid = sbi->options.fs_low_gid; struct iattr newattrs; + if (!sbi->options.gid_derivation) + return; + info = SDCARDFS_I(dentry->d_inode); info_d = info->data; perm = info_d->perm; diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c index a1f12e27f3c..6d6be71c256 100755 --- a/fs/sdcardfs/file.c +++ b/fs/sdcardfs/file.c @@ -334,11 +334,6 @@ static int sdcardfs_fasync(int fd, struct file *file, int flag) return err; } -static struct file *sdcardfs_get_lower_file(struct file *f) -{ - return sdcardfs_lower_file(f); -} - /* * Sdcardfs cannot use generic_file_llseek as ->llseek, because it would * only set the offset of the upper file. So we have to implement our @@ -362,6 +357,11 @@ out: } +static struct file *sdcardfs_get_lower_file(struct file *f) +{ + return sdcardfs_lower_file(f); +} + const struct file_operations sdcardfs_main_fops = { .llseek = generic_file_llseek, .read = sdcardfs_read, diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 030210ac8e1..c7fe86f89ca 100755 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -34,10 +34,14 @@ const struct cred *override_fsids(struct sdcardfs_sb_info *sbi, if (!cred) return NULL; - if (data->under_obb) - uid = AID_MEDIA_OBB; - else - uid = multiuser_get_uid(data->userid, sbi->options.fs_low_uid); + if (sbi->options.gid_derivation) { + if (data->under_obb) + uid = AID_MEDIA_OBB; + else + uid = multiuser_get_uid(data->userid, sbi->options.fs_low_uid); + } else { + uid = sbi->options.fs_low_uid; + } cred->fsuid = uid; cred->fsgid = sbi->options.fs_low_gid; diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index 6c6904e8618..909193e1687 100755 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -32,6 +32,7 @@ enum { Opt_multiuser, Opt_userid, Opt_reserved_mb, + Opt_gid_derivation, Opt_err, }; @@ -43,6 +44,7 @@ static const match_table_t sdcardfs_tokens = { {Opt_mask, "mask=%u"}, {Opt_userid, "userid=%d"}, {Opt_multiuser, "multiuser"}, + {Opt_gid_derivation, "derive_gid"}, {Opt_reserved_mb, "reserved_mb=%u"}, {Opt_err, NULL} }; @@ -64,6 +66,8 @@ static int parse_options(struct super_block *sb, char *options, int silent, vfsopts->gid = 0; /* by default, 0MB is reserved */ opts->reserved_mb = 0; + /* by default, gid derivation is off */ + opts->gid_derivation = false; *debug = 0; @@ -115,6 +119,9 @@ static int parse_options(struct super_block *sb, char *options, int silent, return 0; opts->reserved_mb = option; break; + case Opt_gid_derivation: + opts->gid_derivation = true; + break; /* unknown option */ default: if (!silent) diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index 63c3bd32910..f3c283759cb 100755 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -218,6 +218,7 @@ struct sdcardfs_mount_options { gid_t fs_low_gid; userid_t fs_user_id; bool multiuser; + bool gid_derivation; unsigned int reserved_mb; }; diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c index 7f4539b4b24..b89947d878e 100755 --- a/fs/sdcardfs/super.c +++ b/fs/sdcardfs/super.c @@ -302,6 +302,8 @@ static int sdcardfs_show_options(struct vfsmount *mnt, struct seq_file *m, seq_printf(m, ",mask=%u", vfsopts->mask); if (opts->fs_user_id) seq_printf(m, ",userid=%u", opts->fs_user_id); + if (opts->gid_derivation) + seq_puts(m, ",derive_gid"); if (opts->reserved_mb != 0) seq_printf(m, ",reserved=%uMB", opts->reserved_mb); diff --git a/fs/super.c b/fs/super.c index 0eec81d77bb..55a171fe9d7 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1346,8 +1346,8 @@ int freeze_super(struct super_block *sb) } } /* - * This is just for debugging purposes so that fs can warn if it - * sees write activity when frozen is set to SB_FREEZE_COMPLETE. + * For debugging purposes so that fs can warn if it sees write activity + * when frozen is set to SB_FREEZE_COMPLETE, and for thaw_super(). */ sb->s_writers.frozen = SB_FREEZE_COMPLETE; up_write(&sb->s_umount); @@ -1366,7 +1366,7 @@ int thaw_super(struct super_block *sb) int error; down_write(&sb->s_umount); - if (sb->s_writers.frozen == SB_UNFROZEN) { + if (sb->s_writers.frozen != SB_FREEZE_COMPLETE) { up_write(&sb->s_umount); return -EINVAL; } diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 48de53e8ebf..b0f645e14b8 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -350,8 +350,7 @@ static unsigned int vfs_dent_type(uint8_t type) */ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) { - int err = 0; - int over = 0; + int err, over = 0; loff_t pos = file->f_pos; struct qstr nm; union ubifs_key key; @@ -473,21 +472,15 @@ out: kfree(file->private_data); file->private_data = NULL; - if (err != -ENOENT) + if (err != -ENOENT) { ubifs_err("cannot find next direntry, error %d", c->vi.ubi_num, err); - else - /* - * -ENOENT is a non-fatal error in this context, the TNC uses - * it to indicate that the cursor moved past the current directory - * and readdir() has to stop. - */ - err = 0; - + return err; + } /* 2 is a special value indicating that there are no more direntries */ file->f_pos = 2; - return err; + return 0; } static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int whence) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 5c1120a5fa4..76e54779b7a 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1237,8 +1237,8 @@ int udf_setsize(struct inode *inode, loff_t newsize) return err; } set_size: - truncate_setsize(inode, newsize); up_write(&iinfo->i_data_sem); + truncate_setsize(inode, newsize); } else { if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { down_write(&iinfo->i_data_sem); @@ -1255,9 +1255,9 @@ set_size: udf_get_block); if (err) return err; + truncate_setsize(inode, newsize); down_write(&iinfo->i_data_sem); udf_clear_extent_cache(inode); - truncate_setsize(inode, newsize); udf_truncate_extents(inode); up_write(&iinfo->i_data_sem); } @@ -1495,15 +1495,19 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint); } - /* - * Sanity check length of allocation descriptors and extended attrs to - * avoid integer overflows - */ - if (iinfo->i_lenEAttr > inode->i_sb->s_blocksize || iinfo->i_lenAlloc > inode->i_sb->s_blocksize) - return; - /* Now do exact checks */ - if (udf_file_entry_alloc_offset(inode) + iinfo->i_lenAlloc > inode->i_sb->s_blocksize) - return; + /* Sanity checks for files in ICB so that we don't get confused later */ + if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { + /* + * For file in ICB data is stored in allocation descriptor + * so sizes should match + */ + if (iinfo->i_lenAlloc != inode->i_size) + return; + /* File in ICB has to fit in there... */ + if (inode->i_size > inode->i_sb->s_blocksize - + udf_file_entry_alloc_offset(inode)) + return; + } switch (fe->icbTag.fileType) { case ICBTAG_FILE_TYPE_DIRECTORY: diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index eaa2a373551..0c59d960efe 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -388,13 +388,15 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name, goto out_release; if (type == ACL_TYPE_ACCESS) { - umode_t mode = inode->i_mode; + umode_t mode; struct posix_acl *old_acl = acl; + error = posix_acl_update_mode(inode, &mode, &acl); if (!acl) posix_acl_release(old_acl); if (error) goto out_release; + error = xfs_set_mode(inode, mode); if (error) goto out_release; diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h index d17784ea37f..344c1956581 100644 --- a/include/asm-generic/percpu.h +++ b/include/asm-generic/percpu.h @@ -87,6 +87,9 @@ extern void setup_per_cpu_areas(void); #endif /* SMP */ +/* 3.18 backport */ +#define raw_cpu_ptr(ptr) __this_cpu_ptr(ptr) + #ifndef PER_CPU_BASE_SECTION #ifdef CONFIG_SMP #define PER_CPU_BASE_SECTION ".data..percpu" diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e9b04cd8032..6579f0e4548 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -475,7 +475,7 @@ struct request_queue { #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ (1 << QUEUE_FLAG_STACKABLE) | \ (1 << QUEUE_FLAG_SAME_COMP) | \ - (0 << QUEUE_FLAG_ADD_RANDOM)) + (1 << QUEUE_FLAG_ADD_RANDOM)) static inline void queue_lockdep_assert_held(struct request_queue *q) { diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index ca31306f7b5..8236ef859a9 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -297,6 +297,18 @@ sb_bread(struct super_block *sb, sector_t block) return __bread(sb->s_bdev, block, sb->s_blocksize); } +static inline struct buffer_head * +sb_bread_unmovable(struct super_block *sb, sector_t block) +{ + return sb_bread(sb, block); +} + +static inline struct buffer_head *getblk_unmovable(struct block_device *bdev, + sector_t block, unsigned size) +{ + return __getblk(bdev, block, size); +} + static inline void sb_breadahead(struct super_block *sb, sector_t block) { diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 953cd12175c..cdf13ca7cac 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -66,6 +66,7 @@ #define __deprecated __attribute__((deprecated)) #define __packed __attribute__((packed)) #define __weak __attribute__((weak)) +#define __alias(symbol) __attribute__((alias(#symbol))) /* * it doesn't make sense on ARM (currently the only user of __naked) to trace @@ -100,116 +101,10 @@ #define __maybe_unused __attribute__((unused)) #define __always_unused __attribute__((unused)) -/* gcc version specific checks */ - -#if GCC_VERSION < 30200 -# error Sorry, your compiler is too old - please upgrade it. -#endif - -#if GCC_VERSION < 30300 -# define __used __attribute__((__unused__)) -#else -# define __used __attribute__((__used__)) -#endif - -#ifdef CONFIG_GCOV_KERNEL -# if GCC_VERSION < 30400 -# error "GCOV profiling support for gcc versions below 3.4 not included" -# endif /* __GNUC_MINOR__ */ -#endif /* CONFIG_GCOV_KERNEL */ - -#if GCC_VERSION >= 30400 -#define __must_check __attribute__((warn_unused_result)) -#endif - -#if GCC_VERSION >= 40000 - -/* GCC 4.1.[01] miscompiles __weak */ -#ifdef __KERNEL__ -# if GCC_VERSION >= 40100 && GCC_VERSION <= 40101 -# error Your version of gcc miscompiles the __weak directive -# endif -#endif - -#define __used __attribute__((__used__)) -#define __compiler_offsetof(a, b) \ - __builtin_offsetof(a, b) - -#if GCC_VERSION >= 40100 && GCC_VERSION < 40600 -# define __compiletime_object_size(obj) __builtin_object_size(obj, 0) -#endif - -#if GCC_VERSION >= 40300 -/* Mark functions as cold. gcc will assume any path leading to a call - * to them will be unlikely. This means a lot of manual unlikely()s - * are unnecessary now for any paths leading to the usual suspects - * like BUG(), printk(), panic() etc. [but let's keep them for now for - * older compilers] - * - * Early snapshots of gcc 4.3 don't support this and we can't detect this - * in the preprocessor, but we can live with this because they're unreleased. - * Maketime probing would be overkill here. - * - * gcc also has a __attribute__((__hot__)) to move hot functions into - * a special section, but I don't see any sense in this right now in - * the kernel context - */ -#define __cold __attribute__((__cold__)) - -#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) - -#ifndef __CHECKER__ -# define __compiletime_warning(message) __attribute__((warning(message))) -# define __compiletime_error(message) __attribute__((error(message))) -#endif /* __CHECKER__ */ -#endif /* GCC_VERSION >= 40300 */ - -#if GCC_VERSION >= 40500 -/* - * Mark a position in code as unreachable. This can be used to - * suppress control flow warnings after asm blocks that transfer - * control elsewhere. - * - * Early snapshots of gcc 4.5 don't support this and we can't detect - * this in the preprocessor, but we can live with this because they're - * unreleased. Really, we need to have autoconf for the kernel. - */ -#define unreachable() __builtin_unreachable() - -/* Mark a function definition as prohibited from being cloned. */ -#define __noclone __attribute__((__noclone__, __optimize__("no-tracer"))) - -#endif /* GCC_VERSION >= 40500 */ - -#if GCC_VERSION >= 40600 -/* - * Tell the optimizer that something else uses this function or variable. - */ -#define __visible __attribute__((externally_visible)) -#endif - -/* - * GCC 'asm goto' miscompiles certain code sequences: - * - * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 - * - * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. - * - * (asm goto is automatically volatile - the naming reflects this.) - */ -#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) - -#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP -#if GCC_VERSION >= 40400 -#define __HAVE_BUILTIN_BSWAP32__ -#define __HAVE_BUILTIN_BSWAP64__ -#endif -#if GCC_VERSION >= 40800 || (defined(__powerpc__) && GCC_VERSION >= 40600) -#define __HAVE_BUILTIN_BSWAP16__ -#endif -#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ - -#endif /* gcc version >= 40000 specific checks */ +#define __gcc_header(x) #x +#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h) +#define gcc_header(x) _gcc_header(x) +#include gcc_header(__GNUC__) #if !defined(__noclone) #define __noclone /* not needed */ diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h new file mode 100644 index 00000000000..7d89febe4d7 --- /dev/null +++ b/include/linux/compiler-gcc3.h @@ -0,0 +1,23 @@ +#ifndef __LINUX_COMPILER_H +#error "Please don't include <linux/compiler-gcc3.h> directly, include <linux/compiler.h> instead." +#endif + +#if GCC_VERSION < 30200 +# error Sorry, your compiler is too old - please upgrade it. +#endif + +#if GCC_VERSION >= 30300 +# define __used __attribute__((__used__)) +#else +# define __used __attribute__((__unused__)) +#endif + +#if GCC_VERSION >= 30400 +#define __must_check __attribute__((warn_unused_result)) +#endif + +#ifdef CONFIG_GCOV_KERNEL +# if GCC_VERSION < 30400 +# error "GCOV profiling support for gcc versions below 3.4 not included" +# endif /* __GNUC_MINOR__ */ +#endif /* CONFIG_GCOV_KERNEL */ diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h new file mode 100644 index 00000000000..769e1986463 --- /dev/null +++ b/include/linux/compiler-gcc4.h @@ -0,0 +1,91 @@ +#ifndef __LINUX_COMPILER_H +#error "Please don't include <linux/compiler-gcc4.h> directly, include <linux/compiler.h> instead." +#endif + +/* GCC 4.1.[01] miscompiles __weak */ +#ifdef __KERNEL__ +# if GCC_VERSION >= 40100 && GCC_VERSION <= 40101 +# error Your version of gcc miscompiles the __weak directive +# endif +#endif + +#define __used __attribute__((__used__)) +#define __must_check __attribute__((warn_unused_result)) +#define __compiler_offsetof(a,b) __builtin_offsetof(a,b) + +#if GCC_VERSION >= 40100 && GCC_VERSION < 40600 +# define __compiletime_object_size(obj) __builtin_object_size(obj, 0) +#endif + +#if GCC_VERSION >= 40300 +/* Mark functions as cold. gcc will assume any path leading to a call + to them will be unlikely. This means a lot of manual unlikely()s + are unnecessary now for any paths leading to the usual suspects + like BUG(), printk(), panic() etc. [but let's keep them for now for + older compilers] + + Early snapshots of gcc 4.3 don't support this and we can't detect this + in the preprocessor, but we can live with this because they're unreleased. + Maketime probing would be overkill here. + + gcc also has a __attribute__((__hot__)) to move hot functions into + a special section, but I don't see any sense in this right now in + the kernel context */ +#define __cold __attribute__((__cold__)) + +#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) + +#ifndef __CHECKER__ +# define __compiletime_warning(message) __attribute__((warning(message))) +# define __compiletime_error(message) __attribute__((error(message))) +#endif /* __CHECKER__ */ +#endif /* GCC_VERSION >= 40300 */ + +#if GCC_VERSION >= 40500 +/* + * Mark a position in code as unreachable. This can be used to + * suppress control flow warnings after asm blocks that transfer + * control elsewhere. + * + * Early snapshots of gcc 4.5 don't support this and we can't detect + * this in the preprocessor, but we can live with this because they're + * unreleased. Really, we need to have autoconf for the kernel. + */ +#define unreachable() __builtin_unreachable() + +/* Mark a function definition as prohibited from being cloned. */ +#define __noclone __attribute__((__noclone__)) + +#endif /* GCC_VERSION >= 40500 */ + +#if GCC_VERSION >= 40600 +/* + * Tell the optimizer that something else uses this function or variable. + */ +#define __visible __attribute__((externally_visible)) +#endif + +/* + * GCC 'asm goto' miscompiles certain code sequences: + * + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 + * + * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. + * + * (asm goto is automatically volatile - the naming reflects this.) + */ +#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) + +#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP +#if GCC_VERSION >= 40400 +#define __HAVE_BUILTIN_BSWAP32__ +#define __HAVE_BUILTIN_BSWAP64__ +#endif +#if GCC_VERSION >= 40800 || (defined(__powerpc__) && GCC_VERSION >= 40600) +#define __HAVE_BUILTIN_BSWAP16__ +#endif +#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ + +#if GCC_VERSION >= 40902 +#define KASAN_ABI_VERSION 3 +#endif diff --git a/include/linux/compiler-gcc5.h b/include/linux/compiler-gcc5.h new file mode 100644 index 00000000000..efee493714e --- /dev/null +++ b/include/linux/compiler-gcc5.h @@ -0,0 +1,67 @@ +#ifndef __LINUX_COMPILER_H +#error "Please don't include <linux/compiler-gcc5.h> directly, include <linux/compiler.h> instead." +#endif + +#define __used __attribute__((__used__)) +#define __must_check __attribute__((warn_unused_result)) +#define __compiler_offsetof(a, b) __builtin_offsetof(a, b) + +/* Mark functions as cold. gcc will assume any path leading to a call + to them will be unlikely. This means a lot of manual unlikely()s + are unnecessary now for any paths leading to the usual suspects + like BUG(), printk(), panic() etc. [but let's keep them for now for + older compilers] + + Early snapshots of gcc 4.3 don't support this and we can't detect this + in the preprocessor, but we can live with this because they're unreleased. + Maketime probing would be overkill here. + + gcc also has a __attribute__((__hot__)) to move hot functions into + a special section, but I don't see any sense in this right now in + the kernel context */ +#define __cold __attribute__((__cold__)) + +#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) + +#ifndef __CHECKER__ +# define __compiletime_warning(message) __attribute__((warning(message))) +# define __compiletime_error(message) __attribute__((error(message))) +#endif /* __CHECKER__ */ + +/* + * Mark a position in code as unreachable. This can be used to + * suppress control flow warnings after asm blocks that transfer + * control elsewhere. + * + * Early snapshots of gcc 4.5 don't support this and we can't detect + * this in the preprocessor, but we can live with this because they're + * unreleased. Really, we need to have autoconf for the kernel. + */ +#define unreachable() __builtin_unreachable() + +/* Mark a function definition as prohibited from being cloned. */ +#define __noclone __attribute__((__noclone__)) + +/* + * Tell the optimizer that something else uses this function or variable. + */ +#define __visible __attribute__((externally_visible)) + +/* + * GCC 'asm goto' miscompiles certain code sequences: + * + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 + * + * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. + * + * (asm goto is automatically volatile - the naming reflects this.) + */ +#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) + +#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP +#define __HAVE_BUILTIN_BSWAP32__ +#define __HAVE_BUILTIN_BSWAP64__ +#define __HAVE_BUILTIN_BSWAP16__ +#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ + +#define KASAN_ABI_VERSION 4 diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 6a37ab8073c..20d0d6d6136 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -164,7 +164,6 @@ static inline void disable_cpufreq(void) { } #define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target */ #define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */ -#define CPUFREQ_RELATION_C 2 /* closest frequency to target */ struct freq_attr { struct attribute attr; diff --git a/include/linux/fs.h b/include/linux/fs.h index ca1bbbbf380..94cfd5254f9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2517,6 +2517,9 @@ void inode_dio_wait(struct inode *inode); void inode_dio_done(struct inode *inode); struct inode *dio_bio_get_inode(struct bio *bio); +extern void inode_set_flags(struct inode *inode, unsigned int flags, + unsigned int mask); + extern const struct file_operations generic_ro_fops; #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) @@ -2736,4 +2739,11 @@ static inline void inode_has_no_xattr(struct inode *inode) inode->i_flags |= S_NOSEC; } +static inline bool dir_relax(struct inode *inode) +{ + mutex_unlock(&inode->i_mutex); + mutex_lock(&inode->i_mutex); + return !IS_DEADDIR(inode); +} + #endif /* _LINUX_FS_H */ diff --git a/include/linux/i2c/i2c-msm-v2.h b/include/linux/i2c/i2c-msm-v2.h index 34d2813ade4..02cae9b8759 100644 --- a/include/linux/i2c/i2c-msm-v2.h +++ b/include/linux/i2c/i2c-msm-v2.h @@ -26,12 +26,9 @@ enum msm_i2_debug_level { MSM_DBG, /* Low level details. Use for debugging */ }; -#define CONFIG_I2C_MSM_DEBUG 0 #define i2c_msm_dbg(ctrl, dbg_level, fmt, ...) do {\ - if (CONFIG_I2C_MSM_DEBUG) {\ if (ctrl->dbgfs.dbg_lvl >= dbg_level)\ dev_info(ctrl->dev, pr_fmt(fmt), ##__VA_ARGS__);\ - }\ } while (0) #define BIT_IS_SET(val, idx) ((val >> idx) & 0x1) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 70c7437c41d..300fcc9c9da 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -554,7 +554,7 @@ do { \ #define do_trace_printk(fmt, args...) \ do { \ - static const char *trace_printk_fmt __used \ + static const char *trace_printk_fmt \ __attribute__((section("__trace_printk_fmt"))) = \ __builtin_constant_p(fmt) ? fmt : NULL; \ \ @@ -601,7 +601,7 @@ extern int __trace_puts(unsigned long ip, const char *str, int size); */ #define trace_puts(str) ({ \ - static const char *trace_printk_fmt __used \ + static const char *trace_printk_fmt \ __attribute__((section("__trace_printk_fmt"))) = \ __builtin_constant_p(str) ? str : NULL; \ \ @@ -621,7 +621,7 @@ extern void trace_dump_stack(int skip); #define ftrace_vprintk(fmt, vargs) \ do { \ if (__builtin_constant_p(fmt)) { \ - static const char *trace_printk_fmt __used \ + static const char *trace_printk_fmt \ __attribute__((section("__trace_printk_fmt"))) = \ __builtin_constant_p(fmt) ? fmt : NULL; \ \ diff --git a/include/linux/key.h b/include/linux/key.h index b2752c35f42..994d52f00c1 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -171,6 +171,7 @@ struct key { #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ +#define KEY_FLAG_UID_KEYRING 11 /* set if key is a user or user session keyring */ /* the description string * - this is used to match a key against search criteria @@ -212,6 +213,7 @@ extern struct key *key_alloc(struct key_type *type, #define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ +#define KEY_ALLOC_UID_KEYRING 0x0010 /* allocating a user or user session keyring */ extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); diff --git a/include/linux/mm.h b/include/linux/mm.h index 2629bdd95b3..e5eb3460de6 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1899,6 +1899,12 @@ static inline unsigned int debug_guardpage_minorder(void) { return 0; } static inline bool page_is_guard(struct page *page) { return false; } #endif /* CONFIG_DEBUG_PAGEALLOC */ +/* 3.18 backport */ +static inline void truncate_inode_pages_final(struct address_space *mapping) +{ + truncate_inode_pages(mapping, 0); +} + #if MAX_NUMNODES > 1 void __init setup_nr_node_ids(void); #else diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h index dc680c4b50d..dc680c4b50d 100644..100755 --- a/include/linux/mmc/sdio_func.h +++ b/include/linux/mmc/sdio_func.h diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 7a871e8e2a0..327a0190358 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -109,16 +109,9 @@ enum pageflags { #ifdef CONFIG_TRANSPARENT_HUGEPAGE PG_compound_lock, #endif -#ifdef CONFIG_KSM_CHECK_PAGE - PG_ksm_scan0, /* page has been scanned by even KSM cycle */ -#endif PG_readahead, /* page in a readahead window */ __NR_PAGEFLAGS, -#ifdef CONFIG_KSM_CHECK_PAGE - /* page has been scanned by odd KSM cycle */ - PG_ksm_scan1 = PG_owner_priv_1, -#endif /* Filesystems */ PG_checked = PG_owner_priv_1, @@ -218,10 +211,6 @@ PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved) PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked) __PAGEFLAG(SlobFree, slob_free) -#ifdef CONFIG_KSM_CHECK_PAGE -CLEARPAGEFLAG(KsmScan0, ksm_scan0) TESTSETFLAG(KsmScan0, ksm_scan0) -CLEARPAGEFLAG(KsmScan1, ksm_scan1) TESTSETFLAG(KsmScan1, ksm_scan1) -#endif /* * Private page markings that may be used by the filesystem that owns the page @@ -329,13 +318,23 @@ CLEARPAGEFLAG(Uptodate, uptodate) extern void cancel_dirty_page(struct page *page, unsigned int account_size); int test_clear_page_writeback(struct page *page); -int test_set_page_writeback(struct page *page); +int __test_set_page_writeback(struct page *page, bool keep_write); + +#define test_set_page_writeback(page) \ + __test_set_page_writeback(page, false) +#define test_set_page_writeback_keepwrite(page) \ + __test_set_page_writeback(page, true) static inline void set_page_writeback(struct page *page) { test_set_page_writeback(page); } +static inline void set_page_writeback_keepwrite(struct page *page) +{ + test_set_page_writeback_keepwrite(page); +} + #ifdef CONFIG_PAGEFLAGS_EXTENDED /* * System with lots of page flags available. This allows separate diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 2ae0bba45f1..94d2f4282a2 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h @@ -90,12 +90,14 @@ extern struct posix_acl *posix_acl_from_mode(umode_t, gfp_t); extern int posix_acl_equiv_mode(const struct posix_acl *, umode_t *); extern int posix_acl_create(struct posix_acl **, gfp_t, umode_t *); extern int posix_acl_chmod(struct posix_acl **, gfp_t, umode_t); -extern int posix_acl_update_mode(struct inode *, umode_t *, struct posix_acl **); extern struct posix_acl *get_posix_acl(struct inode *, int); extern int set_posix_acl(struct inode *, int, struct posix_acl *); #ifdef CONFIG_FS_POSIX_ACL +extern int posix_acl_update_mode(struct inode *, umode_t *, + struct posix_acl **); + static inline struct posix_acl **acl_by_type(struct inode *inode, int type) { switch (type) { diff --git a/include/linux/preempt.h b/include/linux/preempt.h index eaac52a8fe6..f5d4723cdb3 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -10,32 +10,19 @@ #include <linux/linkage.h> #include <linux/list.h> -static __always_inline int preempt_count(void) -{ - return current_thread_info()->preempt_count; -} - -static __always_inline int *preempt_count_ptr(void) -{ - return ¤t_thread_info()->preempt_count; -} - -static __always_inline void preempt_count_set(int pc) -{ - *preempt_count_ptr() = pc; -} - #if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER) extern void add_preempt_count(int val); extern void sub_preempt_count(int val); #else -# define add_preempt_count(val) do { *preempt_count_ptr() += (val); } while (0) -# define sub_preempt_count(val) do { *preempt_count_ptr() -= (val); } while (0) +# define add_preempt_count(val) do { preempt_count() += (val); } while (0) +# define sub_preempt_count(val) do { preempt_count() -= (val); } while (0) #endif #define inc_preempt_count() add_preempt_count(1) #define dec_preempt_count() sub_preempt_count(1) +#define preempt_count() (current_thread_info()->preempt_count) + #ifdef CONFIG_PREEMPT asmlinkage void preempt_schedule(void); @@ -94,9 +81,9 @@ do { \ /* For debugging and tracer internals only! */ #define add_preempt_count_notrace(val) \ - do { *preempt_count_ptr() += (val); } while (0) + do { preempt_count() += (val); } while (0) #define sub_preempt_count_notrace(val) \ - do { *preempt_count_ptr() -= (val); } while (0) + do { preempt_count() -= (val); } while (0) #define inc_preempt_count_notrace() add_preempt_count_notrace(1) #define dec_preempt_count_notrace() sub_preempt_count_notrace(1) diff --git a/include/linux/topology.h b/include/linux/topology.h index c4b84dde95a..9138f31200a 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -88,7 +88,7 @@ int arch_update_cpu_topology(void); #define SD_SIBLING_INIT (struct sched_domain) { \ .min_interval = 1, \ .max_interval = 2, \ - .busy_factor = 1, \ + .busy_factor = 64, \ .imbalance_pct = 110, \ \ .flags = 1*SD_LOAD_BALANCE \ diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index 66cb5a0411b..046c74b014c 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -129,9 +129,6 @@ static inline void tracepoint_synchronize_unregister(void) void *it_func; \ void *__data; \ \ - if (!cpu_online(raw_smp_processor_id())) \ - return; \ - \ if (!(cond)) \ return; \ prercu; \ diff --git a/include/linux/wait.h b/include/linux/wait.h index 63648bbfa37..29321895d17 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -1046,5 +1046,33 @@ static inline int wait_on_bit_lock(void *word, int bit, return 0; return out_of_line_wait_on_bit_lock(word, bit, action, mode); } - + +/* 3.18 backport */ +extern int bit_wait_io(void *); + +/** + * wait_on_bit_io - wait for a bit to be cleared + * @word: the word being waited on, a kernel virtual address + * @bit: the bit of the word being waited on + * @mode: the task state to sleep in + * + * Use the standard hashed waitqueue table to wait for a bit + * to be cleared. This is similar to wait_on_bit(), but calls + * io_schedule() instead of schedule() for the actual waiting. + * + * Returned value will be zero if the bit was cleared, or non-zero + * if the process received a signal and the mode permitted wakeup + * on that signal. + */ +static inline int +wait_on_bit_io(void *word, int bit, unsigned mode) +{ + might_sleep(); + if (!test_bit(bit, word)) + return 0; + return out_of_line_wait_on_bit(word, bit, + bit_wait_io, + mode); +} + #endif diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index ac14ecec270..4dab847a1d7 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -304,35 +304,9 @@ enum { WQ_CPU_INTENSIVE = 1 << 5, /* cpu instensive workqueue */ WQ_SYSFS = 1 << 6, /* visible in sysfs, see wq_sysfs_register() */ - /* - * Per-cpu workqueues are generally preferred because they tend to - * show better performance thanks to cache locality. Per-cpu - * workqueues exclude the scheduler from choosing the CPU to - * execute the worker threads, which has an unfortunate side effect - * of increasing power consumption. - * - * The scheduler considers a CPU idle if it doesn't have any task - * to execute and tries to keep idle cores idle to conserve power; - * however, for example, a per-cpu work item scheduled from an - * interrupt handler on an idle CPU will force the scheduler to - * excute the work item on that CPU breaking the idleness, which in - * turn may lead to more scheduling choices which are sub-optimal - * in terms of power consumption. - * - * Workqueues marked with WQ_POWER_EFFICIENT are per-cpu by default - * but become unbound if workqueue.power_efficient kernel param is - * specified. Per-cpu workqueues which are identified to - * contribute significantly to power-consumption are identified and - * marked with this flag and enabling the power_efficient mode - * leads to noticeable power saving at the cost of small - * performance disadvantage. - * - * http://thread.gmane.org/gmane.linux.kernel/1480396 - */ - WQ_POWER_EFFICIENT = 1 << 7, - __WQ_DRAINING = 1 << 16, /* internal: workqueue is draining */ __WQ_ORDERED = 1 << 17, /* internal: workqueue is ordered */ + __WQ_ORDERED_EXPLICIT = 1 << 18, /* internal: alloc_ordered_workqueue() */ WQ_MAX_ACTIVE = 512, /* I like 512, better ideas? */ WQ_MAX_UNBOUND_PER_CPU = 4, /* 4 * #cpus for unbound wq */ @@ -361,19 +335,11 @@ enum { * * system_freezable_wq is equivalent to system_wq except that it's * freezable. - * - * *_power_efficient_wq are inclined towards saving power and converted - * into WQ_UNBOUND variants if 'wq_power_efficient' is enabled; otherwise, - * they are same as their non-power-efficient counterparts - e.g. - * system_power_efficient_wq is identical to system_wq if - * 'wq_power_efficient' is disabled. See WQ_POWER_EFFICIENT for more info. */ extern struct workqueue_struct *system_wq; extern struct workqueue_struct *system_long_wq; extern struct workqueue_struct *system_unbound_wq; extern struct workqueue_struct *system_freezable_wq; -extern struct workqueue_struct *system_power_efficient_wq; -extern struct workqueue_struct *system_freezable_power_efficient_wq; static inline struct workqueue_struct * __deprecated __system_nrt_wq(void) { @@ -443,7 +409,8 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active, * Pointer to the allocated workqueue on success, %NULL on failure. */ #define alloc_ordered_workqueue(fmt, flags, args...) \ - alloc_workqueue(fmt, WQ_UNBOUND | __WQ_ORDERED | (flags), 1, ##args) + alloc_workqueue(fmt, WQ_UNBOUND | __WQ_ORDERED | \ + __WQ_ORDERED_EXPLICIT | (flags), 1, ##args) #define create_workqueue(name) \ alloc_workqueue((name), WQ_MEM_RECLAIM, 1) diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index 21666fbdb72..3a4c37d9fb0 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -8,11 +8,6 @@ #include <net/flow.h> #include <net/rtnetlink.h> -struct fib_kuid_range { - kuid_t start; - kuid_t end; -}; - struct fib_rule { struct list_head list; atomic_t refcnt; @@ -28,7 +23,8 @@ struct fib_rule { struct fib_rule __rcu *ctarget; char iifname[IFNAMSIZ]; char oifname[IFNAMSIZ]; - struct fib_kuid_range uid_range; + uid_t uid_start; + uid_t uid_end; struct rcu_head rcu; struct net * fr_net; }; @@ -87,7 +83,8 @@ struct fib_rules_ops { [FRA_FWMASK] = { .type = NLA_U32 }, \ [FRA_TABLE] = { .type = NLA_U32 }, \ [FRA_GOTO] = { .type = NLA_U32 }, \ - [FRA_UID_RANGE] = { .len = sizeof(struct fib_rule_uid_range) } + [FRA_UID_START] = { .type = NLA_U32 }, \ + [FRA_UID_END] = { .type = NLA_U32 } static inline void fib_rule_get(struct fib_rule *rule) { diff --git a/include/net/flow.h b/include/net/flow.h index 15ecdd07e19..95fa38bda3a 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -10,7 +10,14 @@ #include <linux/socket.h> #include <linux/in6.h> #include <linux/atomic.h> -#include <linux/uidgid.h> + +/* + * ifindex generation is per-net namespace, and loopback is + * always the 1st device in ns (see net_dev_init), thus any + * loopback device should get ifindex 1 + */ + +#define LOOPBACK_IFINDEX 1 /* * ifindex generation is per-net namespace, and loopback is @@ -32,7 +39,7 @@ struct flowi_common { #define FLOWI_FLAG_CAN_SLEEP 0x02 #define FLOWI_FLAG_KNOWN_NH 0x04 __u32 flowic_secid; - kuid_t flowic_uid; + uid_t flowic_uid; }; union flowi_uli { @@ -90,7 +97,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif, __u8 proto, __u8 flags, __be32 daddr, __be32 saddr, __be16 dport, __be16 sport, - kuid_t uid) + uid_t uid) { fl4->flowi4_oif = oif; fl4->flowi4_iif = LOOPBACK_IFINDEX; diff --git a/include/net/ip.h b/include/net/ip.h index c02d09be8ad..752697cd367 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -155,7 +155,7 @@ struct ip_reply_arg { /* -1 if not needed */ int bound_dev_if; u8 tos; - kuid_t uid; + uid_t uid; }; #define IP_REPLY_ARG_NOSRCCHECK 1 diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 30f068fafaa..8d977b34364 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -136,11 +136,10 @@ extern int rt6_route_rcv(struct net_device *dev, const struct in6_addr *gwaddr); extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, - int oif, u32 mark, kuid_t uid); + int oif, u32 mark); extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu); -extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark, - kuid_t uid); +extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark); extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk); struct netlink_callback; diff --git a/include/net/ipv6.h b/include/net/ipv6.h index f3bb9e79fa2..1c581b99c64 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -849,6 +849,7 @@ extern int inet6_hash_connect(struct inet_timewait_death_row *death_row, */ extern const struct proto_ops inet6_stream_ops; extern const struct proto_ops inet6_dgram_ops; +extern const struct proto_ops inet6_sockraw_ops; struct group_source_req; struct group_filter; diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index 5d5a6a4732e..5af07a1ab0c 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h @@ -551,7 +551,8 @@ iwe_stream_add_point(struct iw_request_info *info, char *stream, char *ends, memcpy(stream + lcp_len, ((char *) &iwe->u) + IW_EV_POINT_OFF, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); - memcpy(stream + point_len, extra, iwe->u.data.length); + if (iwe->u.data.length && extra) + memcpy(stream + point_len, extra, iwe->u.data.length); stream += event_len; } return stream; diff --git a/include/net/route.h b/include/net/route.h index 4fe676279a4..43280f6fa56 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -52,6 +52,7 @@ struct rtable { __u8 rt_uses_gateway; int rt_iif; + uid_t rt_uid; /* Info on neighbour */ __be32 rt_gateway; @@ -142,7 +143,7 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos, RT_SCOPE_UNIVERSE, proto, sk ? inet_sk_flowi_flags(sk) : 0, - daddr, saddr, dport, sport, sock_net_uid(net, sk)); + daddr, saddr, dport, sport, sk ? sock_i_uid(sk) : 0); if (sk) security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); return ip_route_output_flow(net, fl4, sk); @@ -254,7 +255,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32 flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE, protocol, flow_flags, dst, src, dport, sport, - sk->sk_uid); + sock_i_uid(sk)); } static inline struct rtable *ip_route_connect(struct flowi4 *fl4, diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 845ab6decc4..ee81c68f24a 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -555,6 +555,8 @@ _sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member) #define _sctp_walk_params(pos, chunk, end, member)\ for (pos.v = chunk->member;\ + (pos.v + offsetof(struct sctp_paramhdr, length) + sizeof(pos.p->length) <=\ + (void *)chunk + end) &&\ pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\ ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\ pos.v += WORD_ROUND(ntohs(pos.p->length))) @@ -565,6 +567,8 @@ _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length)) #define _sctp_walk_errors(err, chunk_hdr, end)\ for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \ sizeof(sctp_chunkhdr_t));\ + ((void *)err + offsetof(sctp_errhdr_t, length) + sizeof(err->length) <=\ + (void *)chunk_hdr + end) &&\ (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\ ntohs(err->length) >= sizeof(sctp_errhdr_t); \ err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length)))) diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index ca4693b4e09..00c0e5bf5d3 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -143,8 +143,12 @@ __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event); static inline int sctp_ulpevent_type_enabled(__u16 sn_type, struct sctp_event_subscribe *mask) { + int offset = sn_type - SCTP_SN_TYPE_BASE; char *amask = (char *) mask; - return amask[sn_type - SCTP_SN_TYPE_BASE]; + + if (offset >= sizeof(struct sctp_event_subscribe)) + return 0; + return amask[offset]; } /* Given an event subscription, is this event enabled? */ diff --git a/include/net/tcp.h b/include/net/tcp.h index 809b3356f9c..eb3efd136f0 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1611,4 +1611,14 @@ struct tcp_request_sock_ops { extern void tcp_v4_init(void); extern void tcp_init(void); +/* At how many jiffies into the future should the RTO fire? */ +static inline s32 tcp_rto_delta(const struct sock *sk) +{ + const struct sk_buff *skb = tcp_write_queue_head(sk); + const u32 rto = inet_csk(sk)->icsk_rto; + const u32 rto_time_stamp = TCP_SKB_CB(skb)->when + rto; + + return (s32)(rto_time_stamp - tcp_time_stamp); +} + #endif /* _TCP_H */ diff --git a/include/sound/msm-dts-eagle.h b/include/sound/msm-dts-eagle.h deleted file mode 100644 index 2ef01136b7c..00000000000 --- a/include/sound/msm-dts-eagle.h +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright (c) 2014, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __MSM_DTS_EAGLE_H__ -#define __MSM_DTS_EAGLE_H__ - -#include <linux/compat.h> -#include <sound/soc.h> -#include <sound/devdep_params.h> -#include <sound/q6asm-v2.h> - -#ifdef CONFIG_COMPAT -enum { - DTS_EAGLE_IOCTL_GET_CACHE_SIZE32 = _IOR(0xF2, 0, __s32), - DTS_EAGLE_IOCTL_SET_CACHE_SIZE32 = _IOW(0xF2, 1, __s32), - DTS_EAGLE_IOCTL_GET_PARAM32 = _IOR(0xF2, 2, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_PARAM32 = _IOW(0xF2, 3, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_CACHE_BLOCK32 = - _IOW(0xF2, 4, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE32 = - _IOW(0xF2, 5, compat_uptr_t), - DTS_EAGLE_IOCTL_GET_LICENSE32 = - _IOR(0xF2, 6, compat_uptr_t), - DTS_EAGLE_IOCTL_SET_LICENSE32 = - _IOW(0xF2, 7, compat_uptr_t), - DTS_EAGLE_IOCTL_SEND_LICENSE32 = _IOW(0xF2, 8, __s32), - DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS32 = _IOW(0xF2, 9, - compat_uptr_t), -}; -#endif - -#ifdef CONFIG_DTS_EAGLE -void msm_dts_ion_memmap(struct param_outband *po_); -int msm_dts_eagle_enable_asm(struct audio_client *ac, u32 enable, int module); -int msm_dts_eagle_enable_adm(int port_id, int copp_idx, u32 enable); -void msm_dts_eagle_add_controls(struct snd_soc_platform *platform); -int msm_dts_eagle_set_stream_gain(struct audio_client *ac, - int lgain, int rgain); -int msm_dts_eagle_handle_asm(struct dts_eagle_param_desc *depd, char *buf, - bool for_pre, bool get, struct audio_client *ac, - struct param_outband *po); -int msm_dts_eagle_handle_adm(struct dts_eagle_param_desc *depd, char *buf, - bool for_pre, bool get); -int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg); -int msm_dts_eagle_is_hpx_on(void); -int msm_dts_eagle_init_pre(struct audio_client *ac); -int msm_dts_eagle_deinit_pre(struct audio_client *ac); -int msm_dts_eagle_init_post(int port_id, int copp_id); -int msm_dts_eagle_deinit_post(int port_id, int topology); -int msm_dts_eagle_init_master_module(struct audio_client *ac); -int msm_dts_eagle_deinit_master_module(struct audio_client *ac); -int msm_dts_eagle_pcm_new(struct snd_soc_pcm_runtime *runtime); -void msm_dts_eagle_pcm_free(struct snd_pcm *pcm); -int msm_dts_eagle_compat_ioctl(unsigned int cmd, unsigned long arg); -#else -static inline void msm_dts_ion_memmap(struct param_outband *po_) -{ - pr_debug("%s\n", __func__); -} -static inline int msm_dts_eagle_enable_asm(struct audio_client *ac, - u32 enable, int module) -{ - return 0; -} -static inline int msm_dts_eagle_enable_adm(int port_id, int copp_idx, - u32 enable) -{ - return 0; -} -static inline void msm_dts_eagle_add_controls(struct snd_soc_platform *platform) -{ -} -static inline int msm_dts_eagle_set_stream_gain(struct audio_client *ac, - int lgain, int rgain) -{ - pr_debug("%s\n", __func__); - return 0; -} -static inline int msm_dts_eagle_handle_asm(struct dts_eagle_param_desc *depd, - char *buf, bool for_pre, bool get, - struct audio_client *ac, - struct param_outband *po) -{ - return 0; -} -static inline int msm_dts_eagle_handle_adm(struct dts_eagle_param_desc *depd, - char *buf, bool for_pre, bool get) -{ - return 0; -} -static inline int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) -{ - return -EPERM; -} -static inline int msm_dts_eagle_is_hpx_on(void) -{ - return 0; -} -static inline int msm_dts_eagle_init_pre(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_deinit_pre(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_init_post(int port_id, int coppid) -{ - return 0; -} -static inline int msm_dts_eagle_deinit_post(int port_id, int topology) -{ - return 0; -} -static inline int msm_dts_eagle_init_master_module(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_deinit_master_module(struct audio_client *ac) -{ - return 0; -} -static inline int msm_dts_eagle_pcm_new(struct snd_soc_pcm_runtime *runtime) -{ - pr_debug("%s\n", __func__); - return 0; -} -static inline void msm_dts_eagle_pcm_free(struct snd_pcm *pcm) -{ - pr_debug("%s\n", __func__); -} -static inline int msm_dts_eagle_compat_ioctl(unsigned int cmd, - unsigned long arg) -{ - return 0; -} -#endif - -#endif diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h index d3a4da8e456..19b6309e2c1 100644 --- a/include/sound/q6adm-v2.h +++ b/include/sound/q6adm-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -34,7 +34,6 @@ enum { ADM_AUDVOL_CAL, ADM_RTAC_INFO_CAL, ADM_RTAC_APR_CAL, - ADM_DTS_EAGLE, ADM_SRS_TRUMEDIA, ADM_MAX_CAL_TYPES }; diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 7d99c0b5b78..8e271438f77 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -729,6 +729,7 @@ struct se_port_stat_grps { struct se_lun { #define SE_LUN_LINK_MAGIC 0xffff7771 u32 lun_link_magic; + bool lun_shutdown; /* See transport_lun_status_table */ enum transport_lun_status_table lun_status; u32 lun_access; diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h index f60ebe918ff..fc512d01f77 100644 --- a/include/uapi/linux/android/binder.h +++ b/include/uapi/linux/android/binder.h @@ -131,6 +131,7 @@ enum { /* struct binder_fd_array_object - object describing an array of fds in a buffer * @hdr: common header structure + * @pad: padding to ensure correct alignment * @num_fds: number of file descriptors in the buffer * @parent: index in offset array to buffer holding the fd array * @parent_offset: start offset of fd array in the buffer @@ -151,6 +152,7 @@ enum { */ struct binder_fd_array_object { struct binder_object_header hdr; + __u32 pad; binder_size_t num_fds; binder_size_t parent; binder_size_t parent_offset; diff --git a/include/uapi/linux/fib_rules.h b/include/uapi/linux/fib_rules.h index 209abc4faf7..9dcdb6251cb 100644 --- a/include/uapi/linux/fib_rules.h +++ b/include/uapi/linux/fib_rules.h @@ -29,11 +29,6 @@ struct fib_rule_hdr { __u32 flags; }; -struct fib_rule_uid_range { - __u32 start; - __u32 end; -}; - enum { FRA_UNSPEC, FRA_DST, /* destination address */ @@ -54,9 +49,8 @@ enum { FRA_TABLE, /* Extended table id */ FRA_FWMASK, /* mask for netfilter mark */ FRA_OIFNAME, - FRA_PAD, - FRA_L3MDEV, /* iif or oif is l3mdev goto its table */ - FRA_UID_RANGE, /* UID range */ + FRA_UID_START, /* UID range */ + FRA_UID_END, __FRA_MAX }; diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index 99c4df8eb2e..b1a99e18b70 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -296,15 +296,8 @@ enum rtattr_type_t { RTA_MP_ALGO, /* no longer used */ RTA_TABLE, RTA_MARK, - RTA_MFC_STATS, - RTA_VIA, - RTA_NEWDST, - RTA_PREF, - RTA_ENCAP_TYPE, - RTA_ENCAP, - RTA_EXPIRES, - RTA_PAD, RTA_UID, + RTA_MFC_STATS, __RTA_MAX }; diff --git a/init/main.c b/init/main.c index c0f8b335f33..8e40280dc49 100644 --- a/init/main.c +++ b/init/main.c @@ -697,7 +697,7 @@ int __init_or_module do_one_initcall(initcall_t fn) if (preempt_count() != count) { sprintf(msgbuf, "preemption imbalance "); - preempt_count_set(count); + preempt_count() = count; } if (irqs_disabled()) { strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); diff --git a/kernel/audit.c b/kernel/audit.c index 8ec45552b21..4dd7529b084 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -373,7 +373,7 @@ static void audit_printk_skb(struct sk_buff *skb) if (nlh->nlmsg_type != AUDIT_EOE) { if (printk_ratelimit()) - pr_debug(KERN_NOTICE "type=%d %s\n", nlh->nlmsg_type, data); + printk(KERN_NOTICE "type=%d %s\n", nlh->nlmsg_type, data); else audit_log_lost("printk limit exceeded\n"); } @@ -690,7 +690,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (audit_enabled != AUDIT_OFF) audit_log_config_change("audit_pid", new_pid, audit_pid, 1); - audit_pid = 0; + audit_pid = new_pid; audit_nlk_portid = NETLINK_CB(skb).portid; } if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) { diff --git a/kernel/events/core.c b/kernel/events/core.c index a4987ae1680..bcac08f9079 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5483,6 +5483,9 @@ struct swevent_htable { /* Recursion avoidance in each contexts */ int recursion[PERF_NR_CONTEXTS]; + + /* Keeps track of cpu being initialized/exited */ + bool online; }; static DEFINE_PER_CPU(struct swevent_htable, swevent_htable); @@ -5729,8 +5732,14 @@ static int perf_swevent_add(struct perf_event *event, int flags) hwc->state = !(flags & PERF_EF_START); head = find_swevent_head(swhash, event); - if (WARN_ON_ONCE(!head)) + if (!head) { + /* + * We can race with cpu hotplug code. Do not + * WARN if the cpu just got unplugged. + */ + WARN_ON_ONCE(swhash->online); return -EINVAL; + } hlist_add_head_rcu(&event->hlist_entry, head); @@ -5802,6 +5811,7 @@ static int swevent_hlist_get_cpu(struct perf_event *event, int cpu) int err = 0; mutex_lock(&swhash->hlist_mutex); + if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) { struct swevent_hlist *hlist; @@ -6996,37 +7006,6 @@ static void mutex_lock_double(struct mutex *a, struct mutex *b) mutex_lock_nested(b, SINGLE_DEPTH_NESTING); } -/* - * Variation on perf_event_ctx_lock_nested(), except we take two context - * mutexes. - */ -static struct perf_event_context * -__perf_event_ctx_lock_double(struct perf_event *group_leader, - struct perf_event_context *ctx) -{ - struct perf_event_context *gctx; - -again: - rcu_read_lock(); - gctx = ACCESS_ONCE(group_leader->ctx); - if (!atomic_inc_not_zero(&gctx->refcount)) { - rcu_read_unlock(); - goto again; - } - rcu_read_unlock(); - - mutex_lock_double(&gctx->mutex, &ctx->mutex); - - if (group_leader->ctx != gctx) { - mutex_unlock(&ctx->mutex); - mutex_unlock(&gctx->mutex); - put_ctx(gctx); - goto again; - } - - return gctx; -} - /** * sys_perf_event_open - open a performance event, associate it to a task/cpu * @@ -7241,31 +7220,13 @@ SYSCALL_DEFINE5(perf_event_open, } if (move_group) { - gctx = __perf_event_ctx_lock_double(group_leader, ctx); - - /* - * Check if we raced against another sys_perf_event_open() call - * moving the software group underneath us. - */ - if (!(group_leader->group_flags & PERF_GROUP_SOFTWARE)) { - /* - * If someone moved the group out from under us, check - * if this new event wound up on the same ctx, if so - * its the regular !move_group case, otherwise fail. - */ - if (gctx != ctx) { - err = -EINVAL; - goto err_locked; - } else { - perf_event_ctx_unlock(group_leader, gctx); - move_group = 0; - } - } + gctx = group_leader->ctx; /* * See perf_event_ctx_lock() for comments on the details * of swizzling perf_event::ctx. */ + mutex_lock_double(&gctx->mutex, &ctx->mutex); mutex_lock(&gctx->mutex); perf_remove_from_context(group_leader, false); @@ -7308,7 +7269,7 @@ SYSCALL_DEFINE5(perf_event_open, perf_unpin_context(ctx); if (move_group) { - perf_event_ctx_unlock(group_leader, gctx); + mutex_unlock(&gctx->mutex); put_ctx(gctx); } mutex_unlock(&ctx->mutex); @@ -7339,11 +7300,6 @@ SYSCALL_DEFINE5(perf_event_open, fd_install(event_fd, event_file); return event_fd; -err_locked: - if (move_group) - perf_event_ctx_unlock(group_leader, gctx); - mutex_unlock(&ctx->mutex); - fput(event_file); err_context: perf_unpin_context(ctx); put_ctx(ctx); @@ -7957,6 +7913,7 @@ static void __cpuinit perf_event_init_cpu(int cpu) struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); mutex_lock(&swhash->hlist_mutex); + swhash->online = true; if (swhash->hlist_refcount > 0) { struct swevent_hlist *hlist; @@ -8057,6 +8014,13 @@ static void perf_event_start_swclock(int cpu) static void perf_event_exit_cpu(int cpu) { + struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); + + mutex_lock(&swhash->hlist_mutex); + swhash->online = false; + swevent_hlist_release(swhash); + mutex_unlock(&swhash->hlist_mutex); + perf_event_exit_cpu_context(cpu); } #else diff --git a/kernel/extable.c b/kernel/extable.c index 67460b93b1a..5ec4b6f861d 100644 --- a/kernel/extable.c +++ b/kernel/extable.c @@ -66,7 +66,7 @@ static inline int init_kernel_text(unsigned long addr) return 0; } -int core_kernel_text(unsigned long addr) +int notrace core_kernel_text(unsigned long addr) { if (addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index a9e5dc5f697..8069725ce90 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -12,7 +12,6 @@ #include <linux/seq_file.h> #include <linux/interrupt.h> #include <linux/kernel_stat.h> -#include <linux/mutex.h> #include "internals.h" @@ -349,29 +348,18 @@ void register_handler_proc(unsigned int irq, struct irqaction *action) void register_irq_proc(unsigned int irq, struct irq_desc *desc) { - static DEFINE_MUTEX(register_lock); char name [MAX_NAMELEN]; - if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip)) + if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip) || desc->dir) return; - /* - * irq directories are registered only when a handler is - * added, not when the descriptor is created, so multiple - * tasks might try to register at the same time. - */ - mutex_lock(®ister_lock); - - if (desc->dir) - goto out_unlock; - memset(name, 0, MAX_NAMELEN); sprintf(name, "%d", irq); /* create /proc/irq/1234 */ desc->dir = proc_mkdir(name, root_irq_dir); if (!desc->dir) - goto out_unlock; + return; #ifdef CONFIG_SMP /* create /proc/irq/<irq>/smp_affinity */ @@ -396,9 +384,6 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc) &irq_disable_depth_proc_fops, (void *)(long)irq); proc_create_data("wake_depth", 0444, desc->dir, &irq_wake_depth_proc_fops, (void *)(long)irq); - -out_unlock: - mutex_unlock(®ister_lock); } void unregister_irq_proc(unsigned int irq, struct irq_desc *desc) diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 15c2dffc1d2..079d567361f 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -270,26 +270,6 @@ config PM_GENERIC_DOMAINS bool depends on PM -config WQ_POWER_EFFICIENT_DEFAULT - bool "Enable workqueue power-efficient mode by default" - depends on PM - default n - help - Per-cpu workqueues are generally preferred because they show - better performance thanks to cache locality; unfortunately, - per-cpu workqueues tend to be more power hungry than unbound - workqueues. - - Enabling workqueue.power_efficient kernel parameter makes the - per-cpu workqueues which were observed to contribute - significantly to power consumption unbound, leading to measurably - lower power usage at the cost of small performance overhead. - - This config option determines whether workqueue.power_efficient - is enabled by default. - - If in doubt, say N. - config PM_GENERIC_DOMAINS_SLEEP def_bool y depends on PM_SLEEP && PM_GENERIC_DOMAINS diff --git a/kernel/rcu/srcu.c b/kernel/rcu/srcu.c index 27b654950cc..01d5ccb8bfe 100644 --- a/kernel/rcu/srcu.c +++ b/kernel/rcu/srcu.c @@ -375,7 +375,7 @@ void call_srcu(struct srcu_struct *sp, struct rcu_head *head, rcu_batch_queue(&sp->batch_queue, head); if (!sp->running) { sp->running = true; - queue_delayed_work(system_power_efficient_wq, &sp->work, 0); + schedule_delayed_work(&sp->work, 0); } spin_unlock_irqrestore(&sp->queue_lock, flags); } @@ -631,8 +631,7 @@ static void srcu_reschedule(struct srcu_struct *sp) } if (pending) - queue_delayed_work(system_power_efficient_wq, - &sp->work, SRCU_INTERVAL); + schedule_delayed_work(&sp->work, SRCU_INTERVAL); } /* diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 19b8eea17ee..02da4984395 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -566,39 +566,6 @@ static inline void init_hrtick(void) #endif /* CONFIG_SCHED_HRTICK */ /* - * cmpxchg based fetch_or, macro so it works for different integer types - */ -#define fetch_or(ptr, val) \ -({ typeof(*(ptr)) __old, __val = *(ptr); \ - for (;;) { \ - __old = cmpxchg((ptr), __val, __val | (val)); \ - if (__old == __val) \ - break; \ - __val = __old; \ - } \ - __old; \ -}) - -#ifdef TIF_POLLING_NRFLAG -/* - * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG, - * this avoids any races wrt polling state changes and thereby avoids - * spurious IPIs. - */ -static bool set_nr_and_not_polling(struct task_struct *p) -{ - struct thread_info *ti = task_thread_info(p); - return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG); -} -#else -static bool set_nr_and_not_polling(struct task_struct *p) -{ - set_tsk_need_resched(p); - return true; -} -#endif - -/* * resched_task - mark a task 'to be rescheduled now'. * * On UP this means the setting of the need_resched flag, on SMP it @@ -615,14 +582,15 @@ void resched_task(struct task_struct *p) if (test_tsk_need_resched(p)) return; - cpu = task_cpu(p); + set_tsk_need_resched(p); - if (cpu == smp_processor_id()) { - set_tsk_need_resched(p); + cpu = task_cpu(p); + if (cpu == smp_processor_id()) return; - } - if (set_nr_and_not_polling(p)) + /* NEED_RESCHED must be visible before we test polling */ + smp_mb(); + if (!tsk_is_polling(p)) smp_send_reschedule(cpu); } @@ -3793,25 +3761,6 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) smp_rmb(); /* - * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be - * possible to, falsely, observe p->on_cpu == 0. - * - * One must be running (->on_cpu == 1) in order to remove oneself - * from the runqueue. - * - * [S] ->on_cpu = 1; [L] ->on_rq - * UNLOCK rq->lock - * RMB - * LOCK rq->lock - * [S] ->on_rq = 0; [L] ->on_cpu - * - * Pairs with the full barrier implied in the UNLOCK+LOCK on rq->lock - * from the consecutive calls to schedule(); the first switching to our - * task, the second putting it to sleep. - */ - smp_rmb(); - - /* * If the owning (remote) cpu is still in the middle of schedule() with * this task as prev, wait until its done referencing the task. */ @@ -4701,13 +4650,10 @@ static long calc_load_fold_active(struct rq *this_rq) static unsigned long calc_load(unsigned long load, unsigned long exp, unsigned long active) { - unsigned long newload; - - newload = load * exp + active * (FIXED_1 - exp); - if (active >= load) - newload += FIXED_1-1; - - return newload / FIXED_1; + load *= exp; + load += active * (FIXED_1 - exp); + load += 1UL << (FSHIFT - 1); + return load >> FSHIFT; } #ifdef CONFIG_NO_HZ_COMMON @@ -5260,20 +5206,6 @@ unsigned long long task_sched_runtime(struct task_struct *p) struct rq *rq; u64 ns = 0; -#if defined(CONFIG_64BIT) && defined(CONFIG_SMP) - /* - * 64-bit doesn't need locks to atomically read a 64bit value. - * So we have a optimization chance when the task's delta_exec is 0. - * Reading ->on_cpu is racy, but this is ok. - * - * If we race with it leaving cpu, we'll take a lock. So we're correct. - * If we race with it entering cpu, unaccounted time is 0. This is - * indistinguishable from the read occurring a few cycles earlier. - */ - if (!p->on_cpu) - return p->se.sum_exec_runtime; -#endif - rq = task_rq_lock(p, &flags); ns = p->se.sum_exec_runtime + do_task_delta_exec(p, rq); task_rq_unlock(rq, p, &flags); @@ -5368,7 +5300,7 @@ void __kprobes add_preempt_count(int val) if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0))) return; #endif - add_preempt_count_notrace(val); + preempt_count() += val; #ifdef CONFIG_DEBUG_PREEMPT /* * Spinlock count overflowing soon? @@ -5399,7 +5331,7 @@ void __kprobes sub_preempt_count(int val) if (preempt_count() == val) trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); - sub_preempt_count_notrace(val); + preempt_count() -= val; } EXPORT_SYMBOL(sub_preempt_count); @@ -6462,8 +6394,6 @@ static void __setscheduler(struct rq *rq, struct task_struct *p, if (policy == -1) /* setparam */ policy = p->policy; - else - policy &= ~SCHED_RESET_ON_FORK; p->policy = policy; @@ -6757,13 +6687,8 @@ change: if (running) p->sched_class->set_curr_task(rq); - if (on_rq) { - /* - * We enqueue to tail when the priority of a task is - * increased (user space view). - */ - enqueue_task(rq, p, oldprio <= p->prio ? ENQUEUE_HEAD : 0); - } + if (on_rq) + enqueue_task(rq, p, 0); check_class_changed(rq, p, prev_class, oldprio); task_rq_unlock(rq, p, &flags); @@ -7700,7 +7625,7 @@ void show_state_filter(unsigned long state_filter) " task PC stack pid father\n"); #endif rcu_read_lock(); - for_each_process_thread(g, p) { + do_each_thread(g, p) { /* * reset the NMI-timeout, listing all files on a slow * console might take a lot of time: @@ -7708,7 +7633,7 @@ void show_state_filter(unsigned long state_filter) touch_nmi_watchdog(); if (!state_filter || (p->state & state_filter)) sched_show_task(p); - } + } while_each_thread(g, p); touch_all_softlockup_watchdogs(); @@ -10290,7 +10215,7 @@ void normalize_rt_tasks(void) struct rq *rq; read_lock_irqsave(&tasklist_lock, flags); - for_each_process_thread(g, p) { + do_each_thread(g, p) { /* * Only normalize user tasks: */ @@ -10321,7 +10246,8 @@ void normalize_rt_tasks(void) __task_rq_unlock(rq); raw_spin_unlock(&p->pi_lock); - } + } while_each_thread(g, p); + read_unlock_irqrestore(&tasklist_lock, flags); } @@ -10507,10 +10433,10 @@ static inline int tg_has_rt_tasks(struct task_group *tg) { struct task_struct *g, *p; - for_each_process_thread(g, p) { + do_each_thread(g, p) { if (rt_task(p) && task_rq(p)->rt.tg == tg) return 1; - } + } while_each_thread(g, p); return 0; } diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index e62356250b1..135e7793350 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c @@ -160,8 +160,10 @@ void account_user_time(struct task_struct *p, cputime_t cputime, /* Account for user time used */ acct_account_cputime(p); +#ifdef CONFIG_CPU_FREQ_STAT /* Account power usage for user time */ acct_update_power(p, cputime); +#endif } /* @@ -213,8 +215,10 @@ void __account_system_time(struct task_struct *p, cputime_t cputime, /* Account for system time used */ acct_account_cputime(p); +#ifdef CONFIG_CPU_FREQ_STAT /* Account power usage for system time */ acct_update_power(p, cputime); +#endif } /* diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 8f3693aec2c..7347861b2de 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5544,10 +5544,6 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu) int idlest = -1; int i; - /* Check if we have any choice: */ - if (group->group_weight == 1) - return cpumask_first(sched_group_cpus(group)); - /* Traverse only the allowed CPUs */ for_each_cpu_and(i, sched_group_cpus(group), tsk_cpus_allowed(p)) { load = weighted_cpuload(i); @@ -7902,6 +7898,7 @@ void idle_balance(int this_cpu, struct rq *this_rq) continue; if (sd->flags & SD_BALANCE_NEWIDLE) { + /* If we've pulled tasks over stop searching: */ pulled_task = load_balance(balance_cpu, balance_rq, sd, CPU_NEWLY_IDLE, &balance); } @@ -7909,11 +7906,7 @@ void idle_balance(int this_cpu, struct rq *this_rq) interval = msecs_to_jiffies(sd->balance_interval); if (time_after(next_balance, sd->last_balance + interval)) next_balance = sd->last_balance + interval; - /* - * Stop searching for tasks to pull if there are - * now runnable tasks on this rq. - */ - if (pulled_task || this_rq->nr_running > 0) { + if (pulled_task) { balance_rq->idle_stamp = 0; break; } diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c index 6698e0c04ea..bca170ef386 100644 --- a/kernel/sched/wait.c +++ b/kernel/sched/wait.c @@ -287,3 +287,12 @@ wait_queue_head_t *bit_waitqueue(void *word, int bit) return &zone->wait_table[hash_long(val, zone->wait_table_bits)]; } EXPORT_SYMBOL(bit_waitqueue); + +__sched int bit_wait_io(void *word) +{ + if (signal_pending_state(current->state, current)) + return 1; + io_schedule(); + return 0; +} +EXPORT_SYMBOL(bit_wait_io); diff --git a/kernel/softirq.c b/kernel/softirq.c index 3c7b56ecf23..96a4c2828ce 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -104,7 +104,7 @@ static void __local_bh_disable(unsigned long ip, unsigned int cnt) * We must manually increment preempt_count here and manually * call the trace_preempt_off later. */ - add_preempt_count_notrace(cnt); + preempt_count() += cnt; /* * Were softirqs turned off above: */ @@ -256,7 +256,7 @@ restart: " exited with %08x?\n", vec_nr, softirq_to_name[vec_nr], h->action, prev_count, preempt_count()); - preempt_count_set(prev_count); + preempt_count() = prev_count; } rcu_bh_qs(cpu); diff --git a/kernel/sys.c b/kernel/sys.c index 60eb8d9dee4..1e63f33beb5 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -2405,6 +2405,26 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, else return -EINVAL; break; + case PR_SET_TIMERSLACK_PID: + if (current->pid != (pid_t)arg3 && + !capable(CAP_SYS_NICE)) + return -EPERM; + rcu_read_lock(); + tsk = find_task_by_pid_ns((pid_t)arg3, &init_pid_ns); + if (tsk == NULL) { + rcu_read_unlock(); + return -EINVAL; + } + get_task_struct(tsk); + rcu_read_unlock(); + if (arg2 <= 0) + tsk->timer_slack_ns = + tsk->default_timer_slack_ns; + else + tsk->timer_slack_ns = arg2; + put_task_struct(tsk); + error = 0; + break; default: return -EINVAL; } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 555616d7a8d..ceb9091d73d 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -129,7 +129,6 @@ static int zero; static int __maybe_unused one = 1; static int __maybe_unused two = 2; static int __maybe_unused three = 3; -static int __maybe_unused four = 4; static unsigned long one_ul = 1; static int one_hundred = 100; #ifdef CONFIG_PRINTK @@ -1019,7 +1018,7 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = proc_dointvec_minmax_sysadmin, .extra1 = &zero, - .extra2 = &four, + .extra2 = &two, }, #endif { diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 105d5d409b7..6211d5d6d46 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -514,13 +514,12 @@ static void sync_cmos_clock(struct work_struct *work) next.tv_sec++; next.tv_nsec -= NSEC_PER_SEC; } - queue_delayed_work(system_power_efficient_wq, - &sync_cmos_work, timespec_to_jiffies(&next)); + schedule_delayed_work(&sync_cmos_work, timespec_to_jiffies(&next)); } void ntp_notify_cmos_timer(void) { - queue_delayed_work(system_power_efficient_wq, &sync_cmos_work, 0); + schedule_delayed_work(&sync_cmos_work, 0); } #else diff --git a/kernel/timer.c b/kernel/timer.c index 87731456d8a..09b86498428 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1150,7 +1150,7 @@ static int cascade(struct tvec_base *base, struct tvec *tv, int index) static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long), unsigned long data) { - int count = preempt_count(); + int preempt_count = preempt_count(); #ifdef CONFIG_LOCKDEP /* @@ -1177,16 +1177,16 @@ static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long), lock_map_release(&lockdep_map); - if (count != preempt_count()) { + if (preempt_count != preempt_count()) { WARN_ONCE(1, "timer: %pF preempt leak: %08x -> %08x\n", - fn, count, preempt_count()); + fn, preempt_count, preempt_count()); /* * Restore the preempt count. That gives us a decent * chance to survive and extract information. If the * callback kept a lock held, bad luck, but not worse * than the BUG() we had. */ - preempt_count_set(count); + preempt_count() = preempt_count; } } diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index a0ed8b55354..18d8047c595 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3068,11 +3068,17 @@ static int tracing_open(struct inode *inode, struct file *file) /* If this file was open for write, then erase contents */ if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { int cpu = tracing_get_cpu(inode); + struct trace_buffer *trace_buf = &tr->trace_buffer; + +#ifdef CONFIG_TRACER_MAX_TRACE + if (tr->current_trace->print_max) + trace_buf = &tr->max_buffer; +#endif if (cpu == RING_BUFFER_ALL_CPUS) - tracing_reset_online_cpus(&tr->trace_buffer); + tracing_reset_online_cpus(trace_buf); else - tracing_reset(&tr->trace_buffer, cpu); + tracing_reset(trace_buf, cpu); } if (file->f_mode & FMODE_READ) { @@ -4664,7 +4670,7 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf, tracing_reset_online_cpus(&tr->trace_buffer); #ifdef CONFIG_TRACER_MAX_TRACE - if (tr->flags & TRACE_ARRAY_FL_GLOBAL && tr->max_buffer.buffer) + if (tr->max_buffer.buffer) ring_buffer_set_clock(tr->max_buffer.buffer, trace_clocks[i].func); tracing_reset_online_cpus(&tr->max_buffer); #endif diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index 7be4d67cecb..3f4ff304a70 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -277,10 +277,7 @@ static int t_show(struct seq_file *m, void *v) const char *str = *fmt; int i; - if (!*fmt) - return 0; - - seq_printf(m, "0x%lx : \"", *(unsigned long *)fmt); + seq_printf(m, "0x%lx : \"", 0L); /* * Tabs and new lines need to be converted. diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 4bd68353f49..dd1a51dc358 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -273,15 +273,6 @@ static cpumask_var_t *wq_numa_possible_cpumask; static bool wq_disable_numa; module_param_named(disable_numa, wq_disable_numa, bool, 0444); -/* see the comment above the definition of WQ_POWER_EFFICIENT */ -#ifdef CONFIG_WQ_POWER_EFFICIENT_DEFAULT -static bool wq_power_efficient = true; -#else -static bool wq_power_efficient; -#endif - -module_param_named(power_efficient, wq_power_efficient, bool, 0444); - static bool wq_numa_enabled; /* unbound NUMA affinity enabled */ /* buf for wq_update_unbound_numa_attrs(), protected by CPU hotplug exclusion */ @@ -318,10 +309,6 @@ struct workqueue_struct *system_unbound_wq __read_mostly; EXPORT_SYMBOL_GPL(system_unbound_wq); struct workqueue_struct *system_freezable_wq __read_mostly; EXPORT_SYMBOL_GPL(system_freezable_wq); -struct workqueue_struct *system_power_efficient_wq __read_mostly; -EXPORT_SYMBOL_GPL(system_power_efficient_wq); -struct workqueue_struct *system_freezable_power_efficient_wq __read_mostly; -EXPORT_SYMBOL_GPL(system_freezable_power_efficient_wq); static int worker_thread(void *__worker); static void copy_workqueue_attrs(struct workqueue_attrs *to, @@ -3414,7 +3401,7 @@ int workqueue_sysfs_register(struct workqueue_struct *wq) * attributes breaks ordering guarantee. Disallow exposing ordered * workqueues. */ - if (WARN_ON(wq->flags & __WQ_ORDERED)) + if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) return -EINVAL; wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL); @@ -3979,8 +3966,12 @@ int apply_workqueue_attrs(struct workqueue_struct *wq, return -EINVAL; /* creating multiple pwqs breaks ordering guarantee */ - if (WARN_ON((wq->flags & __WQ_ORDERED) && !list_empty(&wq->pwqs))) - return -EINVAL; + if (!list_empty(&wq->pwqs)) { + if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) + return -EINVAL; + + wq->flags &= ~__WQ_ORDERED; + } pwq_tbl = kzalloc(wq_numa_tbl_len * sizeof(pwq_tbl[0]), GFP_KERNEL); new_attrs = alloc_workqueue_attrs(GFP_KERNEL); @@ -4228,9 +4219,15 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, struct workqueue_struct *wq; struct pool_workqueue *pwq; - /* see the comment above the definition of WQ_POWER_EFFICIENT */ - if ((flags & WQ_POWER_EFFICIENT) && wq_power_efficient) - flags |= WQ_UNBOUND; + /* + * Unbound && max_active == 1 used to imply ordered, which is no + * longer the case on NUMA machines due to per-node pools. While + * alloc_ordered_workqueue() is the right way to create an ordered + * workqueue, keep the previous behavior to avoid subtle breakages + * on NUMA. + */ + if ((flags & WQ_UNBOUND) && max_active == 1) + flags |= __WQ_ORDERED; /* allocate wq and format name */ if (flags & WQ_UNBOUND) @@ -4420,13 +4417,14 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active) struct pool_workqueue *pwq; /* disallow meddling with max_active for ordered workqueues */ - if (WARN_ON(wq->flags & __WQ_ORDERED)) + if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) return; max_active = wq_clamp_max_active(max_active, wq->flags, wq->name); mutex_lock(&wq->mutex); + wq->flags &= ~__WQ_ORDERED; wq->saved_max_active = max_active; for_each_pwq(pwq, wq) @@ -5141,15 +5139,8 @@ static int __init init_workqueues(void) WQ_UNBOUND_MAX_ACTIVE); system_freezable_wq = alloc_workqueue("events_freezable", WQ_FREEZABLE, 0); - system_power_efficient_wq = alloc_workqueue("events_power_efficient", - WQ_POWER_EFFICIENT, 0); - system_freezable_power_efficient_wq = alloc_workqueue("events_freezable_power_efficient", - WQ_FREEZABLE | WQ_POWER_EFFICIENT, - 0); BUG_ON(!system_wq || !system_highpri_wq || !system_long_wq || - !system_unbound_wq || !system_freezable_wq || - !system_power_efficient_wq || - !system_freezable_power_efficient_wq); + !system_unbound_wq || !system_freezable_wq); return 0; } early_initcall(init_workqueues); diff --git a/lib/cmdline.c b/lib/cmdline.c index eb6791188cf..efc35fbce78 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c @@ -22,14 +22,14 @@ * the values[M, M+1, ..., N] into the ints array in get_options. */ -static int get_range(char **str, int *pint) +static int get_range(char **str, int *pint, int n) { int x, inc_counter, upper_range; (*str)++; upper_range = simple_strtol((*str), NULL, 0); inc_counter = upper_range - *pint; - for (x = *pint; x < upper_range; x++) + for (x = *pint; n && x < upper_range; x++, n--) *pint++ = x; return inc_counter; } @@ -95,7 +95,7 @@ char *get_options(const char *str, int nints, int *ints) break; if (res == 3) { int range_nums; - range_nums = get_range((char **)&str, ints + i); + range_nums = get_range((char **)&str, ints + i, nints - i); if (range_nums < 0) break; /* diff --git a/lib/digsig.c b/lib/digsig.c index 2f31e6a45f0..ae703dfc973 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -86,6 +86,12 @@ static int digsig_verify_rsa(struct key *key, down_read(&key->sem); ukp = key->payload.data; + if (!ukp) { + /* key was revoked before we acquired its semaphore */ + err = -EKEYREVOKED; + goto err1; + } + if (ukp->datalen < sizeof(*pkh)) goto err1; diff --git a/lib/int_sqrt.c b/lib/int_sqrt.c index 3d7a3e0237c..1ef4cc34497 100644 --- a/lib/int_sqrt.c +++ b/lib/int_sqrt.c @@ -14,34 +14,25 @@ * * A very rough approximation to the sqrt() function. */ -inline unsigned long int_sqrt(unsigned long x) +unsigned long int_sqrt(unsigned long x) { - register unsigned long tmp; - register unsigned long place; - register unsigned long root = 0; + unsigned long b, m, y = 0; if (x <= 1) return x; - place = 1UL << (BITS_PER_LONG - 2); + m = 1UL << (BITS_PER_LONG - 2); + while (m != 0) { + b = y + m; + y >>= 1; - do{ - place >>= 2; - }while(place > x); - - do { - tmp = root + place; - root >>= 1; - - if (x >= tmp) - { - x -= tmp; - root += place; + if (x >= b) { + x -= b; + y += m; } - place >>= 2; - }while (place != 0); + m >>= 2; + } - return root; + return y; } EXPORT_SYMBOL(int_sqrt); - diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c index 51b88ec0fe7..c3eb261a7df 100644 --- a/lib/locking-selftest.c +++ b/lib/locking-selftest.c @@ -979,7 +979,7 @@ static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask) * Some tests (e.g. double-unlock) might corrupt the preemption * count, so restore it: */ - preempt_count_set(saved_preempt_count); + preempt_count() = saved_preempt_count; #ifdef CONFIG_TRACE_IRQFLAGS if (softirq_count()) current->softirqs_enabled = 0; diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c index 6324d6d6d86..b16db3b9e62 100644 --- a/lib/lz4/lz4_decompress.c +++ b/lib/lz4/lz4_decompress.c @@ -47,6 +47,11 @@ #include "lz4defs.h" +static const int dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0}; +#if LZ4_ARCH64 +static const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3}; +#endif + static int lz4_uncompress(const char *source, char *dest, int osize) { const BYTE *ip = (const BYTE *) source; @@ -56,10 +61,6 @@ static int lz4_uncompress(const char *source, char *dest, int osize) BYTE *cpy; unsigned token; size_t length; - size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0}; -#if LZ4_ARCH64 - size_t dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3}; -#endif while (1) { @@ -116,7 +117,7 @@ static int lz4_uncompress(const char *source, char *dest, int osize) /* copy repeated sequence */ if (unlikely((op - ref) < STEPSIZE)) { #if LZ4_ARCH64 - size_t dec64 = dec64table[op - ref]; + int dec64 = dec64table[op - ref]; #else const int dec64 = 0; #endif @@ -139,6 +140,13 @@ static int lz4_uncompress(const char *source, char *dest, int osize) /* Error: request to write beyond destination buffer */ if (cpy > oend) goto _output_error; +#if LZ4_ARCH64 + if ((ref + COPYLENGTH) > oend) +#else + if ((ref + COPYLENGTH) > oend || + (op + COPYLENGTH) > oend) +#endif + goto _output_error; LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); while (op < cpy) *op++ = *ref++; @@ -174,11 +182,6 @@ static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, BYTE * const oend = op + maxoutputsize; BYTE *cpy; - size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0}; -#if LZ4_ARCH64 - size_t dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3}; -#endif - /* Main Loop */ while (ip < iend) { @@ -192,6 +195,8 @@ static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, int s = 255; while ((ip < iend) && (s == 255)) { s = *ip++; + if (unlikely(length > (size_t)(length + s))) + goto _output_error; length += s; } } @@ -232,6 +237,8 @@ static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, if (length == ML_MASK) { while (ip < iend) { int s = *ip++; + if (unlikely(length > (size_t)(length + s))) + goto _output_error; length += s; if (s == 255) continue; @@ -242,7 +249,7 @@ static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, /* copy repeated sequence */ if (unlikely((op - ref) < STEPSIZE)) { #if LZ4_ARCH64 - size_t dec64 = dec64table[op - ref]; + int dec64 = dec64table[op - ref]; #else const int dec64 = 0; #endif @@ -263,7 +270,13 @@ static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, if (cpy > oend - COPYLENGTH) { if (cpy > oend) goto _output_error; /* write outside of buf */ - +#if LZ4_ARCH64 + if ((ref + COPYLENGTH) > oend) +#else + if ((ref + COPYLENGTH) > oend || + (op + COPYLENGTH) > oend) +#endif + goto _output_error; LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); while (op < cpy) *op++ = *ref++; @@ -284,7 +297,7 @@ static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, /* write overflow error detected */ _output_error: - return (int) (-(((char *) ip) - source)); + return -1; } int lz4_decompress(const unsigned char *src, size_t *src_len, diff --git a/lib/lz4/lz4defs.h b/lib/lz4/lz4defs.h index abcecdc2d0f..697e08287e4 100644 --- a/lib/lz4/lz4defs.h +++ b/lib/lz4/lz4defs.h @@ -11,8 +11,7 @@ /* * Detects 64 bits mode */ -#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) \ - || defined(__ppc64__) || defined(__LP64__)) +#if defined(CONFIG_64BIT) #define LZ4_ARCH64 1 #else #define LZ4_ARCH64 0 @@ -21,13 +20,12 @@ /* * Architecture-specific macros */ +#define ARM_EFFICIENT_UNALIGNED_ACCESS #define BYTE u8 typedef struct _U16_S { u16 v; } U16_S; typedef struct _U32_S { u32 v; } U32_S; typedef struct _U64_S { u64 v; } U64_S; -#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) \ - || defined(CONFIG_ARM) && __LINUX_ARM_ARCH__ >= 6 \ - && defined(ARM_EFFICIENT_UNALIGNED_ACCESS) +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) #define A16(x) (((U16_S *)(x))->v) #define A32(x) (((U32_S *)(x))->v) @@ -35,6 +33,10 @@ typedef struct _U64_S { u64 v; } U64_S; #define PUT4(s, d) (A32(d) = A32(s)) #define PUT8(s, d) (A64(d) = A64(s)) + +#define LZ4_READ_LITTLEENDIAN_16(d, s, p) \ + (d = s - A16(p)) + #define LZ4_WRITE_LITTLEENDIAN_16(p, v) \ do { \ A16(p) = v; \ @@ -51,10 +53,13 @@ typedef struct _U64_S { u64 v; } U64_S; #define PUT8(s, d) \ put_unaligned(get_unaligned((const u64 *) s), (u64 *) d) -#define LZ4_WRITE_LITTLEENDIAN_16(p, v) \ - do { \ - put_unaligned(v, (u16 *)(p)); \ - p += 2; \ +#define LZ4_READ_LITTLEENDIAN_16(d, s, p) \ + (d = s - get_unaligned_le16(p)) + +#define LZ4_WRITE_LITTLEENDIAN_16(p, v) \ + do { \ + put_unaligned_le16(v, (u16 *)(p)); \ + p += 2; \ } while (0) #endif @@ -140,9 +145,6 @@ typedef struct _U64_S { u64 v; } U64_S; #endif -#define LZ4_READ_LITTLEENDIAN_16(d, s, p) \ - (d = s - get_unaligned_le16(p)) - #define LZ4_WILDCOPY(s, d, e) \ do { \ LZ4_COPYPACKET(s, d); \ diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c index 04abe53f12a..4c0d0e51d49 100644 --- a/lib/smp_processor_id.c +++ b/lib/smp_processor_id.c @@ -9,9 +9,10 @@ notrace unsigned int debug_smp_processor_id(void) { + unsigned long preempt_count = preempt_count(); int this_cpu = raw_smp_processor_id(); - if (likely(preempt_count())) + if (likely(preempt_count)) goto out; if (irqs_disabled()) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 7f5a08b99f4..378445329a7 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -377,32 +377,6 @@ struct printf_spec { s16 precision; /* # of digits/chars */ }; -int kptr_restrict __read_mostly = 4; - -/* - * Always cleanse %p and %pK specifiers - */ -static inline int kptr_restrict_always_cleanse_pointers(void) -{ - return kptr_restrict >= 3; -} - -/* - * Always cleanse physical addresses (%pa* specifiers) - */ -static inline int kptr_restrict_cleanse_addresses(void) -{ - return kptr_restrict >= 4; -} - -/* - * Always cleanse resource addresses (%p[rR] specifiers) - */ -static inline int kptr_restrict_cleanse_resources(void) -{ - return kptr_restrict >= 4; -} - static noinline_for_stack char *number(char *buf, char *end, unsigned long long num, struct printf_spec spec) @@ -646,7 +620,6 @@ char *resource_string(char *buf, char *end, struct resource *res, char *p = sym, *pend = sym + sizeof(sym); int decode = (fmt[0] == 'R') ? 1 : 0; - int cleanse = kptr_restrict_cleanse_resources(); const struct printf_spec *specp; *p++ = '['; @@ -670,11 +643,10 @@ char *resource_string(char *buf, char *end, struct resource *res, specp = &mem_spec; decode = 0; } - p = number(p, pend, cleanse ? 0UL : res->start, *specp); + p = number(p, pend, res->start, *specp); if (res->start != res->end) { *p++ = '-'; - p = number(p, pend, - cleanse ? res->end - res->start : res->end, *specp); + p = number(p, pend, res->end, *specp); } if (decode) { if (res->flags & IORESOURCE_MEM_64) @@ -693,7 +665,6 @@ char *resource_string(char *buf, char *end, struct resource *res, *p = '\0'; return string(buf, end, sym, spec); - } static noinline_for_stack @@ -1011,6 +982,8 @@ char *netdev_feature_string(char *buf, char *end, const u8 *addr, return number(buf, end, *(const netdev_features_t *)addr, spec); } +int kptr_restrict __read_mostly; + /* * Show a '%p' thing. A kernel extension is that the '%p' is followed * by an extra set of alphanumeric characters that are extended format @@ -1058,7 +1031,6 @@ char *netdev_feature_string(char *buf, char *end, const u8 *addr, * Do not use this feature without some mechanism to verify the * correctness of the format string and va_list arguments. * - 'K' For a kernel pointer that should be hidden from unprivileged users - * - 'P' For a kernel pointer that should be shown to all users * - 'NF' For a netdev_features_t * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with * a certain separator (' ' by default): @@ -1072,15 +1044,6 @@ char *netdev_feature_string(char *buf, char *end, const u8 *addr, * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 * function pointers are really function descriptors, which contain a * pointer to the real address. - * - * Note: That for kptr_restrict set to 3, %p and %pK have the same - * meaning. - * - * Note: That for kptr_restrict set to 4, %pa will null out the physical - * address. - * - * Note: That for kptr_restrict set to 4, %p[rR] will null out the memory - * address. */ static noinline_for_stack char *pointer(const char *fmt, char *buf, char *end, void *ptr, @@ -1088,7 +1051,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, { int default_width = 2 * sizeof(void *) + (spec.flags & SPECIAL ? 2 : 0); - if (!ptr && *fmt != 'K' && !kptr_restrict_always_cleanse_pointers()) { + if (!ptr && *fmt != 'K') { /* * Print (null) with the same width as a pointer so it makes * tabular output look nice. @@ -1145,79 +1108,60 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, va_end(va); return buf; } - case 'N': - switch (fmt[1]) { - case 'F': - return netdev_feature_string(buf, end, ptr, spec); - } - break; - case 'a': - { - unsigned long long addr = *((phys_addr_t *)ptr); - spec.flags |= SPECIAL | SMALL | ZEROPAD; - spec.field_width = sizeof(phys_addr_t) * 2 + 2; - spec.base = 16; - return number(buf, end, - kptr_restrict_cleanse_addresses() ? 0UL : addr, - spec); - } - case 'P': - /* - * an explicitly whitelisted kernel pointer should never be - * cleansed - */ - break; - default: + case 'K': /* - * plain %p, no extension, check if we should always cleanse and - * treat like %pK. + * %pK cannot be used in IRQ context because its test + * for CAP_SYSLOG would be meaningless. */ - if (!kptr_restrict_always_cleanse_pointers()) { - break; + if (kptr_restrict && (in_irq() || in_serving_softirq() || + in_nmi())) { + if (spec.field_width == -1) + spec.field_width = default_width; + return string(buf, end, "pK-error", spec); } - /* fallthrough */ - case 'K': + switch (kptr_restrict) { case 0: - /* Always print %p values */ + /* Always print %pK values */ break; case 1: { - const struct cred *cred; - - /* - * kptr_restrict==1 cannot be used in IRQ context - * because its test for CAP_SYSLOG would be meaningless. - */ - if (in_irq() || in_serving_softirq() || in_nmi()) { - if (spec.field_width == -1) - spec.field_width = default_width; - return string(buf, end, "pK-error", spec); - } + /* + * Only print the real pointer value if the current + * process has CAP_SYSLOG and is running with the + * same credentials it started with. This is because + * access to files is checked at open() time, but %pK + * checks permission at read() time. We don't want to + * leak pointer values if a binary opens a file using + * %pK and then elevates privileges before reading it. + */ + const struct cred *cred = current_cred(); - /* - * Only print the real pointer value if the current - * process has CAP_SYSLOG and is running with the - * same credentials it started with. This is because - * access to files is checked at open() time, but %p - * checks permission at read() time. We don't want to - * leak pointer values if a binary opens a file using - * %pK and then elevates privileges before reading it. - */ - cred = current_cred(); - if (!has_capability_noaudit(current, CAP_SYSLOG) || - !uid_eq(cred->euid, cred->uid) || - !gid_eq(cred->egid, cred->gid)) - ptr = NULL; - break; - } - case 2: /* restrict only %pK */ - case 3: /* restrict all non-extensioned %p and %pK */ - case 4: /* restrict all non-extensioned %p, %pK, %pa*, %p[rR] */ + if (!has_capability_noaudit(current, CAP_SYSLOG) || + !uid_eq(cred->euid, cred->uid) || + !gid_eq(cred->egid, cred->gid)) + ptr = NULL; + break; + } + case 2: default: + /* Always print 0's for %pK */ ptr = NULL; break; } break; + + case 'N': + switch (fmt[1]) { + case 'F': + return netdev_feature_string(buf, end, ptr, spec); + } + break; + case 'a': + spec.flags |= SPECIAL | SMALL | ZEROPAD; + spec.field_width = sizeof(phys_addr_t) * 2 + 2; + spec.base = 16; + return number(buf, end, + (unsigned long long) *((phys_addr_t *)ptr), spec); } spec.flags |= SMALL; if (spec.field_width == -1) { @@ -1226,7 +1170,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, } spec.base = 16; - return number(buf, end, (unsigned long long) ptr, spec); + return number(buf, end, (unsigned long) ptr, spec); } /* diff --git a/mm/Kconfig b/mm/Kconfig index 01da31cd07b..77beaa69c7e 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -316,16 +316,6 @@ config KSM until a program has madvised that an area is MADV_MERGEABLE, and root has set /sys/kernel/mm/ksm/run to 1 (if CONFIG_SYSFS is set). -config KSM_CHECK_PAGE - bool "Check page before scanning" - depends on KSM - default n - help - If enabled, this will check and skip if page is already scanned in - same KSM scan cycle. - This is useful in situation where you have parent and - child process marking same area for KSM scanning. - config DEFAULT_MMAP_MIN_ADDR int "Low address space to protect from user allocation" depends on MMU @@ -301,7 +301,8 @@ static inline struct rmap_item *alloc_rmap_item(void) { struct rmap_item *rmap_item; - rmap_item = kmem_cache_zalloc(rmap_item_cache, GFP_KERNEL); + rmap_item = kmem_cache_zalloc(rmap_item_cache, GFP_KERNEL | + __GFP_NORETRY | __GFP_NOWARN); if (rmap_item) ksm_rmap_items++; return rmap_item; @@ -661,9 +662,7 @@ static void remove_rmap_item_from_tree(struct rmap_item *rmap_item) * than left over from before. */ age = (unsigned char)(ksm_scan.seqnr - rmap_item->address); -#ifndef CONFIG_KSM_CHECK_PAGE BUG_ON(age > 1); -#endif if (!age) rb_erase(&rmap_item->node, root_unstable_tree + NUMA(rmap_item->nid)); @@ -1707,31 +1706,6 @@ next_mm: return NULL; } -static inline int is_page_scanned(struct page *page) -{ -#ifdef CONFIG_KSM_CHECK_PAGE - /* page is already marked as ksm, so this will be simple merge */ - if (PageKsm(page)) - return 0; - - if (ksm_scan.seqnr & 0x1) { - /* odd cycle */ - /* clear even cycle bit */ - ClearPageKsmScan0(page); - /* get old value and mark it scanned */ - return TestSetPageKsmScan1(page); - } else { - /* even cycle */ - /* clear odd cycle bit */ - ClearPageKsmScan1(page); - /* get old value and mark it scanned */ - return TestSetPageKsmScan0(page); - } -#else - return 0; -#endif -} - /** * ksm_do_scan - the ksm scanner main worker function. * @scan_npages - number of pages we want to scan before we return. @@ -1746,8 +1720,7 @@ static void ksm_do_scan(unsigned int scan_npages) rmap_item = scan_get_next_rmap_item(&page); if (!rmap_item) return; - if (!is_page_scanned(page)) - cmp_and_merge_page(page, rmap_item); + cmp_and_merge_page(page, rmap_item); put_page(page); } } diff --git a/mm/mmap.c b/mm/mmap.c index 9405d6f7ff8..23e0db0fc24 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2132,7 +2132,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) /* Guard against exceeding limits of the address space. */ address &= PAGE_MASK; - if (address >= TASK_SIZE) + if (address >= (TASK_SIZE & PAGE_MASK)) return -ENOMEM; address += PAGE_SIZE; diff --git a/mm/page-writeback.c b/mm/page-writeback.c index e8bc902eb5f..db8f3b3ca0b 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -485,7 +485,7 @@ static void writeout_period(unsigned long t) * registered backing devices, which, for obvious reasons, can not * exceed 100%. */ -static unsigned int bdi_min_ratio = 5; +static unsigned int bdi_min_ratio; int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio) { @@ -2399,7 +2399,7 @@ int test_clear_page_writeback(struct page *page) return ret; } -int test_set_page_writeback(struct page *page) +int __test_set_page_writeback(struct page *page, bool keep_write) { struct address_space *mapping = page_mapping(page); int ret; @@ -2421,9 +2421,10 @@ int test_set_page_writeback(struct page *page) radix_tree_tag_clear(&mapping->page_tree, page_index(page), PAGECACHE_TAG_DIRTY); - radix_tree_tag_clear(&mapping->page_tree, - page_index(page), - PAGECACHE_TAG_TOWRITE); + if (!keep_write) + radix_tree_tag_clear(&mapping->page_tree, + page_index(page), + PAGECACHE_TAG_TOWRITE); spin_unlock_irqrestore(&mapping->tree_lock, flags); } else { ret = TestSetPageWriteback(page); @@ -2433,7 +2434,7 @@ int test_set_page_writeback(struct page *page) return ret; } -EXPORT_SYMBOL(test_set_page_writeback); +EXPORT_SYMBOL(__test_set_page_writeback); /* * Return true if any of the pages in the mapping are marked with the diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 0c602215eae..bad1245ad9b 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5345,8 +5345,8 @@ unsigned long free_reserved_area(unsigned long start, unsigned long end, } if (pages && s) - pr_info("Freeing %s memory: %ldK (%lx - %lx)\n", - s, pages << (PAGE_SHIFT - 10), start, end); + pr_info("Freeing %s memory: %ldK\n", + s, pages << (PAGE_SHIFT - 10)); return pages; } @@ -6475,9 +6475,6 @@ static const struct trace_print_flags pageflag_names[] = { #ifdef CONFIG_TRANSPARENT_HUGEPAGE {1UL << PG_compound_lock, "compound_lock" }, #endif -#ifdef CONFIG_KSM_CHECK_PAGE - {1UL << PG_ksm_scan0, "PG_ksm_scan0" }, -#endif {1UL << PG_readahead, "PG_readahead" }, }; diff --git a/mm/vmstat.c b/mm/vmstat.c index ecb46431255..cc8ac9b1cfd 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1244,9 +1244,7 @@ static int vmstat_show(struct seq_file *m, void *arg) unsigned long *l = arg; unsigned long off = l - (unsigned long *)m->private; - seq_puts(m, vmstat_text[off]); - seq_put_decimal_ull(m, ' ', *l); - seq_putc(m, '\n'); + seq_printf(m, "%s %lu\n", vmstat_text[off], *l); return 0; } diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 86abb2e59ae..82fdb35154f 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -274,7 +274,8 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) return 0; out_free_newdev: - free_netdev(new_dev); + if (new_dev->reg_state == NETREG_UNINITIALIZED) + free_netdev(new_dev); return err; } diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 13f3b1ff245..f2de0183ab2 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -32,6 +32,7 @@ #include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> +#include <net/bluetooth/l2cap.h> #include <net/bluetooth/hci_core.h> #include "bnep.h" @@ -539,6 +540,9 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) BT_DBG(""); + if (!l2cap_is_socket(sock)) + return -EBADFD; + baswap((void *) dst, &bt_sk(sock->sk)->dst); baswap((void *) src, &bt_sk(sock->sk)->src); diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index d74d9fe5411..e74d331a139 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -334,6 +334,9 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) BT_DBG(""); + if (!l2cap_is_socket(sock)) + return -EBADFD; + session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL); if (!session) return -ENOMEM; diff --git a/net/core/dev.c b/net/core/dev.c index d4e6d248dca..e8bcdeddb0d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2342,9 +2342,10 @@ EXPORT_SYMBOL(skb_mac_gso_segment); static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path) { if (tx_path) - return skb->ip_summed != CHECKSUM_PARTIAL; - else - return skb->ip_summed == CHECKSUM_NONE; + return skb->ip_summed != CHECKSUM_PARTIAL && + skb->ip_summed != CHECKSUM_NONE; + + return skb->ip_summed == CHECKSUM_NONE; } /** @@ -2361,11 +2362,12 @@ static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path) struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t features, bool tx_path) { + struct sk_buff *segs; + if (unlikely(skb_needs_check(skb, tx_path))) { int err; - skb_warn_bad_offload(skb); - + /* We're going to init ->check field in TCP or UDP header */ if (skb_header_cloned(skb) && (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) return ERR_PTR(err); @@ -2375,7 +2377,12 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, skb_reset_mac_header(skb); skb_reset_mac_len(skb); - return skb_mac_gso_segment(skb, features); + segs = skb_mac_gso_segment(skb, features); + + if (unlikely(skb_needs_check(skb, tx_path))) + skb_warn_bad_offload(skb); + + return segs; } EXPORT_SYMBOL(__skb_gso_segment); @@ -4045,9 +4052,16 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd) while (remsd) { struct softnet_data *next = remsd->rps_ipi_next; - if (cpu_online(remsd->cpu)) + if (cpu_online(remsd->cpu)) { __smp_call_function_single(remsd->cpu, &remsd->csd, 0); + } else { + pr_err("%s(), cpu was offline and IPI was not " + "delivered so clean up NAPI", __func__); + rps_lock(remsd); + remsd->backlog.state = 0; + rps_unlock(remsd); + } remsd = next; } } else @@ -5658,7 +5672,7 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, } else { netdev_stats_to_stats64(storage, &dev->stats); } - storage->rx_dropped += atomic_long_read(&dev->rx_dropped); + storage->rx_dropped += (unsigned long)atomic_long_read(&dev->rx_dropped); return storage; } EXPORT_SYMBOL(dev_get_stats); @@ -6056,6 +6070,7 @@ static int dev_cpu_callback(struct notifier_block *nfb, if (action != CPU_DEAD && action != CPU_DEAD_FROZEN) return NOTIFY_OK; + local_irq_disable(); cpu = smp_processor_id(); sd = &per_cpu(softnet_data, cpu); diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 962e3d543aa..fb9adc5d193 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -17,10 +17,10 @@ #include <net/sock.h> #include <net/fib_rules.h> -static const struct fib_kuid_range fib_kuid_range_unset = { - KUIDT_INIT(0), - KUIDT_INIT(~0), -}; +#define uid_valid(uid) ((uid) != -1) +#define uid_lte(a, b) ((a) <= (b)) +#define uid_eq(a, b) ((a) == (b)) +#define uid_gte(a, b) ((a) >= (b)) int fib_default_rule_add(struct fib_rules_ops *ops, u32 pref, u32 table, u32 flags) @@ -36,8 +36,9 @@ int fib_default_rule_add(struct fib_rules_ops *ops, r->pref = pref; r->table = table; r->flags = flags; + r->uid_start = INVALID_UID; + r->uid_end = INVALID_UID; r->fr_net = hold_net(ops->fro_net); - r->uid_range = fib_kuid_range_unset; /* The lock is not required here, the list in unreacheable * at the moment this function is called */ @@ -185,32 +186,21 @@ void fib_rules_unregister(struct fib_rules_ops *ops) } EXPORT_SYMBOL_GPL(fib_rules_unregister); -static int uid_range_set(struct fib_kuid_range *range) +static inline uid_t fib_nl_uid(struct nlattr *nla) { - return uid_valid(range->start) && uid_valid(range->end); + return nla_get_u32(nla); } -static struct fib_kuid_range nla_get_kuid_range(struct nlattr **tb) +static int nla_put_uid(struct sk_buff *skb, int idx, uid_t uid) { - struct fib_rule_uid_range *in; - struct fib_kuid_range out; - - in = (struct fib_rule_uid_range *)nla_data(tb[FRA_UID_RANGE]); - - out.start = make_kuid(current_user_ns(), in->start); - out.end = make_kuid(current_user_ns(), in->end); - - return out; + return nla_put_u32(skb, idx, uid); } -static int nla_put_uid_range(struct sk_buff *skb, struct fib_kuid_range *range) +static int fib_uid_range_match(struct flowi *fl, struct fib_rule *rule) { - struct fib_rule_uid_range out = { - from_kuid_munged(current_user_ns(), range->start), - from_kuid_munged(current_user_ns(), range->end) - }; - - return nla_put(skb, FRA_UID_RANGE, sizeof(out), &out); + return (!uid_valid(rule->uid_start) && !uid_valid(rule->uid_end)) || + (uid_gte(fl->flowi_uid, rule->uid_start) && + uid_lte(fl->flowi_uid, rule->uid_end)); } static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops, @@ -227,8 +217,7 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops, if ((rule->mark ^ fl->flowi_mark) & rule->mark_mask) goto out; - if (uid_lt(fl->flowi_uid, rule->uid_range.start) || - uid_gt(fl->flowi_uid, rule->uid_range.end)) + if (!fib_uid_range_match(fl, rule)) goto out; ret = ops->match(rule, fl, flags); @@ -401,19 +390,17 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh) } else if (rule->action == FR_ACT_GOTO) goto errout_free; - if (tb[FRA_UID_RANGE]) { - if (current_user_ns() != net->user_ns) { - err = -EPERM; - goto errout_free; + /* UID start and end must either both be valid or both unspecified. */ + rule->uid_start = rule->uid_end = INVALID_UID; + if (tb[FRA_UID_START] || tb[FRA_UID_END]) { + if (tb[FRA_UID_START] && tb[FRA_UID_END]) { + rule->uid_start = fib_nl_uid(tb[FRA_UID_START]); + rule->uid_end = fib_nl_uid(tb[FRA_UID_END]); } - - rule->uid_range = nla_get_kuid_range(tb); - - if (!uid_range_set(&rule->uid_range) || - !uid_lte(rule->uid_range.start, rule->uid_range.end)) - goto errout_free; - } else { - rule->uid_range = fib_kuid_range_unset; + if (!uid_valid(rule->uid_start) || + !uid_valid(rule->uid_end) || + !uid_lte(rule->uid_start, rule->uid_end)) + goto errout_free; } err = ops->configure(rule, skb, frh, tb); @@ -475,7 +462,6 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh) struct fib_rules_ops *ops = NULL; struct fib_rule *rule, *tmp; struct nlattr *tb[FRA_MAX+1]; - struct fib_kuid_range range; int err = -EINVAL; if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) @@ -495,14 +481,6 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh) if (err < 0) goto errout; - if (tb[FRA_UID_RANGE]) { - range = nla_get_kuid_range(tb); - if (!uid_range_set(&range)) - goto errout; - } else { - range = fib_kuid_range_unset; - } - list_for_each_entry(rule, &ops->rules_list, list) { if (frh->action && (frh->action != rule->action)) continue; @@ -531,9 +509,12 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh) (rule->mark_mask != nla_get_u32(tb[FRA_FWMASK]))) continue; - if (uid_range_set(&range) && - (!uid_eq(rule->uid_range.start, range.start) || - !uid_eq(rule->uid_range.end, range.end))) + if (tb[FRA_UID_START] && + !uid_eq(rule->uid_start, fib_nl_uid(tb[FRA_UID_START]))) + continue; + + if (tb[FRA_UID_END] && + !uid_eq(rule->uid_end, fib_nl_uid(tb[FRA_UID_END]))) continue; if (!ops->compare(rule, frh, tb)) @@ -593,7 +574,8 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops, + nla_total_size(4) /* FRA_TABLE */ + nla_total_size(4) /* FRA_FWMARK */ + nla_total_size(4) /* FRA_FWMASK */ - + nla_total_size(sizeof(struct fib_kuid_range)); + + nla_total_size(4) /* FRA_UID_START */ + + nla_total_size(4); /* FRA_UID_END */ if (ops->nlmsg_payload) payload += ops->nlmsg_payload(rule); @@ -647,10 +629,15 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, ((rule->mark_mask || rule->mark) && nla_put_u32(skb, FRA_FWMASK, rule->mark_mask)) || (rule->target && - nla_put_u32(skb, FRA_GOTO, rule->target)) || - (uid_range_set(&rule->uid_range) && - nla_put_uid_range(skb, &rule->uid_range))) + nla_put_u32(skb, FRA_GOTO, rule->target))) goto nla_put_failure; + + if (uid_valid(rule->uid_start)) + nla_put_uid(skb, FRA_UID_START, rule->uid_start); + + if (uid_valid(rule->uid_end)) + nla_put_uid(skb, FRA_UID_END, rule->uid_end); + if (ops->fill(rule, skb, frh) < 0) goto nla_put_failure; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 0c5602cf263..b678920f4b9 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -827,7 +827,7 @@ out: * ARP entry timeouts range from 1/2 base_reachable_time to 3/2 * base_reachable_time. */ - queue_delayed_work(system_power_efficient_wq, &tbl->gc_work, + schedule_delayed_work(&tbl->gc_work, tbl->parms.base_reachable_time >> 1); write_unlock_bh(&tbl->lock); } @@ -1561,8 +1561,7 @@ static void neigh_table_init_no_netlink(struct neigh_table *tbl) rwlock_init(&tbl->lock); INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work); - queue_delayed_work(system_power_efficient_wq, &tbl->gc_work, - tbl->parms.reachable_time); + schedule_delayed_work(&tbl->gc_work, tbl->parms.reachable_time); setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl); skb_queue_head_init_class(&tbl->proxy_queue, &neigh_table_proxy_queue_class); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 602c6d0492e..c468470112a 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -899,8 +899,14 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, goto nla_put_failure; if (1) { - struct rtnl_link_ifmap map; - + struct rtnl_link_ifmap map = { + .mem_start = dev->mem_start, + .mem_end = dev->mem_end, + .base_addr = dev->base_addr, + .irq = dev->irq, + .dma = dev->dma, + .port = dev->if_port, + }; memset(&map, 0, sizeof(map)); map.mem_start = dev->mem_start; map.mem_end = dev->mem_end; diff --git a/net/core/sock.c b/net/core/sock.c index 09bb754627e..62a983dd651 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1470,6 +1470,8 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) sock_copy(newsk, sk); + newsk->sk_prot_creator = sk->sk_prot; + /* SANITY */ get_net(sock_net(newsk)); sk_node_init(&newsk->sk_node); diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index c02311f22eb..0438209b294 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1075,7 +1075,7 @@ static struct inet_protosw inetsw_array[] = .type = SOCK_DGRAM, .protocol = IPPROTO_ICMP, .prot = &ping_prot, - .ops = &inet_dgram_ops, + .ops = &inet_sockraw_ops, .no_check = UDP_CSUM_DEFAULT, .flags = INET_PROTOSW_REUSE, }, diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 5b85c29d7d9..b151e0ac7f2 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -469,7 +469,7 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, inet_hash_insert(dev_net(in_dev->dev), ifa); cancel_delayed_work(&check_lifetime_work); - queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, 0); + schedule_delayed_work(&check_lifetime_work, 0); /* Send message first, then call notifier. Notifier will trigger FIB update, so that @@ -678,8 +678,7 @@ static void check_lifetime(struct work_struct *work) if (time_before(next_sched, now + ADDRCONF_TIMER_FUZZ_MAX)) next_sched = now + ADDRCONF_TIMER_FUZZ_MAX; - queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, - next_sched - now); + schedule_delayed_work(&check_lifetime_work, next_sched - now); } static void set_ifa_lifetime(struct in_ifaddr *ifa, __u32 valid_lft, @@ -835,8 +834,7 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh) ifa = ifa_existing; set_ifa_lifetime(ifa, valid_lft, prefered_lft); cancel_delayed_work(&check_lifetime_work); - queue_delayed_work(system_power_efficient_wq, - &check_lifetime_work, 0); + schedule_delayed_work(&check_lifetime_work, 0); rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid); blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); } @@ -2301,7 +2299,7 @@ void __init devinet_init(void) register_gifconf(PF_INET, inet_gifconf); register_netdevice_notifier(&ip_netdev_notifier); - queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, 0); + schedule_delayed_work(&check_lifetime_work, 0); rtnl_af_register(&inet_af_ops); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index fdd555129fa..42da0b216bb 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -1171,13 +1171,14 @@ static struct pernet_operations fib_net_ops = { void __init ip_fib_init(void) { - rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL); - rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL); - rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL); + fib_trie_init(); register_pernet_subsys(&fib_net_ops); + register_netdevice_notifier(&fib_netdev_notifier); register_inetaddr_notifier(&fib_inetaddr_notifier); - fib_trie_init(); + rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL); + rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL); + rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL); } diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 59e63dcb80d..5af8781b65e 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -364,7 +364,6 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) fl4.daddr = daddr; fl4.saddr = saddr; fl4.flowi4_mark = mark; - fl4.flowi4_uid = sock_net_uid(net, NULL); fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); fl4.flowi4_proto = IPPROTO_ICMP; security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); @@ -396,7 +395,6 @@ static struct rtable *icmp_route_lookup(struct net *net, param->replyopts.opt.opt.faddr : iph->saddr); fl4->saddr = saddr; fl4->flowi4_mark = mark; - fl4->flowi4_uid = sock_net_uid(net, NULL); fl4->flowi4_tos = RT_TOS(tos); fl4->flowi4_proto = IPPROTO_ICMP; fl4->fl4_icmp_type = type; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 912cb4dedfe..008b52bc99a 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -430,7 +430,7 @@ struct dst_entry *inet_csk_route_req(struct sock *sk, flags, (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr, ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport, - sk->sk_uid); + sock_i_uid(sk)); security_req_classify_flow(req, flowi4_to_flowi(fl4)); rt = ip_route_output_flow(net, fl4, sk); if (IS_ERR(rt)) @@ -467,7 +467,7 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk, sk->sk_protocol, inet_sk_flowi_flags(sk), (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr, ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport, - sk->sk_uid); + sock_i_uid(sk)); security_req_classify_flow(req, flowi4_to_flowi(fl4)); rt = ip_route_output_flow(net, fl4, sk); if (IS_ERR(rt)) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 650873c3240..1204570dcce 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -846,10 +846,12 @@ static int __ip_append_data(struct sock *sk, csummode = CHECKSUM_PARTIAL; cork->length += length; - if (((length > mtu) || (skb && skb_has_frags(skb))) && + if ((skb && skb_has_frags(skb)) || + ((length > mtu) && + (skb_queue_len(queue) <= 1) && (sk->sk_protocol == IPPROTO_UDP) && (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len && - (sk->sk_type == SOCK_DGRAM)) { + (sk->sk_type == SOCK_DGRAM))) { err = ip_ufo_append_data(sk, queue, getfrag, from, length, hh_len, fragheaderlen, transhdrlen, maxfraglen, flags); @@ -1160,6 +1162,7 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, cork->length += size; if ((size + skb->len > mtu) && + (skb_queue_len(&sk->sk_write_queue) == 1) && (sk->sk_protocol == IPPROTO_UDP) && (rt->dst.dev->features & NETIF_F_UFO)) { skb_shinfo(skb)->gso_size = mtu - fragheaderlen; diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 5f011cc89cd..1e82bdb0f07 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -1305,6 +1305,7 @@ static int __init nf_nat_snmp_basic_init(void) static void __exit nf_nat_snmp_basic_fini(void) { RCU_INIT_POINTER(nf_nat_snmp_hook, NULL); + synchronize_rcu(); nf_conntrack_helper_unregister(&snmp_trap_helper); } diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 99bc6f5cee7..8e4f27332d6 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -785,7 +785,7 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE, sk->sk_protocol, inet_sk_flowi_flags(sk), faddr, saddr, 0, 0, - sk->sk_uid); + sock_i_uid(sk)); security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); rt = ip_route_output_flow(net, &fl4, sk); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index c9b79f48193..b9c87c8c0b1 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -573,7 +573,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP | (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), - daddr, saddr, 0, 0, sk->sk_uid); + daddr, saddr, 0, 0, + sock_i_uid(sk)); if (!inet->hdrincl) { err = raw_probe_proto_opt(&fl4, msg); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 4f3c789cb77..3283060a8cc 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -515,8 +515,7 @@ void __ip_select_ident(struct iphdr *iph, int segs) } EXPORT_SYMBOL(__ip_select_ident); -static void __build_flow_key(const struct net *net, struct flowi4 *fl4, - const struct sock *sk, +static void __build_flow_key(struct flowi4 *fl4, struct sock *sk, const struct iphdr *iph, int oif, u8 tos, u8 prot, u32 mark, int flow_flags) @@ -533,23 +532,22 @@ static void __build_flow_key(const struct net *net, struct flowi4 *fl4, RT_SCOPE_UNIVERSE, prot, flow_flags, iph->daddr, iph->saddr, 0, 0, - sock_net_uid(net, sk)); + sk ? sock_i_uid(sk) : 0); } static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb, - const struct sock *sk) + struct sock *sk) { - const struct net *net = dev_net(skb->dev); const struct iphdr *iph = ip_hdr(skb); int oif = skb->dev->ifindex; u8 tos = RT_TOS(iph->tos); u8 prot = iph->protocol; u32 mark = skb->mark; - __build_flow_key(net, fl4, sk, iph, oif, tos, prot, mark, 0); + __build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0); } -static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk) +static void build_sk_flow_key(struct flowi4 *fl4, struct sock *sk) { const struct inet_sock *inet = inet_sk(sk); const struct ip_options_rcu *inet_opt; @@ -563,11 +561,11 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk) RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, inet_sk_flowi_flags(sk), - daddr, inet->inet_saddr, 0, 0, sk->sk_uid); + daddr, inet->inet_saddr, 0, 0, sock_i_uid(sk)); rcu_read_unlock(); } -static void ip_rt_build_flow_key(struct flowi4 *fl4, const struct sock *sk, +static void ip_rt_build_flow_key(struct flowi4 *fl4, struct sock *sk, const struct sk_buff *skb) { if (skb) @@ -765,7 +763,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf rt = (struct rtable *) dst; - __build_flow_key(sock_net(sk), &fl4, sk, iph, oif, tos, prot, mark, 0); + __build_flow_key(&fl4, sk, iph, oif, tos, prot, mark, 0); __ip_do_redirect(rt, skb, &fl4, true); } @@ -983,7 +981,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, if (!mark) mark = IP4_REPLY_MARK(net, skb->mark); - __build_flow_key(net, &fl4, NULL, iph, oif, + __build_flow_key(&fl4, NULL, iph, oif, RT_TOS(iph->tos), protocol, mark, flow_flags); rt = __ip_route_output_key(net, &fl4); if (!IS_ERR(rt)) { @@ -999,7 +997,7 @@ static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) struct flowi4 fl4; struct rtable *rt; - __build_flow_key(sock_net(sk), &fl4, sk, iph, 0, 0, 0, 0, 0); + __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); if (!fl4.flowi4_mark) fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark); @@ -1018,7 +1016,6 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) struct rtable *rt; struct dst_entry *odst = NULL; bool new = false; - struct net *net = sock_net(sk); bh_lock_sock(sk); odst = sk_dst_get(sk); @@ -1028,7 +1025,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) goto out; } - __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0); + __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); rt = (struct rtable *)odst; if (odst->obsolete && odst->ops->check(odst, 0) == NULL) { @@ -1068,7 +1065,7 @@ void ipv4_redirect(struct sk_buff *skb, struct net *net, struct flowi4 fl4; struct rtable *rt; - __build_flow_key(net, &fl4, NULL, iph, oif, + __build_flow_key(&fl4, NULL, iph, oif, RT_TOS(iph->tos), protocol, mark, flow_flags); rt = __ip_route_output_key(net, &fl4); if (!IS_ERR(rt)) { @@ -1083,10 +1080,9 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk) const struct iphdr *iph = (const struct iphdr *) skb->data; struct flowi4 fl4; struct rtable *rt; - struct net *net = sock_net(sk); - __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0); - rt = __ip_route_output_key(net, &fl4); + __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); + rt = __ip_route_output_key(sock_net(sk), &fl4); if (!IS_ERR(rt)) { __ip_do_redirect(rt, skb, &fl4, false); ip_rt_put(rt); @@ -1161,6 +1157,7 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt) fl4.flowi4_oif = rt->dst.dev->ifindex; fl4.flowi4_iif = skb->dev->ifindex; fl4.flowi4_mark = skb->mark; + fl4.flowi4_uid = skb->sk ? sock_i_uid(skb->sk) : 0; rcu_read_lock(); if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0) @@ -1451,6 +1448,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_iif = 0; rth->rt_pmtu = 0; rth->rt_gateway = 0; + rth->rt_uid = 0; rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); if (our) { @@ -1574,6 +1572,7 @@ static int __mkroute_input(struct sk_buff *skb, rth->rt_is_input = 1; rth->rt_iif = 0; rth->rt_pmtu = 0; + rth->rt_uid = 0; rth->rt_gateway = 0; rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); @@ -1744,6 +1743,7 @@ local_input: rth->rt_is_input = 1; rth->rt_iif = 0; rth->rt_pmtu = 0; + rth->rt_uid = 0; rth->rt_gateway = 0; rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); @@ -1947,6 +1947,7 @@ add: rth->rt_is_input = 0; rth->rt_iif = orig_oif ? : 0; rth->rt_pmtu = 0; + rth->rt_uid = fl4->flowi4_uid; rth->rt_gateway = 0; rth->rt_uses_gateway = 0; INIT_LIST_HEAD(&rth->rt_uncached); @@ -2222,6 +2223,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or rt->rt_is_input = ort->rt_is_input; rt->rt_iif = ort->rt_iif; rt->rt_pmtu = ort->rt_pmtu; + rt->rt_uid = ort->rt_uid; rt->rt_genid = rt_genid(net); rt->rt_flags = ort->rt_flags; @@ -2332,9 +2334,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, nla_put_u32(skb, RTA_MARK, fl4->flowi4_mark)) goto nla_put_failure; - if (!uid_eq(fl4->flowi4_uid, INVALID_UID) && - nla_put_u32(skb, RTA_UID, - from_kuid_munged(current_user_ns(), fl4->flowi4_uid))) + if (rt->rt_uid != (uid_t) -1 && + nla_put_u32(skb, RTA_UID, rt->rt_uid)) goto nla_put_failure; error = rt->dst.error; @@ -2387,7 +2388,6 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh) int err; int mark; struct sk_buff *skb; - kuid_t uid; err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy); if (err < 0) @@ -2415,10 +2415,6 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh) dst = tb[RTA_DST] ? nla_get_be32(tb[RTA_DST]) : 0; iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0; mark = tb[RTA_MARK] ? nla_get_u32(tb[RTA_MARK]) : 0; - if (tb[RTA_UID]) - uid = make_kuid(current_user_ns(), nla_get_u32(tb[RTA_UID])); - else - uid = (iif ? INVALID_UID : current_uid()); memset(&fl4, 0, sizeof(fl4)); fl4.daddr = dst; @@ -2426,7 +2422,6 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh) fl4.flowi4_tos = rtm->rtm_tos; fl4.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0; fl4.flowi4_mark = mark; - fl4.flowi4_uid = uid; if (iif) { struct net_device *dev; diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 296a0a42b2b..c94032b95c6 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -353,7 +353,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP, inet_sk_flowi_flags(sk), (opt && opt->srr) ? opt->faddr : ireq->rmt_addr, - ireq->loc_addr, th->source, th->dest, sk->sk_uid); + ireq->loc_addr, th->source, th->dest, + sock_i_uid(sk)); security_req_classify_flow(req, flowi4_to_flowi(&fl4)); rt = ip_route_output_key(sock_net(sk), &fl4); if (IS_ERR(rt)) { diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index e813bc8c7cd..95de798afcb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2336,9 +2336,15 @@ int tcp_disconnect(struct sock *sk, int flags) tcp_set_ca_state(sk, TCP_CA_Open); tcp_clear_retrans(tp); inet_csk_delack_init(sk); + /* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0 + * issue in __tcp_select_window() + */ + icsk->icsk_ack.rcv_mss = TCP_MIN_MSS; tcp_init_send_head(sk); memset(&tp->rx_opt, 0, sizeof(tp->rx_opt)); __sk_dst_reset(sk); + dst_release(sk->sk_rx_dst); + sk->sk_rx_dst = NULL; WARN_ON(inet->inet_num && !icsk->icsk_bind_hash); diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 019c2389a34..2ca6c080a4b 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -95,6 +95,7 @@ void tcp_init_congestion_control(struct sock *sk) rcu_read_unlock(); } + tcp_sk(sk)->prior_ssthresh = 0; if (icsk->icsk_ca_ops->init) icsk->icsk_ca_ops->init(sk); } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e3ec3ecb4bd..f7513458ea9 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -112,6 +112,7 @@ int sysctl_tcp_default_init_rwnd __read_mostly = TCP_DEFAULT_INIT_RCVWND; #define FLAG_ORIG_SACK_ACKED 0x200 /* Never retransmitted data are (s)acked */ #define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */ #define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */ +#define FLAG_SET_XMIT_TIMER 0x1000 /* Set TLP or RTO timer */ #define FLAG_SACK_RENEGING 0x2000 /* snd_una advanced to a sacked seq */ #define FLAG_UPDATE_TS_RECENT 0x4000 /* tcp_replace_ts_recent() */ @@ -2554,8 +2555,8 @@ static inline void tcp_end_cwnd_reduction(struct sock *sk) struct tcp_sock *tp = tcp_sk(sk); /* Reset cwnd to ssthresh in CWR or Recovery (unless it's undone) */ - if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR || - (tp->undo_marker && tp->snd_ssthresh < TCP_INFINITE_SSTHRESH)) { + if (tp->snd_ssthresh < TCP_INFINITE_SSTHRESH && + (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR || tp->undo_marker)) { tp->snd_cwnd = tp->snd_ssthresh; tp->snd_cwnd_stamp = tcp_time_stamp; } @@ -2973,14 +2974,11 @@ void tcp_rearm_rto(struct sock *sk) /* Offset the time elapsed after installing regular RTO */ if (icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS || icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) { - struct sk_buff *skb = tcp_write_queue_head(sk); - const u32 rto_time_stamp = TCP_SKB_CB(skb)->when + rto; - s32 delta = (s32)(rto_time_stamp - tcp_time_stamp); + s32 delta = tcp_rto_delta(sk); /* delta may not be positive if the socket is locked * when the retrans timer fires and is rescheduled. */ - if (delta > 0) - rto = delta; + rto = max_t(int, delta, 1); } inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto, TCP_RTO_MAX); @@ -3005,6 +3003,13 @@ void tcp_resume_early_retransmit(struct sock *sk) tcp_xmit_retransmit_queue(sk); } +/* Try to schedule a loss probe; if that doesn't work, then schedule an RTO. */ +static void tcp_set_xmit_timer(struct sock *sk) +{ + if (!tcp_schedule_loss_probe(sk)) + tcp_rearm_rto(sk); +} + /* If we get here, the whole TSO packet has not been acked. */ static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb) { @@ -3135,7 +3140,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, } tcp_ack_update_rtt(sk, flag, seq_rtt); - tcp_rearm_rto(sk); + flag |= FLAG_SET_XMIT_TIMER; /* set TLP or RTO timer */ if (tcp_is_reno(tp)) { tcp_remove_reno_sacks(sk, pkts_acked); @@ -3395,10 +3400,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) if (after(ack, tp->snd_nxt)) goto invalid_ack; - if (icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS || - icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) - tcp_rearm_rto(sk); - if (after(ack, prior_snd_una)) flag |= FLAG_SND_UNA_ADVANCED; @@ -3455,6 +3456,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) pkts_acked = previous_packets_out - tp->packets_out; + if (tp->tlp_high_seq) + tcp_process_tlp_ack(sk, ack, flag); + /* If needed, reset TLP/RTO timer; RACK may later override this. */ + if (flag & FLAG_SET_XMIT_TIMER) + tcp_set_xmit_timer(sk); + if (tcp_ack_is_dubious(sk, flag)) { /* Advance CWND, if state allows this. */ if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(sk, flag)) @@ -3467,17 +3474,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) tcp_cong_avoid(sk, ack, prior_in_flight); } - if (tp->tlp_high_seq) - tcp_process_tlp_ack(sk, ack, flag); - if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) { struct dst_entry *dst = __sk_dst_get(sk); if (dst) dst_confirm(dst); } - if (icsk->icsk_pending == ICSK_TIME_RETRANS) - tcp_schedule_loss_probe(sk); if (tp->srtt != prior_rtt || tp->snd_cwnd != prior_cwnd) tcp_update_pacing_rate(sk); return 1; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 7e3ae5513fb..4c5724f6fd1 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -711,7 +711,6 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) arg.bound_dev_if = sk->sk_bound_dev_if; arg.tos = ip_hdr(skb)->tos; - arg.uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL); ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), skb, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); @@ -732,8 +731,7 @@ release_sk1: outside socket context is ugly, certainly. What can I do? */ -static void tcp_v4_send_ack(const struct sock *sk, struct sk_buff *skb, - u32 seq, u32 ack, +static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 tsval, u32 tsecr, int oif, struct tcp_md5sig_key *key, int reply_flags, u8 tos) @@ -748,7 +746,7 @@ static void tcp_v4_send_ack(const struct sock *sk, struct sk_buff *skb, ]; } rep; struct ip_reply_arg arg; - struct net *net = sock_net(sk); + struct net *net = dev_net(skb_dst(skb)->dev); memset(&rep.th, 0, sizeof(struct tcphdr)); memset(&arg, 0, sizeof(arg)); @@ -797,7 +795,6 @@ static void tcp_v4_send_ack(const struct sock *sk, struct sk_buff *skb, if (oif) arg.bound_dev_if = oif; arg.tos = tos; - arg.uid = sock_net_uid(net, sk_fullsock(sk) ? sk : NULL); ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), skb, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); @@ -810,7 +807,7 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) struct inet_timewait_sock *tw = inet_twsk(sk); struct tcp_timewait_sock *tcptw = tcp_twsk(sk); - tcp_v4_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, + tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcp_time_stamp + tcptw->tw_ts_offset, tcptw->tw_ts_recent, @@ -829,10 +826,9 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV * sk->sk_state == TCP_SYN_RECV -> for Fast Open. */ - tcp_v4_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ? + tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, - tcp_rsk(req)->rcv_nxt, - req->rcv_wnd >> inet_rsk(req)->rcv_wscale, + tcp_rsk(req)->rcv_nxt, req->rcv_wnd, tcp_time_stamp, req->ts_recent, 0, diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 9c3fc860d2b..4b41fac4a0a 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -247,12 +247,6 @@ void tcp_select_initial_window(int __space, __u32 mss, else *rcv_wnd = min(*rcv_wnd, init_cwnd * mss); } - - /* Lock the initial TCP window size to 64K*/ - *rcv_wnd = 64240; - - /* Lock the initial TCP window size to 64K*/ - *rcv_wnd = 64240; /* Set the clamp no higher than max representable value */ (*window_clamp) = min(65535U << (*rcv_wscale), *window_clamp); @@ -1948,28 +1942,16 @@ repair: bool tcp_schedule_loss_probe(struct sock *sk) { - struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); - u32 timeout, tlp_time_stamp, rto_time_stamp; u32 rtt = tp->srtt >> 3; + u32 timeout, rto_delta; - if (WARN_ON(icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS)) - return false; - /* No consecutive loss probes. */ - if (WARN_ON(icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)) { - tcp_rearm_rto(sk); - return false; - } /* Don't do any loss probe on a Fast Open connection before 3WHS * finishes. */ if (sk->sk_state == TCP_SYN_RECV) return false; - /* TLP is only scheduled when next timer event is RTO. */ - if (icsk->icsk_pending != ICSK_TIME_RETRANS) - return false; - /* Schedule a loss probe in 2*RTT for SACK capable connections * in Open state, that are either limited by cwnd or application. */ @@ -1990,14 +1972,10 @@ bool tcp_schedule_loss_probe(struct sock *sk) (rtt + (rtt >> 1) + TCP_DELACK_MAX)); timeout = max_t(u32, timeout, msecs_to_jiffies(10)); - /* If RTO is shorter, just schedule TLP in its place. */ - tlp_time_stamp = tcp_time_stamp + timeout; - rto_time_stamp = (u32)inet_csk(sk)->icsk_timeout; - if ((s32)(tlp_time_stamp - rto_time_stamp) > 0) { - s32 delta = rto_time_stamp - tcp_time_stamp; - if (delta > 0) - timeout = delta; - } + /* If the RTO formula yields an earlier time, then use that time. */ + rto_delta = tcp_rto_delta(sk); /* How far in future is RTO? */ + if (rto_delta > 0) + timeout = min_t(u32, timeout, rto_delta); inet_csk_reset_xmit_timer(sk, ICSK_TIME_LOSS_PROBE, timeout, TCP_RTO_MAX); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 333dcb2f5e6..959145f9a8d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -769,7 +769,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) if (is_udplite) /* UDP-Lite */ csum = udplite_csum(skb); - else if (sk->sk_no_check == UDP_CSUM_NOXMIT) { /* UDP csum disabled */ + else if (sk->sk_no_check == UDP_CSUM_NOXMIT && !skb_has_frags(skb)) { /* UDP csum off */ skb->ip_summed = CHECKSUM_NONE; goto send; @@ -970,7 +970,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, RT_SCOPE_UNIVERSE, sk->sk_protocol, inet_sk_flowi_flags(sk)|FLOWI_FLAG_CAN_SLEEP, faddr, saddr, dport, inet->inet_sport, - sk->sk_uid); + sock_i_uid(sk)); security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); rt = ip_route_output_flow(net, fl4, sk); diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 9b5b5ddf8cd..4c436751bf9 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -80,6 +80,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, const struct flowi4 *fl4 = &fl->u.ip4; xdst->u.rt.rt_iif = fl4->flowi4_iif; + xdst->u.rt.rt_uid = fl4->flowi4_uid; xdst->u.dst.dev = dev; dev_hold(dev); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 81958340133..c1119609e2a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2969,6 +2969,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, { struct net_device *dev = (struct net_device *) data; struct inet6_dev *idev = __in6_dev_get(dev); + struct net *net = dev_net(dev); int run_pending = 0; int err; @@ -3065,7 +3066,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, * IPV6_MIN_MTU stop IPv6 on this interface. */ if (dev->mtu < IPV6_MIN_MTU) - addrconf_ifdown(dev, 1); + addrconf_ifdown(dev, dev != net->loopback_dev); } break; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3d90a43e641..4656cb363c5 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -699,7 +699,7 @@ int inet6_sk_rebuild_header(struct sock *sk) fl6.flowi6_mark = sk->sk_mark; fl6.fl6_dport = inet->inet_dport; fl6.fl6_sport = inet->inet_sport; - fl6.flowi6_uid = sk->sk_uid; + fl6.flowi6_uid = sock_i_uid(sk); security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); rcu_read_lock(); diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 15e41c5bea3..bb02e176cb7 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -628,9 +628,9 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, return; if (type == NDISC_REDIRECT) - ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL)); + ip6_redirect(skb, net, 0, 0); else - ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL)); + ip6_update_pmtu(skb, net, info, 0, 0); xfrm_state_put(x); } diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 8abb98c38d3..193274c912f 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -162,7 +162,7 @@ ipv4_connected: fl6.flowi6_mark = sk->sk_mark; fl6.fl6_dport = inet->inet_dport; fl6.fl6_sport = inet->inet_sport; - fl6.flowi6_uid = sk->sk_uid; + fl6.flowi6_uid = sock_i_uid(sk); if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST)) fl6.flowi6_oif = np->mcast_oif; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 4ad65258f54..40ffd72243a 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -447,9 +447,9 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, return; if (type == NDISC_REDIRECT) - ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL)); + ip6_redirect(skb, net, 0, 0); else - ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL)); + ip6_update_pmtu(skb, net, info, 0, 0); xfrm_state_put(x); } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index b0220040ef2..33101f4e3ee 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -90,9 +90,9 @@ static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct net *net = dev_net(skb->dev); if (type == ICMPV6_PKT_TOOBIG) - ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL)); + ip6_update_pmtu(skb, net, info, 0, 0); else if (type == NDISC_REDIRECT) - ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL)); + ip6_redirect(skb, net, 0, 0); if (!(type & ICMPV6_INFOMSG_MASK)) if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST) @@ -467,7 +467,6 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) fl6.flowi6_oif = iif; fl6.fl6_icmp_type = type; fl6.fl6_icmp_code = code; - fl6.flowi6_uid = sock_net_uid(net, NULL); security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); sk = icmpv6_xmit_lock(net); @@ -573,7 +572,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb) fl6.flowi6_oif = skb->dev->ifindex; fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY; fl6.flowi6_mark = mark; - fl6.flowi6_uid = sock_net_uid(net, NULL); security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); sk = icmpv6_xmit_lock(net); diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index a2072a81c93..f92676cb879 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -86,7 +86,7 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk, fl6->flowi6_mark = inet_rsk(req)->ir_mark; fl6->fl6_dport = inet_rsk(req)->rmt_port; fl6->fl6_sport = inet_rsk(req)->loc_port; - fl6->flowi6_uid = sk->sk_uid; + fl6->flowi6_uid = sock_i_uid(sk); security_req_classify_flow(req, flowi6_to_flowi(fl6)); dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); @@ -214,7 +214,6 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk, fl6->flowi6_mark = sk->sk_mark; fl6->fl6_sport = inet->inet_sport; fl6->fl6_dport = inet->inet_dport; - fl6->flowi6_uid = sk->sk_uid; security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); rcu_read_lock(); diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 46458ee3193..6de0d44a942 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -167,6 +167,12 @@ static __inline__ void rt6_release(struct rt6_info *rt) dst_free(&rt->dst); } +static void fib6_free_table(struct fib6_table *table) +{ + inetpeer_invalidate_tree(&table->tb6_peers); + kfree(table); +} + static void fib6_link_table(struct net *net, struct fib6_table *tb) { unsigned int h; @@ -1738,15 +1744,22 @@ out_timer: static void fib6_net_exit(struct net *net) { + unsigned int i; + rt6_ifdown(net, NULL); del_timer_sync(&net->ipv6.ip6_fib_timer); -#ifdef CONFIG_IPV6_MULTIPLE_TABLES - inetpeer_invalidate_tree(&net->ipv6.fib6_local_tbl->tb6_peers); - kfree(net->ipv6.fib6_local_tbl); -#endif - inetpeer_invalidate_tree(&net->ipv6.fib6_main_tbl->tb6_peers); - kfree(net->ipv6.fib6_main_tbl); + for (i = 0; i < FIB6_TABLE_HASHSZ; i++) { + struct hlist_head *head = &net->ipv6.fib_table_hash[i]; + struct hlist_node *tmp; + struct fib6_table *tb; + + hlist_for_each_entry_safe(tb, tmp, head, tb6_hlist) { + hlist_del(&tb->tb6_hlist); + fib6_free_table(tb); + } + } + kfree(net->ipv6.fib_table_hash); kfree(net->ipv6.rt6_stats); } diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 31a6b719336..529348e6a98 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -419,7 +419,7 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (code == ICMPV6_HDR_FIELD) teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data); - if (teli && teli == info - 2) { + if (teli && teli == be32_to_cpu(info) - 2) { tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; if (tel->encap_limit == 0) { net_warn_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n", @@ -431,7 +431,7 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, } break; case ICMPV6_PKT_TOOBIG: - mtu = info - offset; + mtu = be32_to_cpu(info) - offset; if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; t->dev->mtu = mtu; @@ -801,8 +801,6 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev) if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) fl6.flowi6_mark = skb->mark; - fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); - err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); if (err != 0) { /* XXX: send ICMP error even if DF is not set. */ @@ -853,8 +851,6 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev) if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) fl6.flowi6_mark = skb->mark; - fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); - err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); if (err != 0) { if (err == -EMSGSIZE) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 0f514963944..efcba838d4c 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1289,11 +1289,12 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, skb = skb_peek_tail(&sk->sk_write_queue); cork->length += length; - if (((length > mtu) || - (skb && skb_has_frags(skb))) && + if ((skb && skb_has_frags(skb)) || + (((length + fragheaderlen) > mtu) && + (skb_queue_len(&sk->sk_write_queue) <= 1) && (sk->sk_protocol == IPPROTO_UDP) && (rt->dst.dev->features & NETIF_F_UFO) && - (sk->sk_type == SOCK_DGRAM)) { + (sk->sk_type == SOCK_DGRAM))) { err = ip6_ufo_append_data(sk, getfrag, from, length, hh_len, fragheaderlen, transhdrlen, mtu, flags, rt); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index cd0a8bed1ea..efc77acbe9e 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1096,8 +1096,6 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6)); fl6.flowi6_proto = IPPROTO_IPIP; - fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); - dsfield = ipv4_get_dsfield(iph); if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) @@ -1149,7 +1147,6 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6)); fl6.flowi6_proto = IPPROTO_IPV6; - fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); dsfield = ipv6_get_dsfield(ipv6h); if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index a4a4e1c2c9f..7af5aee75d9 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -76,9 +76,9 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, return; if (type == NDISC_REDIRECT) - ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL)); + ip6_redirect(skb, net, 0, 0); else - ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL)); + ip6_update_pmtu(skb, net, info, 0, 0); xfrm_state_put(x); } diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index e48d26beda4..d38e6a8d8b9 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -27,7 +27,6 @@ int ip6_route_me_harder(struct sk_buff *skb) struct flowi6 fl6 = { .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, .flowi6_mark = skb->mark, - .flowi6_uid = sock_net_uid(net, skb->sk), .daddr = iph->daddr, .saddr = iph->saddr, }; diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index 6a38935a9b7..81a687c3c6f 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -167,9 +167,9 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, fl6.daddr = *daddr; fl6.flowi6_oif = oif; fl6.flowi6_mark = sk->sk_mark; - fl6.flowi6_uid = sk->sk_uid; fl6.fl6_icmp_type = user_icmph.icmp6_type; fl6.fl6_icmp_code = user_icmph.icmp6_code; + fl6.flowi6_uid = sock_i_uid(sk); security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index d08e231fff3..a7d8bbbb806 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -763,7 +763,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_mark = sk->sk_mark; - fl6.flowi6_uid = sk->sk_uid; + fl6.flowi6_uid = sock_i_uid(sk); if (sin6) { if (addr_len < SIN6_LEN_RFC2133) @@ -1324,7 +1324,7 @@ void raw6_proc_exit(void) #endif /* CONFIG_PROC_FS */ /* Same as inet6_dgram_ops, sans udp_poll. */ -static const struct proto_ops inet6_sockraw_ops = { +const struct proto_ops inet6_sockraw_ops = { .family = PF_INET6, .owner = THIS_MODULE, .release = inet6_release, diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5481f1dd6a5..937e1b40760 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1146,7 +1146,7 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, } void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, - int oif, u32 mark, kuid_t uid) + int oif, u32 mark) { const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; struct dst_entry *dst; @@ -1159,7 +1159,6 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, fl6.daddr = iph->daddr; fl6.saddr = iph->saddr; fl6.flowlabel = ip6_flowinfo(iph); - fl6.flowi6_uid = uid; dst = ip6_route_output(net, NULL, &fl6); if (!dst->error) @@ -1171,12 +1170,11 @@ EXPORT_SYMBOL_GPL(ip6_update_pmtu); void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu) { ip6_update_pmtu(skb, sock_net(sk), mtu, - sk->sk_bound_dev_if, sk->sk_mark, sk->sk_uid); + sk->sk_bound_dev_if, sk->sk_mark); } EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu); -void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark, - kuid_t uid) +void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark) { const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; struct dst_entry *dst; @@ -1189,7 +1187,6 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark, fl6.daddr = iph->daddr; fl6.saddr = iph->saddr; fl6.flowlabel = ip6_flowinfo(iph); - fl6.flowi6_uid = uid; dst = ip6_route_output(net, NULL, &fl6); if (!dst->error) @@ -1200,8 +1197,7 @@ EXPORT_SYMBOL_GPL(ip6_redirect); void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk) { - ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark, - sk->sk_uid); + ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark); } EXPORT_SYMBOL_GPL(ip6_sk_redirect); @@ -2644,10 +2640,9 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh) fl6.flowi6_mark = nla_get_u32(tb[RTA_MARK]); if (tb[RTA_UID]) - fl6.flowi6_uid = make_kuid(current_user_ns(), - nla_get_u32(tb[RTA_UID])); + fl6.flowi6_uid = nla_get_u32(tb[RTA_UID]); else - fl6.flowi6_uid = iif ? INVALID_UID : current_uid(); + fl6.flowi6_uid = (iif ? (uid_t) -1 : current_uid()); if (iif) { struct net_device *dev; diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 0428544a2be..701d0656a40 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -243,7 +243,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) fl6.flowi6_mark = ireq->ir_mark; fl6.fl6_dport = inet_rsk(req)->rmt_port; fl6.fl6_sport = inet_sk(sk)->inet_sport; - fl6.flowi6_uid = sk->sk_uid; + fl6.flowi6_uid = sock_i_uid(sk); security_req_classify_flow(req, flowi6_to_flowi(&fl6)); dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 7775b61bcb3..cb821c3379c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -253,7 +253,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl6.flowi6_mark = sk->sk_mark; fl6.fl6_dport = usin->sin6_port; fl6.fl6_sport = inet->inet_sport; - fl6.flowi6_uid = sk->sk_uid; + fl6.flowi6_uid = sock_i_uid(sk); opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); final_p = fl6_update_dst(&fl6, opt, &final); @@ -802,7 +802,6 @@ static void tcp_v6_send_response(struct sock *sk, struct sk_buff *skb, u32 seq, fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark); fl6.fl6_dport = t1->dest; fl6.fl6_sport = t1->source; - fl6.flowi6_uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL); security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); /* Pass a socket to ip6_dst_lookup either it is for RST @@ -913,14 +912,8 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, struct request_sock *req) { - /* RFC 7323 2.3 - * The window field (SEG.WND) of every outgoing segment, with the - * exception of <SYN> segments, MUST be right-shifted by - * Rcv.Wind.Shift bits: - */ tcp_v6_send_ack(sk, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, - req->rcv_wnd >> inet_rsk(req)->rcv_wscale, - tcp_time_stamp, req->ts_recent, + req->rcv_wnd, tcp_time_stamp, req->ts_recent, tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0); } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e873b8dc5cf..82deb263edb 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1148,7 +1148,7 @@ do_udp_sendmsg: fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; fl6.flowi6_mark = sk->sk_mark; - fl6.flowi6_uid = sk->sk_uid; + fl6.flowi6_uid = sock_i_uid(sk); if (msg->msg_controllen) { opt = &opt_space; diff --git a/net/key/af_key.c b/net/key/af_key.c index 5482090f285..029e1c97fb0 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1139,6 +1139,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, goto out; } + err = -ENOBUFS; key = ext_hdrs[SADB_EXT_KEY_AUTH - 1]; if (sa->sadb_sa_auth) { int keysize = 0; @@ -1150,8 +1151,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, if (key) keysize = (key->sadb_key_bits + 7) / 8; x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL); - if (!x->aalg) + if (!x->aalg) { + err = -ENOMEM; goto out; + } strcpy(x->aalg->alg_name, a->name); x->aalg->alg_key_len = 0; if (key) { @@ -1170,8 +1173,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, goto out; } x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL); - if (!x->calg) + if (!x->calg) { + err = -ENOMEM; goto out; + } strcpy(x->calg->alg_name, a->name); x->props.calgo = sa->sadb_sa_encrypt; } else { @@ -1185,8 +1190,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, if (key) keysize = (key->sadb_key_bits + 7) / 8; x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL); - if (!x->ealg) + if (!x->ealg) { + err = -ENOMEM; goto out; + } strcpy(x->ealg->alg_name, a->name); x->ealg->alg_key_len = 0; if (key) { @@ -1234,8 +1241,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, struct xfrm_encap_tmpl *natt; x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL); - if (!x->encap) + if (!x->encap) { + err = -ENOMEM; goto out; + } natt = x->encap; n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]; diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 5bd181e296e..8783dfe5ac6 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -517,7 +517,6 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk, memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_mark = sk->sk_mark; - fl6.flowi6_uid = sk->sk_uid; if (lsa) { if (addr_len < SIN6_LEN_RFC2133) diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 1c6a71c41e6..ca66520b894 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -795,10 +795,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, { unsigned int verdict = NF_DROP; - if (IP_VS_FWD_METHOD(cp) != 0) { - pr_err("shouldn't reach here, because the box is on the " - "half connection in the tun/dr module.\n"); - } + if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) + goto ignore_cp; /* Ensure the checksum is correct */ if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) { @@ -832,6 +830,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, ip_vs_notrack(skb); else ip_vs_update_conntrack(skb, cp, 0); + +ignore_cp: verdict = NF_ACCEPT; out: @@ -1182,8 +1182,11 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) */ cp = pp->conn_out_get(af, skb, &iph, 0); - if (likely(cp)) + if (likely(cp)) { + if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) + goto ignore_cp; return handle_response(af, skb, pd, cp, &iph, hooknum); + } if (sysctl_nat_icmp_send(net) && (pp->protocol == IPPROTO_TCP || pp->protocol == IPPROTO_UDP || @@ -1225,9 +1228,15 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) } } } + +out: IP_VS_DBG_PKT(12, af, pp, skb, 0, "ip_vs_out: packet continues traversal as normal"); return NF_ACCEPT; + +ignore_cp: + __ip_vs_conn_put(cp); + goto out; } /* diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 1df17614656..c9f131fc4bf 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -116,6 +116,7 @@ void nf_conntrack_unregister_notifier(struct net *net, BUG_ON(notify != new); RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); mutex_unlock(&nf_ct_ecache_mutex); + /* synchronize_rcu() is called from ctnetlink_exit. */ } EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); @@ -152,6 +153,7 @@ void nf_ct_expect_unregister_notifier(struct net *net, BUG_ON(notify != new); RCU_INIT_POINTER(net->ct.nf_expect_event_cb, NULL); mutex_unlock(&nf_ct_ecache_mutex); + /* synchronize_rcu() is called from ctnetlink_exit. */ } EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index 1a9545965c0..531ca55f1af 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c @@ -53,7 +53,11 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, rcu_read_lock(); t = rcu_dereference(nf_ct_ext_types[id]); - BUG_ON(t == NULL); + if (!t) { + rcu_read_unlock(); + return NULL; + } + off = ALIGN(sizeof(struct nf_ct_ext), t->align); len = off + t->len + var_alloc_len; alloc_size = t->alloc_size + var_alloc_len; @@ -88,7 +92,10 @@ void *__nf_ct_ext_add_length(struct nf_conn *ct, enum nf_ct_ext_id id, rcu_read_lock(); t = rcu_dereference(nf_ct_ext_types[id]); - BUG_ON(t == NULL); + if (!t) { + rcu_read_unlock(); + return NULL; + } newoff = ALIGN(old->len, t->align); newlen = newoff + t->len + var_alloc_len; @@ -186,6 +193,6 @@ void nf_ct_extend_unregister(struct nf_ct_ext_type *type) RCU_INIT_POINTER(nf_ct_ext_types[type->id], NULL); update_alloc_size(type); mutex_unlock(&nf_ct_ext_type_mutex); - rcu_barrier(); /* Wait for completion of call_rcu()'s */ + synchronize_rcu(); } EXPORT_SYMBOL_GPL(nf_ct_extend_unregister); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index c5621b5e3f8..6208b7f0572 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -3137,6 +3137,7 @@ static void __exit ctnetlink_exit(void) #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT RCU_INIT_POINTER(nfq_ct_hook, NULL); #endif + synchronize_rcu(); } module_init(ctnetlink_init); diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 2bb801e3ee8..7658d018105 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -853,6 +853,8 @@ static void __exit nf_nat_cleanup(void) #ifdef CONFIG_XFRM RCU_INIT_POINTER(nf_nat_decode_session_hook, NULL); #endif + synchronize_rcu(); + for (i = 0; i < NFPROTO_NUMPROTO; i++) kfree(nf_nat_l4protos[i]); synchronize_net(); diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index 65074dfb938..10d78dc0d2c 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -431,6 +431,7 @@ static void __exit cttimeout_exit(void) #ifdef CONFIG_NF_CONNTRACK_TIMEOUT RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL); RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL); + synchronize_rcu(); #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ } diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 7011c71646f..c656269c4cf 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -68,7 +68,7 @@ tcpmss_mangle_packet(struct sk_buff *skb, tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); /* Header cannot be larger than the packet */ - if (tcplen < tcph->doff*4) + if (tcplen < tcph->doff*4 || tcph->doff*4 < sizeof(struct tcphdr)) return -1; if (info->mss == XT_TCPMSS_CLAMP_PMTU) { @@ -117,6 +117,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, if (tcplen > tcph->doff*4) return 0; + /* tcph->doff has 4 bits, do not wrap it to 0 */ + if (tcph->doff >= 15) + return 0; + /* * MSS Option not found ?! add it.. */ diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index 2e1c0855159..4c0a6923a3c 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -1732,11 +1732,10 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) res = false; goto put_sock_ret_res; } - - if (do_tag_stat) - account_for_uid(skb, sk, sock_uid, par); - sock_uid = sk->sk_uid; + if (do_tag_stat) + account_for_uid(skb, sk, from_kuid(&init_user_ns, sock_uid), + par); /* * The following two tests fail the match when: @@ -1763,16 +1762,18 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) set_sk_callback_lock = true; read_lock_bh(&sk->sk_callback_lock); MT_DEBUG("qtaguid[%d]: sk=%p->sk_socket=%p->file=%p\n", - par->hooknum, sk, sk->sk_socket, - sk->sk_socket ? sk->sk_socket->file : (void *)-1LL); + par->hooknum, sk, sk->sk_socket, + sk->sk_socket ? sk->sk_socket->file : (void *)-1LL); filp = sk->sk_socket ? sk->sk_socket->file : NULL; if (!filp) { - res = ((info->match ^ info->invert) & XT_QTAGUID_GID) == 0; + res = ((info->match ^ info->invert) & + XT_QTAGUID_GID) == 0; atomic64_inc(&qtu_events.match_no_sk_gid); goto put_sock_ret_res; } MT_DEBUG("qtaguid[%d]: filp...uid=%u\n", - par->hooknum, filp ? from_kuid(&init_user_ns, filp->f_cred->fsuid) : -1); + par->hooknum, filp ? + from_kuid(&init_user_ns, filp->f_cred->fsuid) : -1); if ((gid_gte(filp->f_cred->fsgid, gid_min) && gid_lte(filp->f_cred->fsgid, gid_max)) ^ !(info->invert & XT_QTAGUID_GID)) { @@ -1918,7 +1919,7 @@ static int qtaguid_ctrl_proc_show(struct seq_file *m, void *v) if (sock_tag_entry != SEQ_START_TOKEN) { int sk_ref_count; uid = get_uid_from_tag(sock_tag_entry->tag); - CT_DEBUG("qtaguid: proc_read(): sk=%pK tag=0x%llx (uid=%u) " + CT_DEBUG("qtaguid: proc_read(): sk=%p tag=0x%llx (uid=%u) " "pid=%u\n", sock_tag_entry->sk, sock_tag_entry->tag, diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 0773e3ad991..68934c1bae1 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -3186,14 +3186,19 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (optlen != sizeof(val)) return -EINVAL; - if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) - return -EBUSY; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; if (val > INT_MAX) return -EINVAL; - po->tp_reserve = val; - return 0; + lock_sock(sk); + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { + ret = -EBUSY; + } else { + po->tp_reserve = val; + ret = 0; + } + release_sock(sk); + return ret; } case PACKET_LOSS: { @@ -3341,6 +3346,8 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, case PACKET_HDRLEN: if (len > sizeof(int)) len = sizeof(int); + if (len < sizeof(int)) + return -EINVAL; if (copy_from_user(&val, optval, len)) return -EFAULT; switch (val) { diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 959104648f6..352cb5570cb 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -800,8 +800,7 @@ void rfkill_resume_polling(struct rfkill *rfkill) if (!rfkill->ops->poll) return; - queue_delayed_work(system_power_efficient_wq, - &rfkill->poll_work, 0); + schedule_work(&rfkill->poll_work.work); } EXPORT_SYMBOL(rfkill_resume_polling); @@ -909,8 +908,7 @@ static void rfkill_poll(struct work_struct *work) */ rfkill->ops->poll(rfkill, rfkill->data); - queue_delayed_work(system_power_efficient_wq, - &rfkill->poll_work, + schedule_delayed_work(&rfkill->poll_work, round_jiffies_relative(POLL_INTERVAL)); } @@ -974,8 +972,7 @@ int __must_check rfkill_register(struct rfkill *rfkill) INIT_WORK(&rfkill->sync_work, rfkill_sync_work); if (rfkill->ops->poll) - queue_delayed_work(system_power_efficient_wq, - &rfkill->poll_work, + schedule_delayed_work(&rfkill->poll_work, round_jiffies_relative(POLL_INTERVAL)); if (!rfkill->persistent || rfkill_epo_lock_active) { diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 7633a752c65..10e6e5de36e 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -213,7 +213,7 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, unsigned int *_toklen) { const __be32 *xdr = *_xdr; - unsigned int toklen = *_toklen, n_parts, loop, tmp; + unsigned int toklen = *_toklen, n_parts, loop, tmp, paddedlen; /* there must be at least one name, and at least #names+1 length * words */ @@ -243,16 +243,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, toklen -= 4; if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX) return -EINVAL; - if (tmp > toklen) + paddedlen = (tmp + 3) & ~3; + if (paddedlen > toklen) return -EINVAL; princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL); if (!princ->name_parts[loop]) return -ENOMEM; memcpy(princ->name_parts[loop], xdr, tmp); princ->name_parts[loop][tmp] = 0; - tmp = (tmp + 3) & ~3; - toklen -= tmp; - xdr += tmp >> 2; + toklen -= paddedlen; + xdr += paddedlen >> 2; } if (toklen < 4) @@ -261,16 +261,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, toklen -= 4; if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX) return -EINVAL; - if (tmp > toklen) + paddedlen = (tmp + 3) & ~3; + if (paddedlen > toklen) return -EINVAL; princ->realm = kmalloc(tmp + 1, GFP_KERNEL); if (!princ->realm) return -ENOMEM; memcpy(princ->realm, xdr, tmp); princ->realm[tmp] = 0; - tmp = (tmp + 3) & ~3; - toklen -= tmp; - xdr += tmp >> 2; + toklen -= paddedlen; + xdr += paddedlen >> 2; _debug("%s/...@%s", princ->name_parts[0], princ->realm); @@ -289,7 +289,7 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, unsigned int *_toklen) { const __be32 *xdr = *_xdr; - unsigned int toklen = *_toklen, len; + unsigned int toklen = *_toklen, len, paddedlen; /* there must be at least one tag and one length word */ if (toklen <= 8) @@ -303,15 +303,17 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, toklen -= 8; if (len > max_data_size) return -EINVAL; + paddedlen = (len + 3) & ~3; + if (paddedlen > toklen) + return -EINVAL; td->data_len = len; if (len > 0) { td->data = kmemdup(xdr, len, GFP_KERNEL); if (!td->data) return -ENOMEM; - len = (len + 3) & ~3; - toklen -= len; - xdr += len >> 2; + toklen -= paddedlen; + xdr += paddedlen >> 2; } _debug("tag %x len %x", td->tag, td->data_len); @@ -383,7 +385,7 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, const __be32 **_xdr, unsigned int *_toklen) { const __be32 *xdr = *_xdr; - unsigned int toklen = *_toklen, len; + unsigned int toklen = *_toklen, len, paddedlen; /* there must be at least one length word */ if (toklen <= 4) @@ -395,6 +397,9 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, toklen -= 4; if (len > AFSTOKEN_K5_TIX_MAX) return -EINVAL; + paddedlen = (len + 3) & ~3; + if (paddedlen > toklen) + return -EINVAL; *_tktlen = len; _debug("ticket len %u", len); @@ -403,9 +408,8 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, *_ticket = kmemdup(xdr, len, GFP_KERNEL); if (!*_ticket) return -ENOMEM; - len = (len + 3) & ~3; - toklen -= len; - xdr += len >> 2; + toklen -= paddedlen; + xdr += paddedlen >> 2; } *_xdr = xdr; @@ -549,7 +553,7 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal { const __be32 *xdr = data, *token; const char *cp; - unsigned int len, tmp, loop, ntoken, toklen, sec_ix; + unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix; int ret; _enter(",{%x,%x,%x,%x},%zu", @@ -574,22 +578,21 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal if (len < 1 || len > AFSTOKEN_CELL_MAX) goto not_xdr; datalen -= 4; - tmp = (len + 3) & ~3; - if (tmp > datalen) + paddedlen = (len + 3) & ~3; + if (paddedlen > datalen) goto not_xdr; cp = (const char *) xdr; for (loop = 0; loop < len; loop++) if (!isprint(cp[loop])) goto not_xdr; - if (len < tmp) - for (; loop < tmp; loop++) - if (cp[loop]) - goto not_xdr; + for (; loop < paddedlen; loop++) + if (cp[loop]) + goto not_xdr; _debug("cellname: [%u/%u] '%*.*s'", - len, tmp, len, len, (const char *) xdr); - datalen -= tmp; - xdr += tmp >> 2; + len, paddedlen, len, len, (const char *) xdr); + datalen -= paddedlen; + xdr += paddedlen >> 2; /* get the token count */ if (datalen < 12) @@ -610,10 +613,11 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal sec_ix = ntohl(*xdr); datalen -= 4; _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix); - if (toklen < 20 || toklen > datalen) + paddedlen = (toklen + 3) & ~3; + if (toklen < 20 || toklen > datalen || paddedlen > datalen) goto not_xdr; - datalen -= (toklen + 3) & ~3; - xdr += (toklen + 3) >> 2; + datalen -= paddedlen; + xdr += paddedlen >> 2; } while (--loop > 0); diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 486c551a4de..ceb8f849777 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -492,7 +492,9 @@ static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr, { addr->sa.sa_family = AF_INET6; addr->v6.sin6_port = port; + addr->v6.sin6_flowinfo = 0; addr->v6.sin6_addr = *saddr; + addr->v6.sin6_scope_id = 0; } /* Compare addresses exactly. diff --git a/net/wireless/core.h b/net/wireless/core.h index f0de1503afe..589135c3775 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -69,7 +69,6 @@ struct cfg80211_registered_device { struct list_head bss_list; struct rb_root bss_tree; u32 bss_generation; - u32 bss_entries; struct cfg80211_scan_request *scan_req; /* protected by RTNL */ struct cfg80211_sched_scan_request *sched_scan_req; unsigned long suspend_at; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index bf0bce47b35..4700f2551b3 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -310,8 +310,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, [NL80211_ATTR_PID] = { .type = NLA_U32 }, [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, - [NL80211_ATTR_PMKID] = { .type = NLA_BINARY, - .len = WLAN_PMKID_LEN }, + [NL80211_ATTR_PMKID] = { .len = WLAN_PMKID_LEN }, [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, @@ -366,6 +365,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, + [NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 }, [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 }, [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, @@ -5212,6 +5212,10 @@ static int validate_scan_freqs(struct nlattr *freqs) struct nlattr *attr1, *attr2; int n_channels = 0, tmp1, tmp2; + nla_for_each_nested(attr1, freqs, tmp1) + if (nla_len(attr1) != sizeof(u32)) + return 0; + nla_for_each_nested(attr1, freqs, tmp1) { n_channels++; /* @@ -8305,6 +8309,9 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) if (err) return err; + if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] || + !tb[NL80211_REKEY_DATA_KCK]) + return -EINVAL; if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN) return -ERANGE; if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN) @@ -11321,11 +11328,11 @@ int nl80211_init(void) err = genl_register_mc_group(&nl80211_fam, &nl80211_testmode_mcgrp); if (err) goto err_out; -#endif err = genl_register_mc_group(&nl80211_fam, &nl80211_vendor_mcgrp); if (err) goto err_out; +#endif err = netlink_register_notifier(&nl80211_netlink_notifier); if (err) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 30ed665f1c6..1ef1f150a10 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1588,8 +1588,8 @@ static void reg_process_hint(struct regulatory_request *reg_request, break; default: if (reg_initiator == NL80211_REGDOM_SET_BY_USER) - queue_delayed_work(system_power_efficient_wq, - ®_timeout, msecs_to_jiffies(3142)); + schedule_delayed_work(®_timeout, + msecs_to_jiffies(3142)); break; } } @@ -2191,8 +2191,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) if (!request_wiphy && (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) { - queue_delayed_work(system_power_efficient_wq, - ®_timeout, 0); + schedule_delayed_work(®_timeout, 0); return -ENODEV; } diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 950d1a0b39a..b63fa8d8d37 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -55,20 +55,7 @@ * also linked into the probe response struct. */ -/* - * Limit the number of BSS entries stored in mac80211. Each one is - * a bit over 4k at most, so this limits to roughly 4-5M of memory. - * If somebody wants to really attack this though, they'd likely - * use small beacons, and only one type of frame, limiting each of - * the entries to a much smaller size (in order to generate more - * entries in total, so overhead is bigger.) - */ -static int bss_entries_limit = 1000; -module_param(bss_entries_limit, int, 0644); -MODULE_PARM_DESC(bss_entries_limit, - "limit to number of scan BSS entries (per wiphy, default 1000)"); - -#define IEEE80211_SCAN_RESULT_EXPIRE (3 * HZ) +#define IEEE80211_SCAN_RESULT_EXPIRE (7 * HZ) static void bss_free(struct cfg80211_internal_bss *bss) { @@ -148,10 +135,6 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *dev, list_del_init(&bss->list); rb_erase(&bss->rbn, &dev->bss_tree); - dev->bss_entries--; - WARN_ONCE((dev->bss_entries == 0) ^ list_empty(&dev->bss_list), - "rdev bss entries[%d]/list[empty:%d] corruption\n", - dev->bss_entries, list_empty(&dev->bss_list)); bss_ref_put(dev, bss); return true; } @@ -355,40 +338,6 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev) __cfg80211_bss_expire(dev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE); } -static bool cfg80211_bss_expire_oldest(struct cfg80211_registered_device *rdev) -{ - struct cfg80211_internal_bss *bss, *oldest = NULL; - bool ret; - - lockdep_assert_held(&rdev->bss_lock); - - list_for_each_entry(bss, &rdev->bss_list, list) { - if (atomic_read(&bss->hold)) - continue; - - if (!list_empty(&bss->hidden_list) && - !bss->pub.hidden_beacon_bss) - continue; - - if (oldest && time_before(oldest->ts, bss->ts)) - continue; - oldest = bss; - } - - if (WARN_ON(!oldest)) - return false; - - /* - * The callers make sure to increase rdev->bss_generation if anything - * gets removed (and a new entry added), so there's no need to also do - * it here. - */ - - ret = __cfg80211_unlink_bss(rdev, oldest); - WARN_ON(!ret); - return ret; -} - const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len) { while (len > 2 && ies[0] != eid) { @@ -673,7 +622,6 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, const u8 *ie; int i, ssidlen; u8 fold = 0; - u32 n_entries = 0; ies = rcu_access_pointer(new->pub.beacon_ies); if (WARN_ON(!ies)) @@ -697,12 +645,6 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, /* This is the bad part ... */ list_for_each_entry(bss, &dev->bss_list, list) { - /* - * we're iterating all the entries anyway, so take the - * opportunity to validate the list length accounting - */ - n_entries++; - if (!ether_addr_equal(bss->pub.bssid, new->pub.bssid)) continue; if (bss->pub.channel != new->pub.channel) @@ -732,10 +674,6 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, new->pub.beacon_ies); } - WARN_ONCE(n_entries != dev->bss_entries, - "rdev bss entries[%d]/list[len:%d] corruption\n", - dev->bss_entries, n_entries); - return true; } @@ -880,14 +818,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, } } - if (dev->bss_entries >= bss_entries_limit && - !cfg80211_bss_expire_oldest(dev)) { - kfree(new); - goto drop; - } - list_add_tail(&new->list, &dev->bss_list); - dev->bss_entries++; rb_insert_bss(dev, new); found = new; } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index ea970b8002a..10c556e373b 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -3201,9 +3201,15 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_state *x_new[XFRM_MAX_DEPTH]; struct xfrm_migrate *mp; + /* Stage 0 - sanity checks */ if ((err = xfrm_migrate_check(m, num_migrate)) < 0) goto out; + if (dir >= XFRM_POLICY_MAX) { + err = -EINVAL; + goto out; + } + /* Stage 1 - find policy */ if ((pol = xfrm_migrate_policy_find(sel, dir, type)) == NULL) { err = -ENOENT; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 862e54de538..dc50af30312 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -404,6 +404,9 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es if (up->replay_window > up->bmp_len * sizeof(__u32) * 8) return -EINVAL; + if (up->replay_window > up->bmp_len * sizeof(__u32) * 8) + return -EINVAL; + return 0; } diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 09ad65a0c16..8fcc5ce0572 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -184,7 +184,7 @@ else # LOCALVERSION= is not specified if test "${LOCALVERSION+set}" != "set"; then scm=$(scm_version --short) - res="$res" + res="$res${scm:++}" fi fi diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index c4c8df4b214..b7d7cffe734 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -315,6 +315,13 @@ static struct key *request_user_key(const char *master_desc, u8 **master_key, down_read(&ukey->sem); upayload = ukey->payload.data; + if (!upayload) { + /* key was revoked before we acquired its semaphore */ + up_read(&ukey->sem); + key_put(ukey); + ukey = ERR_PTR(-EKEYREVOKED); + goto error; + } *master_key = upayload->data; *master_keylen = upayload->datalen; error: @@ -428,7 +435,7 @@ static int init_blkcipher_desc(struct blkcipher_desc *desc, const u8 *key, static struct key *request_master_key(struct encrypted_key_payload *epayload, u8 **master_key, size_t *master_keylen) { - struct key *mkey = NULL; + struct key *mkey = ERR_PTR(-EINVAL); if (!strncmp(epayload->master_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) { diff --git a/security/keys/internal.h b/security/keys/internal.h index d4f1468b9b5..ce6d4634a84 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -126,7 +126,7 @@ extern key_ref_t search_process_keyrings(struct key_type *type, key_match_func_t match, const struct cred *cred); -extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); +extern struct key *find_keyring_by_name(const char *name, bool uid_keyring); extern int install_user_keyrings(void); extern int install_thread_keyring_to_cred(struct cred *); diff --git a/security/keys/key.c b/security/keys/key.c index 6595b2dd89f..248c2e73137 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -299,6 +299,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) key->flags |= 1 << KEY_FLAG_IN_QUOTA; + if (flags & KEY_ALLOC_UID_KEYRING) + key->flags |= 1 << KEY_FLAG_UID_KEYRING; memset(&key->type_data, 0, sizeof(key->type_data)); @@ -897,6 +899,16 @@ error: */ __key_link_end(keyring, ktype, prealloc); + key = key_ref_to_ptr(key_ref); + if (test_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) { + ret = wait_for_key_construction(key, true); + if (ret < 0) { + key_ref_put(key_ref); + key_ref = ERR_PTR(ret); + goto error_free_prep; + } + } + key_ref = __key_update(key_ref, &prep); goto error_free_prep; } diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 066baa1926b..7576f49eeb3 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -93,7 +93,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, payload = NULL; vm = false; - if (_payload) { + if (plen) { ret = -ENOMEM; payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN); if (!payload) { @@ -327,7 +327,7 @@ long keyctl_update_key(key_serial_t id, /* pull the payload in if one was supplied */ payload = NULL; - if (_payload) { + if (plen) { ret = -ENOMEM; payload = kmalloc(plen, GFP_KERNEL); if (!payload) diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 6ece7f2e570..b0cabf68c67 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -583,15 +583,15 @@ found: /* * Find a keyring with the specified name. * - * All named keyrings in the current user namespace are searched, provided they - * grant Search permission directly to the caller (unless this check is - * skipped). Keyrings whose usage points have reached zero or who have been - * revoked are skipped. + * Only keyrings that have nonzero refcount, are not revoked, and are owned by a + * user in the current user namespace are considered. If @uid_keyring is %true, + * the keyring additionally must have been allocated as a user or user session + * keyring; otherwise, it must grant Search permission directly to the caller. * * Returns a pointer to the keyring with the keyring's refcount having being * incremented on success. -ENOKEY is returned if a key could not be found. */ -struct key *find_keyring_by_name(const char *name, bool skip_perm_check) +struct key *find_keyring_by_name(const char *name, bool uid_keyring) { struct key *keyring; int bucket; @@ -619,10 +619,15 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) if (strcmp(keyring->description, name) != 0) continue; - if (!skip_perm_check && - key_permission(make_key_ref(keyring, 0), - KEY_SEARCH) < 0) - continue; + if (uid_keyring) { + if (!test_bit(KEY_FLAG_UID_KEYRING, + &keyring->flags)) + continue; + } else { + if (key_permission(make_key_ref(keyring, 0), + KEY_SEARCH) < 0) + continue; + } /* we've got a match but we might end up racing with * key_cleanup() if the keyring is currently 'dead' diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 7a5abb2b9d5..1c963ff8968 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -76,7 +76,9 @@ int install_user_keyrings(void) if (IS_ERR(uid_keyring)) { uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, cred, user_keyring_perm, - KEY_ALLOC_IN_QUOTA, NULL); + KEY_ALLOC_UID_KEYRING | + KEY_ALLOC_IN_QUOTA, + NULL); if (IS_ERR(uid_keyring)) { ret = PTR_ERR(uid_keyring); goto error; @@ -92,7 +94,9 @@ int install_user_keyrings(void) session_keyring = keyring_alloc(buf, user->uid, INVALID_GID, cred, user_keyring_perm, - KEY_ALLOC_IN_QUOTA, NULL); + KEY_ALLOC_UID_KEYRING | + KEY_ALLOC_IN_QUOTA, + NULL); if (IS_ERR(session_keyring)) { ret = PTR_ERR(session_keyring); goto error_release; diff --git a/security/selinux/avc.c b/security/selinux/avc.c index ec8c4883bd3..386aafb2e69 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -626,7 +626,7 @@ static int avc_latest_notif_update(int seqno, int is_insert) spin_lock_irqsave(¬if_lock, flag); if (is_insert) { if (seqno < avc_cache.latest_notif) { - pr_debug(KERN_WARNING "SELinux: avc: seqno %d < latest_notif %d\n", + printk(KERN_WARNING "SELinux: avc: seqno %d < latest_notif %d\n", seqno, avc_cache.latest_notif); ret = -EAGAIN; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3dc771cbd3b..60e1a58c544 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -435,6 +435,7 @@ static int sb_finish_set_opts(struct super_block *sb) if (!strcmp(sb->s_type->name, "sysfs") || !strcmp(sb->s_type->name, "pstore") || !strcmp(sb->s_type->name, "debugfs") || + !strcmp(sb->s_type->name, "tracefs") || !strcmp(sb->s_type->name, "rootfs")) sbsec->flags |= SE_SBLABELSUPP; @@ -445,6 +446,13 @@ static int sb_finish_set_opts(struct super_block *sb) if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0) sbsec->flags |= SE_SBLABELSUPP; + /* + * Special handling for rootfs. Is genfs but supports + * setting SELinux context on in-core inodes. + */ + if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0) + sbsec->flags |= SE_SBLABELSUPP; + /* Initialize the root inode. */ rc = inode_doinit_with_dentry(root_inode, root); @@ -710,6 +718,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, sbsec->flags |= SE_SBPROC | SE_SBGENFS; if (!strcmp(sb->s_type->name, "debugfs") || + !strcmp(sb->s_type->name, "tracefs") || !strcmp(sb->s_type->name, "sysfs") || !strcmp(sb->s_type->name, "pstore")) sbsec->flags |= SE_SBGENFS; diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 11a2f16c0f9..bbe684ddc81 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -46,13 +46,6 @@ #define U32_MAX ((u32)~0U) -/* struct snd_compr_codec_caps overflows the ioctl bit size for some - * architectures, so we need to disable the relevant ioctls. - */ -#if _IOC_SIZEBITS < 14 -#define COMPR_CODEC_CAPS_OVERFLOW -#endif - /* TODO: * - add substream support for multiple devices in case of * SND_DYNAMIC_MINORS is not used @@ -452,7 +445,6 @@ out: return retval; } -#ifndef COMPR_CODEC_CAPS_OVERFLOW static int snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg) { @@ -476,7 +468,6 @@ out: kfree(caps); return retval; } -#endif /* !COMPR_CODEC_CAPS_OVERFLOW */ /* revisit this with snd_pcm_preallocate_xxx */ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, @@ -851,13 +842,6 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) mutex_lock(&stream->device->lock); switch (_IOC_NR(cmd)) { - -#ifndef COMPR_CODEC_CAPS_OVERFLOW - case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS): - retval = snd_compr_get_codec_caps(stream, arg); - break; -#endif - case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS): retval = snd_compr_set_params(stream, arg); break; diff --git a/sound/core/control.c b/sound/core/control.c index 251bc575f5c..c3928261136 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1088,7 +1088,7 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol, mutex_lock(&ue->card->user_ctl_lock); change = ue->tlv_data_size != size; if (!change) - change = memcmp(ue->tlv_data, new_data, size); + change = memcmp(ue->tlv_data, new_data, size) != 0; kfree(ue->tlv_data); ue->tlv_data = new_data; ue->tlv_data_size = size; diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile index 2dfca79ef50..96137eac2f5 100644 --- a/sound/soc/msm/qdsp6v2/Makefile +++ b/sound/soc/msm/qdsp6v2/Makefile @@ -9,7 +9,6 @@ snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o msm-pcm-routing-v2.o \ obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o \ msm-dai-stub-v2.o obj-$(CONFIG_SND_HWDEP) += msm-pcm-routing-devdep.o -obj-$(CONFIG_DTS_EAGLE) += msm-dts-eagle.o obj-$(CONFIG_DOLBY_DAP) += msm-dolby-dap-config.o obj-$(CONFIG_DOLBY_DS2) += msm-ds2-dap-config.o obj-$(CONFIG_DTS_SRS_TM) += msm-dts-srs-tm-config.o diff --git a/sound/soc/msm/qdsp6v2/audio_cal_utils.c b/sound/soc/msm/qdsp6v2/audio_cal_utils.c index 562e9a121d4..07c5b5b7f0f 100644 --- a/sound/soc/msm/qdsp6v2/audio_cal_utils.c +++ b/sound/soc/msm/qdsp6v2/audio_cal_utils.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -136,8 +136,6 @@ size_t get_cal_info_size(int32_t cal_type) case ULP_LSM_CAL_TYPE: size = sizeof(struct audio_cal_info_lsm); break; - case DTS_EAGLE_CAL_TYPE: - size = 0; case AUDIO_CORE_METAINFO_CAL_TYPE: size = sizeof(struct audio_cal_info_metainfo); break; @@ -263,8 +261,6 @@ size_t get_user_cal_type_size(int32_t cal_type) case ULP_LSM_CAL_TYPE: size = sizeof(struct audio_cal_type_lsm); break; - case DTS_EAGLE_CAL_TYPE: - size = 0; case AUDIO_CORE_METAINFO_CAL_TYPE: size = sizeof(struct audio_cal_type_metainfo); break; @@ -567,7 +563,6 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, memset(cal_block, 0, sizeof(*cal_block)); INIT_LIST_HEAD(&cal_block->list); - list_add_tail(&cal_block->list, &cal_type->cal_blocks); cal_block->map_data.ion_map_handle = basic_cal->cal_data.mem_handle; if (basic_cal->cal_data.mem_handle > 0) { @@ -599,6 +594,7 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, goto err; } cal_block->buffer_number = basic_cal->cal_hdr.buffer_number; + list_add_tail(&cal_block->list, &cal_type->cal_blocks); pr_debug("%s: created block for cal type %d, buf num %d, map handle %d, map size %zd paddr 0x%pK!\n", __func__, cal_type->info.reg.cal_type, cal_block->buffer_number, @@ -608,6 +604,10 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, done: return cal_block; err: + kfree(cal_block->cal_info); + cal_block->cal_info = NULL; + kfree(cal_block->client_info); + cal_block->client_info = NULL; kfree(cal_block); cal_block = NULL; return cal_block; diff --git a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c index 1c08842c784..1286d318578 100644 --- a/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-audio-effects-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -15,7 +15,6 @@ #include <sound/q6asm-v2.h> #include <sound/compress_params.h> #include <sound/msm-audio-effects-q6-v2.h> -#include <sound/msm-dts-eagle.h> #include <sound/devdep_params.h> #define MAX_ENABLE_CMD_SIZE 32 @@ -49,26 +48,6 @@ bool msm_audio_effects_is_effmodule_supp_in_top(int effect_module, case EQ_MODULE: switch (topology) { case ASM_STREAM_POSTPROC_TOPO_ID_SA_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - return true; - default: - return false; - } - case DTS_EAGLE_MODULE: - switch (topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: - return true; - default: - return false; - } - case SOFT_VOLUME2_MODULE: - case DTS_EAGLE_MODULE_ENABLE: - switch (topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER: return true; default: return false; @@ -176,7 +155,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "VIRT ENABLE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; *updt_params++ = @@ -204,7 +183,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "VIRT STRENGTH", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; *updt_params++ = @@ -232,7 +211,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "VIRT OUT_TYPE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; *updt_params++ = @@ -260,7 +239,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "VIRT GAIN_ADJUST", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_VIRTUALIZER; *updt_params++ = @@ -276,7 +255,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -339,7 +318,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_ENABLE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -367,7 +346,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_MODE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -395,7 +374,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_PRESET", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -423,7 +402,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_WET_MIX", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -451,7 +430,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_GAIN_ADJUST", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -479,7 +458,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_ROOM_LEVEL", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -507,7 +486,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_ROOM_HF_LEVEL", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -535,7 +514,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_DECAY_TIME", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -563,7 +542,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_DECAY_HF_RATIO", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -591,7 +570,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_REFLECTIONS_LEVEL", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -619,7 +598,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_REFLECTIONS_DELAY", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -647,7 +626,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_LEVEL", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -675,7 +654,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_DELAY", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -703,7 +682,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_DIFFUSION", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -731,7 +710,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "REVERB_DENSITY", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_REVERB; *updt_params++ = @@ -747,7 +726,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -811,7 +790,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "BASS_BOOST_ENABLE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST; *updt_params++ = @@ -839,7 +818,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "BASS_BOOST_MODE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST; *updt_params++ = @@ -867,7 +846,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "BASS_BOOST_STRENGTH", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_BASS_BOOST; *updt_params++ = @@ -883,7 +862,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -945,7 +924,7 @@ int msm_audio_effects_pbe_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "PBE_ENABLE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_PBE; *updt_params++ = @@ -971,7 +950,7 @@ int msm_audio_effects_pbe_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "PBE_PARAM", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_PBE; *updt_params++ = @@ -1056,7 +1035,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "EQ_ENABLE", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; *updt_params++ = @@ -1124,7 +1103,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "EQ_CONFIG", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; *updt_params++ = @@ -1175,7 +1154,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "EQ_BAND_INDEX", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; *updt_params++ = @@ -1207,7 +1186,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, MAX_INBAND_PARAM_SZ, "EQ_SINGLE_BAND_FREQ", rc); if (rc != 0) - break; + goto invalid_config; *updt_params++ = AUDPROC_MODULE_ID_POPLESS_EQUALIZER; *updt_params++ = @@ -1223,7 +1202,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, break; } } - if (params_length && !msm_dts_eagle_is_hpx_on() && (rc == 0)) + if (params_length && (rc == 0)) q6asm_send_audio_effects_params(ac, params, params_length); else @@ -1297,7 +1276,7 @@ static int __msm_audio_effects_volume_handler(struct audio_client *ac, "VOLUME/VOLUME2_GAIN_2CH", rc); if (rc != 0) - break; + goto invalid_config; if (instance == SOFT_VOLUME_INSTANCE_2) *updt_params++ = ASM_MODULE_ID_VOL_CTRL2; @@ -1346,7 +1325,7 @@ static int __msm_audio_effects_volume_handler(struct audio_client *ac, "VOLUME/VOLUME2_GAIN_MASTER", rc); if (rc != 0) - break; + goto invalid_config; if (instance == SOFT_VOLUME_INSTANCE_2) *updt_params++ = ASM_MODULE_ID_VOL_CTRL2; diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index da110c53102..bc0278c1769 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -43,8 +43,6 @@ #include <sound/compress_offload.h> #include <sound/compress_driver.h> #include <sound/msm-audio-effects-q6-v2.h> -#include <sound/msm-dts-eagle.h> - #include "msm-pcm-routing-v2.h" #include "audio_ocmem.h" @@ -83,15 +81,6 @@ const DECLARE_TLV_DB_LINEAR(msm_compr_vol_gain, 0, #define MAX_NUMBER_OF_STREAMS 2 -/* - * Max size for getting DTS EAGLE Param through kcontrol - * Safe for both 32 and 64 bit platforms - * 64 = size of kcontrol value array on 64 bit platform - * 4 = size of parameters Eagle expects before cast to 64 bits - * 40 = size of dts_eagle_param_desc + module_id cast to 64 bits - */ -#define DTS_EAGLE_MAX_PARAM_SIZE_FOR_ALSA ((64 * 4) - 40) - struct msm_compr_gapless_state { bool set_next_stream_id; int32_t stream_opened[MAX_NUMBER_OF_STREAMS]; @@ -310,11 +299,6 @@ static int msm_compr_set_volume(struct snd_compr_stream *cstream, if (rc < 0) pr_err("%s: Send vol gain command failed rc=%d\n", __func__, rc); - else - if (msm_dts_eagle_set_stream_gain(prtd->audio_client, - volume_l, volume_r)) - pr_debug("%s: DTS_EAGLE send stream gain failed\n", - __func__); return rc; } @@ -929,26 +913,6 @@ static int msm_compr_init_pp_params(struct snd_compr_stream *cstream, }; switch (ac->topology) { - case ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS: /* HPX + SA+ topology */ - - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_1); - if (ret < 0) - pr_err("%s: Send SoftVolume Param failed ret=%d\n", - __func__, ret); - - ret = q6asm_set_softvolume_v2(ac, &softvol, - SOFT_VOLUME_INSTANCE_2); - if (ret < 0) - pr_err("%s: Send SoftVolume2 Param failed ret=%d\n", - __func__, ret); - /* - * HPX module init is trigerred from HAL using ioctl - * DTS_EAGLE_MODULE_ENABLE when stream starts - */ - break; - case ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX: /* HPX topology */ - break; default: ret = q6asm_set_softvolume_v2(ac, &softvol, SOFT_VOLUME_INSTANCE_1); @@ -2451,23 +2415,6 @@ static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol, &(audio_effects->equalizer), values); break; - case DTS_EAGLE_MODULE: - pr_debug("%s: DTS_EAGLE_MODULE\n", __func__); - if (!msm_audio_effects_is_effmodule_supp_in_top(effects_module, - prtd->audio_client->topology)) - return 0; - msm_dts_eagle_handle_asm(NULL, (void *)values, true, - false, prtd->audio_client, NULL); - break; - case DTS_EAGLE_MODULE_ENABLE: - pr_debug("%s: DTS_EAGLE_MODULE_ENABLE\n", __func__); - if (msm_audio_effects_is_effmodule_supp_in_top(effects_module, - prtd->audio_client->topology)) - msm_dts_eagle_enable_asm(prtd->audio_client, - (bool)values[0], - AUDPROC_MODULE_ID_DTS_HPX_PREMIX); - - break; case SOFT_VOLUME_MODULE: pr_debug("%s: SOFT_VOLUME_MODULE\n", __func__); break; @@ -2496,7 +2443,6 @@ static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol, struct msm_compr_audio_effects *audio_effects = NULL; struct snd_compr_stream *cstream = NULL; struct msm_compr_audio *prtd = NULL; - long *values = &(ucontrol->value.integer.value[0]); pr_debug("%s\n", __func__); if (fe_id >= MSM_FRONTEND_DAI_MAX) { @@ -2516,28 +2462,6 @@ static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol, return -EINVAL; } - switch (audio_effects->query.mod_id) { - case DTS_EAGLE_MODULE: - pr_debug("%s: DTS_EAGLE_MODULE handling queued get\n", - __func__); - values[0] = (long)audio_effects->query.mod_id; - values[1] = (long)audio_effects->query.parm_id; - values[2] = (long)audio_effects->query.size; - values[3] = (long)audio_effects->query.offset; - values[4] = (long)audio_effects->query.device; - if (values[2] > DTS_EAGLE_MAX_PARAM_SIZE_FOR_ALSA) { - pr_err("%s: DTS_EAGLE_MODULE parameter's requested size (%li) too large (max size is %i)\n", - __func__, values[2], - DTS_EAGLE_MAX_PARAM_SIZE_FOR_ALSA); - return -EINVAL; - } - msm_dts_eagle_handle_asm(NULL, (void *)&values[1], - true, true, prtd->audio_client, NULL); - break; - default: - pr_err("%s: Invalid effects config module\n", __func__); - return -EINVAL; - } return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-dts-eagle.c b/sound/soc/msm/qdsp6v2/msm-dts-eagle.c deleted file mode 100644 index 3e76acf9ea0..00000000000 --- a/sound/soc/msm/qdsp6v2/msm-dts-eagle.c +++ /dev/null @@ -1,1655 +0,0 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/init.h> -#include <linux/err.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/mutex.h> -#include <linux/slab.h> -#include <linux/msm_ion.h> -#include <linux/mm.h> -#include <linux/msm_audio_ion.h> -#include <linux/vmalloc.h> -#include <sound/core.h> -#include <sound/soc.h> -#include <sound/pcm.h> -#include <sound/q6adm-v2.h> -#include <sound/q6asm-v2.h> -#include <sound/apr_audio-v2.h> -#include <sound/q6audio-v2.h> -#include <sound/audio_effects.h> -#include <sound/hwdep.h> -#include <sound/msm-dts-eagle.h> -#include <sound/q6core.h> - -#include "msm-pcm-routing-v2.h" - -#define ION_MEM_SIZE 131072 -#define DEPC_MAX_SIZE 524288 - -#define MPST AUDPROC_MODULE_ID_DTS_HPX_POSTMIX -#define MPRE AUDPROC_MODULE_ID_DTS_HPX_PREMIX - -#define eagle_vol_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_VOLUME: " fmt "\n", ##__VA_ARGS__) -#define eagle_vol_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_VOLUME: " fmt "\n", ##__VA_ARGS__) -#define eagle_drv_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER: " fmt "\n", ##__VA_ARGS__) -#define eagle_drv_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER: " fmt "\n", ##__VA_ARGS__) -#define eagle_precache_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_SENDCACHE_PRE: " fmt "\n", ##__VA_ARGS__) -#define eagle_precache_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_SENDCACHE_PRE: " fmt "\n", ##__VA_ARGS__) -#define eagle_postcache_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_SENDCACHE_POST: " fmt "\n", ##__VA_ARGS__) -#define eagle_postcache_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_SENDCACHE_POST: " fmt "\n", ##__VA_ARGS__) -#define eagle_ioctl_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_IOCTL: " fmt "\n", ##__VA_ARGS__) -#define eagle_ioctl_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_IOCTL: " fmt "\n", ##__VA_ARGS__) -#define eagle_asm_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_ASM: " fmt "\n", ##__VA_ARGS__) -#define eagle_asm_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_ASM: " fmt "\n", ##__VA_ARGS__) -#define eagle_adm_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_DRIVER_ADM: " fmt "\n", ##__VA_ARGS__) -#define eagle_adm_err(fmt, ...) \ - pr_err("DTS_EAGLE_DRIVER_ADM: " fmt "\n", ##__VA_ARGS__) -#define eagle_enable_dbg(fmt, ...) \ - pr_debug("DTS_EAGLE_ENABLE: " fmt "\n", ##__VA_ARGS__) -#define eagle_enable_err(fmt, ...) \ - pr_err("DTS_EAGLE_ENABLE: " fmt "\n", ##__VA_ARGS__) -#define eagle_ioctl_info(fmt, ...) \ - pr_err("DTS_EAGLE_IOCTL: " fmt "\n", ##__VA_ARGS__) - -enum { - AUDIO_DEVICE_OUT_EARPIECE = 0, - AUDIO_DEVICE_OUT_SPEAKER, - AUDIO_DEVICE_OUT_WIRED_HEADSET, - AUDIO_DEVICE_OUT_WIRED_HEADPHONE, - AUDIO_DEVICE_OUT_BLUETOOTH_SCO, - AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, - AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, - AUDIO_DEVICE_OUT_AUX_DIGITAL, - AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET, - AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, - AUDIO_DEVICE_OUT_USB_ACCESSORY, - AUDIO_DEVICE_OUT_USB_DEVICE, - AUDIO_DEVICE_OUT_REMOTE_SUBMIX, - AUDIO_DEVICE_OUT_ANC_HEADSET, - AUDIO_DEVICE_OUT_ANC_HEADPHONE, - AUDIO_DEVICE_OUT_PROXY, - AUDIO_DEVICE_OUT_FM, - AUDIO_DEVICE_OUT_FM_TX, - - AUDIO_DEVICE_OUT_COUNT -}; - -#define AUDIO_DEVICE_COMBO 0x400000 /* bit 23 */ - -enum { /* cache block */ - CB_0 = 0, - CB_1, - CB_2, - CB_3, - CB_4, - CB_5, - CB_6, - CB_7, - - CB_COUNT -}; - -enum { /* cache block description */ - CBD_DEV_MASK = 0, - CBD_OFFSG, - CBD_CMD0, - CBD_SZ0, - CBD_OFFS1, - CBD_CMD1, - CBD_SZ1, - CBD_OFFS2, - CBD_CMD2, - CBD_SZ2, - CBD_OFFS3, - CBD_CMD3, - CBD_SZ3, - - CBD_COUNT, -}; - -static s32 _fx_logN(s32 x) -{ - s32 t, y = 0xa65af; - if (x < 0x00008000) { - x <<= 16; y -= 0xb1721; } - if (x < 0x00800000) { - x <<= 8; y -= 0x58b91; } - if (x < 0x08000000) { - x <<= 4; y -= 0x2c5c8; } - if (x < 0x20000000) { - x <<= 2; y -= 0x162e4; } - if (x < 0x40000000) { - x <<= 1; y -= 0x0b172; } - t = x + (x >> 1); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x067cd; } - t = x + (x >> 2); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x03920; } - t = x + (x >> 3); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x01e27; } - t = x + (x >> 4); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x00f85; } - t = x + (x >> 5); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x007e1; } - t = x + (x >> 6); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x003f8; } - t = x + (x >> 7); - if ((t & 0x80000000) == 0) { - x = t; y -= 0x001fe; } - x = 0x80000000 - x; - y -= x >> 15; - return y; -} - -static inline void *_getd(struct dts_eagle_param_desc *depd) -{ - return (void *)(((char *)depd) + sizeof(struct dts_eagle_param_desc)); -} - -static int _ref_cnt; -/* dts eagle parameter cache */ -static char *_depc; -static u32 _depc_size; -static s32 _c_bl[CB_COUNT][CBD_COUNT]; -static u32 _device_primary; -static u32 _device_all; -/* ION states */ -static struct ion_client *_ion_client; -static struct ion_handle *_ion_handle; -static struct param_outband _po; -static struct audio_client *_ac_NT; -static struct ion_client *_ion_client_NT; -static struct ion_handle *_ion_handle_NT; -static struct param_outband _po_NT; - -#define SEC_BLOB_MAX_CNT 10 -#define SEC_BLOB_MAX_SIZE 0x4004 /*extra 4 for size*/ -static char *_sec_blob[SEC_BLOB_MAX_CNT]; - -/* multi-copp support */ -static int _cidx[AFE_MAX_PORTS] = {-1}; - -/* volume controls */ -#define VOL_CMD_CNT_MAX 10 -static u32 _vol_cmd_cnt; -static s32 **_vol_cmds; -struct vol_cmds_d { - s32 d[4]; -}; -static struct vol_cmds_d *_vol_cmds_d; -static const s32 _log10_10_inv_x20 = 0x0008af84; - -/* hpx master control */ -static u32 _is_hpx_enabled; -/* flag to identify if slim be to be used */ -static u32 _use_slim_be; - -static void _volume_cmds_free(void) -{ - int i; - for (i = 0; i < _vol_cmd_cnt; i++) - kfree(_vol_cmds[i]); - _vol_cmd_cnt = 0; - kfree(_vol_cmds); - kfree(_vol_cmds_d); - _vol_cmds = NULL; - _vol_cmds_d = NULL; -} - -static s32 _volume_cmds_alloc1(s32 size) -{ - _volume_cmds_free(); - _vol_cmd_cnt = size; - _vol_cmds = kzalloc(_vol_cmd_cnt * sizeof(int *), GFP_KERNEL); - if (_vol_cmds) { - _vol_cmds_d = kzalloc(_vol_cmd_cnt * sizeof(struct vol_cmds_d), - GFP_KERNEL); - } else - _vol_cmd_cnt = 0; - if (_vol_cmds_d) - return 0; - _volume_cmds_free(); - return -ENOMEM; -} - -/* assumes size is equal or less than 0xFFF */ -static s32 _volume_cmds_alloc2(s32 idx, s32 size) -{ - kfree(_vol_cmds[idx]); - _vol_cmds[idx] = kzalloc(size, GFP_KERNEL); - if (_vol_cmds[idx]) - return 0; - _vol_cmds_d[idx].d[0] = 0; - return -ENOMEM; -} - -static void _init_cb_descs(void) -{ - int i; - for (i = 0; i < CB_COUNT; i++) { - _c_bl[i][CBD_DEV_MASK] = 0; - _c_bl[i][CBD_OFFSG] = _c_bl[i][CBD_OFFS1] = - _c_bl[i][CBD_OFFS2] = _c_bl[i][CBD_OFFS3] = - 0xFFFFFFFF; - _c_bl[i][CBD_CMD0] = _c_bl[i][CBD_SZ0] = - _c_bl[i][CBD_CMD1] = _c_bl[i][CBD_SZ1] = - _c_bl[i][CBD_CMD2] = _c_bl[i][CBD_SZ2] = - _c_bl[i][CBD_CMD3] = _c_bl[i][CBD_SZ3] = 0; - } -} - -static u32 _get_dev_mask_for_pid(int pid) -{ - switch (pid) { - case SLIMBUS_0_RX: - case AFE_PORT_ID_PRIMARY_MI2S_RX: - return (1 << AUDIO_DEVICE_OUT_EARPIECE) | - (1 << AUDIO_DEVICE_OUT_SPEAKER) | - (1 << AUDIO_DEVICE_OUT_WIRED_HEADSET) | - (1 << AUDIO_DEVICE_OUT_WIRED_HEADPHONE) | - (1 << AUDIO_DEVICE_OUT_ANC_HEADSET) | - (1 << AUDIO_DEVICE_OUT_ANC_HEADPHONE); - case INT_BT_SCO_RX: - return (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT); - case RT_PROXY_PORT_001_RX: - return (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) | - (1 << AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) | - (1 << AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) | - (1 << AUDIO_DEVICE_OUT_USB_ACCESSORY) | - (1 << AUDIO_DEVICE_OUT_USB_DEVICE) | - (1 << AUDIO_DEVICE_OUT_PROXY); - case HDMI_RX: - return 1 << AUDIO_DEVICE_OUT_AUX_DIGITAL; - case INT_FM_RX: - return 1 << AUDIO_DEVICE_OUT_FM; - case INT_FM_TX: - return 1 << AUDIO_DEVICE_OUT_FM_TX; - default: - return 0; - } -} - -static int _get_pid_from_dev(u32 device) -{ - if (device & (1 << AUDIO_DEVICE_OUT_EARPIECE) || - device & (1 << AUDIO_DEVICE_OUT_SPEAKER) || - device & (1 << AUDIO_DEVICE_OUT_WIRED_HEADSET) || - device & (1 << AUDIO_DEVICE_OUT_WIRED_HEADPHONE) || - device & (1 << AUDIO_DEVICE_OUT_ANC_HEADSET) || - device & (1 << AUDIO_DEVICE_OUT_ANC_HEADPHONE)) { - if (_use_slim_be) { - return SLIMBUS_0_RX; - } else { - return AFE_PORT_ID_PRIMARY_MI2S_RX; - } - } else if (device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO) || - device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) || - device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT)) { - return INT_BT_SCO_RX; - } else if (device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) || - device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) || - device & (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) || - device & (1 << AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) || - device & (1 << AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) || - device & (1 << AUDIO_DEVICE_OUT_USB_ACCESSORY) || - device & (1 << AUDIO_DEVICE_OUT_USB_DEVICE) || - device & (1 << AUDIO_DEVICE_OUT_PROXY)) { - return RT_PROXY_PORT_001_RX; - } else if (device & (1 << AUDIO_DEVICE_OUT_AUX_DIGITAL)) { - return HDMI_RX; - } else if (device & (1 << AUDIO_DEVICE_OUT_FM)) { - return INT_FM_RX; - } else if (device & (1 << AUDIO_DEVICE_OUT_FM_TX)) { - return INT_FM_TX; - } - return 0; -} - -static s32 _get_cb_for_dev(int device) -{ - s32 i; - if (device & AUDIO_DEVICE_COMBO) { - for (i = 0; i < CB_COUNT; i++) { - if ((_c_bl[i][CBD_DEV_MASK] & device) == device) - return i; - } - } else { - for (i = 0; i < CB_COUNT; i++) { - if ((_c_bl[i][CBD_DEV_MASK] & device) && - !(_c_bl[i][CBD_DEV_MASK] & AUDIO_DEVICE_COMBO)) - return i; - } - } - eagle_drv_err("%s: device %i not found", __func__, device); - return -EINVAL; -} - -static int _is_port_open_and_eagle(int pid) -{ - if (msm_routing_check_backend_enabled(pid)) - return 1; - return 1; -} - -static int _isNTDevice(u32 device) -{ - if (device & - ((1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) | - (1 << AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) | - (1 << AUDIO_DEVICE_OUT_AUX_DIGITAL))) - return 1; - return 0; -} - -static void _reg_ion_mem(void) -{ - int rc; - rc = msm_audio_ion_alloc("DTS_EAGLE", &_ion_client, &_ion_handle, - ION_MEM_SIZE, &_po.paddr, &_po.size, &_po.kvaddr); - if (rc) - eagle_drv_err("%s: msm audio ion alloc failed with %i", - __func__, rc); -} - -static void _unreg_ion_mem(void) -{ - int rc; - rc = msm_audio_ion_free(_ion_client, _ion_handle); - if (rc) - eagle_drv_err("%s: msm audio ion alloc failed with %i", - __func__, rc); -} - -static void _reg_ion_mem_NT(void) -{ - int rc; - eagle_drv_dbg("%s: NT ion mem", __func__); - rc = msm_audio_ion_alloc("DTS_EAGLE", &_ion_client_NT, - &_ion_handle_NT, ION_MEM_SIZE, - &_po_NT.paddr, &_po_NT.size, &_po_NT.kvaddr); - if (rc) { - eagle_drv_err("%s: msm audio ion alloc failed", __func__); - return; - } - rc = q6asm_memory_map(_ac_NT, _po_NT.paddr, - IN, _po_NT.size, 1); - if (rc < 0) { - eagle_drv_err("%s: memory map failed", __func__); - msm_audio_ion_free(_ion_client_NT, _ion_handle_NT); - _ion_client_NT = NULL; - _ion_handle_NT = NULL; - } -} - -static void _unreg_ion_mem_NT(void) -{ - int rc; - rc = q6asm_memory_unmap(_ac_NT, _po_NT.paddr, IN); - if (rc < 0) - eagle_drv_err("%s: mem unmap failed", __func__); - rc = msm_audio_ion_free(_ion_client_NT, _ion_handle_NT); - if (rc < 0) - eagle_drv_err("%s: mem free failed", __func__); - - _ion_client_NT = NULL; - _ion_handle_NT = NULL; -} - -static struct audio_client *_getNTDeviceAC(void) -{ - return _ac_NT; -} - -static void _set_audioclient(struct audio_client *ac) -{ - _ac_NT = ac; - _reg_ion_mem_NT(); -} - -static void _clear_audioclient(void) -{ - _unreg_ion_mem_NT(); - _ac_NT = NULL; -} - - -static int _sendcache_pre(struct audio_client *ac) -{ - uint32_t offset, size; - int32_t cidx, cmd, err = 0; - cidx = _get_cb_for_dev(_device_primary); - if (cidx < 0) { - eagle_precache_err("%s: no cache for primary device %i found", - __func__, _device_primary); - return -EINVAL; - } - offset = _c_bl[cidx][CBD_OFFSG]; - cmd = _c_bl[cidx][CBD_CMD0]; - size = _c_bl[cidx][CBD_SZ0]; - /* check for integer overflow */ - if (offset > (UINT_MAX - size)) - err = -EINVAL; - if ((_depc_size == 0) || !_depc || (size == 0) || - cmd == 0 || ((offset + size) > _depc_size) || (err != 0)) { - eagle_precache_err("%s: primary device %i cache index %i general error - cache size = %u, cache ptr = %pK, offset = %u, size = %u, cmd = %i", - __func__, _device_primary, cidx, _depc_size, _depc, - offset, size, cmd); - return -EINVAL; - } - - if ((offset < (UINT_MAX - 124)) && ((offset + 124) < _depc_size)) - eagle_precache_dbg("%s: first 6 integers %i %i %i %i %i %i (30th %i)", - __func__, *((int *)&_depc[offset]), - *((int *)&_depc[offset+4]), - *((int *)&_depc[offset+8]), - *((int *)&_depc[offset+12]), - *((int *)&_depc[offset+16]), - *((int *)&_depc[offset+20]), - *((int *)&_depc[offset+120])); - eagle_precache_dbg("%s: sending full data block to port, with cache index = %d device mask 0x%X, param = 0x%X, offset = %u, and size = %u", - __func__, cidx, _c_bl[cidx][CBD_DEV_MASK], cmd, offset, size); - - if (q6asm_dts_eagle_set(ac, cmd, size, (void *)&_depc[offset], - NULL, MPRE)) - eagle_precache_err("%s: q6asm_dts_eagle_set failed with id = %d and size = %u", - __func__, cmd, size); - else - eagle_precache_dbg("%s: q6asm_dts_eagle_set succeeded with id = %d and size = %u", - __func__, cmd, size); - return 0; -} - -static int _sendcache_post(int port_id, int copp_idx, int topology) -{ - int cidx = -1, cmd, mask, index, err = 0; - uint32_t offset, size; - - if (port_id == -1) { - cidx = _get_cb_for_dev(_device_primary); - if (cidx < 0) { - eagle_postcache_err("%s: no cache for primary device %i found. Port id was 0x%X", - __func__, _device_primary, port_id); - return -EINVAL; - } - goto NT_MODE_GOTO; - } - - index = adm_validate_and_get_port_index(port_id); - if (index < 0) { - eagle_postcache_err("%s: Invalid port idx %d port_id %#x", - __func__, index, port_id); - return -EINVAL; - } - eagle_postcache_dbg("%s: valid port idx %d for port_id %#x set to %i", - __func__, index, port_id, copp_idx); - _cidx[index] = copp_idx; - - mask = _get_dev_mask_for_pid(port_id); - if (mask & _device_primary) { - cidx = _get_cb_for_dev(_device_primary); - if (cidx < 0) { - eagle_postcache_err("%s: no cache for primary device %i found. Port id was 0x%X", - __func__, _device_primary, port_id); - return -EINVAL; - } - } else if (mask & _device_all) { - cidx = _get_cb_for_dev(_device_all); - if (cidx < 0) { - eagle_postcache_err("%s: no cache for combo device %i found. Port id was 0x%X", - __func__, _device_all, port_id); - return -EINVAL; - } - } else { - eagle_postcache_err("%s: port id 0x%X not for primary or combo device %i", - __func__, port_id, _device_primary); - return -EINVAL; - } - -NT_MODE_GOTO: - offset = _c_bl[cidx][CBD_OFFSG] + _c_bl[cidx][CBD_OFFS2]; - cmd = _c_bl[cidx][CBD_CMD2]; - size = _c_bl[cidx][CBD_SZ2]; - - /* check for integer overflow */ - if (offset > (UINT_MAX - size)) - err = -EINVAL; - if ((_depc_size == 0) || !_depc || (err != 0) || (size == 0) || - (cmd == 0) || (offset + size) > _depc_size) { - eagle_postcache_err("%s: primary device %i cache index %i port_id 0x%X general error - cache size = %u, cache ptr = %pK, offset = %u, size = %u, cmd = %i", - __func__, _device_primary, cidx, port_id, - _depc_size, _depc, offset, size, cmd); - return -EINVAL; - } - - if ((offset < (UINT_MAX - 24)) && ((offset + 24) < _depc_size)) - eagle_postcache_dbg("%s: first 6 integers %i %i %i %i %i %i", - __func__, *((int *)&_depc[offset]), - *((int *)&_depc[offset+4]), - *((int *)&_depc[offset+8]), - *((int *)&_depc[offset+12]), - *((int *)&_depc[offset+16]), - *((int *)&_depc[offset+20])); - eagle_postcache_dbg("%s: sending full data block to port, with cache index = %d device mask 0x%X, port_id = 0x%X, param = 0x%X, offset = %u, and size = %u", - __func__, cidx, _c_bl[cidx][CBD_DEV_MASK], port_id, cmd, - offset, size); - - if (_ac_NT) { - eagle_postcache_dbg("%s: NT Route detected", __func__); - if (q6asm_dts_eagle_set(_getNTDeviceAC(), cmd, size, - (void *)&_depc[offset], - &_po_NT, MPST)) - eagle_postcache_err("%s: q6asm_dts_eagle_set failed with id = 0x%X and size = %u", - __func__, cmd, size); - } else if (adm_dts_eagle_set(port_id, copp_idx, cmd, - (void *)&_depc[offset], size) < 0) - eagle_postcache_err("%s: adm_dts_eagle_set failed with id = 0x%X and size = %u", - __func__, cmd, size); - else - eagle_postcache_dbg("%s: adm_dts_eagle_set succeeded with id = 0x%X and size = %u", - __func__, cmd, size); - return 0; -} - -static int _enable_post_get_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = _is_hpx_enabled; - return 0; -} - -static int _enable_post_put_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int idx = 0, be_index = 0, port_id, topology; - int flag = ucontrol->value.integer.value[0]; - struct msm_pcm_routing_bdai_data msm_bedai; - eagle_drv_dbg("%s: flag %d", __func__, flag); - - _is_hpx_enabled = flag ? true : false; - msm_pcm_routing_acquire_lock(); - /* send cache postmix params when hpx is set On */ - for (be_index = 0; be_index < MSM_BACKEND_DAI_MAX; be_index++) { - msm_pcm_routing_get_bedai_info(be_index, &msm_bedai); - port_id = msm_bedai.port_id; - if (!(((port_id == SLIMBUS_0_RX) || - (port_id == RT_PROXY_PORT_001_RX) || - (port_id == AFE_PORT_ID_PRIMARY_MI2S_RX)) && - msm_bedai.active)) - continue; - for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) { - topology = adm_get_topology_for_port_copp_idx( - port_id, idx); - if (topology == - ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX) { - msm_dts_eagle_enable_adm(port_id, idx, - _is_hpx_enabled); - } - } - } - msm_pcm_routing_release_lock(); - return 0; -} - -static const struct snd_kcontrol_new _hpx_enabled_controls[] = { - SOC_SINGLE_EXT("Set HPX OnOff", SND_SOC_NOPM, 0, 1, 0, - _enable_post_get_control, _enable_post_put_control) -}; - -static int _be_post_get_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = _use_slim_be; - return 0; -} - -static int _be_post_put_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - _use_slim_be = ucontrol->value.integer.value[0]; - eagle_drv_dbg(" valuse of _use_slim_be == %d", _use_slim_be); - return 0; -} - -static const struct snd_kcontrol_new _hpx_be_controls[] = { - SOC_SINGLE_EXT("Set HPX ActiveBe", SND_SOC_NOPM, 0, 1, 0, - _be_post_get_control, _be_post_put_control) -}; -/** - * msm_dts_ion_memmap() - helper function to map ION memory - * @po_: Out of band memory structure used as memory. - * - * Assign already allocated ION memory for mapping it to dsp. - * - * Return: No return value. - */ -void msm_dts_ion_memmap(struct param_outband *po_) -{ - po_->size = ION_MEM_SIZE; - po_->kvaddr = _po.kvaddr; - po_->paddr = _po.paddr; -} - -/** - * msm_dts_eagle_enable_asm() - Enable/disable dts module - * @ac: Enable/disable module in ASM session associated with this audio client. - * @enable: Enable/disable the dts module. - * @module: module id. - * - * Enable/disable specified dts module id in asm. - * - * Return: Return failure if any. - */ -int msm_dts_eagle_enable_asm(struct audio_client *ac, u32 enable, int module) -{ - int ret = 0; - eagle_enable_dbg("%s: enable = %i on module %i", - __func__, enable, module); - _is_hpx_enabled = enable; - ret = q6asm_dts_eagle_set(ac, AUDPROC_PARAM_ID_ENABLE, - sizeof(enable), &enable, - NULL, module); - if (_is_hpx_enabled) { - if (module == MPRE) - _sendcache_pre(ac); - else if (module == MPST) - _sendcache_post(-1, 0, 0); - } - return ret; -} - -/** - * msm_dts_eagle_enable_adm() - Enable/disable dts module in adm - * @port_id: Send enable/disable param to this port id. - * @copp_idx: Send enable/disable param to the relevant copp. - * @enable: Enable/disable the dts module. - * - * Enable/disable dts module in adm. - * - * Return: Return failure if any. - */ -int msm_dts_eagle_enable_adm(int port_id, int copp_idx, u32 enable) -{ - int ret = 0; - eagle_enable_dbg("%s: enable = %i", __func__, enable); - _is_hpx_enabled = enable; - ret = adm_dts_eagle_set(port_id, copp_idx, AUDPROC_PARAM_ID_ENABLE, - (char *)&enable, sizeof(enable)); - if (_is_hpx_enabled) - _sendcache_post(port_id, copp_idx, MPST); - return ret; -} - -/** - * msm_dts_eagle_add_controls() - Add mixer control to Enable/Disable DTS HPX - * @platform: Add mixer controls to this platform. - * - * Add mixer control to Enable/Disable DTS HPX module in ADM. - * - * Return: No return value. - */ -void msm_dts_eagle_add_controls(struct snd_soc_platform *platform) -{ - snd_soc_add_platform_controls(platform, _hpx_enabled_controls, - ARRAY_SIZE(_hpx_enabled_controls)); - snd_soc_add_platform_controls(platform, _hpx_be_controls, - ARRAY_SIZE(_hpx_be_controls)); - -} - -/** - * msm_dts_eagle_set_stream_gain() - Set stream gain to DTS Premix module - * @ac: Set stream gain to ASM session associated with this audio client. - * @lgain: Left gain value. - * @rgain: Right gain value. - * - * Set stream gain to DTS Premix module in ASM. - * - * Return: failure or success. - */ -int msm_dts_eagle_set_stream_gain(struct audio_client *ac, int lgain, int rgain) -{ - u32 i, val; - s32 idx, err = 0; - - eagle_vol_dbg("%s: - entry: vol_cmd_cnt = %u, lgain = %i, rgain = %i", - __func__, _vol_cmd_cnt, lgain, rgain); - - if (_depc_size == 0) { - eagle_vol_dbg("%s: driver cache not initialized", __func__); - return -EINVAL; - } - - for (i = 0; i < _vol_cmd_cnt; i++) { - if (_vol_cmds_d[i].d[0] & 0x8000) { - idx = (sizeof(struct dts_eagle_param_desc)/sizeof(int)) - + (_vol_cmds_d[i].d[0] & 0x3FF); - val = _fx_logN(((s32)(lgain+rgain)) << 2); - val = ((long long)val * _log10_10_inv_x20) >> 16; - _vol_cmds[i][idx] = (s32)clamp((int)(((long long)val * - _vol_cmds_d[i].d[1]) >> 16), - _vol_cmds_d[i].d[2], - _vol_cmds_d[i].d[3]); - eagle_vol_dbg("%s: loop %u cmd desc found %i, idx = %i. volume info: lgain = %i, rgain = %i, volume = %i (scale %i, min %i, max %i)", - __func__, i, _vol_cmds_d[i].d[0], idx, lgain, - rgain, _vol_cmds[i][idx], _vol_cmds_d[i].d[1], - _vol_cmds_d[i].d[2], _vol_cmds_d[i].d[3]); - } - idx = _get_cb_for_dev(_device_primary); - if (idx < 0) { - eagle_vol_err("%s: no cache for primary device %i found", - __func__, _device_primary); - return -EINVAL; - } - val = _c_bl[idx][CBD_OFFSG] + _vol_cmds[i][2]; - /* check for integer overflow */ - if (val > (UINT_MAX - _vol_cmds[i][1])) - err = -EINVAL; - if ((err != 0) || ((val + _vol_cmds[i][1]) > _depc_size)) { - eagle_vol_err("%s: volume size (%u) + offset (%i) out of bounds %i", - __func__, val, _vol_cmds[i][1], _depc_size); - return -EINVAL; - } - memcpy((void *)&_depc[val], &_vol_cmds[i][4], _vol_cmds[i][1]); - if (q6asm_dts_eagle_set(ac, _vol_cmds[i][0], - _vol_cmds[i][1], (void *)&_depc[val], NULL, MPRE)) - eagle_vol_err("%s: loop %u - volume set failed with id 0x%X, size %i, offset %i, cmd_desc %i, scale %i, min %i, max %i, data(...) %i", - __func__, i, _vol_cmds[i][0], _vol_cmds[i][1], - _vol_cmds[i][2], _vol_cmds_d[i].d[0], - _vol_cmds_d[i].d[1], _vol_cmds_d[i].d[2], - _vol_cmds_d[i].d[3], _vol_cmds[i][4]); - else - eagle_vol_dbg("%s: loop %u - volume set succeeded with id 0x%X, size %i, offset %i, cmd_desc %i, scale %i, min %i, max %i, data(...) %i", - __func__, i, _vol_cmds[i][0], _vol_cmds[i][1], - _vol_cmds[i][2], _vol_cmds_d[i].d[0], - _vol_cmds_d[i].d[1], _vol_cmds_d[i].d[2], - _vol_cmds_d[i].d[3], _vol_cmds[i][4]); - } - return 0; -} - -/** - * msm_dts_eagle_handle_asm() - Set or Get params from ASM - * @depd: DTS Eagle Params structure. - * @buf: Buffer to get queried param value. - * @for_pre: For premix module or postmix module. - * @get: Getting param from DSP or setting param. - * @ac: Set/Get from ASM session associated with this audio client. - * @po: Out of band memory to set or get postmix params. - * - * Set or Get params from modules in ASM session. - * - * Return: Return failure if any. - */ -int msm_dts_eagle_handle_asm(struct dts_eagle_param_desc *depd, char *buf, - bool for_pre, bool get, struct audio_client *ac, - struct param_outband *po) -{ - struct dts_eagle_param_desc depd_ = {0}; - s32 ret = 0, isALSA = 0, err = 0, i, mod = for_pre ? MPRE : MPST; - u32 offset; - - eagle_asm_dbg("%s: set/get asm", __func__); - - /* special handling for ALSA route, to accommodate 64 bit platforms */ - if (depd == NULL) { - long *arg_ = (long *)buf; - depd = &depd_; - depd->id = (u32)*arg_++; - depd->size = (u32)*arg_++; - depd->offset = (s32)*arg_++; - depd->device = (u32)*arg_++; - buf = (char *)arg_; - isALSA = 1; - } - - if (depd->size & 1) { - eagle_asm_err("%s: parameter size %u is not a multiple of 2", - __func__, depd->size); - return -EINVAL; - } - - if (get) { - void *buf_, *buf_m = NULL; - eagle_asm_dbg("%s: get requested", __func__); - if (depd->offset == -1) { - eagle_asm_dbg("%s: get from dsp requested", __func__); - if (depd->size > 0 && depd->size <= DEPC_MAX_SIZE) { - buf_ = buf_m = vzalloc(depd->size); - } else { - eagle_asm_err("%s: get size %u invalid", - __func__, depd->size); - return -EINVAL; - } - if (!buf_m) { - eagle_asm_err("%s: out of memory", __func__); - return -ENOMEM; - } else if (q6asm_dts_eagle_get(ac, depd->id, - depd->size, buf_m, - po, mod) < 0) { - eagle_asm_err("%s: asm get failed", __func__); - ret = -EFAULT; - goto DTS_EAGLE_IOCTL_GET_PARAM_PRE_EXIT; - } - eagle_asm_dbg("%s: get result: param id 0x%x value %d size %u", - __func__, depd->id, *(int *)buf_m, depd->size); - } else { - s32 tgt = _get_cb_for_dev(depd->device); - if (tgt < 0) { - eagle_asm_err("%s: no cache for device %u found", - __func__, depd->device); - return -EINVAL; - } - offset = _c_bl[tgt][CBD_OFFSG] + depd->offset; - /* check for integer overflow */ - if (offset > (UINT_MAX - depd->size)) - err = -EINVAL; - if ((err != 0) || (offset + depd->size) > _depc_size) { - eagle_asm_err("%s: invalid size %u and/or offset %u", - __func__, depd->size, offset); - return -EINVAL; - } - buf_ = (u32 *)&_depc[offset]; - } - if (isALSA) { - if (depd->size == 2) { - *(long *)buf = (long)*(__u16 *)buf_; - eagle_asm_dbg("%s: asm out 16 bit value %li", - __func__, *(long *)buf); - } else { - s32 *pbuf = (s32 *)buf_; - long *bufl = (long *)buf; - for (i = 0; i < (depd->size >> 2); i++) { - *bufl++ = (long)*pbuf++; - eagle_asm_dbg("%s: asm out value %li", - __func__, *(bufl-1)); - } - } - } else { - memcpy(buf, buf_, depd->size); - } -DTS_EAGLE_IOCTL_GET_PARAM_PRE_EXIT: - vfree(buf_m); - return (int)ret; - } else { - s32 tgt = _get_cb_for_dev(depd->device); - if (tgt < 0) { - eagle_asm_err("%s: no cache for device %u found", - __func__, depd->device); - return -EINVAL; - } - offset = _c_bl[tgt][CBD_OFFSG] + depd->offset; - /* check for integer overflow */ - if (offset > (UINT_MAX - depd->size)) - err = -EINVAL; - if ((err != 0) || ((offset + depd->size) > _depc_size)) { - eagle_asm_err("%s: invalid size %u and/or offset %u for parameter (cache is size %u)", - __func__, depd->size, offset, _depc_size); - return -EINVAL; - } - if (isALSA) { - if (depd->size == 2) { - *(__u16 *)&_depc[offset] = (__u16)*(long *)buf; - eagle_asm_dbg("%s: asm in 16 bit value %li", - __func__, *(long *)buf); - } else { - s32 *pbuf = (s32 *)&_depc[offset]; - long *bufl = (long *)buf; - for (i = 0; i < (depd->size >> 2); i++) { - *pbuf++ = (s32)*bufl++; - eagle_asm_dbg("%s: asm in value %i", - __func__, *(pbuf-1)); - } - } - } else { - memcpy(&_depc[offset], buf, depd->size); - } - eagle_asm_dbg("%s: param info: param = 0x%X, size = %u, offset = %i, device = %u, cache block %i, global offset = %u, first bytes as integer = %i", - __func__, depd->id, depd->size, depd->offset, - depd->device, - tgt, offset, *(int *)&_depc[offset]); - if (q6asm_dts_eagle_set(ac, depd->id, depd->size, - (void *)&_depc[offset], po, mod)) - eagle_asm_err("%s: q6asm_dts_eagle_set failed with id = 0x%X, size = %u, offset = %d", - __func__, depd->id, depd->size, depd->offset); - else - eagle_asm_dbg("%s: q6asm_dts_eagle_set succeeded with id = 0x%X, size = %u, offset = %d", - __func__, depd->id, depd->size, depd->offset); - } - return (int)ret; -} - -/** - * msm_dts_eagle_handle_adm() - Set or Get params from ADM - * @depd: DTS Eagle Params structure used to set or get. - * @buf: Buffer to get queried param value in NT mode. - * @for_pre: For premix module or postmix module. - * @get: Getting param from DSP or setting param. - * - * Set or Get params from modules in ADM session. - * - * Return: Return failure if any. - */ -int msm_dts_eagle_handle_adm(struct dts_eagle_param_desc *depd, char *buf, - bool for_pre, bool get) -{ - u32 pid = _get_pid_from_dev(depd->device), cidx; - s32 ret = 0; - - eagle_adm_dbg("%s: set/get adm", __func__); - - if (_isNTDevice(depd->device)) { - eagle_adm_dbg("%s: NT Route detected", __func__); - ret = msm_dts_eagle_handle_asm(depd, buf, for_pre, get, - _getNTDeviceAC(), &_po_NT); - if (ret < 0) - eagle_adm_err("%s: NT Route set failed with id = 0x%X, size = %u, offset = %i, device = %u", - __func__, depd->id, depd->size, depd->offset, - depd->device); - } else if (get) { - cidx = adm_validate_and_get_port_index(pid); - eagle_adm_dbg("%s: get from qdsp requested (port id 0x%X)", - __func__, pid); - if (adm_dts_eagle_get(pid, _cidx[cidx], depd->id, - buf, depd->size) < 0) { - eagle_adm_err("%s: get from qdsp via adm with port id 0x%X failed", - __func__, pid); - return -EFAULT; - } - } else if (_is_port_open_and_eagle(pid)) { - cidx = adm_validate_and_get_port_index(pid); - eagle_adm_dbg("%s: adm_dts_eagle_set called with id = 0x%X, size = %u, offset = %i, device = %u, port id = %u, copp index = %u", - __func__, depd->id, depd->size, depd->offset, - depd->device, pid, cidx); - ret = adm_dts_eagle_set(pid, _cidx[cidx], depd->id, - (void *)buf, depd->size); - if (ret < 0) - eagle_adm_err("%s: adm_dts_eagle_set failed", __func__); - else - eagle_adm_dbg("%s: adm_dts_eagle_set succeeded", - __func__); - } else { - ret = -EINVAL; - eagle_adm_dbg("%s: port id 0x%X not active or not Eagle", - __func__, pid); - } - return (int)ret; -} - -/** - * msm_dts_eagle_ioctl() - ioctl handler function - * @cmd: cmd to handle. - * @arg: argument to the cmd. - * - * Handle DTS Eagle ioctl cmds. - * - * Return: Return failure if any. - */ -int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) -{ - s32 ret = 0; - switch (cmd) { - case DTS_EAGLE_IOCTL_GET_CACHE_SIZE: { - eagle_ioctl_info("%s: called with control 0x%X (get param cache size)", - __func__, cmd); - if (copy_to_user((void *)arg, &_depc_size, - sizeof(_depc_size))) { - eagle_ioctl_err("%s: error writing size", __func__); - return -EFAULT; - } - break; - } - case DTS_EAGLE_IOCTL_SET_CACHE_SIZE: { - u32 size = 0; - eagle_ioctl_info("%s: called with control 0x%X (allocate param cache)", - __func__, cmd); - if (copy_from_user((void *)&size, (void *)arg, sizeof(size))) { - eagle_ioctl_err("%s: error copying size (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &size, sizeof(size)); - return -EFAULT; - } else if (size > DEPC_MAX_SIZE) { - eagle_ioctl_err("%s: cache size %u not allowed (min 0, max %u)", - __func__, size, DEPC_MAX_SIZE); - return -EINVAL; - } - if (_depc) { - eagle_ioctl_dbg("%s: previous param cache of size %u freed", - __func__, _depc_size); - _depc_size = 0; - vfree(_depc); - _depc = NULL; - } - if (size) - _depc = vzalloc(size); - else - eagle_ioctl_dbg("%s: %u bytes requested for param cache, nothing allocated", - __func__, size); - if (_depc) { - eagle_ioctl_dbg("%s: %u bytes allocated for param cache", - __func__, size); - _depc_size = size; - } else { - eagle_ioctl_err("%s: error allocating param cache (vzalloc failed on %u bytes)", - __func__, size); - _depc_size = 0; - return -ENOMEM; - } - break; - } - case DTS_EAGLE_IOCTL_GET_PARAM: { - struct dts_eagle_param_desc depd; - s32 for_pre = 0, get_from_core = 0, err = 0; - u32 offset; - void *buf, *buf_m = NULL; - eagle_ioctl_info("%s: control 0x%X (get param)", - __func__, cmd); - if (copy_from_user((void *)&depd, (void *)arg, sizeof(depd))) { - eagle_ioctl_err("%s: error copying dts_eagle_param_desc (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &depd, sizeof(depd)); - return -EFAULT; - } - if (depd.device & DTS_EAGLE_FLAG_IOCTL_PRE) { - eagle_ioctl_dbg("%s: using for premix", __func__); - for_pre = 1; - } - if (depd.device & DTS_EAGLE_FLAG_IOCTL_GETFROMCORE) { - eagle_ioctl_dbg("%s: 'get from core' requested", - __func__); - get_from_core = 1; - depd.offset = -1; - } - depd.device &= DTS_EAGLE_FLAG_IOCTL_MASK; - if (depd.offset == -1) { - if (depd.size > 0 && depd.size <= DEPC_MAX_SIZE) { - buf = buf_m = vzalloc(depd.size); - } else { - eagle_ioctl_err("%s: get size %u invalid", - __func__, depd.size); - return -EINVAL; - } - if (!buf_m) { - eagle_ioctl_err("%s: out of memory", __func__); - return -ENOMEM; - } - if (get_from_core) - ret = core_dts_eagle_get(depd.id, depd.size, - buf); - else - ret = msm_dts_eagle_handle_adm(&depd, buf, - for_pre, true); - } else { - s32 cb = _get_cb_for_dev(depd.device); - if (cb < 0) { - eagle_ioctl_err("%s: no cache for device %u found", - __func__, depd.device); - return -EINVAL; - } - offset = _c_bl[cb][CBD_OFFSG] + depd.offset; - /* check for integer overflow */ - if (offset > (UINT_MAX - depd.size)) - err = -EINVAL; - if ((err != 0) || - ((offset + depd.size) > _depc_size)) { - eagle_ioctl_err("%s: invalid size %u and/or offset %u", - __func__, depd.size, offset); - return -EINVAL; - } - buf = (void *)&_depc[offset]; - } - if (ret < 0) - eagle_ioctl_err("%s: error %i getting data", __func__, - ret); - else if (copy_to_user((void *)(((char *)arg)+sizeof(depd)), - buf, depd.size)) { - eagle_ioctl_err("%s: error copying get data", __func__); - ret = -EFAULT; - } - vfree(buf_m); - break; - } - case DTS_EAGLE_IOCTL_SET_PARAM: { - struct dts_eagle_param_desc depd; - s32 just_set_cache = 0, for_pre = 0, err = 0; - u32 offset; - s32 tgt; - eagle_ioctl_info("%s: control 0x%X (set param)", - __func__, cmd); - if (copy_from_user((void *)&depd, (void *)arg, sizeof(depd))) { - eagle_ioctl_err("%s: error copying dts_eagle_param_desc (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &depd, sizeof(depd)); - return -EFAULT; - } - if (depd.device & DTS_EAGLE_FLAG_IOCTL_PRE) { - eagle_ioctl_dbg("%s: using for premix", __func__); - for_pre = 1; - } - if (depd.device & DTS_EAGLE_FLAG_IOCTL_JUSTSETCACHE) { - eagle_ioctl_dbg("%s: 'just set cache' requested", - __func__); - just_set_cache = 1; - } - depd.device &= DTS_EAGLE_FLAG_IOCTL_MASK; - tgt = _get_cb_for_dev(depd.device); - if (tgt < 0) { - eagle_ioctl_err("%s: no cache for device %u found", - __func__, depd.device); - return -EINVAL; - } - offset = _c_bl[tgt][CBD_OFFSG] + depd.offset; - /* check for integer overflow */ - if (offset > (UINT_MAX - depd.size)) - err = -EINVAL; - if ((err != 0) || ((offset + depd.size) > _depc_size)) { - eagle_ioctl_err("%s: invalid size %u and/or offset %u for parameter (target cache block %i with offset %i, global cache is size %u)", - __func__, depd.size, offset, tgt, - _c_bl[tgt][CBD_OFFSG], _depc_size); - return -EINVAL; - } - if (copy_from_user((void *)&_depc[offset], - (void *)(((char *)arg)+sizeof(depd)), - depd.size)) { - eagle_ioctl_err("%s: error copying param to cache (src:%pK, tgt:%pK, size:%u)", - __func__, ((char *)arg)+sizeof(depd), - &_depc[offset], depd.size); - return -EFAULT; - } - eagle_ioctl_dbg("%s: param info: param = 0x%X, size = %u, offset = %i, device = %u, cache block %i, global offset = %u, first bytes as integer = %i", - __func__, depd.id, depd.size, depd.offset, - depd.device, tgt, offset, *(int *)&_depc[offset]); - if (!just_set_cache) { - ret = msm_dts_eagle_handle_adm(&depd, &_depc[offset], - for_pre, false); - } - break; - } - case DTS_EAGLE_IOCTL_SET_CACHE_BLOCK: { - u32 b_[CBD_COUNT+1], *b = &b_[1], cb; - eagle_ioctl_info("%s: with control 0x%X (set param cache block)", - __func__, cmd); - if (copy_from_user((void *)b_, (void *)arg, sizeof(b_))) { - eagle_ioctl_err("%s: error copying cache block data (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, b_, sizeof(b_)); - return -EFAULT; - } - cb = b_[0]; - if (cb >= CB_COUNT) { - eagle_ioctl_err("%s: cache block %u out of range (max %u)", - __func__, cb, CB_COUNT-1); - return -EINVAL; - } - eagle_ioctl_dbg("%s: cache block %i set: devices 0x%X, global offset %i, offsets 1:%u 2:%u 3:%u, cmds/sizes 0:0x%X %u 1:0x%X %u 2:0x%X %u 3:0x%X %u", - __func__, cb, _c_bl[cb][CBD_DEV_MASK], _c_bl[cb][CBD_OFFSG], - _c_bl[cb][CBD_OFFS1], _c_bl[cb][CBD_OFFS2], - _c_bl[cb][CBD_OFFS3], _c_bl[cb][CBD_CMD0], _c_bl[cb][CBD_SZ0], - _c_bl[cb][CBD_CMD1], _c_bl[cb][CBD_SZ1], _c_bl[cb][CBD_CMD2], - _c_bl[cb][CBD_SZ2], _c_bl[cb][CBD_CMD3], _c_bl[cb][CBD_SZ3]); - if ((b[CBD_OFFSG]+b[CBD_OFFS1]+b[CBD_SZ1]) > _depc_size || - (b[CBD_OFFSG]+b[CBD_OFFS2]+b[CBD_SZ2]) > _depc_size || - (b[CBD_OFFSG]+b[CBD_OFFS3]+b[CBD_SZ3]) > _depc_size) { - eagle_ioctl_err("%s: cache block bounds out of range", - __func__); - return -EINVAL; - } - memcpy(_c_bl[cb], b, sizeof(_c_bl[cb])); - break; - } - case DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE: { - u32 data[2]; - eagle_ioctl_dbg("%s: with control 0x%X (set active device)", - __func__, cmd); - if (copy_from_user((void *)data, (void *)arg, sizeof(data))) { - eagle_ioctl_err("%s: error copying active device data (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, data, sizeof(data)); - return -EFAULT; - } - if (data[1] != 0) { - _device_primary = data[0]; - eagle_ioctl_dbg("%s: primary device %i", __func__, - data[0]); - } else { - _device_all = data[0]; - eagle_ioctl_dbg("%s: all devices 0x%X", __func__, - data[0]); - } - break; - } - case DTS_EAGLE_IOCTL_GET_LICENSE: { - u32 target = 0, size = 0; - s32 size_only; - eagle_ioctl_dbg("%s: with control 0x%X (get license)", - __func__, cmd); - if (copy_from_user((void *)&target, (void *)arg, - sizeof(target))) { - eagle_ioctl_err("%s: error reading license index. (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &target, sizeof(target)); - return -EFAULT; - } - size_only = target & (1<<31) ? 1 : 0; - target &= 0x7FFFFFFF; - if (target >= SEC_BLOB_MAX_CNT) { - eagle_ioctl_err("%s: license index %u out of bounds (max index is %i)", - __func__, target, SEC_BLOB_MAX_CNT); - return -EINVAL; - } - if (_sec_blob[target] == NULL) { - eagle_ioctl_err("%s: license index %u never initialized", - __func__, target); - return -EINVAL; - } - size = ((u32 *)_sec_blob[target])[0]; - if ((size == 0) || (size > SEC_BLOB_MAX_SIZE)) { - eagle_ioctl_err("%s: license size %u for index %u invalid (min size is 1, max size is %u)", - __func__, size, target, SEC_BLOB_MAX_SIZE); - return -EINVAL; - } - if (size_only) { - eagle_ioctl_dbg("%s: reporting size of license data only", - __func__); - if (copy_to_user((void *)(((char *)arg)+sizeof(target)), - (void *)&size, sizeof(size))) { - eagle_ioctl_err("%s: error copying license size", - __func__); - return -EFAULT; - } - } else if (copy_to_user((void *)(((char *)arg)+sizeof(target)), - (void *)&(((s32 *)_sec_blob[target])[1]), size)) { - eagle_ioctl_err("%s: error copying license data", - __func__); - return -EFAULT; - } else - eagle_ioctl_info("%s: license file %u bytes long from license index %u returned to user", - __func__, size, target); - break; - } - case DTS_EAGLE_IOCTL_SET_LICENSE: { - u32 target[2] = {0, 0}; - eagle_ioctl_dbg("%s: control 0x%X (set license)", __func__, - cmd); - if (copy_from_user((void *)target, (void *)arg, - sizeof(target))) { - eagle_ioctl_err("%s: error reading license index (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, target, sizeof(target)); - return -EFAULT; - } - if (target[0] >= SEC_BLOB_MAX_CNT) { - eagle_ioctl_err("%s: license index %u out of bounds (max index is %u)", - __func__, target[0], SEC_BLOB_MAX_CNT-1); - return -EINVAL; - } - if (target[1] == 0) { - eagle_ioctl_dbg("%s: request to free license index %u", - __func__, target[0]); - kfree(_sec_blob[target[0]]); - _sec_blob[target[0]] = NULL; - break; - } - if ((target[1] == 0) || (target[1] >= SEC_BLOB_MAX_SIZE)) { - eagle_ioctl_err("%s: license size %u for index %u invalid (min size is 1, max size is %u)", - __func__, target[1], target[0], - SEC_BLOB_MAX_SIZE); - return -EINVAL; - } - if (_sec_blob[target[0]] != NULL) { - if (((u32 *)_sec_blob[target[0]])[1] != target[1]) { - eagle_ioctl_dbg("%s: request new size for already allocated license index %u", - __func__, target[0]); - kfree(_sec_blob[target[0]]); - _sec_blob[target[0]] = NULL; - } - } - eagle_ioctl_dbg("%s: allocating %u bytes for license index %u", - __func__, target[1], target[0]); - _sec_blob[target[0]] = kzalloc(target[1] + 4, GFP_KERNEL); - if (!_sec_blob[target[0]]) { - eagle_ioctl_err("%s: error allocating license index %u (kzalloc failed on %u bytes)", - __func__, target[0], target[1]); - return -ENOMEM; - } - ((u32 *)_sec_blob[target[0]])[0] = target[1]; - if (copy_from_user( - (void *)&(((u32 *)_sec_blob[target[0]])[1]), - (void *)(((char *)arg)+sizeof(target)), - target[1])) { - eagle_ioctl_err("%s: error copying license to index %u, size %u (src:%pK, tgt:%pK, size:%u)", - __func__, target[0], target[1], - ((char *)arg)+sizeof(target), - &(((u32 *)_sec_blob[target[0]])[1]), - target[1]); - return -EFAULT; - } else - eagle_ioctl_info("%s: license file %u bytes long copied to index license index %u", - __func__, target[1], target[0]); - break; - } - case DTS_EAGLE_IOCTL_SEND_LICENSE: { - u32 target = 0; - eagle_ioctl_dbg("%s: control 0x%X (send license)", __func__, - cmd); - if (copy_from_user((void *)&target, (void *)arg, - sizeof(target))) { - eagle_ioctl_err("%s: error reading license index (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &target, sizeof(target)); - return -EFAULT; - } - if (target >= SEC_BLOB_MAX_CNT) { - eagle_ioctl_err("%s: license index %u out of bounds (max index is %i)", - __func__, target, SEC_BLOB_MAX_CNT-1); - return -EINVAL; - } - if (!_sec_blob[target] || - ((u32 *)_sec_blob[target])[0] == 0) { - eagle_ioctl_err("%s: license index %u is invalid", - __func__, target); - return -EINVAL; - } - if (core_dts_eagle_set(((s32 *)_sec_blob[target])[0], - (char *)&((s32 *)_sec_blob[target])[1]) < 0) - eagle_ioctl_err("%s: core_dts_eagle_set failed with id = %u", - __func__, target); - else - eagle_ioctl_info("%s: core_dts_eagle_set succeeded with id = %u", - __func__, target); - break; - } - case DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS: { - s32 spec = 0; - eagle_ioctl_info("%s: control 0x%X (set volume commands)", - __func__, cmd); - if (copy_from_user((void *)&spec, (void *)arg, - sizeof(spec))) { - eagle_ioctl_err("%s: error reading volume command specifier (src:%pK, tgt:%pK, size:%zu)", - __func__, (void *)arg, &spec, sizeof(spec)); - return -EFAULT; - } - if (spec & 0x80000000) { - u32 idx = (spec & 0x0000F000) >> 12; - s32 size = spec & 0x00000FFF; - eagle_ioctl_dbg("%s: setting volume command %i size: %i", - __func__, idx, size); - if (idx >= _vol_cmd_cnt) { - eagle_ioctl_err("%s: volume command index %u out of bounds (only %u allocated)", - __func__, idx, _vol_cmd_cnt); - return -EINVAL; - } - if (_volume_cmds_alloc2(idx, size) < 0) { - eagle_ioctl_err("%s: error allocating memory for volume controls", - __func__); - return -ENOMEM; - } - if (copy_from_user((void *)&_vol_cmds_d[idx], - (void *)(((char *)arg) + sizeof(int)), - sizeof(struct vol_cmds_d))) { - eagle_ioctl_err("%s: error reading volume command descriptor (src:%pK, tgt:%pK, size:%zu)", - __func__, ((char *)arg) + sizeof(int), - &_vol_cmds_d[idx], - sizeof(struct vol_cmds_d)); - return -EFAULT; - } - eagle_ioctl_dbg("%s: setting volume command %i spec (size %zu): %i %i %i %i", - __func__, idx, sizeof(struct vol_cmds_d), - _vol_cmds_d[idx].d[0], _vol_cmds_d[idx].d[1], - _vol_cmds_d[idx].d[2], _vol_cmds_d[idx].d[3]); - if (copy_from_user((void *)_vol_cmds[idx], - (void *)(((char *)arg) + (sizeof(int) + - sizeof(struct vol_cmds_d))), size)) { - eagle_ioctl_err("%s: error reading volume command string (src:%pK, tgt:%pK, size:%i)", - __func__, ((char *)arg) + (sizeof(int) + - sizeof(struct vol_cmds_d)), - _vol_cmds[idx], size); - return -EFAULT; - } - } else { - eagle_ioctl_dbg("%s: setting volume command size", - __func__); - if (spec < 0 || spec > VOL_CMD_CNT_MAX) { - eagle_ioctl_err("%s: volume command count %i out of bounds (min 0, max %i)", - __func__, spec, VOL_CMD_CNT_MAX); - return -EINVAL; - } else if (spec == 0) { - eagle_ioctl_dbg("%s: request to free volume commands", - __func__); - _volume_cmds_free(); - break; - } - eagle_ioctl_dbg("%s: setting volume command size requested = %i", - __func__, spec); - if (_volume_cmds_alloc1(spec) < 0) { - eagle_ioctl_err("%s: error allocating memory for volume controls", - __func__); - return -ENOMEM; - } - } - break; - } - default: { - eagle_ioctl_err("%s: control 0x%X (invalid control)", - __func__, cmd); - ret = -EINVAL; - } - } - return (int)ret; -} - -/** - * msm_dts_eagle_compat_ioctl() - To handle 32bit to 64bit ioctl compatibility - * @cmd: cmd to handle. - * @arg: argument to the cmd. - * - * Handle DTS Eagle ioctl cmds from 32bit userspace. - * - * Return: Return failure if any. - */ -#ifdef CONFIG_COMPAT -int msm_dts_eagle_compat_ioctl(unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case DTS_EAGLE_IOCTL_GET_CACHE_SIZE32: - cmd = DTS_EAGLE_IOCTL_GET_CACHE_SIZE; - break; - case DTS_EAGLE_IOCTL_SET_CACHE_SIZE32: - cmd = DTS_EAGLE_IOCTL_SET_CACHE_SIZE; - break; - case DTS_EAGLE_IOCTL_GET_PARAM32: - cmd = DTS_EAGLE_IOCTL_GET_PARAM; - break; - case DTS_EAGLE_IOCTL_SET_PARAM32: - cmd = DTS_EAGLE_IOCTL_SET_PARAM; - break; - case DTS_EAGLE_IOCTL_SET_CACHE_BLOCK32: - cmd = DTS_EAGLE_IOCTL_SET_CACHE_BLOCK; - break; - case DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE32: - cmd = DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE; - break; - case DTS_EAGLE_IOCTL_GET_LICENSE32: - cmd = DTS_EAGLE_IOCTL_GET_LICENSE; - break; - case DTS_EAGLE_IOCTL_SET_LICENSE32: - cmd = DTS_EAGLE_IOCTL_SET_LICENSE; - break; - case DTS_EAGLE_IOCTL_SEND_LICENSE32: - cmd = DTS_EAGLE_IOCTL_SEND_LICENSE; - break; - case DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS32: - cmd = DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS; - break; - default: - break; - } - return msm_dts_eagle_ioctl(cmd, arg); -} -#endif -/** - * msm_dts_eagle_init_pre() - Initialize DTS premix module - * @ac: Initialize premix module in the ASM session. - * - * Initialize DTS premix module on provided ASM session - * - * Return: Return failure if any. - */ -int msm_dts_eagle_init_pre(struct audio_client *ac) -{ - return msm_dts_eagle_enable_asm(ac, _is_hpx_enabled, - AUDPROC_MODULE_ID_DTS_HPX_PREMIX); -} - -/** - * msm_dts_eagle_deinit_pre() - Deinitialize DTS premix module - * @ac: Deinitialize premix module in the ASM session. - * - * Deinitialize DTS premix module on provided ASM session - * - * Return: Currently does nothing so 0. - */ -int msm_dts_eagle_deinit_pre(struct audio_client *ac) -{ - return 0; -} - -/** - * msm_dts_eagle_init_post() - Initialize DTS postmix module - * @port_id: Port id for the ADM session. - * @copp_idx: Copp idx for the ADM session. - * - * Initialize DTS postmix module on ADM session - * - * Return: Return failure if any. - */ -int msm_dts_eagle_init_post(int port_id, int copp_idx) -{ - return msm_dts_eagle_enable_adm(port_id, copp_idx, _is_hpx_enabled); -} - -/** - * msm_dts_eagle_deinit_post() - Deinitialize DTS postmix module - * @port_id: Port id for the ADM session. - * @topology: Topology in use. - * - * Deinitialize DTS postmix module on ADM session - * - * Return: Currently does nothing so 0. - */ -int msm_dts_eagle_deinit_post(int port_id, int topology) -{ - return 0; -} - -/** - * msm_dts_eagle_init_master_module() - Initialize both DTS modules - * @ac: Initialize modules in the ASM session. - * - * Initialize DTS modules on ASM session - * - * Return: Success. - */ -int msm_dts_eagle_init_master_module(struct audio_client *ac) -{ - _set_audioclient(ac); - msm_dts_eagle_enable_asm(ac, _is_hpx_enabled, - AUDPROC_MODULE_ID_DTS_HPX_PREMIX); - msm_dts_eagle_enable_asm(ac, _is_hpx_enabled, - AUDPROC_MODULE_ID_DTS_HPX_POSTMIX); - return 0; -} - -/** - * msm_dts_eagle_deinit_master_module() - Deinitialize both DTS modules - * @ac: Deinitialize modules in the ASM session. - * - * Deinitialize DTS modules on ASM session - * - * Return: Success. - */ -int msm_dts_eagle_deinit_master_module(struct audio_client *ac) -{ - msm_dts_eagle_deinit_pre(ac); - msm_dts_eagle_deinit_post(-1, 0); - _clear_audioclient(); - return 0; -} - -/** - * msm_dts_eagle_is_hpx_on() - Check if HPX effects are On - * - * Check if HPX effects are On - * - * Return: On/Off. - */ -int msm_dts_eagle_is_hpx_on(void) -{ - return _is_hpx_enabled; -} - -/** - * msm_dts_eagle_pcm_new() - Create hwdep node - * @runtime: snd_soc_pcm_runtime structure. - * - * Create hwdep node - * - * Return: Success. - */ -int msm_dts_eagle_pcm_new(struct snd_soc_pcm_runtime *runtime) -{ - if (!_ref_cnt++) { - _init_cb_descs(); - _reg_ion_mem(); - } - return 0; -} - -/** - * msm_dts_eagle_pcm_free() - remove hwdep node - * @runtime: snd_soc_pcm_runtime structure. - * - * Remove hwdep node - * - * Return: void. - */ -void msm_dts_eagle_pcm_free(struct snd_pcm *pcm) -{ - if (!--_ref_cnt) - _unreg_ion_mem(); - vfree(_depc); -} - -MODULE_DESCRIPTION("DTS EAGLE platform driver"); -MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c b/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c index 7c35d19bb61..8fc49b29000 100644 --- a/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c +++ b/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2012-2014, 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014, 2016-2017, The Linux Foundation. All + * rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -19,7 +20,6 @@ #include <sound/control.h> #include <sound/q6adm-v2.h> #include <sound/asound.h> -#include <sound/msm-dts-eagle.h> #include "msm-dts-srs-tm-config.h" #include "msm-pcm-routing-v2.h" diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c index e80b6fb9cf8..fb44bb71043 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-devdep.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -14,8 +14,6 @@ #include <linux/module.h> #include <sound/hwdep.h> #include <sound/devdep_params.h> -#include <sound/msm-dts-eagle.h> - #include "msm-pcm-routing-devdep.h" #include "msm-ds2-dap-config.h" @@ -53,23 +51,6 @@ static int msm_pcm_routing_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, case SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER: ret = msm_ds2_dap_ioctl(hw, file, cmd, argp); break; - case DTS_EAGLE_IOCTL_GET_CACHE_SIZE: - case DTS_EAGLE_IOCTL_SET_CACHE_SIZE: - case DTS_EAGLE_IOCTL_GET_PARAM: - case DTS_EAGLE_IOCTL_SET_PARAM: - case DTS_EAGLE_IOCTL_SET_CACHE_BLOCK: - case DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE: - case DTS_EAGLE_IOCTL_GET_LICENSE: - case DTS_EAGLE_IOCTL_SET_LICENSE: - case DTS_EAGLE_IOCTL_SEND_LICENSE: - case DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS: - ret = msm_dts_eagle_ioctl(cmd, arg); - if (ret == -EPERM) { - pr_err("%s called with invalid control 0x%X\n", - __func__, cmd); - ret = -EINVAL; - } - break; default: pr_err("%s called with invalid control 0x%X\n", __func__, cmd); ret = -EINVAL; @@ -81,7 +62,6 @@ static int msm_pcm_routing_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, void msm_pcm_routing_hwdep_free(struct snd_pcm *pcm) { pr_debug("%s\n", __func__); - msm_dts_eagle_pcm_free(pcm); } #ifdef CONFIG_COMPAT @@ -105,23 +85,6 @@ static int msm_pcm_routing_hwdep_compat_ioctl(struct snd_hwdep *hw, case SNDRV_DEVDEP_DAP_IOCTL_GET_VISUALIZER32: ret = msm_ds2_dap_compat_ioctl(hw, file, cmd, argp); break; - case DTS_EAGLE_IOCTL_GET_CACHE_SIZE32: - case DTS_EAGLE_IOCTL_SET_CACHE_SIZE32: - case DTS_EAGLE_IOCTL_GET_PARAM32: - case DTS_EAGLE_IOCTL_SET_PARAM32: - case DTS_EAGLE_IOCTL_SET_CACHE_BLOCK32: - case DTS_EAGLE_IOCTL_SET_ACTIVE_DEVICE32: - case DTS_EAGLE_IOCTL_GET_LICENSE32: - case DTS_EAGLE_IOCTL_SET_LICENSE32: - case DTS_EAGLE_IOCTL_SEND_LICENSE32: - case DTS_EAGLE_IOCTL_SET_VOLUME_COMMANDS32: - ret = msm_dts_eagle_compat_ioctl(cmd, arg); - if (ret == -EPERM) { - pr_err("%s called with invalid control 0x%X\n", - __func__, cmd); - ret = -EINVAL; - } - break; default: pr_err("%s called with invalid control 0x%X\n", __func__, cmd); ret = -EINVAL; @@ -167,7 +130,7 @@ int msm_pcm_routing_hwdep_new(struct snd_soc_pcm_runtime *runtime, #ifdef CONFIG_COMPAT hwdep->ops.ioctl_compat = msm_pcm_routing_hwdep_compat_ioctl; #endif - return msm_dts_eagle_pcm_new(runtime); + return rc; } #endif diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index f3d1d6e2c7a..1e129c58645 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -33,7 +33,6 @@ #include <sound/pcm_params.h> #include <sound/q6core.h> #include <sound/audio_cal_utils.h> -#include <sound/msm-dts-eagle.h> #include <sound/audio_effects.h> #include <sound/hwdep.h> @@ -155,10 +154,6 @@ static void msm_pcm_routing_cfg_pp(int port_id, int copp_idx, int topology, __func__, topology, port_id, rc); } break; - case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX: - pr_debug("%s: DTS_EAGLE_COPP_TOPOLOGY_ID\n", __func__); - msm_dts_eagle_init_post(port_id, copp_idx); - break; case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_AUDIOSPHERE: pr_debug("%s: TOPOLOGY_ID_AUDIOSPHERE\n", __func__); msm_qti_pp_asphere_init(port_id, copp_idx); @@ -190,10 +185,6 @@ static void msm_pcm_routing_deinit_pp(int port_id, int topology) msm_dolby_dap_deinit(port_id); } break; - case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX: - pr_debug("%s: DTS_EAGLE_COPP_TOPOLOGY_ID\n", __func__); - msm_dts_eagle_deinit_post(port_id, topology); - break; case ADM_CMD_COPP_OPEN_TOPOLOGY_ID_AUDIOSPHERE: pr_debug("%s: TOPOLOGY_ID_AUDIOSPHERE\n", __func__); msm_qti_pp_asphere_deinit(port_id); @@ -6653,8 +6644,6 @@ static int msm_routing_probe(struct snd_soc_platform *platform) device_pp_params_mixer_controls, ARRAY_SIZE(device_pp_params_mixer_controls)); - msm_dts_eagle_add_controls(platform); - snd_soc_add_platform_controls(platform, msm_source_tracking_controls, ARRAY_SIZE(msm_source_tracking_controls)); diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index e83c9c7d55e..1427e24a7f4 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -24,7 +24,6 @@ #include <sound/q6afe-v2.h> #include <sound/audio_cal_utils.h> #include <sound/asound.h> -#include <sound/msm-dts-eagle.h> #include "msm-dts-srs-tm-config.h" #include <sound/adsp_err.h> @@ -250,222 +249,6 @@ static int adm_get_next_available_copp(int port_idx) return idx; } -int adm_dts_eagle_set(int port_id, int copp_idx, int param_id, - void *data, uint32_t size) -{ - struct adm_cmd_set_pp_params_v5 admp; - int p_idx, ret = 0, *ob_params; - - pr_debug("DTS_EAGLE_ADM: %s - port id %i, copp idx %i, param id 0x%X size %u\n", - __func__, port_id, copp_idx, param_id, size); - - port_id = afe_convert_virtual_to_portid(port_id); - p_idx = adm_validate_and_get_port_index(port_id); - pr_debug("DTS_EAGLE_ADM: %s - after lookup, port id %i, port idx %i\n", - __func__, port_id, p_idx); - - if (p_idx < 0) { - pr_err("DTS_EAGLE_ADM: %s: invalid port index 0x%x, port id 0x%x\n", - __func__, p_idx, port_id); - return -EINVAL; - } - - if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) { - pr_err("DTS_EAGLE_ADM: %s: Invalid copp_idx: %d\n", __func__, - copp_idx); - return -EINVAL; - } - - ob_params = (int *)this_adm.outband_memmap.kvaddr; - if (ob_params == NULL) { - pr_err("DTS_EAGLE_ADM: %s - NULL memmap. Non Eagle topology selected?\n", - __func__); - ret = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - ret = -EINVAL; - if ((ret < 0) || - (size + APR_CMD_OB_HDR_SZ > this_adm.outband_memmap.size)) { - pr_err("DTS_EAGLE_ADM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, this_adm.outband_memmap.size, - size + APR_CMD_OB_HDR_SZ); - ret = -EINVAL; - goto fail_cmd; - } - *ob_params++ = AUDPROC_MODULE_ID_DTS_HPX_POSTMIX; - *ob_params++ = param_id; - *ob_params++ = size; - memcpy(ob_params, data, size); - - admp.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, - APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); - admp.hdr.pkt_size = sizeof(admp); - admp.hdr.src_svc = APR_SVC_ADM; - admp.hdr.src_domain = APR_DOMAIN_APPS; - admp.hdr.src_port = port_id; - admp.hdr.dest_svc = APR_SVC_ADM; - admp.hdr.dest_domain = APR_DOMAIN_ADSP; - admp.hdr.dest_port = atomic_read(&this_adm.copp.id[p_idx][copp_idx]); - admp.hdr.token = p_idx << 16 | copp_idx; - admp.hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5; - admp.payload_addr_lsw = lower_32_bits(this_adm.outband_memmap.paddr); - admp.payload_addr_msw = populate_upper_32_bits( - this_adm.outband_memmap.paddr); - admp.mem_map_handle = atomic_read(&this_adm.mem_map_handles[ - ADM_DTS_EAGLE]); - admp.payload_size = size + sizeof(struct adm_param_data_v5); - - pr_debug("DTS_EAGLE_ADM: %s - Command was sent now check Q6 - port id = %d, size %d, module id %x, param id %x.\n", - __func__, admp.hdr.dest_port, - admp.payload_size, AUDPROC_MODULE_ID_DTS_HPX_POSTMIX, - param_id); - atomic_set(&this_adm.copp.stat[p_idx][copp_idx], 0); - atomic_set(&this_adm.copp.cmd_err_code[p_idx][copp_idx], 0); - ret = apr_send_pkt(this_adm.apr, (uint32_t *)&admp); - if (ret < 0) { - pr_err("DTS_EAGLE_ADM: %s - ADM enable for port %d failed\n", - __func__, port_id); - ret = -EINVAL; - goto fail_cmd; - } - ret = wait_event_timeout(this_adm.copp.wait[p_idx][copp_idx], - atomic_read(&this_adm.copp.stat[p_idx][copp_idx]), - msecs_to_jiffies(TIMEOUT_MS)); - if (!ret) { - pr_err("DTS_EAGLE_ADM: %s - set params timed out port = %d\n", - __func__, port_id); - ret = -EINVAL; - } else if (atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]) > 0) { - pr_err("%s: DSP returned error[%s]\n", - __func__, adsp_err_get_err_str( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]))); - ret = adsp_err_get_lnx_err_code( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx])); - } else { - ret = 0; - } - -fail_cmd: - return ret; -} - -int adm_dts_eagle_get(int port_id, int copp_idx, int param_id, - void *data, uint32_t size) -{ - struct adm_cmd_get_pp_params_v5 admp; - int p_idx, ret = 0, *ob_params; - uint32_t orig_size = size; - pr_debug("DTS_EAGLE_ADM: %s - port id %i, copp idx %i, param id 0x%X\n", - __func__, port_id, copp_idx, param_id); - - port_id = afe_convert_virtual_to_portid(port_id); - p_idx = adm_validate_and_get_port_index(port_id); - if (p_idx < 0) { - pr_err("DTS_EAGLE_ADM: %s - invalid port index %i, port id %i, copp idx %i\n", - __func__, p_idx, port_id, copp_idx); - return -EINVAL; - } - - if (copp_idx < 0 || copp_idx >= MAX_COPPS_PER_PORT) { - pr_err("DTS_EAGLE_ADM: %s: Invalid copp_idx: %d\n", __func__, - copp_idx); - return -EINVAL; - } - - if ((size == 0) || !data) { - pr_err("DTS_EAGLE_ADM: %s - invalid size %u or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - - size = (size+3) & 0xFFFFFFFC; - - ob_params = (int *)(this_adm.outband_memmap.kvaddr); - if (ob_params == NULL) { - pr_err("DTS_EAGLE_ADM: %s - NULL memmap. Non Eagle topology selected?", - __func__); - ret = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - ret = -EINVAL; - if ((ret < 0) || - (size + APR_CMD_OB_HDR_SZ > this_adm.outband_memmap.size)) { - pr_err("DTS_EAGLE_ADM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, this_adm.outband_memmap.size, - size + APR_CMD_OB_HDR_SZ); - ret = -EINVAL; - goto fail_cmd; - } - *ob_params++ = AUDPROC_MODULE_ID_DTS_HPX_POSTMIX; - *ob_params++ = param_id; - *ob_params++ = size; - - admp.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, - APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); - admp.hdr.pkt_size = sizeof(admp); - admp.hdr.src_svc = APR_SVC_ADM; - admp.hdr.src_domain = APR_DOMAIN_APPS; - admp.hdr.src_port = port_id; - admp.hdr.dest_svc = APR_SVC_ADM; - admp.hdr.dest_domain = APR_DOMAIN_ADSP; - admp.hdr.dest_port = atomic_read(&this_adm.copp.id[p_idx][copp_idx]); - admp.hdr.token = p_idx << 16 | copp_idx; - admp.hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5; - admp.data_payload_addr_lsw = - lower_32_bits(this_adm.outband_memmap.paddr); - admp.data_payload_addr_msw = - populate_upper_32_bits( - this_adm.outband_memmap.paddr); - admp.mem_map_handle = atomic_read(&this_adm.mem_map_handles[ - ADM_DTS_EAGLE]); - admp.module_id = AUDPROC_MODULE_ID_DTS_HPX_POSTMIX; - admp.param_id = param_id; - admp.param_max_size = size + sizeof(struct adm_param_data_v5); - admp.reserved = 0; - - atomic_set(&this_adm.copp.stat[p_idx][copp_idx], 0); - atomic_set(&this_adm.copp.cmd_err_code[p_idx][copp_idx], 0); - - ret = apr_send_pkt(this_adm.apr, (uint32_t *)&admp); - if (ret < 0) { - pr_err("DTS_EAGLE_ADM: %s - Failed to get EAGLE Params on port %d\n", - __func__, port_id); - ret = -EINVAL; - goto fail_cmd; - } - ret = wait_event_timeout(this_adm.copp.wait[p_idx][copp_idx], - atomic_read(&this_adm.copp.stat[p_idx][copp_idx]), - msecs_to_jiffies(TIMEOUT_MS)); - if (!ret) { - pr_err("DTS_EAGLE_ADM: %s - EAGLE get params timed out port = %d\n", - __func__, port_id); - ret = -EINVAL; - goto fail_cmd; - } else if (atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]) > 0) { - pr_err("%s: DSP returned error[%s]\n", - __func__, adsp_err_get_err_str( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx]))); - ret = adsp_err_get_lnx_err_code( - atomic_read(&this_adm.copp.cmd_err_code - [p_idx][copp_idx])); - goto fail_cmd; - } - - memcpy(data, ob_params, orig_size); - ret = 0; -fail_cmd: - return ret; -} - int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id, void *srs_params) { @@ -2265,13 +2048,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, __func__, port_id, path, rate, channel_mode, perf_mode, topology); - /* For DTS EAGLE only, force 24 bit */ - if ((topology == ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX) && - (perf_mode == LEGACY_PCM_MODE)) { - bit_width = 24; - pr_debug("%s: Force open adm in 24-bit for DTS HPX topology 0x%x\n", - __func__, topology); - } port_id = q6audio_convert_virtual_to_portid(port_id); port_idx = adm_validate_and_get_port_index(port_id); if (port_idx < 0) { @@ -2298,8 +2074,7 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, flags = ADM_LOW_LATENCY_DEVICE_SESSION; if ((topology == DOLBY_ADM_COPP_TOPOLOGY_ID) || (topology == DS2_ADM_COPP_TOPOLOGY_ID) || - (topology == SRS_TRUMEDIA_TOPOLOGY_ID) || - (topology == ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX)) + (topology == SRS_TRUMEDIA_TOPOLOGY_ID)) topology = DEFAULT_COPP_TOPOLOGY; } else { if (path == ADM_PATH_COMPRESSED_RX) @@ -2368,20 +2143,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, (uint32_t)this_adm.outband_memmap.size); } } - if ((topology == ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX) && - (perf_mode == LEGACY_PCM_MODE)) { - int res = 0; - atomic_set(&this_adm.mem_map_index, ADM_DTS_EAGLE); - msm_dts_ion_memmap(&this_adm.outband_memmap); - res = adm_memory_map_regions( - &this_adm.outband_memmap.paddr, - 0, - (uint32_t *)&this_adm.outband_memmap.size, - 1); - if (res < 0) - pr_err("%s: DTS_EAGLE mmap did not work!", - __func__); - } open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); @@ -2661,21 +2422,6 @@ int adm_close(int port_id, int perf_mode, int copp_idx) } } - if ((perf_mode == LEGACY_PCM_MODE) && - (this_adm.outband_memmap.paddr != 0) && - (atomic_read( - &this_adm.copp.topology[port_idx][copp_idx]) == - ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX)) { - atomic_set(&this_adm.mem_map_index, ADM_DTS_EAGLE); - ret = adm_memory_unmap_regions(); - if (ret < 0) { - pr_err("%s: adm mem unmmap err %d", - __func__, ret); - } else { - atomic_set(&this_adm.mem_map_handles - [ADM_DTS_EAGLE], 0); - } - } if ((afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) && (this_adm.sourceTrackingData.memmap.paddr != 0)) { @@ -3062,10 +2808,6 @@ static int adm_init_cal_data(void) {NULL, NULL, NULL, NULL, NULL, NULL} }, {NULL, NULL, cal_utils_match_buf_num} }, - {{DTS_EAGLE_CAL_TYPE, - {NULL, NULL, NULL, NULL, NULL, NULL} }, - {NULL, NULL, cal_utils_match_buf_num} }, - {{SRS_TRUMEDIA_CAL_TYPE, {NULL, NULL, NULL, NULL, NULL, NULL} }, {NULL, NULL, cal_utils_match_buf_num} } diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index 21a0edf68f4..084cde4bf55 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -1015,7 +1015,7 @@ static int afe_get_cal_topology_id(u16 port_id, u32 *topology_id) struct audio_cal_info_afe_top *afe_top_info = NULL; if (this_afe.cal_data[AFE_TOPOLOGY_CAL] == NULL) { - pr_debug("%s: [AFE_TOPOLOGY_CAL] not initialized\n", __func__); + pr_err("%s: [AFE_TOPOLOGY_CAL] not initialized\n", __func__); return -EINVAL; } if (topology_id == NULL) { @@ -1028,7 +1028,7 @@ static int afe_get_cal_topology_id(u16 port_id, u32 *topology_id) cal_block = afe_find_cal_topo_id_by_port( this_afe.cal_data[AFE_TOPOLOGY_CAL], port_id); if (cal_block == NULL) { - pr_debug("%s: [AFE_TOPOLOGY_CAL] not initialized for this port %d\n", + pr_err("%s: [AFE_TOPOLOGY_CAL] not initialized for this port %d\n", __func__, port_id); ret = -EINVAL; goto unlock; diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 7246c944c8a..d7fb514f309 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * Author: Brian Swetland <swetland@google.com> * * This software is licensed under the terms of the GNU General Public @@ -41,8 +41,8 @@ #include <sound/q6core.h> #include <sound/q6audio-v2.h> #include <sound/audio_cal_utils.h> -#include <sound/msm-dts-eagle.h> #include <sound/adsp_err.h> +#include <sound/compress_params.h> #define TRUE 0x01 #define FALSE 0x00 @@ -2147,9 +2147,6 @@ static int __q6asm_open_read(struct audio_client *ac, open.src_endpointype = ASM_END_POINT_DEVICE_MATRIX; open.preprocopo_id = q6asm_get_asm_topology(); - if ((open.preprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.preprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS)) - open.preprocopo_id = ASM_STREAM_POSTPROCOPO_ID_NONE; open.bits_per_sample = bits_per_sample; open.mode_flags = 0x0; @@ -2387,16 +2384,9 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format, open.bits_per_sample = bits_per_sample; open.postprocopo_id = q6asm_get_asm_topology(); - if ((ac->perf_mode != LEGACY_PCM_MODE) && - ((open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS))) + if (ac->perf_mode != LEGACY_PCM_MODE) open.postprocopo_id = ASM_STREAM_POSTPROCOPO_ID_NONE; - /* For DTS EAGLE only, force 24 bit */ - if ((open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_PLUS)) - open.bits_per_sample = 24; - pr_debug("%s: perf_mode %d asm_topology 0x%x bps %d\n", __func__, ac->perf_mode, open.postprocopo_id, open.bits_per_sample); @@ -2596,10 +2586,6 @@ static int __q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format, topology : open.postprocopo_id; ac->topology = open.postprocopo_id; - /* For DTS EAGLE only, force 24 bit */ - if ((open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_DTS_HPX) || - (open.postprocopo_id == ASM_STREAM_POSTPROC_TOPO_ID_HPX_MASTER)) - open.bits_per_sample = 24; switch (wr_format) { case FORMAT_LINEAR_PCM: @@ -5499,215 +5485,6 @@ fail_cmd: return rc; } -int q6asm_dts_eagle_set(struct audio_client *ac, int param_id, uint32_t size, - void *data, struct param_outband *po, int m_id) -{ - int rc = 0, *ob_params = NULL; - uint32_t sz = sizeof(struct asm_dts_eagle_param) + (po ? 0 : size); - struct asm_dts_eagle_param *ad; - - if (!ac || ac->apr == NULL || (size == 0) || !data) { - pr_err("DTS_EAGLE_ASM - %s: APR handle NULL, invalid size %u or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - - ad = kzalloc(sz, GFP_KERNEL); - if (!ad) { - pr_err("DTS_EAGLE_ASM - %s: error allocating mem of size %u\n", - __func__, sz); - return -ENOMEM; - } - pr_debug("DTS_EAGLE_ASM - %s: ac %pK param_id 0x%x size %u data %pK m_id 0x%x\n", - __func__, ac, param_id, size, data, m_id); - q6asm_add_hdr_async(ac, &ad->hdr, sz, 1); - ad->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2; - ad->param.data_payload_addr_lsw = 0; - ad->param.data_payload_addr_msw = 0; - - ad->param.mem_map_handle = 0; - ad->param.data_payload_size = size + - sizeof(struct asm_stream_param_data_v2); - ad->data.module_id = m_id; - ad->data.param_id = param_id; - ad->data.param_size = size; - ad->data.reserved = 0; - atomic_set(&ac->cmd_state, 1); - - if (po) { - struct list_head *ptr, *next; - struct asm_buffer_node *node; - pr_debug("DTS_EAGLE_ASM - %s: using out of band memory (virtual %pK, physical %pK)\n", - __func__, po->kvaddr, &po->paddr); - ad->param.data_payload_addr_lsw = lower_32_bits(po->paddr); - ad->param.data_payload_addr_msw = populate_upper_32_bits( - po->paddr); - list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) { - node = list_entry(ptr, struct asm_buffer_node, list); - if (node->buf_phys_addr == po->paddr) { - ad->param.mem_map_handle = node->mmap_hdl; - break; - } - } - if (ad->param.mem_map_handle == 0) { - pr_err("DTS_EAGLE_ASM - %s: mem map handle not found\n", - __func__); - rc = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - rc = -EINVAL; - if ((rc < 0) || (size + APR_CMD_OB_HDR_SZ > po->size)) { - pr_err("DTS_EAGLE_ASM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, po->size, size + APR_CMD_OB_HDR_SZ); - rc = -EINVAL; - goto fail_cmd; - } - ob_params = (int *)po->kvaddr; - *ob_params++ = m_id; - *ob_params++ = param_id; - *ob_params++ = size; - memcpy(ob_params, data, size); - } else { - pr_debug("DTS_EAGLE_ASM - %s: using in band\n", __func__); - memcpy(((char *)ad) + sizeof(struct asm_dts_eagle_param), - data, size); - } - rc = apr_send_pkt(ac->apr, (uint32_t *)ad); - if (rc < 0) { - pr_err("DTS_EAGLE_ASM - %s: set-params send failed paramid[0x%x]\n", - __func__, ad->data.param_id); - rc = -EINVAL; - goto fail_cmd; - } - - rc = wait_event_timeout(ac->cmd_wait, - (atomic_read(&ac->cmd_state) <= 0), 1*HZ); - if (!rc) { - pr_err("DTS_EAGLE_ASM - %s: timeout, set-params paramid[0x%x]\n", - __func__, ad->data.param_id); - rc = -EINVAL; - goto fail_cmd; - } - rc = 0; -fail_cmd: - kfree(ad); - return rc; -} - -int q6asm_dts_eagle_get(struct audio_client *ac, int param_id, uint32_t size, - void *data, struct param_outband *po, int m_id) -{ - struct asm_dts_eagle_param_get *ad; - int rc = 0, *ob_params = NULL; - uint32_t sz = sizeof(struct asm_dts_eagle_param) + APR_CMD_GET_HDR_SZ + - (po ? 0 : size); - - if (!ac || ac->apr == NULL || (size == 0) || !data) { - pr_err("DTS_EAGLE_ASM - %s: APR handle NULL, invalid size %u or pointer %pK\n", - __func__, size, data); - return -EINVAL; - } - ad = kzalloc(sz, GFP_KERNEL); - if (!ad) { - pr_err("DTS_EAGLE_ASM - %s: error allocating memory of size %u\n", - __func__, sz); - return -ENOMEM; - } - pr_debug("DTS_EAGLE_ASM - %s: ac %pK param_id 0x%x size %u data %pK m_id 0x%x\n", - __func__, ac, param_id, size, data, m_id); - q6asm_add_hdr(ac, &ad->hdr, sz, TRUE); - ad->hdr.opcode = ASM_STREAM_CMD_GET_PP_PARAMS_V2; - ad->param.data_payload_addr_lsw = 0; - ad->param.data_payload_addr_msw = 0; - ad->param.mem_map_handle = 0; - ad->param.module_id = m_id; - ad->param.param_id = param_id; - ad->param.param_max_size = size + APR_CMD_GET_HDR_SZ; - ad->param.reserved = 0; - atomic_set(&ac->cmd_state, 1); - - generic_get_data = kzalloc(size + sizeof(struct generic_get_data_), - GFP_KERNEL); - if (!generic_get_data) { - pr_err("DTS_EAGLE_ASM - %s: error allocating mem of size %u\n", - __func__, size); - rc = -ENOMEM; - goto fail_cmd; - } - - if (po) { - struct list_head *ptr, *next; - struct asm_buffer_node *node; - pr_debug("DTS_EAGLE_ASM - %s: using out of band memory (virtual %pK, physical %pK)\n", - __func__, po->kvaddr, &po->paddr); - ad->param.data_payload_addr_lsw = lower_32_bits(po->paddr); - ad->param.data_payload_addr_msw = populate_upper_32_bits( - po->paddr); - list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) { - node = list_entry(ptr, struct asm_buffer_node, list); - if (node->buf_phys_addr == po->paddr) { - ad->param.mem_map_handle = node->mmap_hdl; - break; - } - } - if (ad->param.mem_map_handle == 0) { - pr_err("DTS_EAGLE_ASM - %s: mem map handle not found\n", - __func__); - rc = -EINVAL; - goto fail_cmd; - } - /* check for integer overflow */ - if (size > (UINT_MAX - APR_CMD_OB_HDR_SZ)) - rc = -EINVAL; - if ((rc < 0) || (size + APR_CMD_OB_HDR_SZ > po->size)) { - pr_err("DTS_EAGLE_ASM - %s: ion alloc of size %zu too small for size requested %u\n", - __func__, po->size, size + APR_CMD_OB_HDR_SZ); - rc = -EINVAL; - goto fail_cmd; - } - ob_params = (int *)po->kvaddr; - *ob_params++ = m_id; - *ob_params++ = param_id; - *ob_params++ = size; - generic_get_data->is_inband = 0; - } else { - pr_debug("DTS_EAGLE_ASM - %s: using in band\n", __func__); - generic_get_data->is_inband = 1; - } - - rc = apr_send_pkt(ac->apr, (uint32_t *)ad); - if (rc < 0) { - pr_err("DTS_EAGLE_ASM - %s: Commmand 0x%x failed\n", __func__, - ad->hdr.opcode); - goto fail_cmd; - } - - rc = wait_event_timeout(ac->cmd_wait, - (atomic_read(&ac->cmd_state) <= 0), 1*HZ); - if (!rc) { - pr_err("DTS_EAGLE_ASM - %s: timeout in get\n", - __func__); - rc = -EINVAL; - goto fail_cmd; - } - - if (generic_get_data->valid) { - rc = 0; - memcpy(data, po ? ob_params : generic_get_data->ints, size); - } else { - rc = -EINVAL; - pr_err("DTS_EAGLE_ASM - %s: EAGLE get params problem getting data - check callback error value\n", - __func__); - } -fail_cmd: - kfree(ad); - kfree(generic_get_data); - generic_get_data = NULL; - return rc; -} - static int __q6asm_set_volume(struct audio_client *ac, int volume, int instance) { struct asm_volume_ctrl_master_gain vol; diff --git a/sound/soc/msm/qdsp6v2/q6core.c b/sound/soc/msm/qdsp6v2/q6core.c index c149c0257a1..4948bef90c9 100644 --- a/sound/soc/msm/qdsp6v2/q6core.c +++ b/sound/soc/msm/qdsp6v2/q6core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -187,7 +187,7 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) generic_get_data->valid = 1; generic_get_data->size_in_ints = data->payload_size/sizeof(int); - pr_debug("DTS_EAGLE_CORE callback size = %i\n", + pr_debug("callback size = %i\n", data->payload_size); memcpy(generic_get_data->ints, data->payload, data->payload_size); @@ -420,115 +420,6 @@ fail_cmd: return ret; } -int core_dts_eagle_set(int size, char *data) -{ - struct adsp_dts_eagle *payload = NULL; - int rc = 0, size_aligned4byte; - - pr_debug("DTS_EAGLE_CORE - %s\n", __func__); - if (size <= 0 || !data) { - pr_err("DTS_EAGLE_CORE - %s: invalid size %i or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - - size_aligned4byte = (size+3) & 0xFFFFFFFC; - ocm_core_open(); - if (q6core_lcl.core_handle_q) { - payload = kzalloc(sizeof(struct adsp_dts_eagle) + - size_aligned4byte, GFP_KERNEL); - if (!payload) { - pr_err("DTS_EAGLE_CORE - %s: out of memory (aligned size %i).\n", - __func__, size_aligned4byte); - return -ENOMEM; - } - payload->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT, - APR_HDR_LEN(APR_HDR_SIZE), - APR_PKT_VER); - payload->hdr.pkt_size = sizeof(struct adsp_dts_eagle) + - size_aligned4byte; - payload->hdr.src_port = 0; - payload->hdr.dest_port = 0; - payload->hdr.token = 0; - payload->hdr.opcode = ADSP_CMD_SET_DTS_EAGLE_DATA_ID; - payload->id = DTS_EAGLE_LICENSE_ID; - payload->overwrite = 1; - payload->size = size; - memcpy(payload->data, data, size); - rc = apr_send_pkt(q6core_lcl.core_handle_q, - (uint32_t *)payload); - if (rc < 0) { - pr_err("DTS_EAGLE_CORE - %s: failed op[0x%x]rc[%d]\n", - __func__, payload->hdr.opcode, rc); - } - kfree(payload); - } - return rc; -} - -int core_dts_eagle_get(int id, int size, char *data) -{ - struct apr_hdr ah; - int rc = 0; - - pr_debug("DTS_EAGLE_CORE - %s\n", __func__); - if (size <= 0 || !data) { - pr_err("DTS_EAGLE_CORE - %s: invalid size %i or pointer %pK.\n", - __func__, size, data); - return -EINVAL; - } - ocm_core_open(); - if (q6core_lcl.core_handle_q) { - ah.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT, - APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); - ah.pkt_size = sizeof(struct apr_hdr); - ah.src_port = 0; - ah.dest_port = 0; - ah.token = 0; - ah.opcode = id; - - q6core_lcl.bus_bw_resp_received = 0; - generic_get_data = kzalloc(sizeof(struct generic_get_data_) - + size, GFP_KERNEL); - if (!generic_get_data) { - pr_err("DTS_EAGLE_CORE - %s: error allocating memory of size %i\n", - __func__, size); - return -ENOMEM; - } - - rc = apr_send_pkt(q6core_lcl.core_handle_q, - (uint32_t *)&ah); - if (rc < 0) { - pr_err("DTS_EAGLE_CORE - %s: failed op[0x%x]rc[%d]\n", - __func__, ah.opcode, rc); - goto fail_cmd_2; - } - - rc = wait_event_timeout(q6core_lcl.bus_bw_req_wait, - (q6core_lcl.bus_bw_resp_received == 1), - msecs_to_jiffies(TIMEOUT_MS)); - if (!rc) { - pr_err("DTS_EAGLE_CORE - %s: EAGLE get params timed out\n", - __func__); - rc = -EINVAL; - goto fail_cmd_2; - } - if (generic_get_data->valid) { - rc = 0; - memcpy(data, generic_get_data->ints, size); - } else { - rc = -EINVAL; - pr_err("DTS_EAGLE_CORE - %s: EAGLE get params problem getting data - check callback error value\n", - __func__); - } - } - -fail_cmd_2: - kfree(generic_get_data); - generic_get_data = NULL; - return rc; -} - uint32_t core_set_dolby_manufacturer_id(int manufacturer_id) { struct adsp_dolby_manufacturer_id payload; diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 123d347881f..bec8016937a 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -246,9 +246,8 @@ static int soc_compr_free(struct snd_compr_stream *cstream) SND_SOC_DAPM_STREAM_STOP); } else { rtd->pop_wait = 1; - queue_delayed_work(system_power_efficient_wq, - &rtd->delayed_work, - msecs_to_jiffies(rtd->pmdown_time)); + schedule_delayed_work(&rtd->delayed_work, + msecs_to_jiffies(rtd->pmdown_time)); } } else { /* capture streams can be powered down now */ diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index b7973e494fa..52f0cc8d4e3 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -65,6 +65,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) struct snd_soc_codec *codec; struct snd_soc_dapm_context *dapm; struct snd_soc_jack_pin *pin; + unsigned int sync = 0; int enable; trace_snd_soc_jack_report(jack, mask, status); @@ -92,12 +93,16 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) snd_soc_dapm_enable_pin(dapm, pin->pin); else snd_soc_dapm_disable_pin(dapm, pin->pin); + + /* we need to sync for this case only */ + sync = 1; } /* Report before the DAPM sync to help users updating micbias status */ blocking_notifier_call_chain(&jack->notifier, jack->status, jack); - snd_soc_dapm_sync(dapm); + if (sync) + snd_soc_dapm_sync(dapm); snd_jack_report(jack->jack, jack->status); @@ -280,7 +285,7 @@ static irqreturn_t gpio_handler(int irq, void *data) if (device_may_wakeup(dev)) pm_wakeup_event(dev, gpio->debounce_time + 50); - queue_delayed_work(system_power_efficient_wq, &gpio->work, + schedule_delayed_work(&gpio->work, msecs_to_jiffies(gpio->debounce_time)); return IRQ_HANDLED; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 3e62ac821f0..d7c78e47788 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -417,9 +417,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) } else { /* start delayed pop wq here for playback streams */ rtd->pop_wait = 1; - queue_delayed_work(system_power_efficient_wq, - &rtd->delayed_work, - msecs_to_jiffies(rtd->pmdown_time)); + schedule_delayed_work(&rtd->delayed_work, + msecs_to_jiffies(rtd->pmdown_time)); } } diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index bbc782e364b..9118fb8cc10 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -672,7 +672,7 @@ static void __ui_browser__line_arrow_down(struct ui_browser *browser, ui_browser__gotorc(browser, row, column + 1); SLsmg_draw_hline(2); - if (row++ == 0) + if (++row == 0) goto out; } else row = 0; |
